QT Q_OBJECT 和 signals/slots
迪丽瓦拉
2024-06-01 02:07:39
0

Q_OBJECT宏展开

#define Q_OBJECT \
public: \QT_WARNING_PUSH \Q_OBJECT_NO_OVERRIDE_WARNING \static const QMetaObject staticMetaObject; \virtual const QMetaObject *metaObject() const; \virtual void *qt_metacast(const char *); \virtual int qt_metacall(QMetaObject::Call, int, void **); \QT_TR_FUNCTIONS \
private: \Q_OBJECT_NO_ATTRIBUTES_WARNING \Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \QT_WARNING_POP \struct QPrivateSignal {}; \QT_ANNOTATE_CLASS(qt_qobject, "")
  • QMetaObject类的作用是为QObject子类存储所有的元信息;还维护类的信号和槽之间的对应表,以及任何连接的类的信号和槽对应表。每一个信号槽都被分配了一个唯一的索引:
  • metaObject()函数对于普通的Qt类返回&staticMetaObject;处理QML对象返回dynamicMetaObject
  • qt_metacast()函数使用类的名称进行动态转换。这个函数是必须的,因为Qt不依赖标准C++RTTI(运行时类型信息)来检索关于一个对象或一个类的元数据
  • qt_metacast()直接通过索引调用一个内部信号或槽。因为使用的是索引而不是指针,所以没有指针的指针解读,生成的switch case可以被编译器大量优化(编译器可以在很早的时候直接包含跳转指令到特定的情况,避免大量的分支评估)。因此,信号/槽机制的执行是相当快的

siganls/slots/emit

  • 定义

    #define slots
    #define signals public
    #define emit
    
  • 当一个信号关键词被发射,QMetaObject::activate()被调用并带有改变的值和信号索引

  • QObject::connect():创建一个新的Connection,在qobject_p.h定义

struct Connection
{QObject *sender;QObject *receiver;union {StaticMetaCallFunction callFunction;QtPrivate::QSlotObjectBase *slotObj;};// The next pointer for the singly-linked ConnectionListConnection *nextConnectionList;//senders linked listConnection *next;Connection **prev;//...
};
  • Connection实例存储了一个指向信号发射器类(sender)、槽接收器类(receiver)的指针,及连接的信号槽关键字的索引。当一个信号被发射出去,每一个连接的槽都必须被调用。为了能做到这一点,每一个QObject为它每个信号都有一个Connection实例的链接列表,它的每个槽关键字也有同样的Connection链接列表
  • 这对链接列表允许Qt正确地走到每个依赖槽/信号对,以使用索引触发正确的函数。同理处理接收器的销毁。Qt走过双链接列表,将对象从它连接的地方删除
  • 这些机制发生在UI线程中。因为QThread类继承了QObject,任何QThread都可以使用信号/槽机制

相关内容