版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wan_shibugong/article/details/80986464
1、单继承
#include <iostream>
using namespace std
class Base
{
public:
Base()
{}
int _b;
};
class Derived : public Base
{
public:
Derived()
{}
int _d;
};
int main()
{
Derived D;
return 0;
}
2、多继承
#include <iostream>
using namespace std;
class A
{
public:
int _a;
};
class B
{
public:
int _b;
};
class D : public A,public B
{
public:
int _d;
};
int main()
{
D dd;
dd._a = 1;
dd._b = 2;
dd._d = 4;
return 0;
}
三个类在内存中的布局形式
3、菱形继承
存在二义性的问题
- 通过作用域限定符
- 通过菱形虚拟继承解决
//菱形继承
#include <iostream>
using namespace std;
class B
{
public:
void test()
{
;
}
int _b;
};
class C1:public B
{
public:
int _c1;
};
class C2:public B
{
public:
int _c2;
};
class D : public C1,public C2
{
public:
int _d;
};
//解决方法 加作用域限定符
void test()
{
D d;
d.C1::_b = 1;
d.C2::_b = 2; //缺点,定义两个相同的变量,如果比较大,浪费空间
}
int main()
{
cout<<sizeof(D)<<endl;
D d;
//d.test(); //不管是B类里面的函数函数变量都不可以直接访问,因为D类里面有两个相同的变量和函数
//d._b = 10; //菱形继承的二义性
test();
return 0;
}
4、虚拟继承
1、普通继承
- 派生类对象大小8
- 派生类对象模型 基类—-派生类
编译器不会合成构造函数
2、虚拟继承
派生类对象大小8+4
- 派生类对象模型 偏移量表格地址—派生类—基类
- 编译器会合成构造函数
D d; //合成构造函数,在调试时会在这里停下来
#include <iostream>
using namespace std;
class B
{
public:
int _b;
};
class D : virtual public B
{
public:
int _d;
};
int main()
{
cout<<sizeof(D)<<endl; //大小是12
D d;
d._b = 8;
d._d = 9;
return 0;
}
虚拟继承在内存中的存储
反汇编代码分析
五、菱形虚拟继承
用来解决菱形继承二义性的问题
函数和数据的二义性都可以解决
#include <iostream>
using namespace std;
class B
{
public:
int _b;
};
class C1: virtual public B
{
public:
int _c1;
};
class C2: virtual public B
{
public:
int _c2;
};
class D : public C1,public C2
{
public:
int _d;
};
int main()
{
cout<<sizeof(D)<<endl;
D d;
d._b = 1;
d._c1 = 2;
d._c2 = 3;
d._d = 4;
return 0;
}
菱形虚拟继承对象模型