Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion regarding name hiding and virtual functions

Refering another so question

Consider the code :

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

    virtual void gogo(int* a){
        printf(" Base :: gogo (int*) \n");
    };
};

class Derived : public Base{
public:
    virtual void gogo(int* a){
        printf(" Derived :: gogo (int*) \n");
    };
};

int main(){

    // 1)       
    Derived * obj = new Derived ; 
    obj->gogo(7);  // this is illegal because of name hiding


    // 2)      
    Base* obj = new Derived ;
    obj->gogo(7); // this is legal
}

For case 2)

The call obj->gogo(7) is resolved at run time.

Since obj->gogo(7) is legal. It seems to imply that vtable of Derived contains ptr to virtual void gogo(int a) which should have been hidden.

My confusion is , since name hiding causes case 1) to be illegal, then how the call in 2) is resolved at run time

a) Does vtable of Derived contains pointer to gogo(int).

b) If a) is not True, Does call resolution for virtual functions proceeds to vtable of base class.

like image 902
hiteshg Avatar asked Apr 16 '12 11:04

hiteshg


People also ask

Can virtual functions be called?

A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.

What happens when a virtual function is called?

Virtual functions ensure that the correct function is called for an object, regardless of the type of reference (or pointer) used for function call. Functions are declared with a virtual keyword in base class.

How virtual and non virtual member functions are called?

Non- virtual member functions are resolved statically. That is, the member function is selected statically (at compile-time) based on the type of the pointer (or reference) to the object. In contrast, virtual member functions are resolved dynamically (at run-time).

Can virtual functions be private?

A virtual function can be private as C++ has access control, but not visibility control. As mentioned virtual functions can be overridden by the derived class but under all circumstances will only be called within the base class.


3 Answers

You are confusing virtual functions calls and overload resolution.

All derived classes have vtables containing all virtual functions, from the base class and any additional own virtual functions. This is used to resolve calls at runtime, like in your case 2).

In case 1) you get an error from overload resolution at compile time. Due to name hiding, class Derived only has one callable function. Your only choice is to call that function, with an int*.

like image 54
Bo Persson Avatar answered Nov 15 '22 03:11

Bo Persson


You want to override overloaded function but hiding rules don't work like this.

"The hiding rule says that an entity in an inner scope hides things with the same name in an outer scope."

Note, it is irrelevant that it has different signature i.e. gogo(int* a) will hide all gogo(whatever) functions from the Base. Overriding occurs only when your functions have same name, same signatures and virtual (so, only gogo(int* a) will be overrided).

The C++FAQ book suggest to use "non-virtual overloads that call non-overloaded virtuals." (chapter 29.05). Basically you create non-virtual overloaded functions in base class:

gogo(int a) and gogo(int* a)

which will call virtual functions respectively:

virtual gogo_i(int a) and virtual gogo_pi(int* a)

And override this virtuals in Derived class.

like image 40
Yodo Avatar answered Nov 15 '22 03:11

Yodo


Basically, function overloading happens only when the functions of same name are defined in the same scope.Now, Base class has its own scope and derived class has its own.

So, when u don't redefine a function in the derived class and call that function, the compiler checks the scope of derived, discovers that there is no such function defined in there. Then it checks the scope of base class, discovers the function and accordingly binds the function call to this particular definition.

But, when u redefine the function with different signature, the compiler matches the call with this function, sees inconsistency and simply complains.

you can change this behaviour by adding "using Base::gogo; " in derived class defenision. I hope this explains.

like image 28
whitetiger Avatar answered Nov 15 '22 03:11

whitetiger