关于信号和槽,Q_OBJECT宏在类的声明中添加了一个虚函数qt_metacall()声明,稍后将由moc. (它还添加了一些转换声明,但这在这里并不重要。)
然后moc读取头文件,当它看到宏时,它会生成另一个以虚函数定义.cpp命名moc_headerfilename.cpp的文件,并且——你可能会问自己,为什么你可以signals:在没有正确定义的情况下在头文件中提及 ——信号。
因此,当调用信号时,将执行 mocfile 中的定义,并QMetaObject::activate()使用信号名称和信号参数调用。然后该activate()函数确定已建立哪些连接并获取相应插槽的名称。
然后它qt_metacall使用槽名称和给信号的参数进行调用,元调用函数在一个大的switch-<code>case 语句的帮助下将其委托给真正的槽。
由于在 C++ 中没有关于信号和槽的实际名称的真正运行时信息,正如已经注意到的,这些将由SIGNAL和SLOT宏编码为简单const char*的 s(将“1”或“2”添加到名称以区分信号和插槽)。
如中所定义qobjectdefs.h:
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
——</p>
Q_OBJECT宏所做的另一件事是tr()在对象中定义可用于翻译应用程序的函数。
编辑
正如你所问的qt_metacast那样。它检查一个对象是否属于某个类,如果它确实返回指向它的指针。如果不是,则返回 0。
Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);
This is needed to provide some runtime reflection which is not possible otherwise. The function is called in QObject::inherits(const char *) for example and simply checks for inheritance.