下面用一段菱形继承的代码来探究菱形继承的对象模型
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()。所以,对于一个类中的虚函数,若是重写的父类的,则将虚表中的函数地址替换为自己的虚函数地址,若不是重写的函数,则直接将该函数地址放入虚表中。
现在把上面的代码改为虚拟继承,再来看内存窗口中的结果:
下面提供完整的代码调用虚函数
新闻热点
疑难解答