Qt源码学习之信号槽

Qt源码版本

  Qt 5.12.0

moc文件

  Qt在编译之前会分析源文件,当发现包含了Q_OBJECT宏,则会生成另外一个标准的C++源文件(包含Q_OBJECT宏实现的代码,文件名为moc_+原文件名),该文件同样进入编译系统,最终被链接到二进制代码中去。此时,Qt将自己增加的扩展转换成了标准的C++文件,moc全称是Meta-Object Compiler,也就是“原对象编译器”。

Q_OBJECT的宏定义

  位置:qobjectdefs.h

 1 /* qmake ignore Q_OBJECT */
 2 #define Q_OBJECT \
 3 public: \
 4     QT_WARNING_PUSH \
 5     Q_OBJECT_NO_OVERRIDE_WARNING \
 6     static const QMetaObject staticMetaObject; \
 7     virtual const QMetaObject *metaObject() const; \
 8     virtual void *qt_metacast(const char *); \
 9     virtual int qt_metacall(QMetaObject::Call, int, void **); \
10     QT_TR_FUNCTIONS \
11 private: \
12     Q_OBJECT_NO_ATTRIBUTES_WARNING \
13     Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
14     QT_WARNING_POP \
15     struct QPrivateSignal {}; \
16     QT_ANNOTATE_CLASS(qt_qobject, "")

Moc文件分析

测试代码

 1 #include <QObject>
 2   class CTestMoc : public QObject
 3   {
 4   Q_OBJECT
 5   public:
 6   CTestMoc(){}
 7   ~CTestMoc(){}
 8   signals:
 9   void Test1();
10   void Test2(int iTemp);
11   private slots:
12   void OnTest1();
13   void OnTest2(int iTemp);
14   };

Moc代码

  测试代码编译之后,生成moc_ctestmoc.cpp文件,包含几个重要的数据结构。

  第一个结构是

1 struct qt_meta_stringdata_CTestMoc_t {
2     QByteArrayData data[7];
3     char stringdata0[44];
4 };

  data字段是一个由数组组成的数组,数组大小取决于信号/槽个数。这个数组在调用QObject::connect时用来匹配信号名或槽名。

  stringdata存放的是字符资源,存放全部的信号名、槽名、类名。  

 1 static const qt_meta_stringdata_CTestMoc_t qt_meta_stringdata_CTestMoc = {
 2     {
 3 QT_MOC_LITERAL(0, 0, 8), // "CTestMoc"
 4 QT_MOC_LITERAL(1, 9, 5), // "Test1"
 5 QT_MOC_LITERAL(2, 15, 0), // ""
 6 QT_MOC_LITERAL(3, 16, 5), // "Test2"
 7 QT_MOC_LITERAL(4, 22, 5), // "iTemp"
 8 QT_MOC_LITERAL(5, 28, 7), // "OnTest1"
 9 QT_MOC_LITERAL(6, 36, 7) // "OnTest2"
10 
11     },
12     "CTestMoc\0Test1\0\0Test2\0iTemp\0OnTest1\0"
13     "OnTest2"
14 };

  qt_meta_stringdata_CTestMoc_t是一个qt_meta_stringdata_CTestMoc的实例

  QT_MOC_LITERAL(0, 0, 8),这个宏生成一个byte数组,第一参数是索引,可以看到索引是由 0-6共7个组成,对应的是data字段的长度7;第二个参数是在stringdata字段中的开始位置;第三个参数是长度。QT_MOC_LITERAL(0, 0, 8) 索引是0, 开始位置是0,长度是8,对应的字符是"CTestMoc",后面的以此类推。

  

  

结论

  1. Qt的信号/槽的调用不是通过指针方式调用的,而是通过索引方式来调用的。
  2. 信号也是一个函数。

猜你喜欢

转载自www.cnblogs.com/fengyaoyao/p/10549320.html