Reputation: 103
My basic question is why name hiding not applicable when both return type and argument list are changed. Please refer below sample piece.
// Example program
#include <iostream>
#include <string>
using namespace std;
class base {
public:
int f() const { cout <<"I am base void version. "<<endl; return 1;}
int f(string) const { cout <<"I am base string version. "<<endl; return 1;}
};
class Derived1 : public base {
public:
int f() const {
cout << "Derived1::f()\n";
return 2;
}
};
class Derived2 : public base {
public:
int f(int) const {
cout << "Derived2::f()\n";
return 3;
}
};
class Derived3 : public base {
public:
void f(int) const {
cout << "Derived3::f()\n";
}
};
int main()
{
string s("hello");
Derived1 d1;
int x = d1.f();
//d1.f(s); // string version hidden
Derived2 d2;
//x = d2.f(); // f() version hidden
x = d2.f(1);
Derived3 d3;
d3.f(1); // No name hiding
}
output :
Derived1::f()
Derived2::f()
Derived3::f()
In the above program
a) Why string version is not hidden for Derived2 object ?
b) Why name hiding is not applicable when both return type and argument is matched ?
Any links or references for "how name hiding works in compiler level ?" are useful.
Thank you.
Upvotes: 1
Views: 76
Reputation: 1411
Name Hiding - If in derived class member function is given a new definition, there are two possibilities
Signature and the return type remains the same
--- Function Redifinition (for ordinary member functions)
--- Function Overriding (for virtual member functions)
Signature and the return type changes --- Name Hiding
If a function is given a new definition in the derived class, all the other versions are automatically hidden in the derived class
Overloading is not possible across scopes
Upvotes: 1
Reputation: 11032
From Bjarne Stroustrup's own FAQ on this subject:
Why doesn't overloading work for derived classes?
That question (in many variations) are usually prompted by an example like this:
#include<iostream> using namespace std; class B { public: int f(int i) { cout << "f(int): "; return i+1; } // ... }; class D : public B { public: double f(double d) { cout << "f(double): "; return d+1.3; } // ... }; int main() { D* pd = new D; cout << pd->f(2) << '\n'; cout << pd->f(2.3) << '\n'; }
which will produce:
f(double): 3.3 f(double): 3.6
rather than the
f(int): 3 f(double): 3.6
that some people (wrongly) guessed.
You can modify the program in the question to make the hidden overloads available by adding using base::f;
to the derived class:
#include <iostream>
#include <string>
using namespace std;
class base {
public:
int f() const { cout <<"I am base int version. "<<endl; return 1; }
int f(string) const { cout <<"I am base string version. "<<endl; return 1; }
};
class Derived1 : public base {
public:
using base::f;
int f() const
{
cout << "Derived1::f()\n";
return 2;
}
};
class Derived2 : public base {
public:
using base::f;
int f(int) const
{
cout << "Derived2::f()\n";
return 3;
}
};
class Derived3 : public base {
public:
void f(int) const
{
cout << "Derived3::f()\n";
}
};
int main()
{
string s("hello");
Derived1 d1;
int x = d1.f();
d1.f(s); // string version hidden
Derived2 d2;
x = d2.f(); // f() version hidden
x = d2.f(1);
Derived3 d3;
d3.f(1); // No name hiding
}
The output is then:
Derived1::f()
I am base string version.
I am base int version.
Derived2::f()
Derived3::f()
Upvotes: 2