在c++中我们有一种继承方式叫做菱形继承,通俗来说就是有两个类(son1,son2)都继承了同一个类(base),然后又有一个类(grandson)来继承这两个类(就是多继承的一种,个人不建议在实际开发中使用多继承)。
但是这样做会带来两个问题
或许这样看不是很清楚,我们上代码看看
class base { public: int m_a; }; class son1:public base{}; class son2:public base{}; class grandson :public son1, public son2{}; int main() { grandson g; g.m_a = 10;//这里就会报错,提示m_a不明确 return 0; }
那么c++给我们提供了虚继承用来解决这种问题,只需要在son1和son2继承base时使用虚继承即可(grandson正常继承son1和son2),语法:class son1 : virtual public base {}; class son2 : virtual public base {}; 其中base类叫作虚基类,这种继承方式就是虚继承。
class base { public: int m_a; }; class son1:virtual public base{}; class son2:virtual public base{}; class grandson :public son1, public son2{}; int main() { grandson g; g.m_a = 10;//这样这里就不会出现之前的不明确的情况 return 0; }
那么为什么加上virtual将能解决上述问题呢,这个就和虚继承的底层实现有关系。
在son1和son2虚继承base时,其实继承过来的是一个虚基类指针(vbptr——virtual base pointer),它指向的是一个虚基类表(vbtable——virtual base table),这个表中记录了一个数据——偏移量,当你继承这个虚基类指针时,它通过偏移量也能找到你想要的成员,所以上面的m_a只有一份,grandson中只是继承了两个不同的虚基类指针,通过这两个指针来找到这唯一的m_a,就能解决二义性以及资源浪费问题。
如果大家不是很能理解,也可以打开vs的开发人员命令行提示符来查看类的对象模型。
具体操作步骤如下:
接下来可以看看我的对象模型