Pimpl习惯用法
Pimpl(pointer to implementation):指向实现的指针。
把某类的数据成员用一个指向某实现类(或结构体)的指针替代,然后把原来在主类的数据成员放到实现类中,并通过指针间接访问这些数据成员。例如:
class Gadget{};//位于头文件Gadget.h中
class Widget {//位于widget.h头文件中
public:
Widget();
private:
string name;
vector<double> data;
Gadget g1, g2, g3;
};
由于要包含#include #include #include"gadget”头文件,导致编译速度变慢,而且假设gadget.h内容被改变,widget.h又要重新编译。此时就需要使用Pimpl习惯用法:
widget.h
class Widget {
public:
Widget();
~Widget();//析构函数必须
private:
struct Impl;//声明实现结构体
Impl* pImpl;//指向该结构体的指针
};
其中Widget::Impl就是一个非完整类型:已声明但未定义。
Pimpl习惯用法:
1、声明一个指针类型的数据成员,指向一个非完整类型;
2、动态分配和回收持有从前在原始类的数据成员的对象,而代码在实现文件中。
实现文件widget.cpp:
#include"widget.h"
#include"gadget.h"
#include<string>
#include<vector>
using namespace std;
struct Widget::Impl {
string name;
vector<double> data;
Gadget g1, g2, g3;
};
Widget::Widget() :pImpl(new Ipml) {}
Widget::~Widget() { delete pImpl; }
考虑到C++11的智能指针,提出改进版本:
widget.h
class Widget {
public:
Widget();
//~Widget();
private:
struct Impl;//声明实现结构体
//Impl* pImpl;//指向该结构体的指针
shared_ptr<Impl> pImpl;
};
实现文件widget.cpp:
#include"widget.h"
#include"gadget.h"
#include<string>
#include<vector>
using namespace std;
struct Widget::Impl {
string name;
vector<double> data;
Gadget g1, g2, g3;
};
Widget::Widget():pImpl(make_shared<Impl>()){}
//Widget::Widget() :pImpl(new Ipml) {}
//Widget::~Widget() { delete pImpl; }
避免了裸指针的使用,析构函数也不用书写,自动析构。