如何解决PIMPL 成语真的在实践中使用吗??
所以,我想知道这种技术是否真的在实践中使用?我应该在任何地方使用它,还是谨慎使用?
当然是用的。我在我的项目中使用它,几乎在每一堂课中。
使用 PIMPL 成语的原因:
二进制兼容性
在开发库时,您可以添加/修改字段,XImpl
而不会破坏与客户端的二进制兼容性(这意味着崩溃!)。由于向X
类添加新字段时类的二进制布局不会改变Ximpl
,因此在次要版本更新中向库添加新功能是安全的。
当然,您也可以在不破坏二进制兼容性的情况下向X
/添加新的公共/私有非虚拟方法XImpl
,但这与标准头文件/实现技术相当。
数据隐藏
如果您正在开发一个库,尤其是专有库,最好不要透露使用了哪些其他库/实现技术来实现您的库的公共接口。要么是因为知识产权问题,要么是因为您认为用户可能会倾向于对实现做出危险的假设,或者只是通过使用可怕的铸造技巧来破坏封装。PIMPL
解决/减轻了这个问题。
编译时间
编译时间减少了,因为当您向类添加/删除字段和/或方法(映射到在标准技术中添加私有字段/方法)时,只X
需要重建源(实现)文件。XImpl
在实践中,这是一种常见的操作。
使用标准标头/实现技术(没有 PIMPL),当您向
中添加新字段时,需要重新编译X
曾经分配过的每个客户端(无论是在堆栈上还是在堆上),因为它必须调整分配的大小。X
好吧,每个不分配 X 的客户端 也
需要重新编译,但这只是开销(客户端的结果代码将是相同的)。
更重要的是,即使在添加和更改XClient1.cpp
私有方法时,也需要重新编译标准头/实现分离,即使出于封装原因不可能调用此方法!像上面一样,它是纯粹的开销,并且与现实生活中的
C++ 构建系统的工作方式有关。X::foo()``X``X.h``XClient1.cpp
当然,当您只修改方法的实现时不需要重新编译(因为您不触摸标题),但这与标准标题/实现技术相当。
是否建议将此技术用于嵌入式系统(性能非常重要)?
这取决于你的目标有多强大。然而,这个问题的唯一答案是:衡量和评估你的得失。此外,请注意,如果您不发布旨在供客户在嵌入式系统中使用的库,则仅适用于编译时间优势!
解决方法
我正在阅读 Herb Sutter 的 “Exceptional C++” 一书,在那本书中我了解了 PIMPL 习语。基本上,这个想法是为 a
的private
对象创建一个结构class
并动态分配它们以 减少编译时间 (并以更好的方式隐藏私有实现)。
例如:
class X
{
private:
C c;
D d;
} ;
可以改为:
class X
{
private:
struct XImpl;
XImpl* pImpl;
};
并且,在 .cpp 文件中,定义:
struct X::XImpl
{
C c;
D d;
};
这看起来很有趣,但我以前从未见过这种方法,无论是在我工作过的公司中,还是在我看过源代码的开源项目中。所以,我想知道这种技术是否真的在实践中使用。
我应该在任何地方使用它,还是谨慎使用?是否建议将此技术用于嵌入式系统(性能非常重要)?