C/C++|Pimpl Idiom(Pointer to IMPLementation) 指针实现模式浅析

Pimpl Idiom(Pointer to IMPLementation),也称为 "Opaque Pointer"(不透明指针)或 "Cheshire Cat"(柴郡猫)模式或者"指针实现模式"和"实现隐藏模式"。这种模式通过将类的实现细节放在一个单独的私有结构体中,并通过指针来访问,从而在不改变类接口的情况下,允许类的实现独立于类的定义进行修改和编译

文章目录

Pimpl Idiom 的基本思想

Pimpl Idiom 的核心思想是将类的实现细节放在一个私有的实现类中,并使用指向该实现类的指针在公共接口类中进行引用。这种方式可以将类的实现细节完全隐藏在实现文件中,用户只需要看到公共接口。

实现步骤

  1. 定义公共接口类:在头文件中定义一个公共接口类,并在其中包含一个指向实现类的私有指针。
  2. 定义实现类:在源文件中定义实现类,包含类的实际实现细节。
  3. 在公共接口类的构造函数和析构函数中管理实现类的指针:在构造函数中创建实现类的实例,在析构函数中销毁它。

典型示例

头文件:Person.h

cpp 复制代码
#ifndef PERSON_H
#define PERSON_H

#include <string>
#include <memory>

class Person {
public:
    Person(const std::string& name, int age);
    ~Person();

    std::string getName() const;
    int getAge() const;
    void setName(const std::string& name);
    void setAge(int age);

private:
    class Impl;  // 前向声明实现类
    std::unique_ptr<Impl> pImpl; // 使用智能指针管理实现类指针
};

#endif // PERSON_H

头文件:PersonImpl.h

cpp 复制代码
#ifndef PERSONIMPL_H
#define PERSONIMPL_H

#include <string>

class Person::Impl {
public:
    Impl(const std::string& name, int age) : name(name), age(age) {}

    std::string name;
    int age;
};

#endif // PERSONIMPL_H

源文件:Person.cpp

cpp 复制代码
#include "Person.h"
#include "PersonImpl.h"

Person::Person(const std::string& name, int age)
    : pImpl(std::make_unique<Impl>(name, age)) {}

Person::~Person() = default;

std::string Person::getName() const {
    return pImpl->name;
}

int Person::getAge() const {
    return pImpl->age;
}

void Person::setName(const std::string& name) {
    pImpl->name = name;
}

void Person::setAge(int age) {
    pImpl->age = age;
}

使用示例:main.cpp

cpp 复制代码
#include <iostream>
#include "Person.h"

int main() {
    Person person("John Doe", 30);
    std::cout << "Name: " << person.getName() << ", Age: " << person.getAge() << std::endl;

    person.setName("Jane Doe");
    person.setAge(25);
    std::cout << "Name: " << person.getName() << ", Age: " << person.getAge() << std::endl;

    return 0;
}

从使用来看,用户仍然是无感的。

通过将 Person 和 PersonImpl 设计成两个不同的头文件,Pimpl Idiom 提供了一种强大的机制来隐藏实现细节,减少编译依赖,并提高代码的封装性和模块化程度。这种设计模式特别适用于需要频繁修改实现但希望接口稳定不变的场景。

Pimpl Idiom 的优点

  1. 隐藏实现细节:用户只能看到头文件中的公共接口,无法看到实现细节。
  2. 减少编译依赖:头文件只包含指向实现类的指针,因此不需要包含实现类的头文件,从而减少编译依赖。
  3. 加快编译时间:由于头文件的变化不会影响依赖该头文件的其他文件,编译时间得到了显著加快。
  4. 二进制兼容性:由于实现类的变化不会影响公共接口类,二进制兼容性得到了保证。

Pimpl Idiom 的缺点

  1. 额外的内存分配和间接访问开销:由于使用了指针,存在额外的内存分配和间接访问的开销。
  2. 代码复杂性增加:需要定义和管理实现类和指针,代码复杂性有所增加。
相关推荐
caimo11 分钟前
Java无法访问网址出现Timeout但是浏览器和Postman可以
java·开发语言·postman
Q741_14736 分钟前
C++ 分治 归并排序 归并排序VS快速排序 力扣 912. 排序数组 题解 每日一题
c++·算法·leetcode·归并排序·分治
三体世界38 分钟前
Qt从入门到放弃学习之路(1)
开发语言·c++·git·qt·学习·前端框架·编辑器
悟能不能悟1 小时前
jdk25结构化并发和虚拟线程如何配合使用?有什么最佳实践?
java·开发语言
柠檬07111 小时前
MATLAB相机标定入门:Camera Calibration工具包详解
开发语言·数码相机·matlab
卓码软件测评1 小时前
借助大语言模型实现高效测试迁移:Airbnb的大规模实践
开发语言·前端·javascript·人工智能·语言模型·自然语言处理
熙客1 小时前
Java8:Lambda表达式
java·开发语言
小咕聊编程1 小时前
【含文档+PPT+源码】基于java web的篮球馆管理系统系统的设计与实现
java·开发语言
minji...1 小时前
算法题 逆波兰表达式/计算器
数据结构·c++·算法·1024程序员节
ZhiqianXia1 小时前
C++ 常见代码异味(Code Smells)
c++