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. 代码复杂性增加:需要定义和管理实现类和指针,代码复杂性有所增加。
相关推荐
&岁月不待人&21 分钟前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
StayInLove24 分钟前
G1垃圾回收器日志详解
java·开发语言
TeYiToKu26 分钟前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
无尽的大道32 分钟前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
互联网打工人no133 分钟前
每日一题——第一百二十四题
c语言
爱吃生蚝的于勒36 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~39 分钟前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
binishuaio1 小时前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE1 小时前
【Java SE】StringBuffer
java·开发语言
就是有点傻1 小时前
WPF中的依赖属性
开发语言·wpf