设计模式-PIMPL 模式

news/2024/9/25 18:10:14/

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 类的所有实现细节。通过这种方式,我们实现了接口与实现的分离,提高了代码的可维护性和二进制兼容性。


http://www.ppmy.cn/news/1530398.html

相关文章

C#|.net core 基础 - 深拷贝的五大类N种实现方式

在实际应用中经常会有这样的需求&#xff1a;获取一个与原对象数据相同但是独立于原对象的精准副本&#xff0c;简单来说就是克隆一份&#xff0c;拷贝一份&#xff0c;复制一份和原对象一样的对象&#xff0c;但是两者各种修改不能互相影响。这一行为也叫深克隆&#xff0c;深…

把命令的语气改成聊天的方式

​在与人沟通时&#xff0c;没人会喜欢别人用下命令的口气对自己说话。 即使是非常明显的错误&#xff0c;一旦用粗鲁的口气命令指责别人&#xff0c;也会引起对方的反感&#xff0c;改正起来也会非常困难。 即使作为领导&#xff0c;也不要用命令的语气面对下级要做到合情合…

Python提供内置正则表达式库

正则表达式是一种强大的文本处理工具&#xff0c;可以匹配文本片段的模式 最简单的正则表达式就是普通的字符串&#xff0c;可以匹配自身 要注意的是&#xff0c;正则表达式并不是一个程序&#xff0c;它使用一种特定的语法模式来描述在搜索文本时要匹配的一个或多个字符串。正…

2024最新!!!iOS高级面试题,全!(一)

TCP,HTTP,HTTPS&#xff0c;,WebSokect 区别&#xff1a; IP协议&#xff08;网络层协议&#xff09; TCP&#xff1a;传输控制协议&#xff0c;主要解决数据如何在网络中传输&#xff0c;面向连接&#xff0c;可靠。&#xff08;传输层协议&#xff09; UDP&#xff1a;用户数…

需求导向的正则表达式

目录 re.sub 需求&#xff1a;把 1. 2.这些序号转成&#xff08;1&#xff09; &#xff08;2&#xff09; 需求&#xff1a;反过来&#xff0c;把(1)->1. ,&#xff08;2&#xff09;》2. 。 需求&#xff1a;把出现的 1 2 3都转成下标 进阶1&#xff01;只想让化学符…

华为HarmonyOS地图服务 4 - 通过“地图相机“控制地图的可见区域

场景介绍 华为地图的移动是通过模拟相机移动的方式实现的&#xff0c;您可以通过改变相机位置&#xff0c;来控制地图的可见区域&#xff0c;效果如图所示。 本章节将向您介绍相机的各个属性与含义&#xff0c;并移动相机。 相机移动前 …

CentOS中使用Docker运行Nginx并挂载本地目录

CentOS 中安装 Docker 并挂载本地目录&#xff1a; 一、安装 Docker 更新系统软件包&#xff1a; sudo yum update -y安装必要的软件包以允许使用 yum 安装 Docker&#xff1a; sudo yum install -y yum-utils device-mapper-persistent-data lvm2添加 Docker 仓库&#xff1a…

哪个编程工具让你的工作效率翻倍?

在探讨哪款编程工具能让工作效率翻倍时&#xff0c;我们不得不承认&#xff0c;这并非是一个非黑即白的答案&#xff0c;因为不同的开发者、不同的项目阶段以及不同的编程需求&#xff0c;都可能使得某种工具成为提升效率的关键。然而&#xff0c;如果要从智能的代码编辑器、强…