news 2026/4/15 12:07:47

多继承与虚基类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多继承与虚基类

多继承派生类的语法格式:

class 派生类名 : <继承方式1> 基类名1,

<继承方式2> 基类名2,

…… {

……//派生类新添加的成员

};

多继承派生类对象的构造和析构:

派生类名(参数表):基类名1(参数表1),

基类名2(参数表2),

对象成员1(参数表3),

对象成员2(参数表4),

… {

//派生类新添加的成员

}

派生类构造执行顺序是按照:基类对象、成员对象、普通变量的高到低优先级执行的,其中其中基类对象的调用顺序和声明继承关系的顺序有关。

但是析构函数的执行顺序与之相反,先调用派生类的析构函数,再调用对象成员的析构函数,最后调用基类的析构函数。

访问不同基类同名成员时的二义性

class A{ public: int value; void f(){}; }; class B{ public: int value; void f(){}; void g(){}; }; class C: public A, public B{ public: void g(){}; void h(){}; }; int main(){ C C1; C1.f(); C1.value=9; return 0; }

这里在调用f()和value时会出现二义性,因为编译器不知道你访问的是A和B中的哪一个()和value。

所以在此我们需要填写他的“绝对路径”,类名对成员加以限定:改成:

int main(){
C C1;
C1.A::f();
C1.A::value=9//访问A的f()和value。
return 0;
}

第二种情况:

class A{ public: int a; void g( ){}; }; class B1: public A{ int b1; }; class B2: public A{ int b2; }; class C: public B1, public B2{ int c; public: int f(){}; }; int main(){ C Cobj; Cobj.a=8; Cobj.A::a=9; Cobj.g( ); return 0; }

这一二义性的冲突是因为B1、B2都有一个公共基类A,这个公共基类会在派生类对象中产生两个基类子对象,于是我们也要来对此进行限定:

Cobj.B1::a=9;或 Cobj.B2::a=9;

但是这还有一个问题,使用绝对路径找到的基类,我们也可以得知派生类对象中存在多个基类对象的拷贝,导致空间浪费,解决方法也很简单,将A设为虚基类即可,这样 B1 和 B2 继承 A 时,C 最终只会保留一份 A 的子对象,就不会有二义性了。

虚基类

虚基类子对象被合并成一个子对象,这种“合并”作用,使得可能出现的二义性被消除。下面是使用虚基类与没使用虚基类的概念图:

class A { public: int a = 10; void g() { cout << "A的g()函数,a=" << a << endl; } }; // B1虚继承A class B1 : virtual public A {}; // B2虚继承A class B2 : virtual public A {};

虚基类构造函数的调用次序有着自己独特的次序,规则:

1:对于最终派生类来说,虚基类的构造必须在非虚基类之前调用;

2:同一个层次中包含多个虚基类,那么按照虚基类构造函数按它们说明的次序调用。

若虚基类由非虚基类派生,则遵守先调用基类构造函数,再调用派生类构造函数的规则。

举个栗子:

class base{…}; class bas2{…}; class level1 : public base2, vitrual public base{…}; class level2 : public base2, vitrual public base{…}; class toplevel : public level1, vitrual public level2{…};

声明toplevel 时,构造顺序是从 “最顶层虚基类” 开始,再到 “普通基类 / 中间类”,最后到自身

第一步,先调用全局虚基类

base被level1、level2都虚继承了,所以base是全局虚基类,会被优先构造且只构造 1 次→ 顺序第 1 位:base

第二步,按照规则优先调用虚基类

