pimpl (the pointer-to-implementation idiom)手法在 C++ 里已是“高手”们广泛运用的成熟方法之一,它的优点很多,诸如降低编译依赖、提高重编译速度之类的工具性优势自不待赘言,而其对“保持接口稳定性”的优点更值得称道。

It makes it possible to avoid other classes to know internal data structures and other information of the class. It also simplifies some#includepreprocessor instructions.避免别的class知道其内部的数据结构。还可以简化预编译指令。

pImpl方法是微软的Herb Sutter提出来的,该方法是为了尽量减小接口和实现之间的耦合,以避免接口改动对程序重新编译等带来的影响。简单来说,如果你的大型程序因为复杂的头文件包含关系,使得你对某头文件的某小改动可能引起的巨大编译时间成本望而生畏,那么你需要用pImpl方法来改善这种处境。

下面看两个代码示例。

1、

#include "classA.h"

class B

{

classA a;

};

2、

class classA;

class B

{

 classA* pa;

};

这两个代码都是对classB的声明,可能会在我们工程的classB.h文件中。它们唯一的不同是1直接引用了classA.h头文件,并声明了classA类型的变量a;而2是通过"class classA;"这句进行classA的声明,然后声明了一个classA类型的指针变量pa,很明显,在2的classB.cpp文件中,需要添加#include "classA.h"。

我们来看看1会发生什么事情。如果你的classB.h文件又被其他头文件classC.h引用,而classC.h又被classD.h文件引用,当你的工程足够复杂,你的头文件之间的引用可能会非常杂乱,问题会随之出现,比如重复引用(幸好我们有#ifdef和#pragma once等方法帮我们解决问题),比如交叉引用(a引用b,b引用a,头疼),还有可能引用一些本不需要的头文件。如果你觉得这些问题都可以忽略,那么当你需要改动classA的声明时,不能忽略的问题来了,所有引用该文件的cpp文件都需要重新编译,对于大型工程,这个编译时间成本有时是不能忽略的。你总不能每改动一次classA,就把几乎大部分代码重新编译一次吧,对于开发和调试来说,这几乎不能忍受。

在1中,classA a语句必须要求引用classA的声明,以便给a变量分配空间;而2中的classA* pa语句则不需要知道classA的具体声明,因为任何指针所占用的空间都是一定的。这样,classB与classA之间就没有了耦合,classA的任何改动,对于classB来说都没有影响,除非classB修改了对classA调用的代码。在这里,指针起到了解耦合的作用。

pImpl方法是应该被提倡应用的,如果运用的恰当,对于工程开发、维护和编译都能起到正面作用,对于这种编码习惯,是需要我们在平时就注意培养的。

 

【转】一个非常常见但容易被忽略的c++问题——用IPML模式可以解决的更多相关文章

  1. 一个linux常见命令的列表

    这是一个linux常见命令的列表. 那些有• 标记的条目,你可以直接拷贝到终端上而不需要任何修改,因此你最好开一个终端边读边剪切&拷贝. 所有的命令已在Fedora和Ubuntu下做了测试 命 ...

  2. SQL报了一个不常见的错误,让新来的实习生懵了

    摘要:前些天一个很简单的SQL报了一个不常见的错误. 本文分享自华为云社区<记一次mysql关联查询格式冲突问题[五月04]>,作者: KevinQ . 问题起源 作为CRUD程序员,最常 ...

  3. Git忽略规则及.gitignore规则不生效的解决办法

    在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如无,则需自己手工建立此文件).这个文件每一行保存了一个匹配的规则例如: # 此为注 ...

  4. Git忽略规则和.gitignore规则不生效的解决办法

    Git忽略规则和.gitignore规则不生效的解决办法   Git忽略规则: 在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如果 ...

  5. asp.net使用post方式action到另一个页面,在另一个页面接受form表单的值!(报错,已解决!)

    原文:asp.net使用post方式action到另一个页面,在另一个页面接受form表单的值!(报错,已解决!) 我想用post的方式把一个页面表单的值,传到另一个页面.当我点击Default.as ...

  6. 一个奇葩常见的问题 nginx 403 forbidden错误

    今天安装dedecms,配置Nginx,然后生成一键生成静态页面,然后就没有然后了,所有栏目页面都显示nginx 403 forbidden. 一般来说nginx 的 403 Forbidden er ...

  7. SQL Server 完整备份遇到的一个不常见的错误

    1. 错误详情 有一次在手动执行数据库完整备份时遇到如下错误: 执行多次都是这个错误信息. 提示无法生成检查点,原因可能是由于系统资源(如磁盘或内存空间)不足或者有时是由于数据库损坏而造成的. 我们检 ...

  8. Unity3D 一个较常见的错误信息“rect[2] == rt->GetGLWidth() && rect[3] == rt->GetGLHeight()”

    rect[2] == rt->GetGLWidth() && rect[3] == rt->GetGLHeight() 这个错误信息的具体含义我还不太清楚.它出现以后会不停 ...

  9. Android记录一个setTextColor常见的一个bug

    今天写代码 一不小心就犯了个错误. 细致检查才发现,仅记录一下,防止各位同学犯相同的错误哦 代码例如以下: remote.setTextColor(summaryId, R.color.news_ha ...

随机推荐

  1. [OpenCV] Install openCV in Qt Creator

    Learn openCV.pdf qmake: link with opencv (Key Point) QT += core gui greaterThan(QT_MAJOR_VERSION, 4) ...

  2. Linux动态库的搜索路径

    下面是目录结构: pengdl@localhost:~$ tree test/test/├── fun.c├── Fun.h└── t1    └── main.c 1 directory, 3 fi ...

  3. HMM 自学教程(六)维特比算法

    本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...

  4. Linux - 进程状态

    ps report a snapshot of the current processes. 能提供一份当前进程的快照,以列表的形式显示正在运行的进程. 列出进程的数量取决于命令所附加的参数,例如:p ...

  5. 设计师必备!免费下载 PSD 素材的32个网站

    今天我想和大家分享一组可以免费下载 PSD 图形素材的最好的网站. PSD 文件是非常有用的资源,因为你可以看到所有的层,使用了什么技术来创建出这些作品和效果. 某些列出的网站可能已是众所周知的,但你 ...

  6. 继续谈论XSS

    这篇文章基于上篇谈论XSS ,想说下自己工作过程中遇到的xss的问题. 易出现XSS的场景 1 jsonp 说说jsonp 中也有说过,jsonp其实是很容易出现安全问题的.由于jsonp的callb ...

  7. Repository模式中,Update总是失败及其解析

    在Repository模式中,我的Update方法总是无法更新实体,这个非常郁闷,Update方法如下: 1: public virtual void Update(T entity) 2: { 3: ...

  8. thread_Exchanger数据交换

    Exchanger 是一个同步辅助类,用于两个并发线程之间在一个同步点进行数据交换.  允许两个线程在某一个点进行数据交换. 可以视作双向的同步队列: 可应用于基因算法.流水线设计等场景 Exchan ...

  9. Free Slideshow, Gallery And Lightboxes Scripts

    http://bootstraphelpers.codeplex.com/SourceControl/list/changesets https://github.com/gordon-matt/Bo ...

  10. DistributedCache小记

    一.DistributedCache简介 DistributedCache是hadoop框架提供的一种机制,可以将job指定的文件,在job执行前,先行分发到task执行的机器上,并有相关机制对cac ...