美文网首页
前言之Pimpl惯用法

前言之Pimpl惯用法

作者: 麦客Nike | 来源:发表于2018-08-12 18:14 被阅读15次

       最近,在公司移植需求,遇到一些比较有代表性的难题,忽然发现没有足够的知识储备,也设计不出好的解决方案,导致这次移植云升级功能时,严重阻塞产品导入的进度。

        这本书从同事那里了解到,一个Pimpl惯用法让我对这本书产生了浓厚的兴趣,借鉴书中的思想,重构了我的功能,很快问题得到解决,产品为此没有付出更多代价。

        想着,既然要深入学习《C++ API设计》,就这么干看,没有输出也是不好,记录读书笔记,也能加深我的理解,若有幸其他网友通过我的笔记了解到此书,然后深刻阅读此书,提高编程技能,拿到更高薪资,也是极好的。


Pimpl惯用法

         产品中的需求,云升级,设备可以向HTTP服务器查询新版本信息,继而执行升级操作。起初我的重构版本,引入一个Manager类,单例创建对象,图1。

图1

       此管理类,是重构之前更糟糕的代码而来,本以为可保一方平安;开机后start(),无论本地GUI、还是Web只要调用到check(),满足条件后upgrade()即可完成升级。

       但是,问题来临了!客户的所有需求只要移植到新建立分支中,虽两个分支差别不是很大,但有些业务还是新分支也简化,最重要的是新分支,GUI界面抽库了。

       抽库就以为着,本意解耦合,更方便管理。升级功能需要界面能实现完成,GUI点击check,条件满足,点击upgrade即可,再getUpgradeInfo用于显示进度条即可。

       移植过程中,本意想包含Manager类的头文件,即可实现需求移植,但是操作后发现我错了。发生了“头文件包含的爆炸行为“----我给起的名字,因为升级功能之前只在一个库中玩耍,比如libapp.a,所有调用随便玩;现在GUI被移植到libGUI.a,现在我想调用Manager类就要包含头文件,犹豫Manager类复杂,各类功能的引用,想要使用Manager,也就意味需要导入其他模块,这对于只完成页面显示、控件布局库是完全错误操作。

        Manager类,对于跨模块的功能提供是非常不友好。设计之初,松耦合、高内聚概念未考虑到。问题提出就像如何解决此问题,开始之初就想,对于libGUI.a来说,它只需一个Manager头文件即可,其他所有东西都是多余的,它不需要知道Manager类其他细节。

       想法提出就要解决,其实解决这个问题方法还是很多的,组件方式等等。在这个需求中想到了组件的重量级,于是选择了Pimpl惯用法来解决。

       Pimpl,英文pointer to implementation,即指向实现的指针。该技巧避免在公有头文件中暴露私有细节,实现了API接口和实现的完全分离。

图2

在公有类拥有一个私有指针,该指针指向隐藏的实现细节。该方法将实现细节从公有头文件中分离出来。理论知识了解到了,接下来看看,我的需求是如何解决的,图3。

图3

把CCloudUpgradeManagerImp当做CCloudUpgradeManager的私有嵌入类,对外的API只提供几个必要接口,其余细节完全隐藏,而且引用的模块只需包含CCloudUpgradeManager一个头文件即可。

      实现代码部分,图4

图4

对于私有类CCloudUpgradeManagerImp采用初始化列表形式赋初值,析构时同时要delete掉,防止内存泄漏。这是Pimpl法容易出问题的地方,程序员难免会忘记delete,针对这一问题,可引入智能指针,图5

图5

至此,我的问题就解决。功能主体设计没有问题,剩下就是一些细节优化。

以下摘自原文

Pimpl的优点:

1. 信息隐藏。私有成员现在可以完全隐藏在公有接口之外,使得实现细节得以隐藏。头文件也更加干净、清晰便于理解。

2. 降低耦合。 以上文例子为例,两个模块不必再重复包含头文件,把依赖项放到cpp文件中。

3. 加速编译。

4.更好的二进制兼容性。采用Pimpl法的对象大小从不改变,因为对象总是单个指针的大小。实现类的修改只影响cpp实现类的大小。

5.惰性分配。m_cloudImp成员可以在真正使用时才new,(和代码实现有关系),我的例子中不满足此情况。

Pimpl的缺点:

1. 需要手动释放资源。

2. 真正执行的操作,需要中间增加一层指针的间接调用,增加开销。

3. 通过间接访问,增加了阅读代码的难度,同是引入类似m_cloudImp->的前缀,程序员书写代码也变得复杂。

不过就以上说的缺点,对于优点来说,也是说的过去的,凡事都有两面性嘛!

以上就是我对Pimpl的理解,现学现卖,正好他又解决了我的问题。若您看到这篇文章,有不恰当的地方,欢迎批评指正~~~

相关文章

  • 前言之Pimpl惯用法

    最近,在公司移植需求,遇到一些比较有代表性的难题,忽然发现没有足够的知识储备,也设计不出好的解决方案,导致这次移...

  • Pimpl机制

    1.简介 这个机制是Private Implementation的缩写,我们常常听到诸如“不要改动你的公有接口”这...

  • Pimpl机制

    1.简介 这个机制是Private Implementation的缩写,我们常常听到诸如“不要改动你的公有接口”这...

  • 如何提高 C++ 项目的编译速度

    C++ 项目的编译时间一般可以从以下几个角度进行优化: 使用 Pimpl 模式 移动语义替代复制语义 前向声明替代...

  • 《C++ API设计》读书笔记之 《Pimpl惯用法》

    Pimpl是“pointer to implementation”的缩写, 该技巧可以避免在头文件中暴露私有细节。...

  • __bridge的用法

    __bridge作为OC与C语言之间的桥接符号使用, 简单的用法:

  • “前,后”用法

    Ⅰ: Al cabo de ; después de ; tras 在……(时间)之后(tiempo) ⒈Al...

  • 实现一个不抛异常的swap函数

    一个基本的swap函数大概如上所述,但是对某些类型而言。典型比如:pimpl手法(pointer to imple...

  • C语言之memcpy()函数用法

    函数原型 void *memcpy(void*dest, const void *src, size_t n...

  • 【写给梦想的一封情书090/365】

    各类名词前冠词的用法 今日目标:掌握4个小知识点 1. 专有名词前冠词的用法 2.抽象名词前冠词的用法 3. 物质...

网友评论

      本文标题:前言之Pimpl惯用法

      本文链接:https://www.haomeiwen.com/subject/xdvsbftx.html