</qt4GUI教程>
2.2深入介绍信号和槽
信号和槽机制是Qt编程的基础。它可以让应用程序编程人员把这些互不了解的对象绑定在一起。
Qt的元对象系统
Qt的主要成就之一就是使用了一种机制对C++进行了扩展,并且使用这种机制创建了独立的软件组件。这些组件可以绑定在一起,但任何一个组件对于它所要连接的组件的情况事先都一无所知。
这种机制称为元对象系统(meta-object system),它提供了关键的两项技术:信号---槽以及内省(introspection)内省功能对于实现信号和槽是必需的,并且允许应用程序的开发人员在运行时获得有关QObject子类的"元信息",包括一个含有对象的类名以及它所支持的信号和槽的列表。
标准C++没有对Qt的元对象系统所需要的动态元信息提供支持。Qt通过提供一个独立的moc工具解决了这个问题。Moc解析Q_OBJECT类的定义并且通过C++函数来提供可使用的信息。
这一机制是这样工作的:
Q_OBJECT宏声明了在每一个QObject子类中必须实现的一些内省函数:metaObject(),tr(),qt_metacall(),以及其他一些函数。
Qt的moc工具生成了角于由Q_OBJECT声明的所有函数和所有信号的实现。
像connnect() 和disconnect()这样的QObject的成员函数使用这些内省函数来完成它们的工作。
</qt4GUI教程>
核心问题1:Informer如何在不知道Receiver的情况下,调用Receiver的方法
这个例子中,要调用的函数为Receiver中的void count(int i)方法。调用过程如下
问题的核心变成了怎么样得到receiver这个对象。Receiver来源于QObject * const receiver = c->receiver; c来源于QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
connectionLists来源于
QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
也就是说,receiver对象被保存在sender对象中。
现在要解决的问题是,receiver对象是如何被保存到sender对象中的。查看源码,发现在QObject::connect中向connectionLists添加元素。connect函数已包含sender对象和receiver对象,只要将receiver对象添到sender的connectionLists中即可。在日后的使用中,便能找到recevier对象了。
核心问题2:触发信号函数时系统如何找到与信号函数匹配的接收函数
这个问题可分为两个小问题:
(1)Reciver对象可能有多个方法,qt如何知道要调用哪个函数.
(2)如何将参数传给reciver对应的函数
突破口在这个段代码中
void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
void **argv)
{
//....................
metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
//....................
}
metacall函数声明如下
static int metacall(QObject *, Call, int, void **);
这个函数又调用了
return object->qt_metacall(cl, idx, argv);
Object是receiver对象,moc为receiver生成了qt_metacall函数。在这个函数内部,通过idx找出要调用的函数,参数地址在argv数组中。通过argv,加上强转,就可以得到参数了。
示例代码如下
通过上面的代码,完成了调用过程。
联系客服