Reputation: 581
Function overloading can happen between two member functions which have the same number of parameters, if one of them is declared as const.
But what if one function has a const argument, another has non-const argument of same type? Will it work for references and pointers? If C++ provides it, why does it provide? Please share the reason with me if you know.
Below is the example that helps you in understanding the above scenario.
void fun(const int i)
{
cout << "fun(const int) called ";
}
void fun(int i)
{
cout << "fun(int ) called " ;
}
int main()
{
const int i = 10;
fun(i);
return 0;
}
Output: Compiler Error: redefinition of 'void fun(int)'
void fun(char *a)
{
cout<<"non-const fun() called";
}
void fun(const char *a)
{
cout<<"const fun() called";
}
int main()
{
const char *ptr = "GeeksforGeeks";
fun(ptr);
return 0;
}
Output: const fun() called
Why is the second one allowed in C++?
Upvotes: 16
Views: 6550
Reputation: 11
Since the parameters are passed by reference in the 2nd part of your example the compiler can differentiate those two function definitions.
These functions are not ambiguous:
1. void fun(const int* num)
2. void fun(int* num)
because you cannot initialize a reference of type int
with a value of type const int
.
The compiler won't allow:
void fun(const int* num){
int* num2 = num;
}
Hence, if you make a call with a value of type const int
you will end up calling the 1st function or, if you make a call with a reference of type int
you will be calling the 2nd function.
The following might provide as an example:
void exClass::convertToConst(int* num)
{
// will call the first definition
useConst(const_cast<const int*>(num));
// will call the second definition
useConst(num);
}
void exClass::useConst(const int* num)
{
std::cout << "Num: " << *num << "\n";
}
void exClass::useConst(int *num)
{
*num += 5;
std::cout << "Num: " << *num << "\n";
}
Upvotes: 0
Reputation: 7516
First, explain why the first code is not allowed while the second one is ok.
const int
and int
as parameter, you pass any related type, double
, int
or anything else can convert to int, both const int
and int
can accept the pass-in value, there's no difference practically. And if the complier allow to the define both, then which one to call? You don't know, neither the complier. So the first part of code is not allowed.
When it comes to second example, reference and pointer makes a difference. Because you can't pass a const int*
to initialize int *
and neither can use const int
to initialize int&
. So if you define two functions with same return type, one is "const version" pointer or reference parameter, and the other is not, that makes a difference. Another question comes up, what if I pass a int
object(or called variable, same meaning) or int *
pointer, then which one is matched (when parameters are pointer or reference)? The answer is the "non-const" one. if you want to match the "const version" with non-const object or non point to const pointer, you may need const_cast
which I am trying to figure out.
So back to your question:
But what if one function has a const argument, another has non-const argument of same type? Will it work for references and pointers?
Yes, it to some extent only works for reference and pointers.
And
If C++ provides it, why does it provide?
Can't tell. I don't have much experience.
For further information, read the very related part sections of C++ Primer 5th. Links of screenshots are listed as follows:
By the way, though I am a newbie. But what is int const i
from the first answer? And I don't understand what "it's an implementation detail" exactly mean. No offense, just can't understand that part of answer. :D
Upvotes: 4
Reputation: 131907
The first one's parameters are top-level const
. This means that the function can't change the parameter's value, however, the caller doesn't care: The callee gets a copy of the argument, so if a parameter has top-level const
, it's an implementation detail. Note that the following works:
void f(int); // forward declare
void g(){ f(42); }
void f(int const i){ /*...*/ } // define above declared function
For the second set of overloads, the const
isn't top-level anymore. It describes whether or not the callee can change what the pointer points at. As a caller, you do care about that. It's not just an implementation detail anymore.
Upvotes: 16