Bharadwaj Gali
Bharadwaj Gali

Reputation: 103

Name hiding when both return type and argument list changed

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

Answers (2)

Saurabh Raoot
Saurabh Raoot

Reputation: 1411

Name Hiding - If in derived class member function is given a new definition, there are two possibilities

  1. Signature and the return type remains the same

    --- Function Redifinition (for ordinary member functions)

    --- Function Overriding (for virtual member functions)

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

wally
wally

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

Related Questions