目录
一、 Pimpl使用
二、使用unique_ptr改写Pimpl
一、 Pimpl使用
- 在编译过程中,只有widget.cpp和main.cpp参与编译,.h文件会自动展开到*.cpp文件中,当Gadget.h发生改变这时候,两个cpp文件都需要重新编译
- 不希望吧.h文件暴露出去
解决:
- 这时候Gadget.h发生改变,只有Widget.cpp需要重新编译。main.cpp不需要重新编译因为与只包含Widget.h文件,二该文件已经与Gadget.h没有关系
二、使用unique_ptr改写Pimpl
Widget.h
#include <vector>
#include <string>
#include <memory>
#include <iostream>class Widget
{
public:Widget();~Widget();Widget(Widget &&rhs);Widget &operator=(Widget &&rhs);private:struct Impl;std::unique_ptr<Impl> pImpl;
};
- 如果 Widget 的析构/移动构造/移动赋值 在Impl还未定义处 就定义了,就会报错,所以析构/移动构造/移动赋值要在 PImpl后面定义。
- 因为在unique_ptr析构的时候,默认删除器会采用delete来销毁内置于unique_ptr的原始指针。然后在delete之前,通常会使用C++11的特性。static_assert来确保原始指针指向的类型不是一个未完成类型
Widget.cpp
#include <iostream>
#include "Widget.h"
#include "Gadget.h"struct Widget::Impl
{// std::string name;// std::vector<double> data;Gadget g1, g2, g3;
};Widget::Widget(): pImpl(std::make_unique<Impl>())
{
}Widget::~Widget() = default;
Widget::Widget(Widget &&rhs) = default;
Widget &Widget::operator=(Widget &&rhs) = default;
三、使用shared_ptr改写Pimple
unique_ptr存在的问题,shared_ptr都不回存在,因为两者支持自定义删除器的方式不同。