Reputation: 89
I currently define a function that gets overloaded multiple times. For some of the overloaded definitions, it calls the same function with different type of input. So, function Foo gets defined to take type A, but within the body of the function, it calls Foo on type B. However, Foo on type B gets defined after A gets defined.
I am currently getting error on compile time and I think this is due to the ordering of the overloading definition. I do not have clear error message or debugging tools, so I would like to know if the above scenario does indeed cause an error.
void Foo (A input) {
B b = B();
Foo(b);
}
void Foo (B input) {
printf("%s", input.toString());
}
int main() {
A a = A();
Foo(a);
return 0;
}
//code has been oversimplified
I think the question can be bottled down to "does the compiler only check whether function has been defined or does it check whether the function has been defined on particular input?"
Upvotes: 4
Views: 1424
Reputation:
Does the order of overloaded function declaration matter in c++?
Short answer: Yes. Order matters in C++. Take the following example:
i = 45;
int i;
This would cause an error (assuming that there is no other i
in a higher scope, of course). It doesn't matter if it is a variable, function, class, or something else; in C++ a symbol must be declared before it is used. Even if it is an overloaded function, any overload you use in the definition must come first.
A Neat Trick
While you must declare a function before it is used, you don't have to define a function before it is used. I'm sure an example will help:
void Foo (A input);
void Foo (B input);
These are function declarations. Notice it is missing a definition--that is, an implementation. This just tells the compiler that such a function is there. It doesn't have to know what it does yet, only that it is there.
How does this help us? Well, consider the following program (which works, btw):
void Foo (A input);
void Foo (B input);
int main() {
A a = A();
Foo(a);
return 0;
}
void Foo (A input) {
B b = B();
Foo(b);
}
void Foo (B input) {
printf("%s", input.toString());
}
Notice anything interesting about this program? We can call Foo(A)
in main()
before it is defined. That's the nice thing about putting the declaration of Foo(A)
above the definition of main()
. The compiler knows that Foo(A)
exists, so we can call it from main()
even if we don't have its definition yet.
The really fun thing about using the declarations like this, is that once we have the declarations, we can put the definitions in any order. So we can do, for instance, this:
void Foo (A input);
void Foo (B input);
int main() {
A a = A();
Foo(a);
return 0;
}
void Foo (B input) {
printf("%s", input.toString());
}
void Foo (A input) {
B b = B();
Foo(b);
}
Or this:
void Foo (A input);
void Foo (B input);
void Foo (A input) {
B b = B();
Foo(b);
}
int main() {
A a = A();
Foo(a);
return 0;
}
void Foo (B input) {
printf("%s", input.toString());
}
Or even this:
void Foo (B input) {
printf("%s", input.toString());
}
int main() {
A a = A();
Foo(a);
return 0;
}
void Foo (A input) {
B b = B();
Foo(b);
}
Because it all comes after the declarations, the definition order does not matter in this case.
Worth mentioning before I leave: if we have a block of declarations like this:
void Foo (A input);
void Foo (B input);
Re-arranging the order of this block doesn't matter. So, we could do this as well:
void Foo (B input);
void Foo (A input);
As long as these declarations come before all the definitions, we are still good.
Upvotes: 1
Reputation: 238311
Declaration order of overloads does not matter in the sense that following are equivalent:
// 1.
void foo(int);
void foo(double);
foo(42);
// 2.
void foo(double);
void foo(int);
foo(42);
Declaration order of overloads does matter in the sense that following are not equivalent:
// 3.
void foo(int);
foo(42);
void foo(double);
// 4.
void foo(double);
foo(42);
void foo(int);
Concisely: Only functions that have been declared before the function call take part in overload resolution.
In your example program Foo(A)
either has infinite recursion (if B
implicitly converts to A
), or the program is ill-formed since you haven't declared Foo(B)
before the call.
Does the compiler only check whether function has been defined
In general, compiler does not to check at all whether a function has been defined. However, function must be declared before it can be called.
Upvotes: 8
Reputation: 462
Short answer is yes - the order matters. (Also, it really has nothing to do with overloads - you could rename Foo(B)
to Goo(B)
.)
One common remedy for your particular problem is to forward-declare Foo(B)
:
// Forward declaration
void Foo(B);
void Foo (A input) {
B b = B();
Foo(b); // Compiler now knows about Foo(B), so this is fine.
}
void Foo (B input) {
// ...
}
The compiler needs to know about that particular function - it must have been declared before it's use. However, it can be defined elsewhere. At link time, all the compiler output is gathered and symbols are "linked" together - the linker will figure out how to produce the right instructions to call Foo(B)
from that line, or possibly inline it, etc.
There may be times where the function must be forward-declared. E.g.
void Foo() {
if (condition) Goo();
}
void Goo() {
if (condition) Foo();
}
Both Foo
and Goo
need to know about each other, so you might declare both before Foo()
's definition (or put them in a header, if appropriate).
Upvotes: 5