C++菱形继承

news/2024/11/23 3:25:33/

菱形继承

菱形继承:指有一个基类被两个不同的类所继承,且存在一个类继承于这两个类而形成的一种菱形关系,故称菱形继承。如下图所示:
在这里插入图片描述

菱形继承存在的问题

  1. 二义性(ambiguity):当派生类同时继承自两个或更多个基类,而这些基类又共同继承自一个公共基类时,会出现二义性。如果基类中有相同的成员函数或成员变量,编译器无法确定应该调用哪个基类中的成员,从而导致编译错误。
  2. 冗余数据(redundant
    data):由于派生类继承了多个相同的基类,这些基类可能包含相同的成员变量。这样就会导致派生类中存在多份相同的数据,造成内存空间的浪费。

假设Person类有一个成员变量 age,Student类的对象中包含了这个 age 成员,Teacher类的对象中也包含了 age 成员,但是 Assistant 类依次继承了 Student 和 Teacher类,不考虑其他成员,就最终结果而言,Assistant类中确实包含了两份 age 成员。
这就导致了菱形继承的 冗余性 和 二义性。

  • 冗余性:存在重复的数据,比如 age要存两份
  • 二义性:如果要访问 age 成员,是访问 Student 类的 age,还是访问 Teacher类的 age.

在这里插入图片描述

菱形继承的解决方案 —— 作用域解析运算符(::)

如果虚继承不适用或不可行,可以使用作用域解析运算符来指定调用哪个基类的成员。通过指定基类名称和作用域解析运算符,可以消除二义性。例如:

class A {
public:void funcA() {	cout << "A::funcA()" << endl;	}
};
class B : public A {
public:void funcB() {	cout << "B::funcB()" << endl;	}
};
class C : public A {
public:void funcC() {	cout << "C::funcC()" << endl;	}
};
class D : public B, public C {
public:void funcD() {	cout << "D::funcD()" << endl;	}
};int main() {D obj;obj.funcA();  // 调用 A::funcA()obj.funcB();  // 调用 B::funcB()obj.funcC();  // 调用 C::funcC()obj.B::funcA();  // 调用 B::funcA()obj.C::funcA();  // 调用 C::funcA()return 0;
}

菱形继承的解决方案 —— 虚拟继承

为了解决菱形继承所带来的问题,C++引入了虚继承(virtual inheritance)。虚继承通过在公共基类前加上virtual关键字来声明,在派生类中只保留一份公共基类的实例,从而避免了冗余数据和二义性的问题。
其实就是将 Student 类和 Teacher 类重复的部分,放到一个公共位置,访问的时候,直接访问这块公共位置。

虚继承的主要作用:
是确保在多重继承中,共享的基类只有一份实例。这样可以避免冗余数据和二义性的问题。
在这里插入图片描述

// 下面是一个示例代码,展示了如何使用虚继承解决菱形继承的问题:
class Animal {
public:int age;
};
class Mammal : virtual public Animal {
};
class Bird : virtual public Animal {
};
class Platypus : public Mammal, public Bird {
};
int main() {Platypus p;p.age = 5;  // 直接访问公共基类的成员return 0;
}
/*
通过使用虚继承,派生类Platypus中只保留了一份公共基类Animal的实例,避免了冗余数据。
此外,我们可以直接访问公共基类Animal的成员变量,而不会出现二义性。
*/

需要注意的是,虚继承可能会引入一些额外的开销,因为需要在内存中存储虚基类的指针或偏移量。此外,虚继承可能会导致一些设计上的复杂性,因此在使用虚继承时需要权衡利弊,并根据具体情况选择合适的解决方案。

虚继承的主要作用:
是确保在多重继承中,共享的基类只有一份实例。这样可以避免冗余数据和二义性的问题。

