【C++】Pimpl设计思想分析

Pimpl设计思想

前言

Pimpl Idiom (Pointer to implementation, 指向实现的指针) 设计模式的核心思想是将类的实现细节隐藏在一个独立的内部类,这样就减少了编译依赖且增强二进制兼容性。这种开发模式也被称之为D-Pointer (D指针)

特点

  • 编译依赖性 : 如果类的实现 (成员变量,私有方法之类的) 频繁的迭代变动,那不可避免的会导致头文件也会随着变更,导致所有的包含该头文件的代码都需要通过重新编译被使用。如果将细节移动到一个Private类且定义在对应的.cpp文件中,头文件就只需要声明一个指针,避免了暴露实现细节;最后只需要重新编译被变动的.cpp文件之后就可以加载到所用模块。
  • 更好的封装 : 头文件最后只暴露了一个接口,符合《最小暴露原则》。工程师也无法直接访问Private类的成员,只保留公有方法提供操作。
  • 二进制兼容 : 如果库中的私有成员有变动 (例如:不需要使用名称了,添加了新的年龄属性和ID属性) 且保证Private类的指针大小不变就能保证库的二进制链接接口(ABI)可以稳定,能保证动态链接库(dll/so)升级稳定兼容。

例如:

//object.h
class Object {
	private:
	class Private;
	Private* _Prv_ptr;
}
//或者
#define DECLARE_PRIVATE_OBJECT class Private; Private* _Prv_ptr;
class Object {
	DECLARE_PRIVATE_OBJECT
}
//更先进的方案
class Object {
private:
struct Private;
std::unique_ptr<Private> m_private;
}
/******************************************/

//object.cpp
class Object::Private {
	std::string name;
	//...
}

Pimpl怎么保证ABI稳定?

变化类型无Pimpl有Pimpl
修改私有成员变量头文件被改动仅仅更改.cpp,依赖项无需重新编译
新增&删除私有成员变量ABI破坏(所占内存变更)ABI稳定(指向的指针大小不变)
修改私有方法头文件被改动仅仅更改.cpp,依赖项无需重新编译

指向实现的D指针,他只是一个指针(32位系统上是4B,64位系统上是8B);无论这个Iimpl类内部如何变化,都保证了所指向的指针不会变;

Pimpl的缺点

  • 访问开销:每次访问私有变量都需要通过D指针跳转(忽略不计)
  • 内存管理:持有了PImpl的D指针就需要负责到底生命周期 (可以通过std::unique_ptr < Private > 解放大脑)

身边的影子

Qt的QPointer广泛使用类似的Q_DECLARE_PRIVATE设计模式

QT宏: Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC(d指针 \ p指针) 及其优化使用Q_Q宏和Q_D宏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值