菱形继承与虚拟菱形继承对象模型

菱形继承对象模型

下面用一段菱形继承的代码来探究菱形继承的对象模型

class AA
{
public:
    virtual void fun1()
    {
        cout << "AA::fun1()" << endl;
    }
public:
    int _a;
};

class BB : public AA
{
public:
    virtual void fun1()
    {
        cout << "BB::fun1()" << endl;
    }
public:
    int _b;
};
class CC : public AA
{
public:
    virtual void fun1()
    {
        cout << "CC::fun1()" << endl;
    }
public:
    int _c;
};
class DD :public BB,public CC
{
public:
    virtual void fun1()
    {
        cout << "DD::fun1()" << endl;
    }
    virtual void fun2()
    {
        cout << "DD::fun2()" << endl;
    }
public:
    int _d;
};
void Test1()
{
    DD d;
    d.BB::_a = 1;
    d.CC::_a = 2;
    d._b = 3;
    d._c = 4;
    d._d = 5;
}

打开内存窗口,进行单步调试,结果如下:
这里写图片描述
这里写图片描述
对于对象d,重写了fun1(),所以将DD的fun1()放入虚表,再将fun2()放入虚表,图片中另一个虚表指针指向的是CC中的虚函数,CC中的fun1()重写了AA中的fun1(),所以在虚表中放入CC的fun1()。这一这样理解,橙色区域本来应给是AA类,续表中存储的是AA::fun1()的地址,但是BB类中从写了fun1(),所以把AA::fun1()替换为了CC::fun1()。所以,对于一个类中的虚函数,若是重写的父类的,则将虚表中的函数地址替换为自己的虚函数地址,若不是重写的函数,则直接将该函数地址放入虚表中。

菱形虚拟继承对象模型

现在把上面的代码改为虚拟继承,再来看内存窗口中的结果:
这里写图片描述
这里写图片描述
下面提供完整的代码调用虚函数

class AA
{
public:
    virtual void fun1()
    {
        cout << "AA::fun1()" << endl;
    }
public:
    int _a;
};
class BB : virtual public AA
{
public:
    virtual void fun1()
    {
        cout << "BB::fun1()" << endl;
    }
public:
    int _b;
};
class CC : virtual public AA
{
public:
    virtual void fun1()
    {
        cout << "CC::fun1()" << endl;
    }
public:
    int _c;
};
class DD :public BB,public CC
{
public:
    virtual void fun1()
    {
        cout << "DD::fun1()" << endl;
    }
    virtual void fun2()
    {
        cout << "DD::fun2()" << endl;
    }
public:
    int _d;
};
typedef void(*FUNC) ();
void PrintfVTable(int *VTable)
{
    cout << "虚表地址:" << "0x" << VTable << endl;
    for (int i = 0; VTable[i] != 0; ++i)
    {
        cout << "虚函数地址:0x" << VTable[i] << " ";
        FUNC f = (FUNC)VTable[i];
        f();
    }
    cout << endl;
}
void Test1()
{
    DD d;
    d.BB::_a = 1;
    d.CC::_a = 2;
    d._b = 3;
    d._c = 4;
    d._d = 5;
    int* VTable = (int *)(*(int *)&d);
    PrintfVTable(VTable);
    VTable = (int *)(*((int*)&d + 6));
    PrintfVTable(VTable);
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/it_10/article/details/55511040
今日推荐