虚继承(virtual inheritance)不仅可以用于解决菱形继承中的二义性问题,还可以在其他情况下使用。在以下情况下,虚继承也是一种有用的工具:

  1. 多重继承中的共享基类:当多个派生类需要共享同一个基类时,可以使用虚继承。通过使用虚继承,这些派生类只会包含一份共享基类的数据和函数。
  2. 基类作为接口:如果一个基类被用作接口,而派生类需要实现这个接口,但同时又需要从其他基类继承其他功能,可以使用虚继承。这样可以确保派生类只实现接口,并且不会出现二义性问题。
  3. 多层次的继承关系:在多层次的继承关系中,如果存在需要共享的基类,可以使用虚继承来减少重复数据和解决二义性问题。

总之,虚继承不仅仅用于解决菱形继承中的问题,也可以在其他情况下使用,以确保共享基类只有一份实例。


http://www.ppmy.cn/news/810334.html

相关文章

Ubuntu16.04无法连接Wifi解决方案

装双系统后&#xff0c;Ubuntu不能连Wifi,每次都要插网线才能上网&#xff0c;找了很多教程都没有解决&#xff0c;本来打算换一个版本的Ubuntu了&#xff0c;但是还是又尝试了一下&#xff0c;现在问题很好的解决啦。总结一下我的整个过程&#xff0c;希望能帮助到有遇到同样恼…

Win10无法连接网络映射的原因及解决方法

文章目录 故障原因解决办法1 &#xff1a;&#xff08;错误代码&#xff1a;0x80004005&#xff09;解决办法2 &#xff1a;&#xff08;错误代码&#xff1a;0x80070035&#xff09;解决方法3&#xff1a;&#xff08;方法二的补充&#xff09; 故障原因 造成新版Win10无法连…

安装ubuntu20.04无法连接wifi问题

1. 一些闲话 在安装完毕ubuntu20.04后&#xff0c;发现右上角未显示wifi图标&#xff0c;且设置中未显示wifi选项&#xff0c;于是看了非常多博客&#xff0c;按照各个博客里的说明一顿操作&#xff0c;删完这个改那个&#xff0c;一顿操作猛如虎&#xff0c;一看效果等于无&a…

deepin系统无法连接到自己的wifi

步骤如下&#xff1a; 1.deepin系统网卡驱动问题2.分享一下我的公众号和小程序 1.deepin系统网卡驱动问题 1.网卡驱动的问题&#xff0c;无法链接wifi 需要删除 iwlwifi.conf 此文件&#xff08;路径&#xff1a;/etc/modprobe.d/iwlwifi.conf&#xff09;-如何删除 使用liu…

关于Ubuntu18.04双系统安装后无法连接WiFi问题解决方法

解决过程如下&#xff1a; 第一&#xff0c;插网线&#xff1a; 确保能通过网线连上网&#xff0c;通过路由器连还是直接接口连都没事&#xff0c;因为我们需要联网去下载些驱动以及更新。 第二&#xff0c;更改软件源&#xff1a; 打开“设置”&#xff0c;选择“软件和更…

Ubuntu18.04 下联想电脑 无法连接WIFI问题解决

联想笔记本电脑Ubuntu系统下无法开启无线硬件开关的解决。总结了3个方法&#xff0c;方便以后使用。 方法一: 一.问题描述&#xff1a; 本人使用联想拯救者14IFI笔记本在安装Ubuntu系统时会出现无线硬件开关关闭的问题&#xff0c;当然也就无法连网&#xff08;Wi-Fi&#x…

安装了双系统,Ubuntu未显示WiFi连接,无法上网怎么办,以及windows无法上网怎么办

我最近刚装了双系统&#xff0c;但是当我登录上Ubuntu系统时&#xff0c;却没有看到WiFi图标显示&#xff0c;没法连接网络 于是输入下面命令进行操作&#xff0c;就恢复了 大家可以参考一下 更新并激活网卡&#xff1a; 1、首先打开终端&#xff0c;输入命令行&#xff1a…

Win11 解决wifi连接出现的无法连接该网络的问题

Win11 解决wifi连接出现的无法连接该网络的问题 文章目录 Win11 解决wifi连接出现的无法连接该网络的问题前言问题描述问题原因及解决方法外部设备内部&#xff0c;计算机本身设置IP和DNS自动分配重新启动wlan服务 终极解决办法后话 前言 最近回家了&#xff0c;前面因为各种原…