PImpl(Pointer to Implementation)指向实现的指针 [使用ChatGPT学习系列]

news2025/1/11 20:47:11

PImpl是Pointer to Implementation的缩写,也被称为“编译期实现”,是一种C++设计的模式。 用于将类的实现细节与其公共接口分离开来。该模式的核心思想是 通过一个指向类的实现的指针来隐藏类的实现细节,从而提高类的封装性和安全性。

PImpl一种C++编程技巧它将类的实现细节从对象表示中移除,放到一个分离的类中,并以一个不透明的指针进行访问。 此技巧用于构造拥有稳定 ABI 的 C++ 库接口,及减少编译时依赖。

【拓展:ABI指的是Application Binary Interface,是应用程序二进制接口的缩写。ABI定义了应用程序与操作系统或库之间的二进制接口规范,包括二进制数据格式、调用约定、符号命名规则等方面的规定。这些规定是保证不同的二进制模块能够相互调用和兼容的重要保障。

在编译程序时,编译器会按照ABI规范生成二进制代码,而在链接时,链接器会根据ABI规范将不同的二进制模块合并成可执行程序或共享库。因此,遵守ABI规范可以保证二进制模块的互操作性和可移植性,降低软件开发和维护的成本,同时也能提高系统的稳定性和安全性】

一.PImpl的好处

使用PImpl模式的好处是:

  1. 可以避免对实现细节的公开,从而减少了头文件中的依赖项和编译时间,并且使得类的实现可以更加灵活和方便地修改,而不会影响其公共接口。

在使用PImpl模式时,通常需要将类的实现细节封装在一个单独的结构体或类中,称为“实现类”或“pImpl类”,然后通过一个指向该实现类的指针来访问实现细节。这个指针通常作为 类的私有成员变量,并在类的构造函数和析构函数中进行初始化和清理。这样,当类的实现细节发生变化时,只需要修改实现类而不需要修改公共接口,从而实现了类的高内聚低耦合的设计目标

2.使用PImpl模式还可以降低类的二进制兼容性问题,因为类的公共接口不受实现细节的影响,减少编译时依赖。

因为类的私有数据成员参与其对象表示,影响大小和布局,也因为类的私有成员函数参与重载决议(这会在成员访问检查之前发生),因此对实现细节的任何更改都要求该类的所有用户重新编译。

pImpl 打破了这种编译依赖;实现的改动不会导致重编译。结果是,如果某个库在其 ABI 中使用 pImpl,那么这个库的新版本可以更改实现,并且与旧版本保持 ABI 兼容。

二.示例代码

在下面的代码中,我们使用了std::unique_ptr智能指针来管理指向实现类的指针。因为 std::unique_ptr要求被指向类型在任何实例化删除器的语境中均为完整类型,所以特殊成员函数必须由用户声明,并在实现文件(实现类完整处)中类外定义。

Widget类的构造函数中,我们使用了std::make_unique函数来创建一个新的WidgetImpl对象,并将其传递给智能指针。

Widget类的拷贝构造函数中,我们使用了std::make_unique和拷贝构造函数来创建一个新的WidgetImpl对象,并将其传递给智能指针。

Widget类的赋值操作符中,我们使用了智能指针的默认赋值操作符来赋值实现类的指针。需要注意的是,在Widget类的析构函数中,我们不需要手动释放指向实现类的指针,因为智能指针会自动管理其生命周期,确保在Widget对象被销毁时自动释放实现类的资源。

// Widget.h

class Widget
{
public:
    Widget();
    ~Widget();

    Widget(const Widget& other);
    Widget& operator=(const Widget& other);

    void doSomething();

private:
    class WidgetImpl;  // 前向声明

    std::unique_ptr<WidgetImpl> pImpl;  // 指向实现类的智能指针
};

// Widget.cpp

#include "Widget.h"

class Widget::WidgetImpl
{
public:
    void doSomethingImpl();
};

//初始化指针
Widget::Widget() : pImpl(std::make_unique<WidgetImpl>())
{
}

Widget::~Widget()
{
}

//拷贝构造
Widget::Widget(const Widget& other)
        :pImpl(std::make_unique<WidgetImpl>(*other.pImpl))
{
}
//赋值构造
Widget& Widget::operator=(const Widget& other)
{
    *pImpl = *other.pImpl;
    return *this;
}