level2是toplevel的虚基类,所以要先构造level2(规则1),而构造level2时,要先构造它的基类:
level2的基类:base2(普通,先构造) + base(虚基类,已经构造过了,不再构造)(规则2
→ 顺序第 2-3 位:base2(level2 的普通基类) → level2

第三步

level1是toplevel的普通基类,构造level1时,要先构造它的基类:
level1的基类:base2(普通,先构造) + base(虚基类,已构造)(规则2
→ 顺序第 4-5 位:base2(level1 的普通基类) → level1

第四步

最后构造toplevel→ 顺序第 6 位:toplevel

综合

base(全局虚基类)→ base2(level2 的普通基类)→ level2(toplevel 的虚基类)→ base2(level1 的普通基类)→ level1(toplevel 的普通基类)→ toplevel

例2:

class base{…}; class base2{…}; class level1 : virtual public base2, virtual public base{…}; class level2 : virtual public base2, virtual public base{…}; class toplevel : public level1, virtual public level2{…};

同样的道理,但不同的是level1和level2都是虚基类。

此时base与base2都是全局变量,当有多个全局虚基类时,构造顺序遵循:
最终派生类继承链中,虚基类首次出现的 继承声明顺序排序。

最终派生类toplevel的继承链中,base2和base首次出现在level1、level2的继承声明里,且声明顺序是base2在前、base在后 → 先构造base2,再构造base。所以按照构造顺序定下base2为第一位,basee为第二位。

再通过规则1优先构造toplevel的虚基类level2为第三位,再构造普通类level1为第五位,最后构造自身toplevel。

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

电子产品EMC整改:智能化设计工具重塑电磁兼容性优化|南柯电子

在万物互联的智能时代&#xff0c;电子产品的电磁兼容性&#xff08;EMC&#xff09;已成为决定产品市场准入与可靠性的核心指标。从消费电子到工业设备&#xff0c;从新能源汽车到医疗仪器&#xff0c;EMC问题不仅关乎设备自身的稳定运行&#xff0c;更直接影响用户安全与行业…

作者头像 李华
网站建设 2026/4/5 16:02:35

APP自动化第一步:Appium环境搭建

一、安装Appium Python client包 1.直接cmd窗口输入pip install Appium-Python-Client 2.要确保安装匹配版本的selenium和appium 使用命令pip install selenium -U 首先进入网盘下载这三个软件的压缩包 二、安装Appium Server 1.双击打开压缩包Appium 2.双击进行安装。 3.点…

作者头像 李华
网站建设 2026/4/11 8:27:38

【专家亲授】量子机器学习环境搭建:VSCode核心参数调优9大秘诀

第一章&#xff1a;量子机器学习与VSCode集成概览量子机器学习&#xff08;Quantum Machine Learning, QML&#xff09;是量子计算与经典机器学习深度融合的前沿领域&#xff0c;利用量子态叠加、纠缠等特性加速模型训练或提升预测能力。随着开发工具生态的成熟&#xff0c;将Q…

作者头像 李华
网站建设 2026/4/14 4:54:16

iFlow-CLI独家实测 开源模型中最会写代码的 MiMo-V2-Flash效果如何?

前言 小米今日发布了开源基座大模型 MiMo-V2-Flash。这款模型采用了Mixture-of-Experts (MoE) 架构&#xff0c;总参数规模达到 3090 亿&#xff0c;激活参数 150 亿&#xff0c;通过混合注意力机制的创新设计&#xff0c;在保持高性能的同时实现了推理效率的极致优化。 在代…

作者头像 李华
网站建设 2026/4/8 4:39:23

从入门到精通:Docker Buildx构建上下文控制的8个最佳实践

第一章&#xff1a;Docker Buildx构建上下文的核心概念Docker Buildx 是 Docker 官方提供的一个 CLI 插件&#xff0c;扩展了原生 docker build 命令的能力&#xff0c;支持多平台构建、并行执行和更高效的构建流程。其核心优势之一在于对“构建上下文&#xff08;Build Contex…

作者头像 李华
网站建设 2026/4/7 1:48:52

发现Qiskit运行异常?这5个VSCode调试技巧让你秒级定位问题根源

第一章&#xff1a;发现Qiskit运行异常&#xff1f;这5个VSCode调试技巧让你秒级定位问题根源在使用 Qiskit 开发量子电路时&#xff0c;代码逻辑复杂或环境配置不当常导致运行异常。借助 VSCode 强大的调试功能&#xff0c;可快速定位并解决潜在问题。启用断点调试查看量子态演…

作者头像 李华