【C++程序设计技巧】Pimpl机制

简介: 作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.简介 这个机制是Private Implementation的缩写,我们常常听到诸如“不要改动你的公有接口”这样的建议,所以我们一般都会修改私有接口,但是这会导致包含该头文件的所有源文件都要重新编译,这会是个麻烦事儿。

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

1.简介

这个机制是Private Implementation的缩写,我们常常听到诸如“不要改动你的公有接口”这样的建议,所以我们一般都会修改私有接口,但是这会导致包含该头文件的所有源文件都要重新编译,这会是个麻烦事儿。Pimpl机制,顾名思义,将实现私有化,力图使得头文件对改变不透明。

2.机制分析

首先,我们先看看不使用这个机制的一个实现:

 
  1: // MyBase.h
  2: class MyBase {
  3: public:
  4:   int foo();
  5: };
  6: 
  7: // MyDerived.h
  8: #include "MyBase.h"
  9: class MyDerived : public MyBase {
 10: public:
 11:   int bar();
 12: };

假设你现在希望在MyBase.h中加入一个新的private和protected成员函数,那么MyDerived和所有包含MyBase.h的源文件都需要重新编译。在一个大工程中,这样的修改可能导致重新编译时间的激增。你可以使用Doxygen或者SciTools看看头文件依赖。

一般来说,不在头文件中包含头文件是一个比较好的习惯,但是这也不能完全消除修改MyBase.h带来的重新编译代价。有没有一个机制可以使得对私有接口做修改时我们可以减小重新编译的代价。

在Pimpl机制中,我们使用前置声明一个Impl类,并将这个类的一个指针实例放入主类中,如下:

 
  1: // MyClass.h
  2: class MyClassImpl;    // forward declaration
  3: class MyClass {
  4: public:
  5:   MyClass();
  6: ~MyClass();
  7:   int foo();
  8: private:
  9:   MyClassImpl *m_pImpl;
 10: };

现在,除非我们修改MyClass的公有接口,否则这个头文件是不会被修改了。然后,我们用这个Impl类的实现来完成主类的细节实现,在主类的构造函数中,我们完成了实现类指针的实例化:

 

 
  1: // MyClass.cpp
  2: class MyClassImpl {
  3: public:
  4: int foo() {
  5:         return bar();
  6: }
  7: int bar() { return var++; }
  8:         int var;
  9: };
 10: 
 11: MyClass::MyClass() : m_pImpl(new MyClassImpl){}
 12: 
 13: MyClass::~MyClass()
 14: {
 15:     try {
 16:             delete m_pImpl;
 17:     }
 18:     catch (...) {}
 19: }
 20: 
 21: int MyClass::foo(){ return m_pImpl->foo(); }

Pimpl机制其实这是桥接模式的一种变种。我们可以对实现类随意的进行增删和修改,而不会导致包含MyClass.h的源代码重新编译。当然,这样做的时间开销和空间开销也是有的。

在实践中,我们常常采用内部类来完成Pimpl机制:

 
  1: // header
  2: class fruit
  3: {
  4: public: 
  5: 
  6: private:
  7: class impl;
  8: impl* pimpl_;
  9: } 
 10: 
 11: // implementation
 12: class fruit::impl
 13: { 
 14: 
 15: }; 
 16: 
 17: fruit::fruit()
 18: {
 19: pimpl_ = new impl();
 20: }


               作者:gnuhpc
               出处:http://www.cnblogs.com/gnuhpc/
               除非另有声明,本网站采用知识共享“署名 2.5 中国大陆”许可协议授权。


分享到:

目录
相关文章
|
2月前
|
设计模式 算法 测试技术
C++ 创建兼容多个IPC机制的上层接口
C++ 创建兼容多个IPC机制的上层接口
60 1
|
2月前
|
安全 算法 程序员
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
49 0
|
2月前
|
设计模式 编译器 API
【C/C++ Pimpl模式】隐藏实现细节的高效方式 (Pimpl Idiom: An Efficient Way to Hide Implementation Details)
【C/C++ Pimpl模式】隐藏实现细节的高效方式 (Pimpl Idiom: An Efficient Way to Hide Implementation Details)
73 1
|
14天前
|
存储 C++
C++ 异常处理机制详解:轻松掌握异常处理技巧
C++ 异常处理提供结构化错误管理,增强程序健壮性。通过`throw`抛出异常,`try-catch`捕获并处理。示例展示了当年龄小于18时抛出异常。优点包括提高健壮性和代码可维护性,但可能降低性能并复杂化代码。另外,介绍了四种在C++中相加两个数的方法,包括使用运算符、函数、类、STL函数和lambda表达式。
20 0
|
18天前
|
安全 编译器 C++
C++从入门到精通:3.2异常处理——掌握C++的异常处理机制,提高程序健壮性
C++从入门到精通:3.2异常处理——掌握C++的异常处理机制,提高程序健壮性
|
1月前
|
存储 C++
C++ 栈和堆的作用机制,及特点区别
在介绍C++中的十分重要的动态内存管理机制之前,有必要先单独来介绍一下C++中的两个概念,分别是栈和堆。
19 2
|
2月前
|
传感器 安全 程序员
【C++多线程 同步机制】:探索 从互斥锁到C++20 同步机制的进化与应用
【C++多线程 同步机制】:探索 从互斥锁到C++20 同步机制的进化与应用
103 1
|
2月前
|
编译器 程序员 C++
【C/C++ 容器操作】C++高效编程:掌握emplace_back与push_back的使用和机制
【C/C++ 容器操作】C++高效编程:掌握emplace_back与push_back的使用和机制
70 0
|
2月前
|
Linux 程序员 C++
【C++ 常见的异步机制】探索现代异步编程:从 ASIO 到协程的底层机制解析
【C++ 常见的异步机制】探索现代异步编程:从 ASIO 到协程的底层机制解析
146 2
|
2月前
|
存储 编译器 C++
从Proto到C++:探索Protocol Buffers的强大转换机制
从Proto到C++:探索Protocol Buffers的强大转换机制
262 4