当前位置: 首页 > article >正文

虚继承 -- 解决菱形继承问题以及无法跨继承访问

目录

什么是菱形继承?

菱形继承造成的问题: 

如何解决这种问题:  

代码分析: 

注意:  

什么是菱形继承?

上图就是一个菱形继承的例子。 

菱形继承:    有两个类(Father,Mother),都继承于一个类(Human),然后还有一个类,又同时继承于这两个类(Son),这样就构成了菱形继承。

菱形继承造成的问题: 

1.  会导致继承于Human类中的属性形成二义性,因为Father类从Human中继承了name和age,Mother类也从Human中继承了name和age,子类Son同时继承了父类和母类的name和age。所以在子类中直接访问name和age,编译器就不知道访问的是哪个类继承来的name和age(二义性

访问就会报错 ->  属性不明确。 

如何解决这种问题:  

菱形继承中,必然会存在不明确的属性,和多继承中有所不同(因为多继承中有时可以避免)。为了能够方便写代码(直接访问name和age),我们可以使用虚继承来解决。  

class Human {
public:
	Human();
	Human(const string& name, int age);
protected:
	string name;
	int age;
};

class Father : virtual public Human {
public:
	Father();
	Father(const string& name, int age);
};

class Mother : virtual public Human {
public:
	Mother();
	Mother(const string& name, int age);
};

class Son : public Father, public Mother {
public: 
	Son(const string& name, int age);
};

int main(void) {

	system("pause");

	return 0;
}

Human::Human()
{
}

Human::Human(const string& name, int age)
{
	this->name = name;
	this->age = age;
}

Father::Father()
{
}

Father::Father(const string& name, int age):Human(name,age)
{
}

Mother::Mother()
{
}

Mother::Mother(const string& name, int age):Human(name,age)
{
}

Son::Son(const string& name, int age)
{
	this->name = name;
	this->age = age;
}

代码分析: 

1.  我们在Father和Mother类继承前加上了virtual关键字,这样在Son的构造函数中就可以直接访问name和age了,因为虚继承之后,编译器认为name和age既不来自于Father,也不来自于Mother,而是直接访问的Human类中的,这样就不会有二义性了。

2.   那么共同的祖先就被称为虚基类(此处的Human)

3.  实现虚继承后,我们在初始化继承来的name和age属性的时候,也可以直接调用Human的构造函数。 

 这样也是可以的。 

注意: 

1.  虽然多继承中也有可能存在二义性,但是是不能使用虚继承来解决的。(仔细对比就知道,菱形继承存在三层继承关系,多继承一般就两层) 

2.  只有在实现虚继承的时候,子类才能调用父类的父类的(也就是Son调用Human)类中的属性和方法,其它情况,子类最多只能访问父类的。  (父类的父类等等,是不能访问的) 

 Huamn类中的test()方法,在没有实现虚继承的情况下,也会报错->不明确,因为这个方法,Father类和Mother类中也继承了。

不使用虚继承,直接使用Human类的构造方法,也是会报错的。 

3.  所以,多层继承中,子类最多只能访问到上一层。(在没有实现虚继承的情况下) 


http://www.kler.cn/a/231649.html

相关文章:

  • 亿咖通科技应邀出席微软汽车行业智享会,分享ECARX AutoGPT全新实践
  • LeetCode 2816.翻倍以链表形式表示的数字
  • Nacos 配置中心变更利器:自定义标签灰度
  • 【unity小技巧】一些unity3D灯光的使用与渲染及性能优化方案
  • 浅谈数据仓库的架构及其演变
  • shell 100例
  • 【flink状态管理(四)】MemoryStateBackend的实现
  • NDK Could NOT find OpenGL (missing: OPENGL_glx_LIBRARY) Ubuntu
  • VTK 体渲染设置帧率
  • 单片机无线发射的原理剖析
  • GEE详细教程之:将Landsat8与Landsat9影像合成一个影像
  • Windows下MySQL的界面安装
  • [每日一题] 02.07 - 小鱼比可爱
  • 【射影几何13 】梅氏定理和塞瓦定理探讨
  • C#阿里云消息列队推送消息
  • 深度学习手写字符识别:训练模型
  • 计算机组成原理——计算机系统概述
  • python将word文件转换成pdf文件
  • 队列---数据结构
  • 学习与非学习
  • Docker-Learn(三)创建镜像Docker(换源)
  • nohup基本使用
  • Ubuntu权限相关命令
  • 【Linux】Ubuntu 22.04 升级 nodejs 到 v18
  • Java学习网络编程
  • QT QCombox 样式表 比起作用