【Qt】d_ptr指针、p_ptr指针详解

此文章可以参考:
Pimpl技术的基本应用
PImpl机制以及Qt的D-Pointer实现
Qt的d_ptr本质上使用了pimp技术

D指针

保持一个库中的所有公有类的大小恒定的问题可以通过单独的私有指针给予解决。这个指针指向一个包含所有数据的私有数据结构体。这个结构体的大小可以随意改变而不会产生副作用,应用程序只使用相关的公有类,所使用的对象大小永远不会改变,它就是该指针的大小。这个指针就被称作D指针。

/* widget.h */
// 私有数据结构体声明。 其定义会在 widget.cpp 或是
//  widget_p.h,总之不能在此头文件
class   WidgetPrivate; 
 
class   Widget {
   
   
   ...
   Rect geometry()const;
   ...
private:
   // d指针永远不能在此头文件中被引用
   //  由于WidgetPrivate没有在此头文件中被定义, 
   // 任何访问都会导致编译错误。
   WidgetPrivate *d_ptr;
}; 
 
/* widget_p.h */(_p 指示private)
struct WidgetPrivate {
   
   
    Rect geometry;
    String stylesheet;
}; 
 
/* widget.cpp */
#include "widget_p.h"
Widget::Widget() 
    : d_ptr(new WidgetPrivate)// 初始化 private 数据 {
   
   
} 
 
Rect Widget::geoemtry()const{
   
   
    // 本类的d指针只能被在自己的库内被访问
    return d_ptr->geometry;
} 
 
/* label.h */
class   LabelPrivate;
class  Label :publicWidget {
   
   
   ...
   String text();
private:
   // 自己类对应自己的d指针
   LabelPrivate *d_ptr;
}; 
 
/* label.cpp */
// 这里将私有结构体在cpp中定义
struct LabelPrivate {
   
   
    String text;
}; 
  
Label::Label() 
    : d_ptr(new LabelPrivate) {
   
   
} 
 
String Label::text() {
   
   
    return d_ptr->text;
} 

有了上面的结构,CuteApp就不会与d指针直接打交道。因为d指针只能在WidgetLib中被访问,在每一次对Widget修改之后都要对其重新编译,私有的结构体可以随意更改,而不需要重新编译整个工程项目。

D指针的其他好处

除了以上优点,d指针还有如下优势:
1.隐藏实现细节——我们可以不提供widget.cpp文件而只提供WidgetLib和相应的头文件和二进制文件。
2.头文件中没有任何实现细节,可以作为API使用。
3.由于原本在头文件的实现部分转移到了源文件,所以编译速度有所提高。
其实以上的点都很细微,自己跟过源代码的人都会了解,qt是隐藏了d指针的管理和核心源的实现。像是在_p.h中部分函数的声明,qt也宣布在以后版本中将会删除。( This file is not part of the Qt API. It exists purely as an implementation detail. This header file may change from version to version without notice, or even be removed.)

Q指针

到目前为止,我们已经熟悉了指向私有结构体的d指针。而在实际中,往往它将包含私有方法(helper函数)。例如,LabelPrivate可能会有getLinkTargetFromPoint()(helper函数)以当按下鼠标时去找到相应的链接目标。在很多场合,这些helper函数需要访问公有类,例如访问一些属于Label类或是其基类Widget的函数。
比方说,一个帮助函数setTextAndUpdateWidget()可能会调用Widget::update()函数去重新绘制Widget。因此,我们同样需要WidgetPrivate存储一个指向公有类的q指针。

/* widget.h */
class  WidgetPrivate; 
 
class  Widget {
   
   
   ...
   Rect geometry()const;
   ...
private:
      WidgetPrivate *d_ptr;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值