news 2026/4/28 18:55:51

C++多重继承与虚继承分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++多重继承与虚继承分析

本文以实例形式较为全面的讲述了C++的多重继承与虚继承,是大家深入学习C++面向对象程序设计所必须要掌握的知识点,具体内容如下:

一、多重继承

我们知道,在单继承中,派生类的对象中包含了基类部分 和 派生类自定义部分。同样的,在多重继承(multiple inheritance)关系中,派生类的对象包含了每个基类的子对象和自定义成员的子对象。下面是一个多重继承关系图:

1

2

3

4

classA{/* */};

classB{/* */};

classC :publicA {/* */};

classD :publicB,publicC {/* */};

C继承了A,派生类D又继承了B和C,如图所示,一个D对象中含有一个B部分、一个C部分(其中又含有一个A部分)以及在D中声明的非静态数据成员:

构造与析构:

构造一个派生类对象将首先构造它的所有基类子对象,其中基类的构造顺序与派生列表中基类的出现顺序保持一致,即B –> A –> C –> D。
销毁一个派生类对象的顺序正好与其创建的顺序相反,即析构函数的调用顺序正好与构造函数相反,即D –> C –> A –> B。注意派生类的析构函数只负责清除派生类本身分配的资源(析构函数体),派生类的成员及基类都是自动销毁的(隐式析构阶段)。

类型转换:

在多重继承的情况下,可以令某个可访问基类的指针或引用直接指向一个派生类对象。编译器不会在派生类向基类的几种转换中进行比较和选择,在它看来转换到任意一种基类都一样好。

二、虚继承

尽管在派生列表中不允许同一个基类出现两次,但实际上派生类可以多次继承同一个类。

派生类通常会含有继承链上每个类对应的子部分。在上面的两种情况中,class D都间接地继承了class A两次,那么意味着class D中包含了class A的两份拷贝。所以在一个class D的对象中将含有2组class A的成员,此时若不加前缀限定符直接使用某个成员将引发“二义性”错误:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

classA{

public:

A():str("name"){};

string str;

voidprint(){cout << str << endl;};

};

classB :publicA { };

classC :publicA { };

classD :publicB,publicC { };

intmain(){

D d;

d.str ="songlee";// 错误:对成员‘str'的请求有歧义

d.print();// 错误:对成员‘print'的请求有歧义

return0;

}

当然你可以使用作用域 d.B::str="songlee"; 和 d.B::print(); 来规避“二义性”错误,但这并没有从根本上解决问题。

为了解决上述问题,C++提供了虚继承(virtual inheritance)的机制。虚继承的目的是令某个类作出声明,承诺愿意共享它的基类。其中,共享的基类子对象称为虚基类。在这种机制下,不论虚基类在继承体系中出现多少次,在派生类中都只包含唯一一个共享的虚基类子对象。我们指定虚基类的方式是在派生列表中添加关键字virtual:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

classA{

public:

A():str("name"){};

string str;

voidprint(){cout << str << endl;};

};

classB :virtualpublicA { };// 虚继承,A为虚基类

classC :virtualpublicA { };// 关键字public和virtual的顺序随意

classD :publicB,publicC { };

intmain(){

D d;

d.str ="songlee";// 正确

d.print();// 正确

return0;

}

通过在派生列表中添加virtual(关键字public和virtual的顺序随意)指定A为虚基类,B和C将共享A的同一份实例,这样在D的对象中也将只有A的唯一一份实例,所以A的成员可以被直接访问,并且不会产生二义性。

虚继承最典型的应用是iostream继承于istream和ostream,而istream和ostream虚继承于ios:

1

2

3

classistream :virtualpublicios {/* */};

classostream :virtualpublicios {/* */};

classiostream :publicistream,publicostream {/* */};


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/28 18:54:37

如何在 Discord.py 中实现按钮权限控制:仅允许特定角色点击按钮

本文详解如何在 discord.py 的 discord.ui.Button 中动态校验用户角色权限&#xff0c;避免误用命令装饰器&#xff0c;并提供可直接运行的健壮实现方案。 本文详解如何在 discord.py 的 discord.ui.button 中动态校验用户角色权限&#xff0c;避免误用命令装饰器&#xff0c;并…

作者头像 李华
网站建设 2026/4/28 18:53:56

ClickHouse实战避坑:从单机到集群,我的日志分析系统搭建血泪史

ClickHouse实战避坑&#xff1a;从单机到集群&#xff0c;我的日志分析系统搭建血泪史 去年接手公司日志分析系统改造项目时&#xff0c;我完全没想到会与ClickHouse展开长达三个月的"相爱相杀"。这套最初在单机环境跑得飞快的系统&#xff0c;在数据量突破百亿后突然…

作者头像 李华
网站建设 2026/4/28 18:52:49

基于脑电波与Stable Diffusion的意念绘画:开源项目Mind-Brush实践指南

1. 项目概述&#xff1a;当AI画笔遇见你的脑电波 想象一下&#xff0c;你脑海中浮现出一片宁静的湖泊&#xff0c;夕阳西下&#xff0c;波光粼粼。你不需要拿起画笔&#xff0c;甚至不需要说出一个字&#xff0c;仅仅通过“想”&#xff0c;一幅描绘此情此景的画作就在屏幕上缓…

作者头像 李华