Z
ZHANK
编程在线教程C++ 教程PIMPL 编译防火墙
C++20/23 与惯用法

PIMPL 编译防火墙

隐藏实现细节、减少编译依赖、ABI 稳定、unique_ptr 实现

PIMPL 编译防火墙

PIMPL(Pointer to IMPLementation)把实现细节隐藏在 .cpp 文件中——修改实现不触发重新编译。

学完本章你将: 掌握隐藏实现细节、减少编译依赖、ABI 稳定。


基本实现

cpp
// widget.h —— 清爽的公共接口
#include <memory>

class Widget {
public:
    Widget();
    ~Widget();           // 必须在 .cpp 中定义(unique_ptr 需要完整类型)
    Widget(Widget&&);    // 移动构造
    Widget& operator=(Widget&&);

    void doSomething();
    int getValue() const;

private:
    struct Impl;                          // 只声明,不定定义
    std::unique_ptr<Impl> pImpl;          // 指向前向声明的类型
};
cpp
// widget.cpp —— 所有实现细节在这里
#include "widget.h"

struct Widget::Impl {
    int value = 42;
    std::string name = "Widget";
    std::vector<int> data;

    void complexOperation() { /* ... */ }
};

Widget::Widget() : pImpl(std::make_unique<Impl>()) { }
Widget::~Widget() = default;  // 必须在这里——Impl 此时完整

void Widget::doSomething() {
    pImpl->complexOperation();  // 委托给实现
}
int Widget::getValue() const {
    return pImpl->value;
}

PIMPL 的价值

好处说明
编译隔离修改 .cpp 不触发依赖者重编译
ABI 稳定类大小不变——二进制兼容
隐藏依赖头文件不需要 #include 实现用到的库
成本一次堆分配 + 指针间接访问

现代替代

cpp
// 如果不需要真正的 PIMPL——只隐藏实现
// 可以用模块(C++20 Modules)——import 不会泄漏实现细节