菱形继承问题及解决方法—虚继承与虚基类(C++)
2023-06-13 09:14:07 时间
菱形继承
菱形继承的概念
两个派生类继承同一个基类,又有某个类同时继承着这两个派生类
菱形继承典型案例
这种继承带来的问题主要有两方面:
- 羊和驼都继承了动物的类成员,当羊驼想要使用时,会产生二义性
- 羊驼实际继承了两份来自动物的数据,但实际只需要一份
想要解决有两个思路,一是给羊驼的每一份数据加上作用域,但本质上羊驼还是继承了两份数据。二是通过虚继承的方式,使羊驼仅继承一份数据。
示例代码
#include<iostream>
using namespace std;
class Animal //动物类
{
public:
int m_Age;
};
class Sheep :public Animal{}; //羊类
class Tuo :public Animal{}; //驼类
class SheepTuo :public Sheep, public Tuo{}; //羊驼类
void test()
{
SheepTuo st;
st.Sheep::m_Age = 18;
st.Tuo::m_Age = 28;
cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;
}
int main()
{
test();
system("pause");
}
代码运行结果如下:
可以看到羊驼实际上存在两份数据,为了更直观的看到羊驼类的对象模型,可以借助VS自带的命令提示工具,到cpp文件存放目录后执行cl /d1 reportSingleClassLayoutSheepTuo test.cpp
,其中test.cpp
就是文件名,执行结果如下:
很明显羊驼从羊和驼两个父类中各自继承了一份m_Age
,通过限定作用域的方式无法彻底解决这个问题,这个时候就要使用虚继承
虚继承与虚基类
具体实现为在羊类和驼类的继承前加上virtual关键词,Animal类称为虚基类 代码如下:
#include<iostream>
using namespace std;
class Animal //虚基类
{
public:
int m_Age;
};
class Sheep :virtual public Animal{}; //虚继承
class Tuo :virtual public Animal{}; //虚继承
class SheepTuo :public Sheep, public Tuo{};
void test()
{
SheepTuo st;
st.Sheep::m_Age = 18;
st.Tuo::m_Age = 28;
cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;
cout << "m_Age=" << st.m_Age << endl;
}
int main()
{
test();
system("pause");
}
此时的运行结果为:
可以看到此时可直接用st.m_Age
访问类成员,说明此时羊驼类中的m_Age
只有一份
再次借助VS命令提示工具查看对象模型,运行结果如下:
画的有点凌乱......
可以看出羊类和驼类中的数据只是一个虚基类指针,并未继承具体的数据,这个虚基类指针指向各自的虚基类表,而虚基类表中存在一个偏移量,通过这个偏移量再加上首地址可以找到基类中的数据,所以实际上羊驼只继承了一份数据(也就是基类中的那份)。
写的有点乱,如果看不懂的话可以移步[黑马程序员]的视频讲解,讲的相当详细,点此跳转
相关文章
- C++输入输出文件流[通俗易懂]
- C++ 数据抽象与数据封装
- c++ auto类型_auto C++
- C++ 新增的 stl 容器实用方法,你知道几个?(文末赠送 C++20 书籍)
- C++精通之路:红黑树迭代器的模拟实现和讲解
- c++ strstr函数_简述酒精灯的正确使用方法
- Gamma校正_c++调试方法
- 2022ReSharper C++激活码(2022ReSharper C++最新激活码)2022ReSharper C++激活码
- 准大三学生给想学习C++同学的学习路线
- C/C++ 获取进程某模块入口地址
- c++stl
- 【Android FFMPEG 开发】C++ 回调 Java 方法 模板 ( JavaVM *vm | JNIEnv *env | jobject instance | 引用类型 | 模板代码示例 )
- C++ list(STL list)删除元素方法详解
- C++ valarray获取(访问)对象方法详解
- Python调用VC++的动态链接库(DLL)
- C++函数中return语句的使用方法
- C++实现两个日期间差多少天的解决方法
- C++中Operator类型强制转换成员函数解析
- php调用c++的方法
- VisualC++中TabView的多种实现方法
- C++调用C#的DLL实现方法
- C++输入输出注意事项总结