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. 代码复杂性增加:需要定义和管理实现类和指针,代码复杂性有所增加。
相关推荐
cdut_suye2 分钟前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
波音彬要多做26 分钟前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
捕鲸叉27 分钟前
C++软件设计模式之外观(Facade)模式
c++·设计模式·外观模式
Swift社区34 分钟前
Excel 列名称转换问题 Swift 解答
开发语言·excel·swift
一道微光38 分钟前
Mac的M2芯片运行lightgbm报错,其他python包可用,x86_x64架构运行
开发语言·python·macos
矛取矛求43 分钟前
QT的前景与互联网岗位发展
开发语言·qt
Leventure_轩先生43 分钟前
[WASAPI]从Qt MultipleMedia来看WASAPI
开发语言·qt
向宇it1 小时前
【从零开始入门unity游戏开发之——unity篇01】unity6基础入门开篇——游戏引擎是什么、主流的游戏引擎、为什么选择Unity
开发语言·unity·c#·游戏引擎
是娜个二叉树!1 小时前
图像处理基础 | 格式转换.rgb转.jpg 灰度图 python
开发语言·python
Schwertlilien1 小时前
图像处理-Ch5-图像复原与重建
c语言·开发语言·机器学习