Reputation: 2886
void test(int& in);
void test(const int& in){
}
int main(){
int a = 5;
test(a);
return 0;
}
Above doesn't compile with a link error: undefined reference to `test(int&)'
.
I have 3 questions on this:
1- Why do we get a link error? is it because adding const
to the definition makes it a completely different function? why would it work when not using references, i.e this works fine:
void test(int in);
void test(const int in){}
..
int a = 5;
test(a);
..
2- Does const
go in function declaration, or definition or both? Seems like
the behaviour is different if references are used.
3- Does the const
keyword on an argument say "the parameter passed to me should be a constant in the caller" or "this parameter is treated as a constant in this function scope, regardless of it being constant in the caller or not". I'm sure it's the latter but wanted to confirm.
Upvotes: 2
Views: 289
Reputation: 45674
A function-definition is always also a function-declaration.
Thus, to differentiate them, the latter is often called a forward-declaration if it is not also a definition.
The function-signature used for overload-resolution derives from the function-declaration, and there are a few peculiarities in deriving it from the written source:
Top-level cv-specifiers on argument-types are discarded.
Top-level cv-specifiers on return-type are discarded if the type is not a class- or union-type. (A struct
is a class-type.)
The function is not affected by these rules outside overload-resolution and matching declarations.
Applied to your examples:
void test(int& in);
void test(const int& in) { // const is not top-level
// The above two declarations are for different functions
void test(int in);
void test(const int in){} // const is top-level
// Equivalent declarations above
Upvotes: 2
Reputation: 4659
In C++ the two functions:
void test(int& in);
void test(const int& in);
are TWO different, overloaded functions. The first binds to "writeable" integers, the second - to constant ones.
In your code:
int a = 5;
test(a);
a
is a modifiable object, hence void test (int &)
is a better match from compiler perspective and it selects this function for a call.
The reason why you are getting linker error is that you declared but not defined this function.
In both cases below the const
function would have been selected:
int const a = 5;
test(a);
test(10);
Additionally if you only had const
version declared as below, it would have been selected as well:
//void test(int &in);
void test(const int &in){}
..
int a = 5;
test(a);
..
As for the second question in case of references - const
goes both to declaration and definition as these are different functions.
With normal values there is NO difference between the two when declared:
void test(int in);
void test(const int in);
They refer to THE SAME function. The const
version will prevent modification of the function parameter in function definition.
For the third one, when applied to references it means two things:
const
it promises to the caller not to modify referenced object and prevents the function from doing so.Upvotes: 4
Reputation: 38773
A function definition is also a function declaration. Thus, you declare two overloaded functions, but only one function is defined, has a body.
The compiler choses the first function, since a
is not const and the first choice is the exact match.
You get the linker error, since the first function has no definition, i.e. no body.
Upvotes: 1
Reputation: 439
It's best to do both, as the const
keyword is intended to hint at the user that the variable will not be modified. I believe most compilers will treat a const
type as a different type as well, so you'll have a compile error.
Upvotes: -1