一、普通继承
- 代码
class A
{
public:
virtual void virtualfunA(){
}
virtual void virtualfunAA(){
}
void funA(){
}
public:
int a;
};
class B : public A
{
public:
virtual void virtualfunA(){
}
virtual void virtualfunB(){
}
void funB(){
}
public:
int b;
};
int main(){
A obj1;
B obj2;
return 0;
}
- 内存结构
看到我发现了一个有趣的地方,就是B类中的虚函数virtualfunB出现在obj2的虚表中。
- 总结
普通继承中,子类重写父类的虚函数后会在虚表中覆盖父类的虚函数,子类增加特有的虚函数, 要在第一个虚表中添加.
二、多继承
- 代码
class A1
{
public:
virtual void funA1(){}
virtual void funA11(){}
public:
int a1;
};
class A2
{
public:
virtual void funA2(){}
virtual void funA22(){}
public:
int a2;
};
class B : public A1 ,public A2
{
public:
virtual void funA1(){}
virtual void funA2(){}
virtual void funB(){}
public:
int b;
};
int main()
{
B obj;
return 0;
}
- 内存结构
总结:多继承的内存空间顺序是按照继承顺序排布的。
三、菱形继承
描述:上面的多继承中有一个经典的菱形继承问题,如果多继承的对象中存在某两个类继承同一个基类,那么会出现数据冗余现象,这会导致数据不一致。
如图:
这种情况C对象中会出现两个a变量
- 代码
#include<iostream>
using namespace std;
class A
{
public:
int a;
};
class B1 : public A
{
public:
int b1;
};
class B2 : public A
{
public:
int b2;
};
class C : public B1,public B2
{
public:
int c;
};
int main()
{
C obj;
return 0;
}
- 内存结构
总结:这种情况我么可以用虚继承来解决这类问题
四、虚继承
虚继承特性:
- 父类和子类在空间上倒置关系(与普通继承比较)
- 虚继承, 子类会复制父类的虚表, 此外, 自己特有虚函数, 自己会有虚表, 自己也会有对应的虚指针. 2个虚指针, 一个指向父类复制过来的虚表,一个指向自己的虚表
- 子类存在指向虚基类(虚继承里面的基类) 的虚基表 , 子类会有指向虚基表的指针 vbptr , 虚基表里面内容是指向自己和虚基类的偏移量
- 最底层的子类, 完成虚基类的构造.
1.部分虚继承
- 代码
class A
{
public:
virtual void funA(){}
public:
int a;
};
class B1 : virtual public A
{
public:
virtual void funB1(){}
public:
int b1;
};
class B2 : virtual public A
{
public:
virtual void funB2(){}
public:
int b2;
};
class C : public B1,public B2
{
public:
virtual void funC(){}
public:
int c;
};
int main()
{
C obj;
return 0;
}
2.内存结构
vbptr的作用是找到自己的虚表和自己继承类的虚表
2.完全虚继承
- 代码
class A
{
public:
virtual void funA(){}
public:
int a;
};
class B1 : virtual public A
{
public:
virtual void funB1(){}
public:
int b1;
};
class B2 : virtual public A
{
public:
virtual void funB2(){}
public:
int b2;
};
class C : virtual public B1,public B2
{
public:
virtual void funC(){}
public:
int c;
};
int main()
{
C obj;
return 0;
}
- 内存结构
vbptr的作用是找到自己的虚表和自己继承类的虚表
总结
由内存结构可知,这两种方法都是可以解决菱形继承问题的。