首页 > 编程 > C++ > 正文

C++对象模型

2019-11-08 18:21:08
字体:
来源:转载
供稿:网友

一.单继承的对象模型

class Car{public:    virtual void func1()    {        cout << "Car::func1()" << endl;    }    virtual void func2()    {        cout << "Car::func2()" << endl;    }PRotected:    int _c;//种类};class Bike :public Car{public:    virtual void func1()    {        cout << "Bike::func1()" << endl;    }    virtual void func2()    {        cout << "Bike::func2()" << endl;    }    virtual void func3()    {        cout << "Bike::func3()" << endl;    }protected:    int _b;//自行车数量};int main(){    Car c;    Bike b;    system("pause");    return 0;}通过这种表我们对单继承有个初步的了解,可以看道派生类Bike::func1重写(覆盖)了父类Car::func1,覆盖了虚表函数的位置。但是我们细心发现,派生类Bike::func3消失了。我们可以打印函数的地址打开内存看个究竟:
class Car{public:    virtual void func1()    {        cout << "Car::func1()" << endl;    }    virtual void func2()    {        cout << "Car::func2()" << endl;    }protected:    int _c;//种类};class Bike :public Car{public:    virtual void func1()    {        cout << "Bike::func1()" << endl;    }    virtual void func2()    {        cout << "Bike::func2()" << endl;    }    virtual void func3()    {        cout << "Bike::func3()" << endl;    }protected:    int _b;//自行车数量};typedef void(*FUNC) ();void PrintfVtable(void *_vfptr){    int *Vtable = (int *)_vfptr;    printf("虚表的地址Vtable:0x%x/n",Vtable);    for (size_t i = 0; Vtable[i] != 0; ++i)    {        printf("第%d个虚函数的地址:0x%x/n", i, Vtable[i]);        FUNC f = (FUNC)Vtable[i];        f();    }}int main(){    Car c;    Bike b;    int *Vtable1 = (int*)(*((int*)&c));    int *Vtable2 = (int*)(*((int*)&b));    PrintfVtable(Vtable1);    PrintfVtable(Vtable2);    system("pause");    return 0;}我们画一下它的对象模型:

三.菱形对象

class AA{public:    virtual void fun1()    {        cout << "AA::fun1()" << endl;    }    virtual void funA()    {        cout << "AA::funA()" << endl;    }public:    int _aa;};class BB :public AA{public:    virtual void fun1()    {        cout << "BB::funB()" << endl;    }    virtual void funB()    {        cout << "BB::funB()" << endl;    }public:    int _bb;};class CC :public AA{public:    virtual void fun1()    {        cout << "CC::fun1()" << endl;    }    virtual void funC()    {        cout << "CC::funC()" << endl;    }public:    int _cc;};class DD :public BB,public CC{public:    virtual void fun1()    {        cout << "DD::fun1()" << endl;    }    virtual void funD()    {        cout << "DD::funD()" << endl;    }public:    int _dd;};typedef void(*FUNC)();void PrintfVtable(void *_vfptr){         int*Vtable = (int *)_vfptr;        printf("虚表的地址Vtable:0x%x/n",Vtable);        for (size_t i = 0; Vtable[i] != 0; ++i)        {            printf("第%d个虚函数的地址:0x%x/n", i, Vtable[i]);            FUNC f = (FUNC)Vtable[i];            f();        }   }int main(){    DD d;    d.BB::_aa = 0;    d.CC::_aa = 1;    d._bb  = 2;    d._cc = 3;    d._dd = 4;    int *Vtable1 = (int*)(*((int*)&d));    PrintfVtable(Vtable1);    system("pause");    return 0;}通过上面我们很清楚的看到有两个虚表分别存放虚函数的地址,第一个存放派生类DD::fun1()的地址和AA::funA();第二个虚函数存放AA::funA()的地址。这里面就出现菱形继承的问题二义性和数据的冗余的问题。通过观察内存看到。

三.菱形虚拟继承

在public前面加上关键字virtual:class AA{public:    virtual void fun1()    {        cout << "AA::fun1()" << endl;    }    virtual void funA()    {        cout << "AA::funA()" << endl;    }public:    int _aa;};class BB :virtual public AA{public:    virtual void fun1()    {        cout << "BB::funB()" << endl;    }    virtual void funB()    {        cout << "BB::funB()" << endl;    }public:    int _bb;};class CC :virtual public AA{public:    virtual void fun1()    {        cout << "CC::fun1()" << endl;    }    virtual void funC()    {        cout << "CC::funC()" << endl;    }public:    int _cc;};class DD :public BB,public CC{public:    virtual void fun1()    {        cout << "DD::fun1()" << endl;    }    virtual void funD()    {        cout << "DD::funD()" << endl;    }public:    int _dd;};typedef void(*FUNC)();void PrintfVtable(void* _vptr){    int *Vtable = (int*)_vptr;    printf("虚表的地址)0x%x/n", Vtable);        for (size_t i = 0; Vtable[i] != 0; ++i)        {            printf("第%d个虚函数的地址:0x%x/n", i, Vtable[i]);            FUNC f = (FUNC)Vtable[i];            f();        }   }int main(){    DD d;    d.BB::_aa = 0;    d.CC::_aa = 1;    d._bb  = 2;    d._cc = 3;    d._dd = 4;    int *Vtable = (int*)(*((int*)&d));    PrintfVtable(Vtable);    system("pause");    return 0;}前面我们也知道菱形继承就是多继承的一种,看到上面也发现多继承与单继承的区别,至于多继承的模型我们下次继续。。。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选