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.
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.
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.
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).
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.
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*
.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With