什么是 Private-IMPL ?
即【隐藏实现的方式】,如果你还停留在学习的阶段,那这种方式对你的代码几乎毫无用处。
但是如果你走入到真实项目当中,这种方式又显得尤为重要。
微软对 Private-IMPL 模式的简单概述(现代C++)
为什么:
1,它可以对外人尽可能隐藏你类内部实现,因为你的 dll 要给别人用,总要提供头文件,对吧?
2,它可以尽可能减少头文件的 include 次数。
3,它可以尽可能减轻编译依赖,从而提高编译速度。
4,接口与实现分离的概念。
5,提高代码可移植性,接口专注当前项目业务,实现则专注于算法。如果需要复用代码,直接Copy走实现类改名重写接口就可以了。
那什么时候不能使用呢?
1,如果你的类本身非常简单,比如说职责就是共享个数据,就不要使用这种模式,函数的过度嵌套调用会大量消耗栈内存。
2,继承了更深层次的基类,这时你的子类应该专注于业务,将高度复用的代码写入基类,而不是进一步将子类复杂化。
那么 Private-IMPL 的具体实现方式是?
在类内部创建一个私有子类,将函数功能的具体实现写入到私有子类当中,类本身的函数只当做接口专注于业务交互。
演示代码:
================== 创建一个叫大脑工具箱的“工具类” ==================
----------------- 头文件 -----------------
// 假设这是一个工具类classBrainToolBox{ public: // 构造和析构函数BrainToolBox(); ~BrainToolBox(); // 接口// 比方说...对一个vector进行冒泡排序(无聊)voidSortVector(std::vector<int>&input); // 比方说...找到一个vector当中的最大值(更无聊)intGetVectorMaxValue(std::vector<int>&input); // 私有化实现类private: // 声明实现类classPrivateIMPL; // 实现类的指针std::unique_ptr<PrivateIMPL>_u; };
我们已经在类定义头文件中将私有子类声明并且使用智能指针进行包装。
----------------- CPP 文件 -----------------
在构造函数执行时,就要创建子类(实现类)的实例,这时必须要有实现类的定义,接着往下看。
// 在构造函数执行时 同时构造实现类BrainToolBox::BrainToolBox(): _u(newBrainToolBox::PrivateIMPL) { } // 毫无存在感的析构 假设不使用智能指针方式 务必在析构中释放实现类的裸指针BrainToolBox::~BrainToolBox() { // 假设为裸指针// delete _u;} // 接口函数 对一个Vector进行冒泡的接口voidBrainToolBox::SortVector(std::vector<int>&input) { // 调用实现函数_u->BubbleSortVector(input); // 假设在实际开发当中 需要将排序结果传出去 这里就可以进行传递操作// zmq_send(socket, vec, len, ZMQ_SNDMORE);return; } // 接口函数 找到一个Vector的最大值intBrainToolBox::GetVectorMaxValue(std::vector<int>&input) { // 调用实现函数return_u->SearchVectorMaxValue(input); }
================== 创建大脑工具箱的实现类 ==================
----------------- 头文件 -----------------
我们在外部类当中仅仅是将实现类声明,这时就需要进行定义。
// 定义BrainToolBox的实现类classBrainToolBox::PrivateIMPL{ public: // 对 Vector 进行冒泡排序的实现函数voidBubbleSortVector(std::vector<int>&vec); // 找到一个 Vector 当中的最大值实现函数intSearchVectorMaxValue(std::vector<int>&vec); };
----------------- CPP 文件 -----------------
将函数的实现代码封装进实现类。
// 实现一个冒泡排序voidBrainToolBox::PrivateIMPL::BubbleSortVector(std::vector<int>&vec) { intvec_size=vec.size(); for (size_ti=0; i<vec_size; i++) { inttrend_size=vec_size-i-1; for (size_tj=0; j<trend_size; j++) { if (vec[j] >vec[j+1]) { intk=vec[j]; vec[j] =vec[j+1]; vec[j+1] =k; } } } return; } // 实现返回vector最大值intBrainToolBox::PrivateIMPL::SearchVectorMaxValue(std::vector<int>&vec) { automax_item=std::max_element(vec.begin(), vec.end()); return*max_item; }
================== 测试一下 ==================
usingstd::shared_ptr; usingstd::vector; intmain() { std::cout<<"Hello Byte!"<<std::endl; vector<int>values= {8, 5, 6, 1, 2, 7, 9, 3, 4, 10, 99, 50}; shared_ptr<BrainToolBox>brain=shared_ptr<BrainToolBox>(newBrainToolBox); std::cout<<"Vector最大值: "<<brain->GetVectorMaxValue(values) <<std::endl; brain->SortVector(values); std::cout<<"排序后的Vector:"<<std::endl; for (auto&item : values) { std::cout<<item<<" "; } returnEXIT_SUCCESS; }
====================================
芯片烤电池 C++ Example 2022-Spring Season Pass :
【Example】C++ 回调函数及 std::function 与 std::bind
【Example】C++ 标准库智能指针 unique_ptr 与 shared_ptr
【Example】C++ Template (模板)概念讲解及编译避坑
【Example】C++ 标准库 std::thread 与 std::mutex
【Example】C++ 标准库多线程同步及数据共享 (std::future 与 std::promise)
【Example】C++ 标准库 std::condition_variable
【Example】C++ 用于编译时封装的 Pimpl 演示 (编译防火墙 Private-IMPL)
【Example】C++ 单例模式 演示代码 (被动模式、兼容VS2022编译)
====================================