Pimpl常用法

对于规模较大的C++项目,头文件的互包含和互依赖关系经常困扰开发者.例如:
class foo
{
public:
foo();
void method_foo_b(const foo_a& b);
private:
void method_foo_c(const foo_b& c);
private:
foo_b b_;
foo_c c_;
};

int main(...)
{
foo fooi;
}
如果要使得main或者一个必须包含foo的class通过编译,则不仅需要包含foo头文件,还必须包含foo_b, foo_c的头文件.而实际上foo_b, foo_c是foo内部使用的类,完全不需要外部调用着关心.而且这样做带来两个问题:
1. 大量的依赖包含或者互包含带来更多的编译错误和更长的编译时间,对于大项目,其编译时间可能让人无法承受.
2. 实际上暴露了部分内部实现,违背OO封装的原则.

有些人通过继承纯续接口类的方法解决,但对于实际上并不存在多态概念的类而言,使用续基类来封装接口完全是多余的,增加不必要的虚函数开销和维护开销.
Pimpl用了只有一个实现的Bridge模式解决了这一问题.
class foo
{
public:
foo();
void method_foo_b(const foo_a& b);
private:
struct Pimpl;
boost::scoped_ptr pimpl_ptr_;
};
只出现公有接口,自己用的私有函数和成员变量完全被隐藏.
struct foo::Pimpl
{
void method_foo_b(const foo_a& b) {...};
void method_foo_c(const foo_b& c) {...};
}
void foo::method_foo_b(const foo_a& b)
{
pimpl_ptr_->method_foo_b(b);
}

个人经验,使用Pimpl有几个需要注意的地方,
1. 不要滥用,终究还是增加了一个间接的层次,尽量只在模块的边界使用.
2. 对于内部操作比较复杂的类, 应该把操作移到pimpl里执行,对于非常简单的类,可以只在pimpl里存放成员变量.

时间: 2024-09-20 14:57:25

Pimpl常用法的相关文章

网站优化常用法归纳(上)

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 俗话说,事出必有因,一个网站能够成功,一个网站能够得到好的效果,这跟网站的各大因素是分不开的,者在这里就归纳一下通常网站中的优化常用方法和网站中的相关因素. 服务器因素: 1.服务器的地区分布影响排名,不同地区的服务器会影响到搜索结果,这样就解释了网站的区域性,为何 不同的地方搜索结果会不一样.以王通老师举的一个例子例子来说,如果做的是英文网

最好的朋友:C++11移动语义和Pimpl手法

当编译器可以用廉价的挪动操作替换昂贵的复制操作时,也就是当它可以用一个指向一个大对象的指针的浅层复制来替换对这个大对象的深层复制的时候,挪动语义要比复制语义更快速.因此,在类中利用 PIMPL方法 结合挪动语义,应该能预见到有相当大的速度提升.由于QT对于每个非常规类都采用PIMPL方法,因此通过简单地使用Qt类而不是与它们对应的STL,我们应该可以看到速度有很大的提升.我将会对使用了挪动语义,应用和没有应用PIMPL方法的Qt和STL类进行比较. 使用了挪动语义和 PIMPL 方法的一个类 在

T-SQL设计模式详解

一.ITERATOR(迭代) 这种模式提供一种在相似对象列表中遍历对象的标准化方法.在SQL Server数据库中的同义词是游标. DECLARE tables CURSOR FOR select TABLE_NAME FROM INFORMATION_SCHEMA.TABLES FOR READ ONLY DECLARE @table varchar(40) OPEN tables FETCH tables INTO @table WHILE (@@FETCH_STATUS = 0) BEGI

使用 GUID 值来作为数据库行标识讲解_MsSql

GUID(Global unique identifier)全局唯一标识符,它是由网卡上的标识数字(每个网卡都有唯一的标识号)以及 CPU 时钟的唯一数字生成的的一个 16 字节的二进制值. GUID 的格式为"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字.例如:6F9619FF-8B86-D011-B42D-00C04FC964FF 即为有效的 GUID 值. 世界上的任何两台计算机都不会

STL区间成员函数及区间算法总结_C 语言

在这里总结下可替代循环的区间成员函数和区间算法: 相比单元素遍历操作,使用区间成员函数的优势在于: 1)更少的函数调用 2)更少的元素移动 3)更少的内存分配 在区间成员函数不适用的情况下也应该使用区间算法,至少,相比手写循环而言,它更加简单,有效,并且不容易出错: 区间成员函数 区间构造 标准容器都支持区间构造函数: 复制代码 代码如下: container::container(InputIterator begin, // 区间的起点                   InputIter

C++基本功:全面掌握const、volatile和mutable关键字

   C++ 程式设计过程中 ,const 的使用可以频度是非常高的 . 它在保证程式安全方面起到了不可估量的作用 .用一句话来表达最确切不过了:"小兵立大功" .    有了 const, 那么 mutable 当然缺不了 .    然作为 const 的同胞兄弟 ,volatile 却在很多人的视野中消失 . 其实 volatile 担负的责任有何尝小呢 ?    自然 , 它们的用法多样而灵巧 , 以至新手迷惑久久 , 下面就来系统的探讨总结一下吧: 一 . 一般应用 1.con

C# GUID介绍和的使用

GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成GUID的API.生成算法很有意思,用到了以太网卡地址.纳秒级时间.芯片ID码和许多可能的数字.GUID的唯一缺陷在于生成的结果串会比较大. GUID永远是方便的;对于程序开发的各个方面,.NET Framework简化了建立和处理GUID数值的过程.在.NET程序需要的地方,这一功能很容易地生成唯一的数值. 1. 一个GUID为一个128位的整数(16字节),在使用唯一标识符的情况

Hadoop MapReduce:数据科学家探索之路

Forrester分析师James Kobielus在一篇关于"大数据"的博客中指出:"关键不在于采用什么方法,而在于能够使用任意可用工具或方法真正地解决问题." 近几年在解决大数据问题的迫切感驱使下,许多组织的数据架构师开始走向探索之路.简单而言,他们通常用于分析企业数据的传统数据库和商业智能工具已经无法胜任大数据处理任务. 要理解这个挑战,必须回到十年前:当时很少有TB级的企业数据仓库.Forrester分析报告指出,在2009年之前,有三分之二的企业数据仓库(

《C++覆辙录》——1.8:未能区分可访问性和可见性

1.8:未能区分可访问性和可见性 C++语言压根儿没有实现什么数据隐藏,它实现了的是访问层级.在class中具有protected和private访问层级并非不可见,只是不能访问罢了.如同一切可见而不可及的事物一样(经理的形象跃入脑海),他们总是惹出各种麻烦. 最显而易见的问题就是即使是class的实现仅仅更改了一些貌似不可见的部分,也会带来必须重新编译代码的苦果.考虑一个简单的class,我们为其添加一个新的数据成员: class C { public: C( int val ) : a_(