QT源码分析-d指针

二进制兼容

什么是二进制兼容?
简单理解就是升级了QT的dll文件,不需要重新编译项目就能正常运行。

为什么要保证二进制兼容?
因为违反二进制兼容的行为容易出错,UB(未定义的行为),甚至奔溃。

什么行为会破坏二进制兼容?

  1. 添加或删除非静态变量
  2. 改变非静态变量的顺序
  3. 更改成员的类型(但签名除外)

什么行为不会破坏二进制兼容?

  1. 添加非虚函数到类型(包括信号、槽、构造函数)
  2. 添加新的静态数据成员

d指针

什么是d指针?
d指针一般是接口类文件里指向实现类的指针。
d指针是不透明指针的一种实现,也可以说d指针是一种设计模式(桥接模式)。

什么是不透明指针?
不透明指针可以隐藏实现细节,当实现改变后不需要重新编译就能使用。程序员可将接口/接口类写的很简洁,而降大部分的实现放在另一个文件中,这也保证了二进制兼容。

什么是桥接模式?
将抽象部分(业务功能)与实现部分(平台实现)分离,使他们都可以独立的改变。

d指针的优点

  1. 隐藏类的实现细节
  2. 添加新的数据成员到私有类中不会影响二进制兼容性
  3. 头文件只需要包含接口类需要的头文件,不需要包含私有实现类的头文件(编译速度会提升)

从QT源码看d指针
在这里插入图片描述
在QT中QObjectData是所有Private类的基类。
通过向上传递d_ptr,避免继承层次中多次分配xxxPrivate类。例如:在QLabel构造时,QLabelPrivate一直向上传递,直到传给QObject。

Q_DECLARE_PRIVATE是接口类调用的,声明私有类指针。
Q_DECLARE_PUBLIC是实现类调用的,声明公共类指针。

使用Q_D宏获取到的d指针是实现类的指针,它可以直接访问和操作私有数据。
使用Q_Q宏获取到的q指针是接口类的指针,它只能访问接口类的公有成员函数和公有成员变量。无法直接访问接口类的私有成员函数和私有成员变量。
Q_Q() 和 Q_D() 优点:提高代码复用性和可维护性。

class MyClassPrivate;  // 声明私有类
class MyClass : public QObject
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(MyClass)  // 声明私有类指针(使用 Q_DECLARE_PRIVATE 宏将 MyClass 类的私有类指针声明为 MyClassPrivate)

public:
    explicit MyClass(QObject *parent = nullptr);
    ~MyClass();

    void publicFun();

private:
	void anOtherFun();

private:
    QScopedPointer<MyClassPrivate> d_ptr;  // 私有类指针
};

// Q_D使用
void MyClass::publicFunction()
{
    Q_D(MyClass); // 使用 Q_D() 宏声明并初始化 d 指针
    
    // 在此可以使用 d 指针来访问实现类的私有成员和成员函数。
    d->anOtherPriFun();
}
class MyClassPrivate {
    Q_DECLARE_PUBLIC(MyClass)  // 声明公共类指针
    
public:
    explicit MyClassPrivate(MyClass *q);
        
    void privateFun();

private:
	void anOtherPriFun(); 
   
private:
    MyClass *const q_ptr;  // 公共类指针
};


// Q_Q使用
void MyClassPrivate::anOtherPriFun()
{
    Q_Q(MyClass); // 使用 Q_Q() 宏声明并初始化 q 指针
    
    // 在此可以使用 q 指针来访问接口类的公有成员和成员函数,不能访问私有成员。
    q->publicFun();
}

RAII

构造时初始化资源,析构时释放资源,是C++为了解决异常安全提出的思想。
C++标准保证了即使抛出异常也能调用栈上对象的析构函数。
QScopedPointer的思想是RAII,作用是抛出异常时也能正确释放资源。

参考文档:
qt-wiki
https://wiki.qt.io/D-Pointer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值