提高C++编译速度-------pimpl 模式& 桥接模式(转)
pimpl 模式(Private Implementation),我们常常听到诸如“不要改动你的公有接口”这样的建议,所以我们一般都会修改私有接口,但是这会导致包含该头文件的所有源文件都要重新编译,这会是个麻烦事儿。Pimpl机制,顾名思义,将实现私有化,力图使得头文件对改变不透明。
桥接模式(bridge)是一种结构型设计模式,它把类的具体实现细节对用户隐藏起来,以达到类之间的最小耦合关系。在具体编程实践中桥接模式也被称为pimpl或者handle/body惯用法,它可以将头文件的依赖关系降到最小,减少编译时间,而且可以不使用虚函数实现多态。
首先,我们先看看不使用这个机制的一个实现:
// MyBase.h
class MyBase {
public:
int foo();
};
// MyDerived.h
#include "MyBase.h"
class MyDerived : public MyBase {
public:
int bar();
};
假设你现在希望在MyBase.h中加入一个新的private和protected成员函数,那么MyDerived和所有包含MyBase.h的源文件都需要重新编译。在一个大工程中,这样的修改可能导致重新编译时间的激增。你可以使用Doxygen或者SciTools看看头文件依赖。
一般来说,不在头文件中包含头文件是一个比较好的习惯,但是这也不能完全消除修改MyBase.h带来的重新编译代价。有没有一个机制可以使得对私有接口做修改时我们可以减小重新编译的代价。
在Pimpl机制中,我们使用前置声明一个Impl类,并将这个类的一个指针实例放入主类中,如下:
// MyClass.h
class MyClassImpl; // forward declaration
class MyClass {
public:
MyClass();
~MyClass();
int foo();
private:
MyClassImpl *m_pImpl;
};
现在,除非我们修改MyClass的公有接口,否则这个头文件是不会被修改了。然后,我们用这个Impl类的实现来完成主类的细节实现,在主类的构造函数中,我们完成了实现类指针的实例化:
// MyClass.cpp
class MyClassImpl {
public:
int foo() {
return bar();
}
int bar() { return var++; }
int var;
}; MyClass::MyClass() : m_pImpl(new MyClassImpl){} MyClass::~MyClass()
{
try {
delete m_pImpl;
}
catch (...) {}
} int MyClass::foo(){ return m_pImpl->foo(); }
Pimpl机制其实这是桥接模式的一种变种。我们可以对实现类随意的进行增删和修改,而不会导致包含MyClass.h的源代码重新编译。当然,这样做的时间开销和空间开销也是有的。
在实践中,我们常常采用内部类来完成Pimpl机制:
首先我们声明一个类sample,它仅向外界暴露了最小的细节,真正的实现在内部类impl,sample用一个shared_ptr来保存它的指针:
class sample
{
private:
class impl; //不完整的内部类声明
shared_ptr<impl> p; //shared_ptr成员变量
public:
sample(); //构造函数
void print(); //提供给外界的接口
}; 在sample的cpp中完整定义impl类和其他功能: class sample::impl //内部类的实现
{
public:
void print()
{ cout << "impl print" << endl;}
}; sample::sample():p(new impl){} //构造函数初始化shared_ptr
void sample::print() //调用pimpl实现print()
{ p->print();}
最后是桥接模式的使用,很简单:
sample s;
s.print();
桥接模式非常有用,它可以任意改变具体的实现而外界对此一无所知,也减小了源文件之间的编译依赖,使程序获得了更多的灵活性。而shared_ptr是实现它的最佳工具之一,它解决了指针的共享和引用计数问题。
提高C++编译速度-------pimpl 模式& 桥接模式(转)的更多相关文章
- iOS进阶--提高XCode编译速度、Xcode卡顿解决方案
提升编译链接的速度主要有以下三个方式: 1. 提高XCode编译时使用的线程数 defaults write com.apple.Xcode PBXNumberOfParallelBuildSubta ...
- java设计模式--结构型模式--桥接模式
桥接模式 概述 将抽象部分与它的实现部分分离,使它们都可以独立地变化. 适用性 1.你不希望在抽象和它的实现部分之间有一个固定的绑定关系. 例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或 ...
- [19/04/26-星期五] GOF23_结构型模式(桥接模式、组合模式)
一.桥接模式(bridge) 场景:商城系统中常见的商品分类,以电脑为例,首先想到使用多层继承结构. —— 台式机(联想台式机.戴尔台式机.神舟台式机) 电脑 ——笔记本(联想笔记本.戴尔笔记本 ...
- VMware网络连接模式——桥接模式、NAT模式以及仅主机模式的介绍和区别
在使用VMware Workstation(以下简称:VMware)创建虚拟机的过程中,配置虚拟机的网络连接是非常重要的一环,当我们为虚拟机配置网络连接时,我们可以看到如下图所示的几种网络连接模式:桥 ...
- vmware三种网络模式:桥接模式|仅主机|NAT模式
VMware 网络模式 1. Bridged(桥接)桥接模式下,宿主机物理网卡(主机网卡)和虚拟网卡通过 VMnet0 虚拟交换机进行桥接,物理网卡和虚拟网卡在拓扑图上处于同等地位,物理网卡和虚拟网卡 ...
- Vmare虚拟机网络连接方式桥接模式+桥接模式+主机模式
虚拟机网络连接模式 最近在学习虚拟机和计算机网络,在网上看了一些关于虚拟机网络连接方式的介绍 这篇文章写的不错:https://www.cnblogs.com/luxiaodai/p/9947343. ...
- Bridge 桥梁模式 桥接模式
简介 将[抽象部分](Abstraction,人)与[实现部分](Implementor,人穿的衣服)分离,使它们都可以独立的变化. [业务抽象角色]引用[业务实现角色],或者说[业务抽象角色]的部分 ...
- 快速提高 Xcode 编译速度的方法(转载自网上一个大神的方法)
1.,中的 Debug Information Format 的选项中选择 DWARF ,平时调试就是用整个选项,经过测试,速度确实有很大的提升,等发行版本的时候在调回 DWARF with dsYM ...
- 【编程思想】【设计模式】【结构模式Structural】桥梁模式/桥接模式bridge
Python版 https://github.com/faif/python-patterns/blob/master/structural/bridge.py #!/usr/bin/env pyth ...
随机推荐
- 解决mysql 1062 主从错误
1062错误----主键冲突,出现这种情况就是从库出现插入操作,主库又重新来了一遍,iothread没问题,sqlthread出错 解决方案: 从库操作 mysql> stop slave; Q ...
- lufylegend库 LTextField
lufylegend库 LTextField <!DOCTYPE html> <html lang="en"> <head> <meta ...
- ConcurrentHashMap原理
转载地址:http://www.blogjava.net/xylz/archive/2010/07/20/326661.html 在上一篇中介绍了HashMap的原理,这一节是ConcurrentMa ...
- opp(Object Oriented Programming)
嗯,昨天忙了一天没来及发,过年啊,打扫啊,什么搽窗户啊,拖地啊,整理柜子啊,什么乱七八糟的都有,就是一个字,忙. 好了,废话也不多说,把自己学到的放上来吧.嗯,说什么好呢,就说原型链啊 原型对象 每个 ...
- [No0000B7]If else 与 三元表达式? : 效率对比
先看 if else 一段代码 using System; class Program { private static void Main() { ; ) i = -; ; Console.Writ ...
- PS切图篇(一)---界面设置
#工作区设置 四大主要面板:信息 字符 图层 历史记录 打开必要属性: 选择工具设置 选择图层的方式:ctrl+鼠标左击想选择的图层
- String,StringBuffer,StringBuilder个人认为较重要的区别
今天在整理不可变对象知识点时,突然看到了String,StringBuffer,StringBuilder三者的区别,这里就挑一些我认为比较重要的点记录一下,方便日后查看. Strin ...
- 分析下为什么spring 整合mybatis后为啥用不上session缓存
因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验 ...
- wpf中子窗口的几个问题
今天研究了一下wpf中的窗口,写这篇文章来总结一下今天的收获.(转载请注明出处~) 总所周知,窗口是windows系统中十分重要的一个元素(从名字上就能体现出来),而一个应用程序总是包含很多窗口(主窗 ...
- js DOM操作---登录例子总结
简单的总结下用 javascript DOM 实现简易登录框例子,下面是简单的模拟登录,没有具体的登录样子,但只是模拟,整理下思路. 页面简单布局,我这个确实太简单了,看代码: <body> ...