c++ - 派生类声明新的虚函数后再派生,虚函数表里没有新的虚函数地址
迷茫
迷茫 2017-04-17 12:01:48
0
1
437

有这样三个类的声明:

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的地址的呢?

迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

全部回覆(1)
大家讲道理

真實的情況是這樣的。你的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;
}
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!