【C++ Efficiency】理解虚函数、多重继承、虚基类和RTTI

虚函数

虚函数的实现

当调用一个虚函数时,一般都是使用了virtual table和virtual table pointer,简称vtbl和vptr:

vtbl

一个函数指针数组。

在程序中,一个类凡是声明或继承了虚函数,都有一个vtbl,是指向虚函数实现体的指针。例如:

class C1
{
public:C1();virtual ~C1();virtual void f1();virtual int f2(char c) const;virtual void f3(const string& s);void f4() const;...
};
//虚函数按照其声明顺序放于vtbl表中
//vtbl数组中的每一个元素对应一个函数指针指向该类的虚函数
//如果C2继承自C1,重新定义某些继承而来的虚函数,并加入新的虚函数:
class C2 : public C1
{
public:C2();						//非虚函数virtual ~C2();				//重定义函数virtual void f1();			//重定义函数virtual void f5(char* str);	//新的虚函数...
};
//此时,C2的vtbl包括没有被C2重定义的C1虚函数的指针f2、f3

vptr

凡是声明了虚函数的类的对象都含有一个隐藏的数据成员,指向对应的类的virtual table,称为vptr。

虚函数的调用

  1. 通过对象的 vptr 找到类的 vtbl。这是一个简单的操作,因为编译器知道在对象内 哪里能找到 vptr(毕竟是由编译器放置的它们)。因此这个代价只是一个偏移调整(以得到 vptr)和一个指针的间接寻址(以得到 vtbl)。
  2. 找到对应 vtbl 内的指向被调用函数的指针。这也是很简单的, 因为编译器为每个虚函数在 vtbl 内分配了一个唯一的索引。这步的代价只是在 vtbl 数组内 的一个偏移。
  3. 调用第二步找到的的指针所指向的函数。

虚函数的成本

  1. 虚函数的第一个成本:
    你必须为每个拥有虚函数的类耗费一个virtual table空间,其大小视虚函数的个数而定,包括继承而来的。

  2. 虚函数的第二个成本:
    你必须在每一个拥有虚函数的对象内付出“一个额外指针”的代价。

  3. 虚函数的第三个成本:
    你放弃了使用内联函数。

参考:C++虚函数实现原理与代价

多重继承

每个对象含有多个vptr,针对不同的父类vtbl,子类产生一个特殊的vtbl。

虚基类

D->B->A,D->C->A,会导致A的字段在D中有两份,这显然不合理。为了解决这个问题,使用虚拟继承:B,C虚继承A,大多数编译器会利用这样的机会来减少编译器的负担。。

运行时类型识别RTTI

  • C++提供关键字typeid 获取类的type_info对象;
  • 一个类对应于一个type_info对象;
  • 类及其所有的对象共享一份RTTI信息。

RTTI的设计理念是:根据class的vtbl来实现。

总结

理解虚函数、多重继承、虚基类及RTTI的成本很重要。
但你必须知道:如果你需要这些功能,就要忍受这些成本,世事难两全。有时你确实想要回避编译器生成的服务,例如隐式vptr和“指向虚基类”的指针会造成“将C++对象存储于数据库”和“跨进程移动C++对象”困难度提高,所以你希望有某种方法模拟这些性质。不过从效率上来讲,自己写的不可能比编译器生成的更好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/95698.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CDN网络基础入门:CDN原理及架构

背景 互联网业务的繁荣让各类门户网站、短视频、剧集观看、在线教育等内容生态快速发展,互联网流量呈现爆发式增长,自然也面临着海量内容分发效率上的挑战,那么作为终端用户,我们获取资源的体验是否有提升呢? 答案是…

一文了解硬盘AFR年化故障率评估方式和预测方案

目前常用评价硬盘(或者其他硬件产品)有一个关键的指标就是年化故障率(AFR)。年化故障率(AFR)是一种衡量产品可靠性的指标,表示在一年内产品发生故障的概率。 除了年化故障率(AFR&…

Netron可视化深度学习网络结构

有时候,我们构建网络模型想要直观的查看网络详细结构图,但是苦于没有办法。但是有了Netron以后,我们就可以将对应的onnx模型直接可视化,这样不仅可以观察网络的详细结构图,还可以查看网络每一层的具体参数,…

简述 AOP 动态代理

一、AopAutoConfiguration 源码: Configuration(proxyBeanMethods false) ConditionalOnProperty(prefix "spring.aop", name "auto", havingValue "true", matchIfMissing true) public class AopAutoConfiguration {Configur…

【数据结构】排序算法(二)—>冒泡排序、快速排序、归并排序、计数排序

👀樊梓慕:个人主页 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 🌝每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.冒泡排序 2.快速排序 2.1Hoare版 2.2占…

C++入门

一、C关键字 C总计63个关键字,C语言32个关键字。 二、命名空间 在C/C中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存 在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称…

谁“动”了我的信息?

通信公司“内鬼” 批量提供手机卡 超6万张手机卡用来发涉赌短信 2023年10月2日,据报道2022年12月,湖北省公安厅“雷火”打击整治治安突出问题专项行动指挥部研判发现,有人在湖北随州利用虚拟拨号设备GOIP发出大量赌博短信。随州市公安局研判…

蓝桥等考Python组别十三级004

第一部分:选择题 1、Python L13 (15分) 运行下面程序,输出的结果是( )。 t = (0, 1, 2, 3, 4) print(t[3]) 1234正确答案:C 2、Python L13 (15分) 运行下

【最新】如何在CSDN个人主页左侧栏添加二维码?侧边推广怎么弄?

目录 引言 效果展示 步骤讲解 引言 当你决定在CSDN上展示自己的技术才能和项目时,💡 将你的个人主页变得更炫酷和引人注目是必不可少的!在这篇博客中,我们将向你揭开神秘的面纱,教你如何在CSDN个人主页的左侧栏上添…

RabbitMQ集群搭建详细介绍以及解决搭建过程中的各种问题——实操型

RabbitMQ集群搭建详细介绍以及解决搭建过程中的各种问题——实操型 1. 准备工作1.1 安装RabbitMQ1.2 简单部署搭建设计1.3 参考官网 2. RabbitMQ 形成集群的方法3. 搭建RabbitMQ集群3.1 部署架构3.2 rabbitmq集群基础知识3.2.1 关于节点名称(标识符)3.2.…

Java常见API---split()

package daysreplace;public class SplitTest {public static void main(String[] args) {String str"武汉市|孝感市|长沙市|北京市|上海市";String[] array str.split("\\|");System.out.println(array[0]);System.out.println(array[1]);System.out.pri…

解决recovery页面反转的问题

1.前言 在android 10.0的系统rom定制化开发工作中,在系统中recoverv的页面也是相关重要的一部分,在系统recovery ta升级等功能,都是需要recoverv功能的,在某些产品定制化中 在recovery的时候,发现居然旋转了180度&…

javaee thymeleaf简介

thymeleaf 使用thymeleaf可以实现动静分离,jsp页面是无法直接用浏览器打开的,使用了thymeleaf后,页面是html格式,可以直接用浏览器打开,这样可以方便测试人员进行测试。

【C++】一文带你走入vector

文章目录 一、vector的介绍二、vector的常用接口说明2.1 vector的使用2.2 vector iterator的使用2.3 vector空间增长问题2.4 vector 增删查改 三、总结 ヾ(๑╹◡╹)ノ" 人总要为过去的懒惰而付出代价ヾ(๑╹◡╹)ノ" 一、vector的介绍 vector…

golang gin——文件上传(单文件,多文件)

文件上传 单文件上传 从form-data获取文件 package uploadimport ("github.com/gin-gonic/gin""net/http" ) // 单文件上传,多文件上传 func Upload(c *gin.Context) {file, _ : c.FormFile("file") // file为字段名dst : "…

背包问题学习笔记-混合背包问题

题意描述: 有 N 种物品和一个容量是 V 的背包。物品一共有三类:第一类物品只能用1次(01背包); 第二类物品可以用无限次(完全背包); 第三类物品最多只能用 si 次(多重背包…

nodejs开发环境搭建

Nodejs是一个开源的、跨平台JavaScript运行时环境,其使用V8引擎对JavaScript脚本执行解释,在前后端分离的应用架构设计中,其既能支持web页面服务应用的开发、也能支持后端接口服务应用的开发,类似于Java语言的J2EE运行时环境&…

安装matplotlib__pygame,以pycharm调入模块

安装pip 安装matplotlib 安装完毕,终端输入pip list检查 导入模块出现bug,发现不是matplotlib包的问题,pycharm版本貌似不兼容,用python编辑器可正常绘图,pygame也可正常导入。 ​​​​​​​ pycharm版本问题解决 终…

MarqueeView - 跑马灯

官网 https://github.com/sunfusheng/MarqueeView 项目简介 俗名&#xff1a;可垂直跑、可水平跑的跑马灯&#xff1b; 学名&#xff1a;可垂直翻、可水平翻的翻页公告 Gradle compile com.sunfusheng:MarqueeView:<latest-version> 属性 Attribute 属性 Descrip…

Java开发一些偏冷门的面试题

文章目录 1.进程间的通信&#xff0c;线程间的通信首先可以先回答进程、线程和协程关于线程和进程通信 2.MySQL中的缓存情况&#xff0c;以及缓存命中率查询 主要从别人的面经那里看来的&#xff0c;以及自己被问住的一些面试题。 拿出来给自己做记录&#xff0c;也顺便给大家做…