Dan
Dan

Reputation: 2886

Is the `const` keyword used in function declaration, or definition or both?

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

Answers (4)

Deduplicator
Deduplicator

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:

  1. Top-level cv-specifiers on argument-types are discarded.

  2. 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

Tomek
Tomek

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:

  1. A reference will be passed to a function and not a copy for an object.
  2. When accompanied by a const it promises to the caller not to modify referenced object and prevents the function from doing so.

Upvotes: 4

3CxEZiVlQ
3CxEZiVlQ

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

Guy Marino
Guy Marino

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

Related Questions