探讨:菱形虚拟继承的虚基表和虚表
在继承和多态里,总是能听到虚表、虚基表这样的词汇,没有洞悉其根本的人很容易将它们混淆,因此,我们对这两个“虚”“表”进行实践,来更好地理解它们。
通俗些说:
虚基表,即虚基类表,存放的是偏移量,是该表的位置与基类那一部分内容的地址之间的距离。
虚表:即虚函数表,存放的是函数指针,是某个类中所有虚函数的指针的集合。
-
初始&菱形虚拟继承
有这么一段菱形虚拟继承的代码:
class A { public: void func1() { cout << "A::func1()" << endl; } int a; }; class B : virtual public A { public: int b; }; class C : virtual public A { public: int c; }; class D : public B, public C { public: int d; }; int main() { D d1; d1.a = 1; d1.b = 2; d1.c = 3; d1.d = 4; return 0; }
这是一个典型的菱形虚拟继承,我们通过调试,来看看它在内存中的布局:
因为没有虚函数,所以没有虚函数表(虚表)。
而虚基类表(虚基表)来自于:菱形虚拟继承(虚拟:解决菱形继承的二义性和冗余) -
重写/覆盖
class A { public: virtual void func1() { cout << "A::func1()" << endl; } int a; }; class B : virtual public A { public: void func1() { cout << "B::func1()" << endl; } int b; }; class C : virtual public A { public: int c; }; class D : public B, public C { public: int d; }; int main() { D d1; d1.a = 1; d1.b = 2; d1.c = 3; d1.d = 4; return 0; }
此时B中的
func1()
与A中的func1()
构成重写(覆盖),整个过程请参看下面的调试过程:刚才仅仅是在B中重写,那如果C中也进行重写呢?此时到底是重写B的实现,还是C的实现呢?
答案是:都不是!
如果B和C同时对A的func1()
进行重写,编译器会报错,因为不明确!此时只需要在D中,也进行func1()
的重写,那么就OK了!编译器会把D的实现重写进去,不会写B和C的实现。(当然B和C的重写并非没用,当有些场景创建“B b1;
”B类型的对象b1时,就可以用到B的重写了) -
中间两个派生类有自己的虚函数
刚才的代码都是
基类A
的虚函数,如果派生类自己也有虚函数呢?请看:class A { public: virtual void func1() { cout << "A::func1()" << endl; } int a; }; class B : virtual public A { public: void func1() { cout << "B::func1()" << endl; } virtual void funcB() { cout << "B::funcB()" << endl; } int b; }; class C : virtual public A { public: void func1() { cout << "C::func1()" << endl; } virtual void funcC() { cout << "C::funcC()" << endl; } int c; }; class D : public B, public C { public: void func1() { cout << "D::func1()" << endl; } int d; }; int main() { D d1; d1.a = 1; d1.b = 2; d1.c = 3; d1.d = 4; return 0; }
两个中间的派生类B和C,分别加上自己的虚函数
funcB()
和funcC()
,此时就没有刚才那么简单了,请看下图:在原先的基础上,B和C分别多了一个虚函数表,存放它们自己的虚函数的地址。
-
最后一个派生类有自己的虚函数
刚才是中间两个派生类有自己的虚函数,它们会产生自己的虚函数表,那么如果最后一个派生类(多继承的那个)也有自己的虚函数呢?你肯定以为它也会产生一个自己的虚函数表,但是你错了。请看下面的调试图:
至此可以窥得,C++多继承中的菱形继承,是多么的让人费解!也正因如此,我们不必要时,尽量避免写出菱形虚拟继承这样的结构出来,这对大家都好!