PImpl(pointer to implementation) 是一种减少代码依赖和编译时间的C++编程技巧,其基本思想是将一个外部可见类(visible class)的实现细节(一般是所有私有的非虚成员)放在一个单独的实现类(implementation class)中,而在可见类中通过一个私有指针来间接访问该实现类。
在类中使用 Pimpl 惯用法,具有如下优点:
- 降低耦合
- 信息隐藏
- 降低编译依赖,提高编译速度
- 接口与实现分离
1.Widget.h
// file path:
// example: repo-name/pipeline/nodes/p1/Widget.h
#ifndef PIPILINE_NODES_P1_WIDGET_H_
#define PIPILINE_NODES_P1_WIDGET_H_
#include <iostream>
#include <memory>
// #include "selfDefine.h"
namespace NSPho {
namespace V2 {
namespace Widget {
class Widget {
private:
class Impl;
std::unique_ptr<Impl> mpImpl; //指向Impl类的指针
public:
Widget(int);
Widget(const Widget&) = delete;
Widget(Widget&&) = default;
Widget& operator= (const Widget&) = delete;
Widget& operator= (Widget&&);
~Widget();
void draw();
};
}; // Widget
}; // V2
}; // NSPho
#endif // PIPILINE_NODES_P1_WIDGET_H_
2.Widget.cpp
// file path:
// example: repo-name/pipeline/nodes/p1/Widget.cpp
#include "Widget.h"
// using namespace std; //会引入内容太多,可能会有name 冲突
using std::cout;
using std::endl;
// using NSIImageBuffer;
// using others
#define MY_LOGV(fmt, arg...) Todo;
#define MY_LOGI(fmt, arg...) Todo;
#define MY_LOGE(fmt, arg...) Todo;
#define MY_LOGF(fmt, arg...) Todo;
namespace NSPho {
namespace V2 {
namespace Widget {
class Widget::Impl {
private:
int n = 0; //private data
public:
void draw(const Widget& w);
Impl(int n);
};
Widget::Widget(int n) : mpImpl{std::make_unique<Impl>(n)} {}
Widget& Widget::operator= (Widget&&) = default;
Widget::~Widget() = default;
void Widget::draw() {
mpImpl->draw(*this);
cout<<"Widget::draw() over!!!"<<endl;
}
Widget::Impl::Impl(int n) : n(n) {}
void Widget::Impl::draw(const Widget& w) {
/* ... */
}
}; // Widget
}; // V2
}; // NSPho
3. main.cpp
#include <iostream>
#include <memory>
#include "Widget.h"
using std::cout;
using std::endl;
using namespace NSPho::V2::Widget; //引入全部内容
// using NSPho::V2::Widget::Widget; // 引入部分内容
int main()
{
std::shared_ptr<Widget> spWidget = std::make_shared<Widget>(100);
spWidget->draw();
cout<<"main eixt"<<endl;
return 0;
}