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;
}
请帮助我理解为什么输出是Hello Derived。如何发生此函数绑定。如何为Base和派生类创建虚拟表条目。
答案 0 :(得分:1)
伪代码如下所示:
#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)};
同样合格的调用如:obj.Base::func1()
直接调用Base::func1_def(obj)
,否则会抛出Base::func1
中描述的虚拟化过程。
答案 1 :(得分:1)
构造类对象时会创建虚拟表。构造Derived
对象时,它将首先调用Base
构造函数(创建vtable并将其自己的Base::fun1
写入其中。然后Derived
构造函数运行并覆盖fun1
的vtable条目及其自己的实现(Derived::fun1
)。
如果你那么,在任何后来的点(甚至从任何Base
函数内)调用这样一个对象实例的fun1
,它将查看vtable并调用它在那里找到的任何函数。如上所述,构造后Derived::fun1
对象的vtable中为Derived
,因此这将被调用。您当前处于Base
函数中并不重要,vtable条目不会更改。
请注意构建期间的,vtable未完全设置:如果您要从fun1
构造函数中调用Base
,则不< / em>致电Derived::fun1
,但Base::fun1
因为Derived
尚未替换vtable条目。
另请注意,完全指定函数(例如,在Base::fun1()
实例上调用Derived
)将不会执行vtable查找,而是使用完全指定的函数。