//调用WidgetImpl的方法
void Widget::doSomething()
{
    pImpl->doSomethingImpl();
}

void Widget::WidgetImpl::doSomethingImpl()
{
    // 实现具体的功能
}

三.PImpl的替代方案

内联实现:私有成员和公开成员是同一类的成员

纯虚类(OOP工厂):用户获得到某个轻量级或纯虚的基类的唯一指针,实现细节则处于覆盖其虚成员函数的派生类中。

简单情况下,PImpl 和工厂方法 都会打破实现和类接口的用户之间的编译时依赖。 工厂方法创建对虚表的一次隐藏依赖,故而对虚函数进行重排序、添加或移除都会打破 ABI。

有一些信息是从ChatGPT获取的,更多信息参见:https://zh.cppreference.com/w/cpp/language/pimpl

ChatGPT太强大了,它能持续对话,还能理解我的意思,并且还有学习的能力。

AI元年,就由GPT来开启了。

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

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

相关文章

「考研算法」

考研算法 前言 本系列文章涉及的算法内容&#xff0c;针对的是哈尔滨工业大学854科目。在本文中通过具体的算法题进行讲解相应算法。 今天涉及的算法主要有线性筛&#xff0c;十大排序中快速排序和归并排序。 后续会有动态规划的相关算法以及尝试模型的总结&#xff0c;如果…

[Java·算法·中等]LeetCode17. 电话号码的字母组合

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1分析思路2题解2题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。…

本科毕业设计-基于ORB SLAM3的多从机SLAM导航系统

耗时&#xff1a;两个月 需求&#xff1a;多从机协作 多地图系统 稠密建图 定位 导航 硬件&#xff1a;二个D435 一台X86主机&#xff08;CPU:13600kf 内存:32G&#xff09; X86主机环境&#xff1a;ubuntu18.04 opencv3.2 ROS1 主要代码参考&#xff1a;ORB-SLAM3 主要调用…

【CNN】FractalNet——与DenseNet有异曲同工之妙

FractalNet论文名称&#xff1a;FractalNet: Ultra-Deep Neural Networks without Residuals FractalNet论文下载链接&#xff1a; FractalNet&#xff08;分型网络&#xff09;&#xff0c;2016年Gustav Larsson首次提出。 &#xff08;1&#xff09;分形网络不像resNet那样…

嵌入式 Linux 文件IO操作

目录 Linux 文件操作 1 Linux 系统环境文件操作概念 2 缓冲 IO 文件操作 1 文件的创建&#xff0c;打开与关闭 fopen 函数函数 2 freopen 函数 3、fdopen函数 4、fclose函数 5、格式化读写 6、单个字符读写 7、文件定位 8、标准目录文件 9、非缓冲IO文件操作 Linux 文…

十二、MyBatis的高级映射及延迟加载

1 数据库表的准备 准备数据库表&#xff1a;一个班级对应多个学生。班级表&#xff1a;t_clazz。学生表&#xff1a;t_stu 2 环境搭建 创建模块 打包方式&#xff1a;jar 引入依赖&#xff1a;mybatis依赖、mysql驱动依赖、junit依赖、logback依赖 配置文件&#xff1a;…

C#/.net程序调用python

C#/.net程序调用python C#的优势在于window下的开发&#xff0c;不仅功能强大而且开发周期短。而python则有众多的第三方库&#xff0c;可以避免自己造轮子&#xff0c;利用C#来做界面&#xff0c;而具体实现使用python来实现可以大大提高开发效率。本文介绍如何使用pythonnet…

Kubernetes初始化容器

初始化容器 之前了解了容器的健康检查的两个探针&#xff1a;liveness probe&#xff08;存活探针&#xff09;和readiness probe&#xff08;可读性探针&#xff09;的使用方法&#xff0c;我们说在这两个探针是可以影响容器的生命周期的&#xff0c;包括我们之前提到的容器的…

如何或者无插件Web页面监控播放软件LiveNVR的固定视频流地址,实现大屏上墙、播放、视频分析等目的

1、LiveNVR介绍 LiveNVR的安防监控的视频直播&#xff0c;可以按标准的Onvif/RTSP协议接入监控设备&#xff0c;也可以通过海康、大华、天地伟业等厂家私有SDK接入监控&#xff0c;实现web页面的播放和录像回放。 可以分发HTTP-FLV、WS-FLV、WebRTC、RTMP、HLS(M3U8)、RTSP等多…

