>  Q&A  >  본문

c++ - 派生类声明新的虚函数后再派生,虚函数表里没有新的虚函数地址

有这样三个类的声明:

class A {
public:
    virtual void fun1() {
        cout << "A::fun1" << endl;
    }
};

class B : public A {
public:
    virtual void fun1() {
        cout << "B::fun1" << endl;
    }
    virtual void fun2() {
        cout << "B::fun2" << endl;
    }
};

class C : public B {
public:
    virtual void fun2() {
        cout << "C::fun2" << endl;
    }
};

B *pb1 = new B;
B *pb2 = new C;
pb1->fun2(); // B::fun2
pb2->fun2(); // C::fun2

B继承A后,新声明了个虚函数fun2,并被C继承,此时用B的指针指向C的对象可以实现多态。然而观察内存发现B和C的虚函数表里只保存了fun1的地址,并没有fun2的地址:

即使直接观察内存也是没有的:

可以看到C的虚函数表里,第一个地址0x008814e7就是B::fun1的地址,而后一个地址0x008814dd却不是B::fun2或C::fun2的地址


那么,程序在运行时是怎么找到fun2的地址的呢?

迷茫迷茫2766일 전443

모든 응답(1)나는 대답할 것이다

  • 大家讲道理

    大家讲道理2017-04-17 12:03:48

    真实的情况是这样的。你的B不仅覆盖了A,还增加了一个虚函数,所以B里面就会有两张虚函数表,一张用来保存fun1,一张用来保存fun2。

    因此写成C语言大概就这样:

    void A_fun1(A* this)
    {
        cout << "A::fun1" << endl;
    }
    
    void B_fun1(A* this)
    {
        cout << "B::fun1" << endl;
    }
    
    void B_fun2(B* this)
    {
        cout << "B::fun2" << endl;
    }
    
    void C_fun2(B* this)
    {
        cout << "C::fun2" << endl;
    }
    
    struct vtable_A
    {
        void (*fun1)(A*);
    };
    
    struct vtable_B
    {
        void (*fun2)(B*);
    };
    
    vtable_A vtable_A_instance_A = { &A_fun1 };
    vtable_A vtable_A_instance_B = { &B_fun1 };
    vtable_B vtable_B_instance_B = { &B_fun2 };
    vtable_B vtable_B_instance_C = { &C_fun2 };
    
    struct A
    {
        vtable_A* vtable;
    };
    
    struct B
    {
        A _A;
        vtable_B* vtable;
    };
    
    struct C
    {
        B _B;
    };
    
    void ctor_A(A* a)
    {
        a->vtable = &vtable_A_instance_A;
    }
    
    void ctor_B(B* b)
    {
        ctor_A(&b._A);
        b->_A.vtable = &vtable_A_instance_B;
        b->vtable = &vtable_B_instance_B;
    }
    
    void ctor_C(C* c)
    {
        ctor_B(&c._B);
        c._B.vtable = &vtable_B_instance_C;
    }
    
    int main()
    {
        B* pb1 = (B*)malloc(sizeof(B));
        ctor_B(pb1);
        C* temp = (C*)malloc(sizeof(C));
        ctor_C(temp);
        B* pb2 = &temp._B;
        pb1->vtable->fun2(pb1);
        pb2->vtable->fun2(pb1);
        return 0;
    }

    회신하다
    0
  • 취소회신하다