前提:之前在工作当中遇到一个崩溃问题,由于是一套很老的代码配合新的库,所以导致了引用的库和头文件产生了不匹配的问题,最后还是公司的大佬通过阅读汇编定位到的问题,之前也了解过Qt是如何规避这类问题的,所以写一篇关于D指针和Q指针的文章。
**自己的一些理解:**首先将对外接口和具体实现进行分离,避免具体实现发生变化影响对外接口,造成二进制不兼容的问题(也就是我之前遇到的崩溃问题),通过具体实现类和对外接口类互相持有对方的指针(也就是D指针和Q指针)来实现双方的交互。所以当我们阅读Qt源码的时候,可以通过对外接口类了解该类对外支持的功能(对外接口),但是具体的实现要看实现类中是如何实现功能的。
下面是一些定义和解析:
一、D指针和Q指针的基本概念
D指针和Q指针实际上是类的成员指针变量,分别指向一个私有类(通常称为Private类)对象和一个公有类对象。这种设计模式的核心是将类的实现细节与接口分离,从而减少编译依赖,提高代码的灵活性和可维护性。
- D指针(d_ptr) :
- 定义在公有类中,指向一个私有类对象。
- 私有类对象包含类的所有实现细节和成员变量。
- 通过宏
Q_DECLARE_PRIVATE
和Q_D
在主类中访问私有类对象。
- Q指针(q_ptr) :
- 定义在私有类中,指向一个公有类对象。
- 允许私有类访问公有类的公有接口和成员变量。
- 通过宏
Q_DECLARE_PUBLIC
和Q_Q
在私有类中访问公有类对象。
二、D指针和Q指针解决的问题
- 数据隐藏 :
- 通过将实现细节封装在私有类中,D指针使得公有类的头文件更加简洁,只暴露必要的接口。
- 这有助于隐藏类的内部实现,减少不必要的依赖。
- 二进制兼容性 :
- 当私有类的实现发生变化时,由于公有类的接口保持不变,因此不需要重新编译依赖该公有类的程序。
- 这对于库的维护者来说是一个巨大的优势,因为它允许在不破坏现有代码的情况下进行改进和扩展。
- 减少编译依赖 :
- 由于实现细节被封装在私有类中,因此公有类的头文件不需要包含私有类的头文件。
- 这减少了编译时的依赖关系,提高了编译速度。
三、D指针和Q指针的优缺点
优点:
- 提高代码的可维护性:通过分离接口和实现,使得代码更加清晰和易于维护。
- 增强二进制兼容性:允许在不重新编译依赖程序的情况下修改私有类的实现。
- 减少编译时间:通过减少头文件之间的依赖关系,提高了编译速度。
缺点:
- 增加内存开销:每个公有类对象都需要一个额外的指针来指向私有类对象。
- 复杂性增加:对于初学者来说,理解D指针和Q指针的使用可能需要一些时间。