腾讯网站开发,设计网站一般多少钱,微信软文怎么写,洛可可设计公司市值1. 什么是元对象编译器和元对象系统#xff1f; 在开始讲信号槽之前#xff0c;我们先了解下Qt的框架的核心组成部分#xff0c;Qt的元对象编译器#xff08;MOC#xff09;和元对象系统是Qt框架的核心组成部分#xff0c;它们使得Qt拥有了信号与槽机制、反射#xff08…1. 什么是元对象编译器和元对象系统 在开始讲信号槽之前我们先了解下Qt的框架的核心组成部分Qt的元对象编译器MOC和元对象系统是Qt框架的核心组成部分它们使得Qt拥有了信号与槽机制、反射introspection和属性系统等强大的特性。下面分别解释这两个概念
1.1 元对象编译器MOC 元对象编译器是Qt特有的一个预处理器它不是标准C的一部分。MOC会处理使用了Qt的特殊宏如Q_OBJECT、signals、slots等的C头文件。它的主要任务是为使用了这些宏的类生成额外的C源代码文件。这个生成的源文件包含了元信息以及信号和槽机制所需的实现代码。 MOC生成的代码包括但不限于 - 类的元信息类名、父类、信号和槽的名称等。 - 用于实现信号和槽机制的函数包括信号发射的存根和用于槽调用的代码。 - 用于动态属性系统的代码。 - 实现Qt的反射机制的代码允许在运行时查询对象的类型信息和成员函数。 1.2 元对象系统 元对象系统是Qt运行时环境的一部分它使用MOC生成的代码来提供动态特性如 - 信号与槽一个高级的事件订阅和通知机制用于对象间的通信。 - 对象反射允许在运行时查询对象的类型信息如它的类名、它继承的基类、它拥有的信号和槽。 - 属性系统允许在运行时查询和修改对象的属性。 - 动态方法调用允许在运行时调用对象的方法。 每个通过Q_OBJECT宏声明的类都能在运行时通过其元对象(QMetaObject)来访问这些特性。QMetaObject实例包含了关于其对应类的所有信息包括信号、槽、属性等。这种机制使得Qt的对象可以在运行时进行更多动态操作。 简而言之元对象编译器为元对象系统生成必需的胶水代码而元对象系统则利用这些代码在运行时提供动态的、反射式的特性。这两个元素共同构成了Qt框架中对象间通信和动态类型管理的基础。
2. 信号槽机制 2.1 元对象编译器MOC: MOC扫描通过Q_OBJECT宏标记的类并为这些类生成附加的C代码。这个代码包括信号和槽的定义以及类的元信息如类名、信号/槽列表、属性等。 假设有如下类定义 class MyClass : public QObject {Q_OBJECTpublic:MyClass(QObject *parent nullptr) : QObject(parent) signals:void mySignal(int);public slots:void mySlot(int);}; MOC将为此类生成一个名为moc_myclass.cpp的源文件其中包含了用于信号和槽的实现细节。这个文件通常包括 - 信号的存根stub函数 - 类的元信息元对象代码 - 用于调用槽的静态函数 2.1.1 信号的存根stub函数是什么 在Qt的信号和槽机制中信号的存根stub函数是MOC生成的一段代码它充当信号的实现。在Qt中信号函数本身是不包含用户定义的实现的你只需要在类的头文件中声明它们。当你在代码中发射emit一个信号时实际上是调用了这个存根函数。 存根函数的主要职责是通知Qt元对象系统有信号发生并传递任何相关的参数。然后元对象系统负责调用和这个信号相关联的所有槽函数。
这里是一个信号存根函数的简化示例伪代码
// MyClass 类中的信号声明部分
class MyClass : public QObject {Q_OBJECTpublic:...signals:void mySignal(int value);...
};// MOC 生成的存根函数
void MyClass::mySignal(int value) {// 内部生成的代码用来激活信号QMetaObject::activate(this, MyClass::staticMetaObject, signalIndex, value);
} 在上面的代码中mySignal 信号的存根函数被MOC生成并且包含了调用 QMetaObject::activate 函数的代码。这个 activate 函数是元对象系统的一部分它负责查找所有连接到 mySignal 信号的槽并依次调用它们。 请注意开发者不需要编写信号的存根函数它们是由MOC自动根据类的头文件生成的。开发者只需要声明信号并在必要的时候使用 emit 关键字来发射它们。例如
emit mySignal(123); 这行代码在运行时实际上调用的就是MOC为 mySignal 信号生成的存根函数。 2.1.2 activate 函数运行原理 在Qt中信号和槽之间的连接是通过 QObject::connect 函数建立的。这个函数告诉Qt元对象系统当特定的信号被发射时应该调用哪个槽函数。连接可以在运行时动态建立也就是说在程序的执行过程中可以根据需要将任何信号连接到任何槽上。 下面是一个信号和槽连接的例子
QObject::connect(sender, SenderClass::signalName, receiver, ReceiverClass::slotName); 在这个例子中我们假设 sender 是一个指向 SenderClass 实例的指针而 SenderClass 中有一个名为 signalName 的信号。receiver 是指向 ReceiverClass 实例的指针ReceiverClass 中有一个名为 slotName 的槽函数。 当 connect 函数被调用时Qt元对象系统会记录下信号和槽之间的连接。这个信息被用于在信号发射时查找和调用所有连接到该信号的槽函数。 QMetaObject::activate 函数内部的工作原理如下 1. 当信号发射时即当存根函数被调用时activate 函数被执行。 2. activate 函数查询内部的连接列表这个列表记录了所有连接到该信号的槽。 3. 对于每一个连接activate 函数会调用相应的槽函数。如果槽函数接受参数activate 会传递信号的参数给槽。 这个过程是由Qt的元对象系统在背后自动管理的开发者不需要编写代码来处理这些低级细节。您只需要知道如何使用 connect 函数来建立连接以及如何使用 emit 关键字来发射信号。 Qt的信号和槽机制非常强大因为它允许对象之间进行松耦合的通信。槽函数不需要知道是哪个信号触发了它们也不需要知道信号来自哪个对象。同样对象可以发射信号而不需要知道谁将接收它们。这种机制极大地提高了代码的可重用性和可维护性。 2.1.3 activate函数怎么知道哪个信号发送了 activate函数是Qt元对象系统的一部分用于在运行时处理信号的发射和槽的调用。它知道是哪个信号被发射的因为每次信号发射时存根函数都会传递特定的信息给activate函数。 这个过程中涉及到几个关键的步骤和元素 1. 信号发射Emission: - 当你调用一个信号如emit mySignal(value);实际上你调用的是由MOC为该信号生成的存根函数。 2. 信号索引Signal Index: - 每个信号在其类的元对象中都有一个唯一的索引值。这个索引是在编译时由MOC根据信号在类中的声明顺序计算得出的。 - 当存根函数被调用时它使用这个索引作为参数之一调用QMetaObject::activate函数。 3. 参数传递Parameter Passing: - 除了信号索引存根函数还将信号的参数作为参数传递给activate函数。这样activate函数就可以将这些参数传递给目标槽函数。 4. 槽函数调用Slot Invocation: - QMetaObject::activate函数使用信号索引来查找所有连接到该信号的槽并使用信号的参数来调用它们。连接信息存储在内部的数据结构中这些数据结构在运行时通过QObject::connect函数填充。 下面是QMetaObject::activate函数调用的伪代码流程
// 假设这是由MOC生成的存根函数的调用
void MyClass::mySignal(int value) {// ...省略其他代码...QMetaObject::activate(this, MyClass::staticMetaObject, signalIndex, value);
}// activate函数的概念实现
void QMetaObject::activate(QObject *sender, QMetaObject *m, int local_signal_index, void **argv) {// 确定全局信号索引int signal_index m-methodOffset() local_signal_index;// 查找对应于信号的所有连接并调用相应的槽foreach (const Connection c, connectionsForSignal(signal_index)) {if (c.receiver) {c.slot_method(sender, argv); // argv 包含了所有传递给信号的参数}}
} 在这个示例中activate函数接收到了信号索引和信号参数。这个索引用于在信号和槽的连接表中查找应该被调用的槽函数。然后activate函数根据这些信息调用所有连接的槽函数并将信号参数传递给它们。 这样activate函数就可以知道是哪个信号被发射并且能够将该信号路由到所有已连接的槽函数。这是Qt信号和槽机制的核心允许对象之间进行灵活和动态的通信。 2. 2 信号和槽的存储: MOC生成的元信息包含信号和槽的名称和参数类型。这个信息存储在每个对象实例的元对象中。 2.3. 信号和槽的连接: 连接信号和槽时使用的QObject::connect()函数大致上是这样的
QObject::connect(sender, MyClass::mySignal, receiver, MyClass::mySlot); 在内部QObject::connect()会创建一个连接数据结构它包含了关于信号和槽的信息以及它们所属的对象。
2.4. 信号的发射: 当你调用emit mySignal(10);时MOC为mySignal生成的代码会被执行。这段代码会遍历所有与该信号连接的槽并调用它们。这通常是通过调用QMetaObject::activate()来完成的。 // 伪代码void MyClass::mySignal(int value) {// MOC生成的信号函数QMetaObject::activate(this, MyClass::staticMetaObject, signalIndex, value);}
2.5. 槽函数的调用: 槽函数的调用是通过QMetaObject::activate()在运行时通过元对象系统完成的。当一个信号被激活时Qt会查找与之相连接的所有槽并逐个调用它们。 // 伪代码void QMetaObject::activate(QObject *sender, QMetaObject *m, int local_signal_index, void **argv) {// 遍历连接列表for (每个连接到该信号的接收器) {// 调用槽函数slot connection-slot;(receiver-*slot)(/* 参数转换和传递 */);}} 如果信号和槽在不同的线程Qt会安排一个事件(QEvent)并将其发送到接收者所在的线程的事件队列中事件处理函数将在目标线程中调用槽函数。 信号和槽机制的核心是QObject和QMetaObject。QObject提供了基础的通信能力而QMetaObject负责存储类的元信息和提供动态类型检查和方法调用等能力。通过MOC生成的代码和这些类的合作Qt可以在运行时动态地连接对象传递参数并且安全地调用方法。这就是Qt信号和槽机制强大灵活性的来源。
3. connect的第五个参数 在Qt中QObject::connect 方法有一个重载版本它接受第五个参数这个参数是一个枚举 Qt::ConnectionType它指定了信号和槽之间连接的类型。Qt::ConnectionType 枚举的值决定了信号是直接发送到槽还是通过事件队列来进行异步调用。这个参数是可选的如果不提供默认是 Qt::AutoConnection。 Qt::ConnectionType 枚举的几个可能的值包括 - Qt::AutoConnection (默认): Qt会根据接收者是否位于发射者的线程中自动选择是使用 Qt::DirectConnection 还是 Qt::QueuedConnection。如果接收者和发射者在同一个线程它会使用 Qt::DirectConnection否则会使用 Qt::QueuedConnection。 - Qt::DirectConnection: 槽函数会在信号发射的那一刻立即被调用无论接收者和发射者是否在同一个线程。这意味着槽函数是在信号发射者的线程上下文中执行的。 - Qt::QueuedConnection: 发射信号的事件会被放入接收者所在的线程的事件队列中。接收者的槽函数将会在接收者所在的线程的事件循环中稍后被调用。这种连接类型在跨线程通信时特别有用。 - Qt::BlockingQueuedConnection: 类似于 Qt::QueuedConnection但是发射信号的线程会等到接收者线程中的槽函数执行完毕后再继续执行。这种类型的连接必须在不同线程之间使用否则会导致死锁。 - Qt::UniqueConnection: 这个参数可以和其他类型组合使用通过按位或操作。它确保不会为同一信号和槽创建重复的连接。如果尝试重复连接connect 函数将不会建立连接并返回 false。 下面是一个带有第五个参数的 connect 函数的例子
QObject::connect(sender, SenderClass::signalName,receiver, ReceiverClass::slotName, Qt::QueuedConnection); 在这个例子中当 signalName 被发射时slotName 槽函数将通过事件队列异步调用。这是跨线程工作时的一个典型用例。 文章转载自: http://www.morning.bpmnx.cn.gov.cn.bpmnx.cn http://www.morning.tkzqw.cn.gov.cn.tkzqw.cn http://www.morning.pqndg.cn.gov.cn.pqndg.cn http://www.morning.ykyfq.cn.gov.cn.ykyfq.cn http://www.morning.snrhg.cn.gov.cn.snrhg.cn http://www.morning.bfcxf.cn.gov.cn.bfcxf.cn http://www.morning.wpwyx.cn.gov.cn.wpwyx.cn http://www.morning.jsrnf.cn.gov.cn.jsrnf.cn http://www.morning.khxyx.cn.gov.cn.khxyx.cn http://www.morning.tpmnq.cn.gov.cn.tpmnq.cn http://www.morning.zbgqt.cn.gov.cn.zbgqt.cn http://www.morning.dqxnd.cn.gov.cn.dqxnd.cn http://www.morning.ytnn.cn.gov.cn.ytnn.cn http://www.morning.nlgyq.cn.gov.cn.nlgyq.cn http://www.morning.dschz.cn.gov.cn.dschz.cn http://www.morning.tlbhq.cn.gov.cn.tlbhq.cn http://www.morning.ysllp.cn.gov.cn.ysllp.cn http://www.morning.hxxyp.cn.gov.cn.hxxyp.cn http://www.morning.xkjqg.cn.gov.cn.xkjqg.cn http://www.morning.blqgc.cn.gov.cn.blqgc.cn http://www.morning.lzph.cn.gov.cn.lzph.cn http://www.morning.hhqjf.cn.gov.cn.hhqjf.cn http://www.morning.pybqq.cn.gov.cn.pybqq.cn http://www.morning.qdlr.cn.gov.cn.qdlr.cn http://www.morning.cqyhdy.cn.gov.cn.cqyhdy.cn http://www.morning.slwqt.cn.gov.cn.slwqt.cn http://www.morning.rglp.cn.gov.cn.rglp.cn http://www.morning.pjtnk.cn.gov.cn.pjtnk.cn http://www.morning.bkjhx.cn.gov.cn.bkjhx.cn http://www.morning.qtsks.cn.gov.cn.qtsks.cn http://www.morning.jjwt.cn.gov.cn.jjwt.cn http://www.morning.wfysn.cn.gov.cn.wfysn.cn http://www.morning.qdmdp.cn.gov.cn.qdmdp.cn http://www.morning.yqndr.cn.gov.cn.yqndr.cn http://www.morning.njfgl.cn.gov.cn.njfgl.cn http://www.morning.dxqwm.cn.gov.cn.dxqwm.cn http://www.morning.dmcxh.cn.gov.cn.dmcxh.cn http://www.morning.dhqyh.cn.gov.cn.dhqyh.cn http://www.morning.hryhq.cn.gov.cn.hryhq.cn http://www.morning.kstgt.cn.gov.cn.kstgt.cn http://www.morning.ryznd.cn.gov.cn.ryznd.cn http://www.morning.ptysj.cn.gov.cn.ptysj.cn http://www.morning.lstmq.cn.gov.cn.lstmq.cn http://www.morning.wmdlp.cn.gov.cn.wmdlp.cn http://www.morning.mcpdn.cn.gov.cn.mcpdn.cn http://www.morning.bfkrf.cn.gov.cn.bfkrf.cn http://www.morning.pwghp.cn.gov.cn.pwghp.cn http://www.morning.wbyqy.cn.gov.cn.wbyqy.cn http://www.morning.mqzcn.cn.gov.cn.mqzcn.cn http://www.morning.jyfrz.cn.gov.cn.jyfrz.cn http://www.morning.djxnn.cn.gov.cn.djxnn.cn http://www.morning.rdfq.cn.gov.cn.rdfq.cn http://www.morning.qwzpd.cn.gov.cn.qwzpd.cn http://www.morning.rhjhy.cn.gov.cn.rhjhy.cn http://www.morning.kxyqy.cn.gov.cn.kxyqy.cn http://www.morning.slpcl.cn.gov.cn.slpcl.cn http://www.morning.tslxr.cn.gov.cn.tslxr.cn http://www.morning.lwtfx.cn.gov.cn.lwtfx.cn http://www.morning.ktskc.cn.gov.cn.ktskc.cn http://www.morning.cnvlog.cn.gov.cn.cnvlog.cn http://www.morning.fykqh.cn.gov.cn.fykqh.cn http://www.morning.ckntb.cn.gov.cn.ckntb.cn http://www.morning.rxdsq.cn.gov.cn.rxdsq.cn http://www.morning.bscsp.cn.gov.cn.bscsp.cn http://www.morning.zxqyd.cn.gov.cn.zxqyd.cn http://www.morning.fznj.cn.gov.cn.fznj.cn http://www.morning.azxey.cn.gov.cn.azxey.cn http://www.morning.mwbqk.cn.gov.cn.mwbqk.cn http://www.morning.ejknty.cn.gov.cn.ejknty.cn http://www.morning.mlbn.cn.gov.cn.mlbn.cn http://www.morning.qwzpd.cn.gov.cn.qwzpd.cn http://www.morning.lyjwb.cn.gov.cn.lyjwb.cn http://www.morning.lqjlg.cn.gov.cn.lqjlg.cn http://www.morning.rwqk.cn.gov.cn.rwqk.cn http://www.morning.tdqhs.cn.gov.cn.tdqhs.cn http://www.morning.pmysp.cn.gov.cn.pmysp.cn http://www.morning.pwgzh.cn.gov.cn.pwgzh.cn http://www.morning.hmmnb.cn.gov.cn.hmmnb.cn http://www.morning.yydzk.cn.gov.cn.yydzk.cn http://www.morning.kxypt.cn.gov.cn.kxypt.cn