
PImpl idiom(Pointer to Implementation)是一种常用的C++编程技巧,用来隐藏类的实现细节并减少编译依赖。它的核心思想是将类的具体实现移到一个独立的、不公开的结构体或类中,并通过一个指针在主类中引用它。这样,即使实现发生变化,只要接口不变,使用该类的代码就不需要重新编译。
PImpl 是 "Pointer to Implementation" 的缩写,也被称为“桥接模式”的简化版本。它通过在头文件中只声明一个前向声明的类和一个指向其实现的指针,把所有私有成员变量和实现细节从头文件移到源文件中。
例如,一个普通的类可能在头文件中暴露大量包含其他类的头文件,导致依赖复杂:
// widget.h
#include <string>
#include <vector>
#include "big_object.h"
<p>class Widget {
public:
Widget();
void do<em>something();
private:
std::string name</em>;
std::vector<int> data_;
BigObject heavy<em>obj</em>;
};</p>每次修改BigObject或私有成员,所有包含widget.h的文件都要重新编译。而使用PImpl后:
立即学习“C++免费学习笔记(深入)”;
// widget.h
class Widget {
public:
Widget();
~Widget(); // 注意:需要定义析构函数
void do_something();
private:
class Impl; // 前向声明
Impl* pImpl_; // 指向实现
};
// widget.cpp
#include "widget.h"
#include <string>
#include <vector>
#include "big_object.h"
<p>class Widget::Impl {
public:
std::string name<em>;
std::vector<int> data</em>;
BigObject heavy<em>obj</em>;
};</p><p>Widget::Widget() : pImpl<em>(new Impl) {}
Widget::~Widget() { delete pImpl</em>; }
void Widget::do<em>something() {
// 使用 pImpl</em>->...
}</p>头文件是编译依赖的主要来源。当一个头文件被修改,所有包含它的翻译单元都必须重新编译。PImpl 把对具体类型的依赖从头文件转移到了实现文件中。
好处包括:使用PImpl需要注意资源管理和特殊成员函数的定义。
关键点:std::unique_ptr代替原始指针,避免内存泄漏改进版本:
// widget.h
#include <memory>
<p>class Widget {
public:
Widget();
~Widget;
Widget(const Widget&);
Widget& operator=(const Widget&);
Widget(Widget&&);
Widget& operator=(Widget&&);</p><pre class='brush:php;toolbar:false;'>void do_something();private: class Impl; std::uniqueptr<Impl> pImpl; };
std::unique_ptr可以在头文件中完成删除器的定义,因此即使Impl是前向声明,也能合法释放资源。
PImpl 特别适合接口稳定但实现频繁变动的类,如库开发、大型项目中的模块封装。
优点:因此,是否使用PImpl应权衡项目规模、编译时间与性能要求。
基本上就这些。PImpl idiom 是一个实用的C++惯用法,尤其在大型项目中能显著改善构建性能和模块化程度。合理使用,能让代码更健壮、更易维护。
以上就是C++中的PImpl idiom是什么_C++减少编译依赖与隐藏实现细节的编程技巧的详细内容,更多请关注php中文网其它相关文章!
编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号