简体   繁体   English

意外的输出…函数绑定在虚拟表中如何发生

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM