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

从纯虚类到普通类:提升C++ ABI兼容性的策略

在C++编程中,纯虚类(也被称为抽象类)通常用于定义接口,而普通类则包含具体的实现。然而,在某些情况下,将纯虚类转换为普通类并提供默认实现,可以显著提升应用程序二进制接口(ABI)的兼容性。本文将深入探讨这一策略,解释其背后的理论依据,对比纯虚类与普通类的优缺点,并展示相应的应用场景和代码示例。

一、理论依据

在C++中,每个包含虚函数的类都有一个与之关联的虚函数表(vtable)。这个表包含了指向该类所有虚函数的指针。当类被继承时,派生类的vtable会继承基类的vtable,并添加自己的虚函数。如果基类中的虚函数签名发生变化(例如添加新的纯虚函数),那么派生类的vtable也会相应地改变,这可能导致二进制不兼容。

通过为纯虚函数提供默认实现,我们实际上是在基类中定义了一个具体的函数体。这样,即使我们在基类中添加了新的虚函数或改变了现有虚函数的行为,只要这些变化不影响到已经发布的二进制版本,就不会影响派生类的vtable布局。因此,这种方法有助于保持旧版本库与新版本库之间的二进制兼容性。

提高二进制兼容性和减少编译依赖方面同样可参考: 设计模式-PIMPL 模式

二、纯虚类 vs 普通类:优缺点对比

1. 纯虚类(抽象类)

  • 优点

    • 强制实现:确保所有派生类都必须提供特定功能的实现。
    • 明确接口:清晰地表达了这是一个接口,不允许实例化。
  • 缺点

    • ABI 不兼容:任何对虚函数的更改都会导致派生类的vtable变化,可能引起二进制不兼容。
    • 无默认行为:不能为接口提供默认实现,除非将其变为非纯虚函数。

2. 普通类

  • 优点

    • 默认实现:可以为接口提供默认实现,便于维护和扩展。
    • ABI 兼容性:通过提供默认实现,减少了vtable变化的可能性,提高了二进制兼容性。
  • 缺点

    • 可能允许实例化:如果不小心,可能会实例化这个类,尽管它本来应该作为接口使用(可以通过将构造函数设为protected或private来避免)。
    • 接口不够明确:不如纯虚类那样直观地表达这是一个接口(可以通过命名约定和文档来弥补)。

三、应用场景

  • 长期维护的库:对于需要长期维护并可能有多个版本同时使用的库来说,提供默认实现可以减少更新带来的风险,保护现有的二进制接口。
  • 框架和插件系统:在框架或插件系统中,提供默认实现可以让开发者更容易地扩展系统,同时保持系统的稳定性和一致性。
  • 跨平台开发:在不同平台上编译和链接代码时,确保二进制兼容性是非常重要的,尤其是在使用静态库的时候。

四、代码示例

以下是一个简单的代码示例,展示了如何将纯虚类转换为包含默认实现的普通类。

// 纯虚类(接口)定义
class IShape {
public:virtual ~IShape() = default;virtual double area() const = 0; // 纯虚函数virtual double perimeter() const = 0; // 纯虚函数
};// 具体实现类(圆形)
class Circle : public IShape {
public:Circle(double radius) : radius_(radius) {}double area() const override { return 3.141592653589793 * radius_ * radius_; }double perimeter() const override { return 2 * 3.141592653589793 * radius_; }
private:double radius_;
};// 转换为包含默认实现的普通类
class Shape {
public:virtual ~Shape() = default;virtual double area() const { return 0.0; } // 默认实现virtual double perimeter() const { return 0.0; } // 默认实现
};// 具体实现类(矩形,继承自普通类)
class Rectangle : public Shape {
public:Rectangle(double width, double height) : width_(width), height_(height) {}double area() const override { return width_ * height_; }double perimeter() const override { return 2 * (width_ + height_); }
private:double width_;double height_;
};

在这个例子中,IShape是一个纯虚类接口,定义了areaperimeter两个纯虚函数。Circle类实现了这个接口。然后,我们将IShape转换为一个包含默认实现的普通类Shape,并添加了一个具体实现类Rectangle。在Shape类中,areaperimeter函数有默认实现,这意味着任何继承自Shape的类都可以选择性地覆盖这些函数。

五、注意事项

虽然这种方法有助于提高ABI兼容性,但它并不能完全消除所有可能的二进制不兼容问题。例如,如果修改了类的数据成员或改变了非虚函数的行为,仍然可能会导致二进制不兼容。因此,在设计库时,应当综合考虑各种因素,以确保最佳的兼容性和稳定性。

相关文章:

从纯虚类到普通类:提升C++ ABI兼容性的策略

在C编程中,纯虚类(也被称为抽象类)通常用于定义接口,而普通类则包含具体的实现。然而,在某些情况下,将纯虚类转换为普通类并提供默认实现,可以显著提升应用程序二进制接口(ABI&#…...

QT中如何限制 限制QLineEdit只能输入字母,或数字,或某个范围内数字等限制约束?

在 Qt 中,你可以通过多种方式来限制 QLineEdit 只能输入特定类型的字符,如字母、数字或某个范围内的数字。以下是一些常见的方法: 1. 使用输入验证器(QIntValidator, QDoubleValidator, QRegExpValidator) Qt 提供了…...

Tailwind CSS 使用简介

参考网站安装 - Tailwind CSS 中文网 号称是开始使用 Tailwind CSS 通过 npm 安装 tailwindcss,并创建你的 tailwind.config.js 文件。 npm install -D tailwindcss npx tailwindcss init 在 tailwind.config.js 文件中添加所有模板文件的路径。 /** type {im…...

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer 一、Cocoa Touch Layer 简介二、Cocoa Touch Layer 的核心功能1. UIKit2. Event Handling(事件处理)3. Multitasking(多任务处理)4. Push Notifications(推送通知&…...

C语言实现库函数strlen

size_t是 unsigned int fgets会读入\n&#xff0c;用strcspn函数除去 assert判读指针是否为空指针&#xff0c;使用前要引头文件<assert.h> #include <stdio.h> #include <assert.h> size_t mystrlen(const char* str) {assert(str);size_t count 0;while …...

050_小驰私房菜_MTK Camera debug, data rate 、mipi_pixel_rate 确认

mipi_pixel_rate = data rate * 4 / 10 (4 是表示4lane,10表示raw数据是10bit) mipi_pixel_rate 信息,我们可以通过 sentest命令打印看到: 下面的信息我们可以看到,mipi_pixel_rate = 501.357739Mpps,mipi rate = 10000000,是对应的我们驱动文件里面配置写的mipi_pixel_r…...

(六)vForm 动态表单(数据量大,下拉选卡顿问题)

系列文章目录 (一)vForm 动态表单设计器之使用 (二)vForm 动态表单设计器之下拉、选择 (三)vForm 动态表单解决下拉框无数据显示id问题 (四)vForm 动态表单自定义组件、属性 (五)vForm 动态表单文件上传、下载 文章目录 目录 前言 一、组件改造 1.添加分页所需参…...

【mybatis-plus问题集锦系列】mybatis使用xml配置文件实现数据的基础增删改查

简单的数据查询&#xff0c;我们可以在mapper接口里面去实现&#xff0c;但是如果是复杂的查询&#xff0c;我们就可以使用xml配置文件去做&#xff0c; 官网链接xml配置文件 实现效果 实现代码 根据mapper接口的包结构&#xff0c;在resources包里面新建同名同结构的xml文件…...

投稿指南【NO.12_14】【极易投中】期刊投稿(毛纺科技)

近期有不少同学咨询投稿期刊的问题&#xff0c;大部分院校的研究生都有发学术论文的要求&#xff0c;少部分要求高的甚至需要SCI或者多篇核心期刊论文才可以毕业&#xff0c;但是核心期刊要求论文质量高且审稿周期长&#xff0c;所以本博客梳理一些计算机特别是人工智能相关的期…...

机器学习算法的分类

一、按学习方式分类 1.监督学习&#xff08;Supervised Learning&#xff09; &#xff08;1&#xff09;定义&#xff1a;使用已标记的数据进行训练&#xff0c;每个输入数据都有对应的输出标签。模型学习输入与输出之间的映射关系。 按以上可以分为以下两种&#xff1a; …...

Linux操作系统下,挂ILA

一、在linux下安装vivado2018.3 参考视频&#xff1a;Linux下vivado安装教程_哔哩哔哩_bilibili 复制安装包进入虚拟机 安装包链接&#xff1a;https://pan.quark.cn/s/ca1a15d446fa 我的vmware tools无法使用&#xff0c;不能直接拖进虚拟机&#xff0c;所以使用了U盘复制…...

HTML——26.像素单位

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>像素</title></head><body><!--像素&#xff1a;1.指设备屏幕上的一个点&#xff0c;单位px&#xff0c;如led屏上的小灯朱2.当屏幕分辨率固定时&…...

【HTML】Day02

【HTML】Day02 1. 列表标签1.1 无序列表1.2 有序列表1.3 定义列表 2. 表格标签2.1 合并单元格 3. 表单标签3.1 input标签基本使用3.2 上传多个文件 4. 下拉菜单、文本域5. label标签6. 按钮button7. div与span、字符实体字符实体 1. 列表标签 作用&#xff1a;布局内容排列整齐…...

AI 自动化编程对编程教育的影响

AI 自动化编程的未来 引言 你是否曾想过&#xff0c;未来的程序员需要掌握哪些技能呢&#xff1f;随着人工智能的迅猛发展&#xff0c;特别是生成式AI工具的普及&#xff0c;编程的世界正在发生翻天覆地的变化。编程教育也在这种环境下进行着深刻的转型。那么&#xff0c;AI …...

Java100道面试题

1.JVM内存结构 VM内存结构指的是JVM运行时数据区结构&#xff0c;它主要包含以下几个部分&#xff1a; 堆&#xff08;Heap&#xff09;&#xff1a;线程共享。 JVM堆&#xff08;Heap&#xff09;是Java虚拟机中的一块内存区域&#xff08;所有线程共享&#xff09;&#x…...

解密人工智能:如何改变我们的工作与生活

引言&#xff1a;AI崛起背后的思考 在过去的几十年里&#xff0c;人工智能&#xff08;AI&#xff09;从科幻小说中的神秘存在&#xff0c;逐渐走进了我们的日常生活。无论是智能手机的语音助手&#xff0c;还是推荐心仪商品的电商平台&#xff0c;AI技术已悄然融入工作与生活的…...

Linux postgresql-15部署文档

一、PostgreSQL的安装 1、下载地址 postgresql安装包下载地址&#xff1a;https://www.postgresql.org/download/linux/redhat/ 2、安装脚本 复制下面的安装脚本即可&#xff1a; sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64…...

visual studio 安全模式

一、安全模式&#xff1a; 在 Visual Studio 中&#xff0c;安全模式是一种启动方式&#xff0c;允许你在禁用所有扩展和自定义设置的情况下启动 Visual Studio。这个模式可以帮助排除插件或扩展引起的问题&#xff0c;特别是在 Visual Studio 无法正常启动时。 二、安全模式下…...

Pandas-timestamp和datetime64的区别

文章目录 1. Timestamp&#xff08;时间戳&#xff09;2. Datetime64&#xff08;日期时间64位&#xff09;3. 主要区别&#xff1a; pandas.Timestamp 和 pandas.Datetime64 都是用于表示日期和时间的 Pandas 对象&#xff0c;但它们有一些关键的区别&#xff1a; 1. Timesta…...

@MapperScan

简介&#xff1a; MapperScan注解是MyBatis框架在Spring Boot中的一个重要集成注解 作用&#xff1a; MapperScan主要作用是告诉Spring框架在启动时扫描指定的包路径&#xff0c;并将该路径下的所有MyBatis的Mapper接口批量注入到Spring容器中。这样&#xff0c;开发者就可以…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...