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;}前面我们也知道菱形继承就是多继承的一种,看到上面也发现多继承与单继承的区别,至于多继承的模型我们下次继续。。。
新闻热点
疑难解答
图片精选