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

C++中的多重继承与虚继承

1、什么是多重继承

在前面的例子中,派生类都只有一个基类,称为单继承(Single Inheritance)。除此之外,C++也支持多继承(Multiple Inheritance)即一个派生类可以有两个或多个基类(注意这是多重继承最重要的性质)

这里指出我之前笔记中的一个错误,那就是我之前误将继承的嵌套叫做多重继承,这里需要说明是错误的。

直接看代码,就更加直接了。

class D: public A, private B, protected C
{//类D新增加的成员
}

也就是D,继承了A,B,C。注意语法上的区别,不同的继承声明语句,直接使用“,”分割起来即可。

多继承的作用,也很好理解,即D同时继承了A、B、C,需注意ABC之间没有任何关系存在。

2、多重继承的构造函数与析构函数

先讲构造函数,本质上构造函数就是对成员的初始化,这点大家现在都有概念。与之前说的继承的嵌套中对构造函数的调用,差不多,即D在调用自己的构造函数时,需要同事调用它的所有基类的构造函数。

看代码

C::C(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), m_e(e)
{cout<<"C++的多态继承"<<endl;
}

不过这里,基类构造函数调用的顺序,没有强制要求,

3、被继承的多个父类中存在同名成员变量或成员函数

首先,需要说的是,这种状态是符合C++语法的。但是在子类中直接调用时,就会出现错误,编译器是不知道,具体该调用哪一个父类中的变量,如下代码

class A
{public:int m_var_1;
}class Bpublic:int m_var_1;
}class C:public A,public B
{public:int m_var_2;
}int main()
{
C C_Instance1;
C_Instance1.m_var_1; //此时在编译阶段就会出现错误
/*解决方法也很简单*/
/*就是在具体调用时,z在前面加上"类名"和“::”*/
C_Instance1.A::m_var_1 //即告诉编译器,我是要调用A中的m_var_1}

4、什么是虚继承

4.1 虚继承概念理解

先记一下,C++中的关键字,virtual,直译为虚拟的,非真实的。

上文讲过多继承,实际情况会更复杂,如果有以下状态,也就是A同时是B和C的父类,然后B和C又同时是D的父类。这样的结构,又被称为菱形继承。如果此时我们使用C的实例化对象,来调用A中的成员,此时编译器就不知道到底走D-B-A,还是D-C-A。路径在这里可以直接用上面构造函数或析构函数来理解,即到底是D-B-A的路径去调用构造函数,还是走D-C-A去调用构造函数。

虚继承的目的是让某个类做出声明,承诺愿意共享它的基类。其中,这个被共享的基类就称为虚基类(Virtual Base Class)本例中的 A 就是一个虚基类。在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含一份虚基类的成员。

现在让我们重新梳理一下本例的继承关系,如下图所示:
 

菱形继承和虚继承

使用虚继承有以下关键点:

(1)在B和C继承时,第一个关键字就要声明是对A执行虚继承

//间接基类A
class A{
protected:int m_a;
};
//直接基类B
class B: virtual public A{  //虚继承
protected:int m_b;
};
//直接基类C
class C: virtual public A{  //虚继承
protected:int m_c;
};
//派生类D
class D: public B, public C{
public:void seta(int a){ m_a = a; }  //正确void setb(int b){ m_b = b; }  //正确void setc(int c){ m_c = c; }  //正确void setd(int d){ m_d = d; }  //正确
private:int m_d;
};
int main(){D d;return 0;
}

4.2 虚继承的一个隐蔽点

大家,学习到这里,有没有感觉到一个比较隐蔽的问题,还是以上文的图为例:

项目第一阶段中,我们只需要设计3个class,即B和C都是A的子类,这样明显是不需要B和C,在继承A时,做出虚继承的说明。

但是到第二阶段后,因为需求变更,必须要设计一个Dclass,且D同时继承了B和C,此时就必须修改B和C的声明,在声明中添加虚继承描述。

4.3 一个实际执行虚继承的实例

C++标准库中的 iostream 类就是一个虚继承的实际应用案例。iostream 从 istream 和 ostream 直接继承而来,而 istream 和 ostream 又都继承自一个共同的名为 base_ios 的类,是典型的菱形继承。此时 istream 和 ostream 必须采用虚继承,否则将导致 iostream 类中保留两份 base_ios 类的成员。
 

虚继承在C++标准库中的实际应用

http://www.dtcms.com/a/494902.html

相关文章:

  • 兰州市建设厅官方网站网站建设与管理实用教程课后答案
  • 清理磁盘垃圾
  • 专项智能练习(教学过程的概念)
  • 我想创业,但是没有合适的商业模式,我 该如何入手来构建自己的商业模式-来自deepseek的答案
  • 免费下载软件的网站asp.net网站备份
  • 基于微服务的在线判题系统重点总结
  • GEE提取 MODIS 地表温度
  • 使用快捷键迅速调整多个通道 | IPEmotion
  • cartographer 原理及代码
  • 膨胀算法去除低谷噪声
  • 计算机操作系统——磁盘管理
  • 【ROS2】IDL(Interface Definition Language)语法解析和使用
  • vs2008不能新建网站制作网页焦点图
  • 一款专业的多数据库安全评估工具,支持 **PostgreSQL、MySQL、Redis、MSSQL** 等多种数据库的后渗透操作
  • Redis 缓存模式与注解缓存
  • Ansible之剧本和角色
  • 有什么平台做网站比较好河南省住房和城乡建设部网站首页
  • 靶场练习2
  • 把 1688 商品详情「搬进 MySQL」:Java 爬虫全链路实战(2025 版)
  • java内存性能优化工具Mat
  • React 18.x 学习计划 - 第四天:React Hooks深入
  • 地学考研专业选择学科地理、人文地理,还是GIS?不想考数学怎么选?
  • React 2025 完全指南:核心原理、实战技巧与性能优化
  • 大数据平台建站重庆网站制作团队
  • Linux CentOS 7 安装配置HAProxy完整指南:实现高可用负载均衡
  • 【小白笔记】PyTorch 和 Python 基础的这些问题
  • linux学习笔记(35)C语言连接mysql
  • 消息推送策略:如何在营销与用户体验间找到最佳平衡点
  • go资深之路笔记(九)kafka浅析
  • Java String 性能优化与内存管理:现代开发实战指南