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

设计模式-PIMPL 模式

PIMPL(Pointer to IMPLementation),又称Opaque Pointer模式或编译防火墙,是一种在C++中广泛应用的编程技术。其核心思想是将类的实现细节从公共接口中分离出来,通过指向实现类的指针来访问类的具体功能。这种模式在提高代码的可维护性、二进制兼容性和减少编译依赖方面表现出了显著的优势。

一、PIMPL 模式的原理

PIMPL模式通过两个主要的类来实现:接口类(Interface Class)和实现类(Implementation Class)。

  • 接口类:这是用户使用的类,包含公共接口(即类的公有成员函数)。在接口类的头文件中,只声明一个指向实现类的私有指针(如std::unique_ptr<Impl>),并通过这个指针来调用实现类中的成员函数。
  • 实现类:包含类的实现细节和私有成员,它只在.cpp文件中定义,不暴露给外部用户。实现类通过接口类中的指针被调用,实现了接口与实现的分离。

这种分离机制使得接口类的头文件更加简洁,减少了头文件之间的依赖关系,提高了编译效率。同时,由于实现类的定义被隐藏在.cpp文件中,外部用户无法直接访问或修改实现细节,增强了代码的安全性和稳定性。

二、PIMPL 模式的应用场景

PIMPL模式在多种场景下表现出色,特别是在以下情况下尤为适用:

  1. 大型库或框架开发:如Qt、Boost等大型库通过PIMPL模式隔离实现细节,确保使用者不受实现变动的影响。
  2. 需要保持ABI稳定性:对于需要长期维护二进制兼容性的库开发,PIMPL模式允许在不改变接口的情况下修改实现。
  3. 减少头文件依赖:对于大型项目,通过PIMPL模式减少头文件依赖,可以显著减少编译时间。

三、PIMPL 模式的优缺点

优点

  1. 提高二进制兼容性:由于接口类和实现类之间的松耦合关系,实现类的变化不会影响到依赖于接口类的二进制代码。
  2. 减少编译依赖:通过只在头文件中声明指向实现类的指针,减少了头文件之间的依赖关系,加快了编译速度。
  3. 隐藏实现细节:实现了接口与实现的分离,增强了代码的安全性和稳定性。
  4. 支持动态加载:在某些情况下,可以通过动态加载库来实现类的具体实现,提高系统的灵活性和可扩展性。

缺点

  1. 性能开销:由于使用指针进行间接访问,增加了访问成本。
  2. 内存使用:每个实例都包含一个指向实现类的指针,增加了内存占用。
  3. 复杂性增加:需要维护两个类,增加了代码的复杂性。
  4. 调试难度:实现细节被隐藏,增加了调试的难度。

C++ 使用示例

以下是一个简单的C++示例,展示了PIMPL模式的应用。

// Book.h
#pragma once
#include <memory>class BookImpl; // 前向声明实现类class Book {
public:Book(const std::string& title, const std::string& author);~Book();void open();void close();std::string getTitle() const;std::string getAuthor() const;private:std::unique_ptr<BookImpl> pImpl; // 指向实现的指针
};// Book.cpp
#include "Book.h"class BookImpl {
public:BookImpl(const std::string& title, const std::string& author): title_(title), author_(author) {}void open() { /* 实现打开书籍的具体逻辑 */ }void close() { /* 实现关闭书籍的具体逻辑 */ }std::string getTitle() const { return title_; }std::string getAuthor() const { return author_; }private:std::string title_;std::string author_;
};Book::Book(const std::string& title, const std::string& author): pImpl(std::make_unique<BookImpl>(title, author)) {}Book::~Book() = default;void Book::open() { pImpl->open(); }
void Book::close() { pImpl->close(); }std::string Book::getTitle() const { return pImpl->getTitle(); }
std::string Book::getAuthor() const { return pImpl->getAuthor(); }// main.cpp
#include "Book.h"
#include <iostream>int main() {Book book("C++ Primer", "Stanley B. Lippman");book.open();std::cout << "Title: " << book.getTitle() << ", Author: " << book.getAuthor() << std::endl;book.close();return 0;
}

在这个示例中,Book 类是接口类,它包含公共接口和一个指向 BookImpl 实现类的指针。BookImpl 类在 Book.cpp 文件中定义,并包含了 Book 类的所有实现细节。通过这种方式,我们实现了接口与实现的分离,提高了代码的可维护性和二进制兼容性。

相关文章:

  • RNN模型学习
  • C++ 排序算法
  • 自适应查询优化(Adaptive Query Optimization, AQO)技术简介
  • react crash course 2024(5) useState钩子
  • DPDK 简易应用开发之路 2:UDP数据包发送及实现
  • 记录打鼾软件
  • 2024最新版 Tuxera NTFS for Mac 2023绿色版图文安装教程
  • 基于单片机的智能温控风扇系统的设计
  • llamafactory0.9.0微调qwen2.5
  • 深度学习驱动智能超材料设计与应用
  • 云服务器连接不上是什么原因引起的?
  • spark 大表与大表join时的Shuffle机制和过程
  • 【视频讲解】非参数重采样bootstrap逻辑回归Logistic应用及模型差异Python实现
  • 【STM32】 TCP/IP通信协议(1)
  • Ubuntu24.04中安装Electron
  • Angular 响应式表单之下拉框
  • CSS居中完全指南——构建CSS居中决策树
  • docker-consul
  • Meteor的表单提交:Form
  • rc-form之最单纯情况
  • React-flux杂记
  • Spring-boot 启动时碰到的错误
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • 安装python包到指定虚拟环境
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 小程序开发之路(一)
  • 异步
  • 译有关态射的一切
  • 因为阿里,他们成了“杭漂”
  • 原生Ajax
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • #Z2294. 打印树的直径
  • (力扣)循环队列的实现与详解(C语言)
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (三)模仿学习-Action数据的模仿
  • (转)C#调用WebService 基础
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .chm格式文件如何阅读
  • .gitattributes 文件
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 使用 XPath 来读写 XML 文件
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .net后端程序发布到nignx上,通过nginx访问
  • .NET文档生成工具ADB使用图文教程
  • @Data注解的作用
  • @PreAuthorize注解
  • @我的前任是个极品 微博分析
  • [2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用
  • [BT]BUUCTF刷题第4天(3.22)
  • [C++]高精度 bign (重载运算符版本)
  • [CF482B]Interesting Array
  • [CISCN2019 华东南赛区]Web11