Pimpl(Pointer to implementation) 是一种隐藏实现的小技巧。尤其是我们在对外提供API时,通常需要将头文件给出,这样很明显的将头文件中的私有成员暴漏给外部。另外Pimpl还可以少代码依赖和编译时间,实现了简单的编译解耦。
Pimpl如何实现?在接口类内部实例化一个业务的子类,将函数功能实现写入到业务的子类中,接口类本身的函数只用于和外部的业务交互。
通过Pimpl又达成了接口与实现的解耦,提高了代码的可复用性(移植性)。
- 首选创建好实现类
//=================================traffic.h=================================// #pragma once #includeclass Traffic { public: Traffic(); ~Traffic(); int GetType(); int GetPrice(); std::string GetName(); private: int type_; int price_; std::string name_; }; //=================================traffic.cpp=================================// #include "traffic.h" Traffic::Traffic() { type_=1; price_=1000; name_ = "xiaomi car"; } Traffic::~Traffic() {} int Traffic::GetType() { return type_; } int Traffic::GetPrice() { return price_; } std::string Traffic::GetName() { return name_; }
- 接着实现我们的接口类,通过接口函数来调用与之对应的实例类函数
//=================================i_traffic.h=================================// #pragma once #include#include class Traffic; class I_Traffic { public: I_Traffic(); ~I_Traffic(); int GetType(); int GetPrice(); std::string GetName(); private: std::unique_ptr traffic_pimpl_; }; //=================================i_traffic.cpp=================================// #include "i_traffic.h" #include "traffic.h" I_Traffic::I_Traffic() : traffic_pimpl_(std::make_unique ()) {} I_Traffic::~I_Traffic() { } int I_Traffic::GetType() { return traffic_pimpl_->GetType(); } int I_Traffic::GetPrice() { return traffic_pimpl_->GetPrice(); } std::string I_Traffic::GetName() { return traffic_pimpl_->GetName(); }
- 调用
#include代码解析#include #include "i_traffic.h" using namespace std; int main() { std::unique_ptr traffic = std::make_unique (); cout << traffic->GetName() << endl; cout << traffic->GetPrice() << endl; cout << traffic->GetType() << endl; return 0; }
- 在i_traffic.h文件中,通过前置声明的形式来声明业务类Traffic
- 在i_traffic.cpp访问实体业务类的函数
- 在对外的接口文件i_traffic.h中,无法看到业务类的中的私有变量
- 极大程度上减少了编译的依赖项,减少头文件的Include的次数;
- 接口和实现分离;
- 隐藏了业务类的实现;私有变量,私有函数等,外部人员拿到的接口类无从知晓业务类的头文件声明
- 提高了代码的可阅读、可移植性;接口类专注对外暴漏,业务类专注与算法和逻辑,接口文件稳定性大大提高;
- 如果类本身比较简单,使用Pimpl则会过度嵌套,消耗堆栈内存
MSDN C++ PIMPL



