What is name hiding in C++?

Name hiding in C++ is best illustrated by an example – so take a look at this simple code below and then read on for an explanation:

Name Hiding in C++ Example

class ParentClass {
public: 
     virtual void someFunc(int a){
        printf(" ParentClass :: someFunc (int) \n");
    };

    virtual void someFunc(int* a){
        printf(" ParentClass :: someFunc (int*) \n");
    };
};

class ChildClass : public ParentClass {
public:
    virtual void someFunc(int* a){
        printf(" ChildClass ::  someFunc(int*) \n");
    };
};

int main(){
    ChildClass obj;
    /* This function call results in an error: */
    obj.someFunc(7);
}

It looks like the call to the someFunc function in the main function in the code above should run just fine.

But, in reality that method call results in an error which will say something like “error: no matching function for call to `ChildClass::someFunc(int)’”. Why would it return that error? The ChildClass clearly derives from the ParentClass, so it looks like the ChildClass object in the main function should have access to the someFunc(int) function declared inside the ParentClass in addition to the someFunc(int*) that accepts an integer pointer and is defined inside the ChildClass .

The reason the function call above results in an error is because of a property of C++ called name hiding. But, before we fully explain what name hiding is, how it works, and why it exists in C++, let’s go through another quick example.

Another Example of Name Hiding Functions in C++

class ParentClass
{
    public:
    void someFunction(string s){ };
};

class ChildClass : public ParentClass
{
    public:
    int someFunction(int i){};
};

class GrandChildClass : public ChildClass
{
    public:
    void differentFunction()
    {
        String s;
        /*This call will result in an error:  */
        someFunction(s); 
    }
};

Once again, it looks like the call to someFunction in the GrandChildClass in the code above should run just fine. But, in reality that function call results in an error which will say something like “In member function `void GrandChildClass::differentFunction()’: no matching function for call to `GrandChildClass::someFunction(std::string&)’ candidates are: int ChildClass::someFunction(int)”.

The meaning of the “no matching function for call” error in C++

What is the meaning of that error? Well, as you probably guessed it (again) has to do with name hiding.

So, what should be done here?

Functions in derived classes with the same name as the functions in the parent classes, but that do not override the parent classes’ function are considered to be bad practice because it can result in errors just like the one above. So, having a function like someFunction above is considered to be bad practice. This is technically not method overloading either, because overloading functions is done within the same class – not in an inheritance hierarchy.

The reason it’s bad practice is because it leads to ambiguity, and it’s much easier to just give the functions different names instead.

Understanding the error message you would get with name hiding

So, why does the code above result in that error message? Actually, the name lookup that is run by C++ will stop looking for other names as soon as it finds a single name in one of your base classes. This is because the someFunction declaration in ChildClass actually hides the someFunction declaration in ParentClass – so when a call to someFunction is made from GrandChildClass, the name lookup does not “see” the someFunction declaration that is in the ParentClass. But, there is another interesting “solution” to name hiding. It’s more of a way to override the name hiding behavior if you need to, because we can’t really say that name hiding is a “problem” since it’s intention is really to prevent other problems in C++. So, our “solution” is to unhide the someFunction declaration in ChildClass – read below for more details on how to do this.

Name hiding and using

We can actually provide a solution to the name hiding problem in the example above. All we have to do is implement the using keyword. Here is how to do it:

class ParentClass
{
    public:
    void someFunction(string s){ };
};

class ChildClass : public ParentClass
{
    public:
    int someFunction(int i){};

    /*This makes the someFunction
       declaration in ParentClass visible
       here as well:
    */
    using ParentClass::someFunction;
};

class GrandChildClass : public ChildClass
{
    public:
    void differentFunction()
    {
        String s;
        /*This call will result in an error:  */
        someFunction(s); 

    }
};

When we redeclare someFunction in the scope of ChildClass (with the “using” keyword), it makes both versions of that function (from both ChildClass and GrandChildClass) visible in just the ChildClass.

Why does C++ have the concept of name hiding?

There is actually a good reason why C++ has name hiding. Consider the example below:

class ParentClass
{
    public:
    void someFunction(string s){ };
};

class ChildClass : public ParentClass
{
    public:
    int someOtherFunction(int i){};

    /*This will use the same version of someFunction
       that is in the ParentClass, since it does not have
       it's own definition of someFunction
    */
};

class GrandChildClass : public ChildClass
{
   /* This overrides someFunction, creating
       a new version */
    public:
    float someFunction(float i){};
 
};

What if there was no concept of name hiding in C++?

Let’s suppose that there was no name hiding. Then this means that in the GrandChildClass, both versions of someFunction are now visible including the one in the parent class ParentClass – so float someFunction(float i), and void someFunction(string s) are both visible in the GrandChildClass class. If a call to “someFunction(29)” is made in either the ChildClass or the ParentClass, then it would obviously use the “void someFunction(string s){ };” version of the function since that is the only version of the function that those classes can “see”.

However, in the GrandChildClass if a call to “someFunction(29)” is made then there are 2 different functions that are visible – both someFunction(float i) and someFunction(string s) . It will obviously use someFunction(float i) since that is a better match for the parameter of 29. But, the issue here is that in the entire hierarchy of classes, the version of someFunction that is used is typically someFunction(string s), but once we get to the GrandChildClass, a different version of the someFunction function is used. This type of behavior was then considered to be undesirable by the C++ standard writers, so they implemented name hiding, which effectively gives each class a “clean slate” or a new, clean class that does not carry over the scope of inherited functions with the same name.

How to undo name hiding or override name hiding?

The way to override the name hiding behavior in C++ is to implement the “using” keyword as we showed above.


Hiring? Job Hunting? Post a JOB or your RESUME on our JOB BOARD >>

Subscribe to our newsletter for more free interview questions.



FOLLOW Varoon Sahgal, Author of ProgrammerInterviewon

  • Anon

    In "execution order of constructor and destructor in inheritance", the base class destructor is not virtual.