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 不会泄漏实现细节