【问题标题】:How does Qt implement signals and slots?Qt 是如何实现信号和槽的?
【发布时间】:2011-01-01 18:09:36
【问题描述】:

有人可以向我解释一下 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);
}

【问题讨论】:

标签: qt signals-slots


【解决方案1】:

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

moc 然后读取头文件,当它看到宏时,它会生成另一个名为 moc_headerfilename.cpp.cpp 文件,其中包含对虚函数的定义 - 您可能会问自己为什么可以逃脱在没有正确定义信号的情况下在头文件中提及signals:

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

然后它调用qt_metacall 并使用槽名称和为信号提供的参数,元调用函数在一个大的switchcase 语句的帮助下将其委托给真正的槽。

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

【讨论】:

【解决方案2】:

这些宏在“纯 C++ 中”完全没有做任何事情,——它们扩展为空字符串(我认为)。

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

您可以在official documentation 中了解更多信息。

【讨论】:

  • 确实如此。其实,如果你编译代码,你可以看看产生的源代码。
  • 信号和插槽在扩展时需要有一个小的差异,因为你可以connect() 信号对信号,然后就不清楚字符串代表什么了。
【解决方案3】:

基本思想是你可以连接你的对象,让它们在信号完成时执行一个方法(槽)。

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

做上面的连接,当pistol发出信号时,runner就会执行它的slot。

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

是基本思想。

祝你好运!

【讨论】:

  • 但是 OP 询问的是内部实现,而不是如何使用它。
  • 这个想法看起来像dojo处理消息系统。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多