ranganath111
ranganath111

Reputation: 581

function overloading with const parameters

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

Answers (3)

Egemen
Egemen

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

Rick
Rick

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:

  1. https://i.sstatic.net/ch4aO.jpg
  2. https://i.sstatic.net/DVxbi.jpg
  3. https://i.sstatic.net/rPJFC.jpg

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

Xeo
Xeo

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

Related Questions