</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,加上强转,就可以得到参数了。 示例代码如下
通过上面的代码,完成了调用过程。 |
|