定义
Pimpl(Pointer to Implementation)是一种设计模式,它将类的实现细节(私有成员变量和方法)隐藏在一个单独的实现类中,并在公共接口类中仅使用指向实现类的指针。
使用pimpl好处
封装实现细节
Pimpl模式可以将类的实现细节与其公共接口分离开来。这样做可以避免在头文件中暴露私有成员和实现细节,从而降低了类之间的耦合性,提高了代码的模块化和可维护性。
减少编译依赖
将实现细节隐藏在实现类中意味着头文件中不再包含私有成员变量和方法的声明。这样一来,如果实现类的实现发生变化,只有实现类的编译单元需要重新编译,而不必重新编译使用公共接口的客户端代码。
加快编译速度
减少编译依赖可以减少需要重新编译的代码量,从而提高编译速度。特别是对于大型项目,这种优势尤为明显。
隐藏第三方库的细节
当你的类依赖于第三方库时,Pimpl模式可以帮助你隐藏这些依赖的实现细节。这样一来,如果你决定更改或删除依赖的库,只需更改实现类即可,而不必更改公共接口或客户端代码。
示例
// Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <memory>
class WidgetImpl; // 前向声明实现类
class Widget {
public:
Widget();
~Widget();
void doSomething();
private:
std::unique_ptr<WidgetImpl> pImpl; // 指向实现类的指针
};
#endif // WIDGET_H
// Widget.cpp
#include "Widget.h"
#include "WidgetImpl.h"
Widget::Widget() : pImpl(std::make_unique<WidgetImpl>()) {}
Widget::~Widget() = default;
void Widget::doSomething() {
pImpl->doSomething(); // 委托给实现类处理
}
// WidgetImpl.h
#ifndef WIDGETIMPL_H
#define WIDGETIMPL_H
class WidgetImpl {
public:
void doSomething();
};
#endif // WIDGETIMPL_H
// WidgetImpl.cpp
#include "WidgetImpl.h"
#include <iostream>
void WidgetImpl::doSomething() {
std::cout << "Doing something..." << std::endl;
}
在这个例子中,Widget类的实现细节被隐藏在WidgetImpl类中。客户端只需包含Widget.h头文件即可使用Widget类,而无需了解其具体实现细节。