C++详解PIMPL指向实现的指针

 更新时间:2022年07月25日 10:12:44   作者:litanyuan  
PIMPL 是 C++ 中的一个编程技巧,意思为指向实现的指针。具体操作是把类的实现细节放到一个单独的类中,并用一个指针进行访问

二进制兼容性

①.概述

二进制兼容是指当库文件升级后所有使用该库的应用程序不必重新编译,其本质就是类的内存布局不变。使用 pimpl 方法设计类可以实现二进制兼容的目的。

②.类成员更改后的内存布局

原始类定义:

class demoClass
{
private:
  int a;
  int b;
};

类更改后的定义:

class demoClass
{
private:
  char c;
  int a;
  int b;
};

②.pimpl 下类的内存布局

class demoClass
{
private:
  class demoClassImpl;
  demoClassImpl* impl;
};
class demoClass::demoClassImpl
{
public:
  int a;
  int b;
};

如上图所示,无论类的实现类的数据成员如何变化,类的布局始终不变。

功能实现细节隐藏

①.概述

作为接口的提供者,我们希望接口的使用者不必知道接口实现的更多细节,因为根据类的私有数据成员和方法一般就可以猜测出接口的设计方式。

②.隐藏实现细节

通过 pimp 方法设计类可以实现隐藏类的私有成员和方法的目的,仅对外暴露公有的接口。

class demoClass
{
public:
  void func();//对外接口
private:
  class demoClassImpl;
  demoClassImpl* impl;
};
class demoClass::demoClassImpl
{
private:
  int a;
  int b;
  void func1();
  void func2();
public:
  void func();
};
void demoClass::func()
{
  impl->func();
}

编译依赖

①.概述

在一个常用的头文件中如果包含了太多其他不必要的头文件会严重降低编译效率。

②.值类型的成员必须引用其头文件

值类型的成员因为要分配内存大小必须知道其确定的定义,需要包含其头文件

#include "A.h"
class demoClass
{
  A a;
};

如果仅有类的申明则会出错:

class A;
class demoClass
{
  A a;
};

③.指针或者引用类型,仅需要类的申明

class A;
class demoClass
{
  A *a;
};

④.函数的参数和返回值类型,仅需要类的申明

class A;
class demoClass
{
  A  func(A a);
};

⑤.使用 pimpl 降低编译依赖

一般库文件使用者仅需要包含当前库对应的头文件即可,不应该再包含其他的头文件。假设库的头文件定义如下:

#include "A.h"
class demoClass
{
private:
  A a;
public:
  void func();
};

此时,若 A 为另外一个公共库,则库的使用者需要在项目中配置 A.h 的路径;若 A 为自定义类,则库的提供者还需要额外提供 A.h 文件。

使用 pimpl 方法改进则可以减少编译依赖,仅在类的实现文件中包含头文件即可:

// demoClass.h
class demoClass
{
public:
  void func();//对外接口
private:
  class demoClassImpl;
  demoClassImpl* impl;
};
// demoClass.cpp
#include "A.h"
class demoClass::demoClassImpl
{
private:
  A a;
public:
  void func();
};

动态配置功能的实现方法

①.概述

使用 pimpl 的方式把类的功能实现用另外一个独立的类来完成,可以在需要的时候动态的配置类的实现方法,而保持类的接口不变。

②.代码示例

公共接口类:

class demoClassImpl;
class demoClass
{
public:
    void func();//对外接口
public:
    demoClassImpl* impl;
};
void demoClass::func()
{
    impl->func();
}

功能实现抽象类:

class demoClassImpl
{
public:
    virtual void func() = 0;
};

功能实现派生类:

class demoClassImpl1 : public demoClassImpl
{
public:
    void func() { cout << "实现方式1" << endl; }
};
class demoClassImpl2 : public demoClassImpl
{
public:
    void func() { cout << "实现方式2" << endl; }
};

功能实现方式的动态配置:

demoClass* demo = new demoClass;

demoClassImpl1* impl1 = new demoClassImpl1;
demo->impl = impl1;
demo->func();

demoClassImpl2* impl2 = new demoClassImpl2;
demo->impl = impl2;
demo->func();

到此这篇关于C++详解PIMPL指向实现的指针的文章就介绍到这了,更多相关C++ PIMPL内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言main函数的参数及其返回值详细解析

    C语言main函数的参数及其返回值详细解析

    main函数的返回值用于说明程序的退出状态。如果返回0,则代表程序正常退出;返回其它数字的含义则由系统决定。通常,返回非零代表程序异常退出
    2013-10-10
  • vscode使用cmake时将命令行参数传递给调试目标的方法

    vscode使用cmake时将命令行参数传递给调试目标的方法

    这篇文章主要介绍了vscode使用cmake时将命令行参数传递给调试目标,下面介绍了一个示例,将参数first_arg, second-arg和third arg传递给程序(此处需要注意,third arg中间虽然存在空格,但是仍然被视作一个参数),需要的朋友参考下吧
    2024-03-03
  • c语言 两字符串交叉合并实例

    c语言 两字符串交叉合并实例

    今天小编就为大家分享一篇c语言 两字符串交叉合并实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • C++中string类的常用方法实例总结

    C++中string类的常用方法实例总结

    string类是C++提供的抽象数据类型,其支持可变长字符串,下面这篇文章主要给大家总结介绍了关于C++中string类的常用方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • C++ 单例模式的详解及实例

    C++ 单例模式的详解及实例

    这篇文章主要介绍了C++ 单例模式的详解及实例的相关资料,这里对单例中的懒汉模式和饿汉模式进行实现和比较,需要的朋友可以参考下
    2017-07-07
  • 为什么要学习C语言 C语言优势分析

    为什么要学习C语言 C语言优势分析

    不止一个学生问到我:“老师,为什么我们的应用程序设计要学C语言而不是别的?C语言不是已经过时了吗?如果现在要写一个Windows程序,用VB或Dephi开发多快呀,用C行吗?退一万步,为什么选择C而不是C++呢?”
    2013-07-07
  • 讲解C++中的枚举类型以及声明新类型的方法

    讲解C++中的枚举类型以及声明新类型的方法

    这篇文章主要介绍了讲解C++中的枚举类型以及声明新类型的方法,是C预言入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++读写ini配置文件实现过程详解

    C++读写ini配置文件实现过程详解

    这篇文章主要介绍了C++读写ini配置文件实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • C++类和对象实战之Date类的实现方法

    C++类和对象实战之Date类的实现方法

    C++ 标准库没有提供所谓的日期类型,C++ 继承了C语言用于日期和时间操作的结构和函数,这篇文章主要给大家介绍了C++类和对象实战之Date类的实现方法,需要的朋友可以参考下
    2021-12-12
  • C语言 八大排序算法的过程图解及实现代码

    C语言 八大排序算法的过程图解及实现代码

    排序是数据结构中很重要的一章,本文主要为大家介绍了常用的八个排序算法(插入,希尔,选择,堆排,冒泡,快排,归并,计数)的过程及代码实现,需要的朋友可以参考一下
    2021-12-12

最新评论