本期对继承的知识进行一些补充,还没看过之前对继承讲解的建议先看之前的
C++继承_KLZUQ的博客-CSDN博客
本期补充知识为菱形继承以及菱形虚拟继承相关知识
class A
{
public:
virtual void func1()
{
cout << "A::func1" << endl;
}
public:
int _a;
};
class B : public A
//class B : virtual public A
{
public:
int _b;
};
class C : public A
//class C : virtual public A
{
public:
int _c;
};
class D : public B, public C
{
public:
int _d;
};
我们进入调试,然后看内存窗口,&d,一上来就可以看到两个指针 ,这里就是虚表的指针
当我们走完时,可以看到里面1,2,3,4,5的变化
也就是说,我们单纯的看菱形继承,其实是和多继承没有区别的
下面我们再看看菱形虚拟继承
菱形虚拟继承又分为几个问题,首先是只有A里面有虚函数 ,此时是将A单独拿出来了,放在了下面,这里我们说过了
而它不同的地方在于,我们上面给A写了func1函数,如果我们对他进行重写
我们会发现,首先编译会报错 ,不重写还没事,B和C重写后就有问题了,这是为什么?
原因是,这里A是属于B和C共享的,B去重写,C也去重写,那到底是谁去重写?
我们先把重写的func去掉,然后此时只有A里面有func1, 只有一张虚表,只有A有虚函数,B也要重写,C也要重写,就不行了
解决方案是让D也去重写 ,此时B,C,D都进行了重写
此时就会有人问,那B和C为什么还要去重写?直接让D重写不就好了吗?其实我们在实际中不仅仅会定义D对象,B和C对象也是可能定义的
对于菱形继承,D里面的B和C各自有各自的A,所以重写没有问题,但是菱形虚拟继承,这个A变成公共的了,B也要用,C也要用,那就都别用了,让D用吧
菱形虚拟继承还有更复杂的问题
B和C增加一些新的虚函数,这些虚函数不是重写A的,那该怎么办?
此时B和C就会各自再建一张虚表
画出来就是这样,如果我们再开几个内存窗口验证的话,比如我们验证B,我们看地址00329d4c和00329d60,就可以发现一个是虚表,存的虚函数地址,另一个是虚机表,存的偏移量
我们再给D单独加一个func3,大家猜一猜会不会再建立一个虚表?
答案是不会,它直接放在A的虚表里了
以上即为本期全部内容,希望大家可以有所收获
如果错误,还请指正