有人可以向我解释Qt信号和插槽机制实现的基本概念吗? 我想知道所有这些Q_OBJECT宏在“纯C ++”中做了什么。 这个问题不是关于信号和插槽的使用。
加入: 我知道Qt使用moc编译器在普通的C ++中转换Qt-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);
}
答案 0 :(得分:17)
关于信号和槽,Q_OBJECT
宏将一个虚函数qt_metacall()
声明添加到类的声明中,稍后将由moc
定义。 (它还为转换添加了一些声明,但这里并不重要。)
moc
然后读取头文件,当它看到宏时,它会生成另一个名为.cpp
的{{1}}文件,其中包含对虚函数的定义,并且 - 您可能已经问过自己为什么你可以在没有正确定义信号的情况下提及头文件中的moc_headerfilename.cpp
。
因此,当调用信号时,将执行mocfile中的定义,并使用信号名称和信号参数调用signals:
。
然后QMetaObject::activate()
函数确定已建立的连接并获取相应插槽的名称。
然后它使用插槽名称和给予信号的参数调用activate()
,并且metacall函数在大qt_metacall
- switch
语句的帮助下将其委托给真正的插槽
由于C ++中没有关于信号和插槽的实际名称的实际运行时信息,正如已经注意到的那样,这些信息将由case
和SIGNAL
宏编码为简单{ {1}} s(名称中加上“1”或“2”以区分信号和插槽)。
如SLOT
中所定义:
const char*
-
qobjectdefs.h
宏所做的另一件事是定义对象中的#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
函数,这些函数可用于翻译您的应用程序。
修改强>
当你问Q_OBJECT
正在做什么时。它检查对象是否属于某个类,如果它确实返回指向它的指针。如果没有,则返回0.
tr()
这需要提供一些运行时反射,否则这是不可能的。例如,在QObject::inherits(const char *)
中调用该函数,并简单地检查继承。
答案 1 :(得分:3)
那些宏在“纯C ++”中完全没有任何作用, - 它们扩展为空字符串(我认为)。
QT使用元对象编译器,为Q_OBJECT启用的类生成C ++代码(实现您定义的信号/插槽等)。
您可以在official documentation中了解更多相关信息。
答案 2 :(得分:-1)
基本思想是你可以连接你的对象,让它们在信号完成时执行一个方法(插槽)。
connect(pistol,SIGNAL(sigShoot()),runner,SLOT(slotRun()))
进行上述连接时,当手枪发出信号时,跑步者将执行其插槽。
为此,您必须在各自的班级中声明您的信号和插槽。
是基本想法。
祝你好运!