文档目录

一、解决什么问题?

问题:你有一个类的头文件,暴露了私有成员。每次修改私有成员,所有包含这个头文件的 .cpp 都要重新编译——大项目里一次改动触发 10 分钟的全量编译。

// widget.h — ❌ 私有成员在头文件里
class Widget {
    std::string title_;       // private
    std::vector<int> data_;   // private
    // 每次改这些私有成员,所有 include widget.h 的 .cpp 都要重编
public:
    void show();
};

PIMPL 的做法:私有成员放到一个 Impl 结构体,只在前向声明:

// widget.h
class Widget {
    struct Impl;               // 只声明,不定义
    std::unique_ptr<Impl> pimpl_;

public:
    Widget();
    ~Widget();                 // 析构必须在 .cpp 中定义(因为 Impl 是不完整类型)
    void show();
};

// widget.cpp
struct Widget::Impl {
    std::string title_;
    std::vector<int> data_;
};

Widget::Widget() : pimpl_(std::make_unique<Impl>()) {}
Widget::~Widget() = default;  // 必须在这里定义

void Widget::show() {
    // 通过 pimpl_ 访问私有成员
    std::cout << pimpl_->title_;
}

效果:改 Impl 的成员只需要编译 widget.cpp,不需要重新编译所有 #include "widget.h" 的文件。

二、什么时候用?

场景 用 PIMPL
你写一个公共库的头文件,不想暴露实现细节 ✅ 头文件干净,方便其他团队使用
你的类私有成员包含大量 STL 容器 ✅ 避免暴露 <vector> <string> 等头文件依赖
你的头文件被几百个 .cpp 包含,编译慢 ✅ PIMPL 能显著提升增量编译速度
你的类很小,私有成员很少 ❌ PIMPL 增加了一次堆分配 + 一次间接调用,小类不值得