[英]Unexpected Output…how function binding happens in virtual table
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. 请帮助我理解为什么输出是Hello Derived。如何进行此函数绑定。如何为Base和派生类创建虚拟表条目。
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
. 还有一个合格的调用,例如:
obj.Base::func1()
直接调用Base::func1_def(obj)
,否则它将引发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
). 构造
Derived
对象时,它将首先调用Base
构造函数(它将创建vtable并将其自身写入Base::fun1
。然后, Derived
构造函数将运行并使用其自己的实现覆盖fun1
的vtable条目( 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. 如果这样,那么在以后的任何时刻(甚至从任何
Base
函数中)调用此类对象实例的fun1
,它都将调查vtable并调用在其中找到的任何函数。 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. 如上所述,构造后,它位于
Derived
对象的vtable中的Derived::fun1
,因此将被调用。 It doesn't matter that you are currently in a Base
function, the vtable entry does not change. 无论您当前是否处于
Base
函数中,vtable条目都不会更改。
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. 请注意, 在构建过程中 ,尚未完全建立vtable:如果要从
Base
构造函数中调用fun1
,则不会调用Derived::fun1
而是Base::fun1
因为Derived
尚未替换vtable条目。
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. 还要注意,完全指定函数(例如,在
Derived
实例上调用Base::fun1()
)不会执行vtable查找,而是完全使用指定的函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.