zoukankan      html  css  js  c++  java
  • Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

    Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

    来源 https://blog.csdn.net/liulihuo_gyh/article/details/80081069

    参考 https://blog.csdn.net/seanyxie/article/details/6120036

    参考 https://blog.csdn.net/Andy_93/article/details/77587797

    参考 https://blog.csdn.net/qq_39937902/article/details/79738160

    Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

    这两个宏在Qt的源码中随处可见,重要性不言而喻。在 部落格的 Inside Qt Series 系列文章中,他用了3篇文章来讲这个问题。

    因为 QObject 本身比较复杂,这两个宏和一个复杂的东西搅和到一块,还真是不好理解。不过幸好,这个两个宏和QObject 没有必然的联系。故接下来,忘记 QObject,看一个普通的C++的类。

    例子

    类 QtServiceController 定义:

    class QtServiceController 
    {
       Q_DECLARE_PRIVATE(QtServiceController) 
     public:
     QtServiceController(const QString &name);
     //省略其他 
    private:
     QtServiceControllerPrivate *d_ptr; 
    };

    宏定义

    宏定义在 QtGlobal(即qglobal.h)头文件中:

    #define Q_DECLARE_PRIVATE(Class) 
     inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } 
     inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } 
     friend class Class##Private;  
    
    #define Q_DECLARE_PUBLIC(Class) 
     inline Class* q_func() { return static_cast<Class *>(q_ptr); } 
     inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } 
     friend class Class;

    这两个宏在这看起来真蛮绕的,因为这个例子太简单了,两个宏的威力发挥不出来。反正核心就是:

    • 在 QtServiceController 中通过 d_func() 可以获得 QtServiceControllerPrivate 的指针 d_ptr

    • 在 QtServiceControllerPrivate 中通过 q_func() 可以获得 QtServiceController 的指针 q_ptr

    Q_D 与 Q_Q

    这是另两个Qt源码中随处可见的宏,那么它们有什么用呢?

    #define Q_D(Class) Class##Private * const d = d_func() 
    #define Q_Q(Class) Class * const q = q_func() 

    两个宏展开后分别是对 d_func 和 q_func 两个函数的调用,返回值分别赋值给 d 和 q 两个指针变量。

    于是:

    • 在 QtServiceController 中的成员函数中,我们只需要添加 Q_D(QtServiceController) 宏,在该函数内就可以直接用 d 来指代 d_ptr

    • 在 QtServiceControllerPrivate 中的成员函数中,我们只需要添加 Q_Q(QtServiceController)宏,在该函数内就可以直接用 q 来指代 q_ptr

    d_ptr与q_ptr

    绕这么大圈,为什么不直接用 d_ptr 与 q_ptr 呢。在,在我们的例子中,确实可以直接用,而且会更直接更简单。官方这么用了,或许是为了和其他类保持一致吧。

    但在其他情况下,这么做显然是有意义的,因为 d_ptr 与 d,q_ptr 与 q 的类型并不一致(比如QObject系列)。这也是为何宏展开后有cast的原因

     

    Q_DISABLE_COPY

    QObject 中没有提供一个拷贝构造函数和赋值操作符给外界使用,其实拷贝构造和赋值的操作都是已经声明了的,但是它们被使用了Q_DISABLE_COPY() 宏放在了private区域。因此所有继承自QObject的类都使用这个宏声明了他们的拷贝构造函数和赋值操作符为私有。

    为什么要这样做?

    我们都知道Qt对标准C++增加了一些功能:signals, slots, object properties, events, event filters, string translation, timers,object trees, guarded pointers, dynamic cast.

    新加入的这些功能就要求我们把每一个QObject的对象看做是唯一(identities)的。唯一的意思就是不能通过拷贝或者赋值操作

    制作出一个一模一样的复制体。

    试想如果我们有一个QPushButton对象btnSubmit,如果我们可以复制出一个和btnSubmint完全一样的button对象,那么新的button对象的名字应该是什么?如果也叫btnSubmit,当我们给其中的btnSubmit接收事件或发出信号时,系统如何区分把事件由哪个button对象接收,或者哪个对象发送了信号?

    我们知道在各种容器中能以value方式存放的类型,必须有默认的构造函数,拷贝构造函数和赋值操作。由于QObject及所有继承自它的子类都没有提供拷贝构造和赋值操作,当我们使用QList<QObject>时,编译器就会报错。如果我们要在容器中存储这中类型的对象,我们就要使用它们的指针。如QList<QObject *>

    ========== End

  • 相关阅读:
    基于udp简单聊天的系统
    网络编程_tcp与dup协议简单应用
    logging_modules
    linux内核配置与编译
    linux内核简介
    对于国嵌上学期《一跃进入C大门》Mini2440的代码修正
    通过按键玩中断
    MMU功能解析、深入剖析、配置与使用
    C与汇编混合编程
    一跃进入C大门
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/12166643.html
Copyright © 2011-2022 走看看