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

虚函数VS虚拟继承:C++多重继承二义性破解与性能调优

目录

虚拟继承

虚函数 vs 虚拟继承

虚拟继承时派生类对象的构造和析构

效率分析


虚拟继承

虚函数 vs 虚拟继承

在虚函数机制(动态多态机制)中

1、虚函数是存在的;(存在)

2、通过间接的方式去访问;(间接)

3、通过基类的指针访问到派生类的函数,基类的指针共享了派生类的方法(共享)

(如果没有虚函数,当通过pbase指针去调用一个普通的成员函数,那么就不会通过虚函数指针和虚表,直接到程序代码区中找到该函数;有了虚函数,去找这个虚函数的方式就成了间接的方式)

虚拟继承同样使用virtual关键字(存在、间接、共享)

1、存在即表示虚继承体系和虚基类确实存在

2、间接性表现在当访问虚基类的成员时同样也必须通过某种间接机制来完成(通过虚基表来完成)

3、共享性表现在虚基类会在虚继承体系中被共享,而不会出现多份拷贝

(虚基类的说法,如果B类虚拟继承了A类,那么说A类是B类虚基类,因为A类还可以以非虚拟的方式派生其他类)

补充:

(1)虚拟继承的内存结构

(2)如果虚基类中包含了虚函数

(3)如果派生类中又定义了新的虚函数,会在内存中多出一个属于派生类的虚函数指针,指向一张新的虚表(VS的实现)

(4)带虚函数的菱形继承——虚拟继承方式(拔高,不要求一定掌握)

虚拟继承时派生类对象的构造和析构

中间派生类公有继承,顶层基类,在底层派生类时会创建多个顶层基类子对象在调用函数时会出现问题,他不会知道使用哪个去调用函数,所以需要虚拟继承。

如下菱形继承的结构中,中间层基类虚拟继承了顶层基类,注意底层派生类的构造函数

class A
{
public:A(double a): _a(a){cout << "A(double)" << endl;}~A(){cout << "~A()" << endl;}
private:double _a = 10;
};class B
: virtual public A
{
public:B(double a, double b): A(a), _b(b){cout << "B(double,double)" << endl;}~B(){ cout << "~B()" << endl; }
private:double _b;
};class C
: virtual public A
{
public:C(double a, double c): A(a), _c(c){cout << "C(double,double)" << endl;}~C(){ cout << "~C()" << endl; }
private:double _c;
};class D
: public B
, public C
{
public:D(double a,double b,double c,double d): A(a), B(a,b), C(a,c), _d(d){cout << "D(double * 4)" << endl;}~D(){ cout << "~D()" << endl; }
private:double _d;
};

在虚拟继承的结构中,最底层的派生类不仅需要显式调用中间层基类的构造函数,还要在初始化列表最开始调用顶层基类的构造函数。

——那么A类构造岂不是会调用3次?

并不会,有了A类的构造之后会压抑B、C构造时调用A类构造,A类构造只会调用一次。可以对照菱形继承的内存模型理解,D类对象中只有一份A类对象的内容。

对于析构函数,同样存在这样的压抑效果,D类析构执行完后,根据继承声明顺序的反序调用C类的析构函数,C的析构函数执行完后并没有自动调用A的析构函数,而是接下来调用B的析构函数,最后调用A的析构函数。

效率分析

多重继承和虚拟继承对象模型较单一继承复杂的对象模型,造成了成员访问低效率,表现在两个方面:对象构造时 vptr 的多次设定,以及 this 指针的调整。对于多种继承情况的效率比较如下:

http://www.xdnf.cn/news/3876.html

相关文章:

  • 论快乐的学习和学习的快乐
  • 万字详解ADC药物Payload
  • Debezium 架构详解与实战示例
  • 【操作系统】深入理解内存管理:从虚拟内存到OOM Killer
  • cloudfare+gmail 配置 smtp 邮箱
  • 【CISCO】Se2/0, Se3/0:串行口(Serial) 这里串口的2/0 和 3/0分别都是什么?
  • React hooks详解
  • 快速外网访问,证书自动续约 | 极空间IPv4IPv6 DDNS 配置详解
  • 数据结构与算法:回溯
  • Python:Seaborn 美化图表的技术指南
  • 【五一培训】Day 4
  • 常用命令集合
  • PCB叠层设计方案
  • 探秘DeepSeek模型参数:解锁AI潜能的密码
  • GenCLS++:通过联合优化SFT和RL,提升生成式大模型的分类效果
  • Python之学习笔记(六)
  • Prompt compress 技术探究-LLMLingua
  • SpringAi接入DeepSeek大模型
  • SurfSense开源程序是NotebookLM / Perplexity / Glean的开源替代品,连接到外部来源,如搜索引擎
  • ArrayList的扩容机制(源码解析)
  • 深度学习的简单介绍
  • PISI:眼图1:眼图相关基本概念
  • 使用synchronized关键字同步Java线程
  • AndroidLogger常用命令和搜索功能介绍
  • STM32Cube-FreeRTOS任务调度与任务管理-笔记
  • ruoyi-flowable框架关于启动时提示锁住问题
  • LLM论文笔记 27: Looped Transformers for Length Generalization
  • n8n工作流自动化平台的实操:利用本地嵌入模型,完成文件内容的向量化及入库
  • 【Linux网络#3】:Socket编程应用层UDP
  • Scartch038(四季变换)