关于信号和插槽,Q_OBJECT
宏将虚拟函数qt_metacall()
声明添加到类声明中,该声明稍后将由moc
定义。 (它也增加了一些声明的转换,但在这里,这不是太重要。)
的moc
然后读取头文件,当它看到的宏时,它产生另一个.cpp
文件名为moc_headerfilename.cpp
与定义,虚拟功能和 - 你可能会问自己,为什么你可以在头文件中提到signals:
而没有正确定义信号。
因此,当调用一个信号时,将执行mocfile的定义并调用QMetaObject::activate()
以及信号的名称和信号的参数。 然后activate()
函数计算出哪些连接已建立并获取相应插槽的名称。
然后它调用qt_metacall
插槽名称和给出的信号的参数和元调用功能代表这个借助于一个大的switch
- case
声明真实的插槽。
由于没有关于对信号和槽的实际名称可能在C中没有真正运行时信息++,正如已经注意到了,这些将由SIGNAL
和SLOT
宏简单const char*
s为单位进行编码(或者用“1”或“2”添加到该名称以区分插槽中的信号)。
正如在qobjectdefs.h
定义:
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
-
的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);
这是需要提供一些运行时反射,否则不可能。例如,该函数在QObject::inherits(const char *)
中调用,并简单地检查继承。
dup:http://stackoverflow.com/questions/1406940/how-signal-and-slots-are-implemented-under-the-hood – elcuco 2010-01-05 20:45:22