Linux安装Tomcat9

默认Linux已经安装了JDK 并且已经配置好了环境变量 下载链接 Tomcat9 下载完成如下图 &#xff0c;这个下载完成需要看一下&#xff0c;有的包里bin目录内缺少bootstrap.jar文件&#xff0c;因此下载包的时候要看看bin目录下的是不是有这个文件&#xff0c;如果没有启动Tomcat…

CHAPTER 1 Linux 集群

集群1 集群介绍2 集群分类1. 高可用性集群&#xff08;High Availability Cluster&#xff09;HA2. 负载均衡集群&#xff08;Load Balance Cluster&#xff09;LB3. 高性能集群&#xff08;High Performance Computing Cluster&#xff09;HPC3 HA集群逻辑架构1. 信息层/基础架…

Qt页面菜单栏、工具栏、状态栏

1、菜单栏 QMenu *editMenu ui->menuBar->addMenu("编辑(&E)");2、编辑菜单栏及工具栏内容 QAction *action_copy editMenu->addAction(QIcon("copy.png"),QString("复制(&c)"));action_copy->setShortcut(QKeySequence(…

数学建模竞赛的一些心得体会

1.数学建模经验首先简要的介绍一下我的情况。数学建模我也是在大一暑假开始接触的&#xff0c;之前对其没有任何的了解。我本身对数学也有相对较厚的兴趣&#xff0c;同时我也是计算机专业的学生&#xff0c;因此&#xff0c;我觉得我可参加数学建模的这个比赛。大一的暑假参加…

Linux->进程终止和等待

目录 1. 进程终止场景 1.1 进程退出码 1.2 进程常见退出方式 2. 进程等待 2.1 进程等待的必要性 2.2 进程等待的方式 wait()方式 waitpid()方式 options参数 status参数 1. 进程终止场景 代码运行完毕&#xff0c;结果正确 代码运行完毕&#xff0c;结果不正确 代码异…

【编程架构实践】关于技术栈和架构

架构是什么&#xff1f;老生常谈了。那就看看ChatGPT怎么说&#xff1a;软件架构是软件工程师在设计一个软件系统时&#xff0c;定义系统架构结构的一种科学方法。它指的是软件系统在软件工程师关注功能、性能和安全等质量属性的条件下&#xff0c;组织系统的方式。换句话说&am…

Flask源码篇:wsgi、Werkzeug与Flask启动工作流程

目录1 wsgi介绍2 使用wsgi实现一个web应用3 Werkzeug介绍4 Flask工作流程分析&#xff08;1&#xff09;创建Flask app&#xff08;2&#xff09;启动Falsk app&#xff08;3&#xff09;分析run_simple方法&#xff08;4&#xff09;分析make_server方法&#xff08;5&#xf…

内容分发网络

介绍 CDN 内容分发网络&#xff08;英语&#xff1a;Content Delivery Network 或 Content Distribution Network&#xff0c;缩写&#xff1a;CDN&#xff09;是建立并覆盖在承载网上&#xff0c;由不同区域的服务器组成的分布式网络。将源站资源缓存到全国各地的边缘服务器&…

【数据库视图】简单学习视图,了解一些视图的简单功能

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#x1f345;&#x1f345;&#x1f345;&#xff0c;今天我想带大家去了解一下数据库的视图,虽然视图这个东西在很多地方(各种公司以及项目)已经不再用了,但是许多大学生在考试的时候涉及,&#x1f6f4;&#x1f6f4;&#x1f…

【c++】STL常用容器5—list容器

文章目录list基本概念list构造函数list赋值和交换list大小操作list插入和删除list数据存取list反转和排序list基本概念 功能&#xff1a;将数据进行链式存储。 链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链…

京东物流实时风控实践

摘要&#xff1a;本文整理自京东风控数据产品组架构师周文跃&#xff0c;在 FFA 2022 实时风控专场的分享。本篇内容主要分为六个部分&#xff1a;1. 京东物流业务介绍2. 物流风控场景概括3. 物流风控平台建设4. Flink 赋能5. 技术挑战6. 未来规划Tips&#xff1a;点击「阅读原…