class Base
{
public:
int a;
virtual void fun1()
{
cout<<"Hello Base"<<endl;
}
void fun2()
{
fun1();
}
};
class Derived: public Base
{
int a;
void fun1()
{
cout<<"Hello Derived"<<endl;
}
};
int main()
{
Base * B = new Derived;
B->fun2();
return 1;
}
Please help me understand why output is Hello Derived.How this function binding takes place.How is virtual table entry created for Base and derived class.
The pseudo code looks like this:
#include <iostream>
class Base{
protected:
void **vt_ptr;
public:
int a;
//Executed prior to base member initialization
//and reexecuted prior to Base destructor call
void set_dynamic_type(){
vt_ptr = Base::vtable;
}
/*virtual*/
void fun1(){
reinterpret_cast<void(*)(Base&)>(vt_ptr[1])(*this);
}
void fun2(){
fun1();
}
private:
static void func1_def(Base& pseudo_obj_arg){
Base* this=&pseudo_obj_arg;
std::cout<<"Hello Base"<<std::endl;
}
static void* vtable[2];
};
void* Base::vtable[2]={
reinterpret_cast<void*>(&type_id_of_Base),
reinterpret_cast<void*>(&Base::func1_def)};
class Derived: public Base
{
int a;
//Executed after Base intialization,
//before Derived member initialization.
//Reexecuted prior to Derived destructor call
void set_dynamic_type(){
Base::vt_ptr = Derived::vtable;
}
private:
static void func1_def(Base& pseudo_obj_arg){
Derived* this=static_cast<Derived*>(&pseudo_obj_arg);
std::cout<<"Hello Derived"<<std::endl;
}
static void* vtable[2];
};
void* Derived::vtable[2]={
reinterpret_cast<void*>(&type_id_of_Derived),
reinterpret_cast<void*>(&Derived::func1_def)};
Also a qualified call as in: obj.Base::func1()
directly calls Base::func1_def(obj)
, otherwise it goes throw the devirtualization process described in Base::func1
.
The virtual table is created when the class objects are constructed. When you construct a Derived
object, it will first call the Base
constructor (which creates the vtable and writes its own Base::fun1
into that. Then the Derived
constructor runs and overwrites the vtable entry for fun1
with its own implementation ( Derived::fun1
).
If you then, at any later point (even from within any Base
function) call fun1
of such an object instance, it will look into the vtable and call whatever function it finds there. As explained above, it is Derived::fun1
that is in the vtable of a Derived
object after construction, so this is the one that will get called. It doesn't matter that you are currently in a Base
function, the vtable entry does not change.
Note that during construction, the vtable is not fully set up: If you were to call fun1
from within the Base
constructor, you would not call Derived::fun1
but Base::fun1
because Derived
did not replace the vtable entries yet.
Also note that fully specifying the function (eg calling Base::fun1()
on a Derived
instance) will not do a vtable lookup but instead use exactly the specified function.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.