19

有人可以向我解释 Qt 信号和插槽机制实现的基本思想吗?我想知道所有那些 Q_OBJECT 宏在“纯 C++”中做了什么。这个问题与信号和插槽的使用无关。

补充:我知道 Qt 使用 moc 编译器将 Qt-C++ 转换为纯 C++。但是 moc 是做什么的呢?我试图阅读“moc_filename.cpp”文件,但我不知道这样的东西是什么意思

void *Widget::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Widget))
    return static_cast<void*>(const_cast< Widget*>(this));
return QDialog::qt_metacast(_clname);
}
4

3 回答 3

22

关于信号和槽,Q_OBJECT宏在类的声明中添加了一个虚函数qt_metacall()声明,稍后将由moc. (它还添加了一些转换声明,但这在这里并不重要。)

然后moc读取头文件,当它看到宏时,它会生成另一个以虚函数定义.cpp命名moc_headerfilename.cpp的文件,并且——你可能会问自己,为什么你可以signals:在没有正确定义的情况下在头文件中提及 ——信号。

因此,当调用信号时,将执行 mocfile 中的定义,并QMetaObject::activate()使用信号名称和信号参数调用。然后该activate()函数确定已建立哪些连接并获取相应插槽的名称。

然后它qt_metacall使用槽名称和给信号的参数进行调用,元调用函数在一个大的switch-<code>case 语句的帮助下将其委托给真正的槽。

由于在 C++ 中没有关于信号和槽的实际名称的真正运行时信息,正如已经注意到的,这些将由SIGNALSLOT宏编码为简单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.

于 2010-01-05T19:30:10.333 回答
3

这些宏“在普通的 C++ 中”绝对没有任何作用,它们扩展为空字符串(我认为)。

QT 使用元对象编译器,为启用 Q_OBJECT 的类生成 C++ 代码(实现您定义的信号/槽等)。

您可以在官方文档中阅读更多相关信息。

于 2010-01-05T18:06:08.883 回答
-1

基本思想是您可以连接您的对象,允许它们在信号完成时执行方法(插槽)。

connect(pistol,SIGNAL(sigShoot()),runner,SLOT(slotRun()))

做上面的连接,当手枪发出信号时,跑步者将执行它的插槽。

为此,您必须在各自的类中声明信号和插槽。

是基本思想。

祝你好运!

于 2010-01-05T19:10:45.323 回答