Qt:使用元对象编辑器Moc
元对象编辑器moc时处理Qt的C++扩展的程序
该moc工具读取C++头文件。如果找到包含Q_OBJECT
宏的一个或者多个类声明,它将生成一个C++源文件,其中包含这些类的元对象代码。其中,信号和槽机制、运行时类型信息和动态属性系统需要元对象代码。
由MOC生成的C++源文件必须编译并链接到类的实现。
如果使用qmake创建makefile,则将包含在需要时调用moc的构建规则,因此您无需直接使用moc。有关的更多背景信息moc,请参阅Qt为什么将Moc用于信号和插槽?
用法
moc通常与包含以下类声明的输入文件一起使用
class MyClass : public QObject
{Q_OBJECTpublic:MyClass(QObject *parent = 0);~MyClass();signals:void mySignal();public slots:void mySlot();
};
除了上面显示的信号和插槽之外,moc还可以像下一个示例一样实现对象属性。Q_PROPERTY()
宏声明一个对象属性,而Q_ENUM()
声明类中可在属性系统中使用的枚举类型列表
在下面的示例中,我们声明了枚举类型Priority的属性,该属性也称为Priority,具有get函数Priority()和set函数setPriority()
class MyClass : public QObject
{Q_OBJECTQ_PROPERTY(Priority priority READ priority WRITE setPriority)Q_ENUMS(Priority)public:enum Priority { High, Low, VeryHigh, VeryLow };MyClass(QObject *parent = 0);~MyClass();void setPriority(Priority priority) { m_priority = priority; }Priority priority() const { return m_priority; }private:Priority m_priority;
};
Q_FLAGS()
宏声明将用作标志的枚举。另一个宏Q_CLASSINFO()
,允许您将其他名称/值对附加到类的元对象上:
class MyClass : public QObject
{Q_OBJECTQ_CLASSINFO("Author", "Oscar Peterson")Q_CLASSINFO("Status", "Active")public:MyClass(QObject *parent = 0);~MyClass();
};
moc必须将产生的输出进行编译和链接,就像程序中的其他代码一样;否则,构建将在最后的链接阶段失败。如果您使用qmake,这是自动完成的。无论何时qmake运行,它都会解析项目的头文件,并生成make规则以调用moc包含Q_OBJECT
宏的那些文件
如果在文件中找到类声明myclass.h,则应将moc输出放入名为的文件中moc_myclass.cpp。然后应像往常一样编译该文件,从而生成一个目标文件,例如moc_myclass.obj在Windows上。然后,应将该对象包含在程序的最终构建阶段中链接在一起的对象文件列表中。
编写调用规则moc
对于除最简单的测试程序以外的任何程序,建议您自动运行moc。通过向程序的makefile中添加一些规则,make可以在必要时照顾运行moc并处理moc输出。
我们建议使用qmake生成文件生成工具来生成您的生成文件。该工具生成一个执行所有必要moc处理的makefile 。
如果要自己创建makefile,则以下是有关如何包括moc处理的提示。
对于头文件中的Q_OBJECT类声明,如果仅使用GNU make,这是一个有用的makefile规则:
moc_%.cpp: %.hmoc $(DEFINES) $(INCPATH) $< -o $@
如果您想轻便地编写代码,则可以使用以下格式的各个规则:
moc_foo.cpp: foo.hmoc $(DEFINES) $(INCPATH) $< -o $@
你还必须记住添加moc_foo.cpp到你的SOURCES(代替自己喜欢的名字)变量,moc_foo.o或者moc_foo.obj你的OBJECTS变量。
这两个示例均假定$(DEFINES)
并$(INCPATH)
扩展到define并包括传递给C ++编译器的路径选项。这些是moc预处理源文件所必需的。
虽然我们喜欢我们的命名C ++源文件.cpp,你可以使用任何其他扩展名,如.C,.cc,.CC,.cxx,和.c++。
对于实现()文件中的Q_OBJECT类声明.cpp,我们建议使用以下makefile规则:
foo.o: foo.mocfoo.moc: foo.cppmoc $(DEFINES) $(INCPATH) -i $< -o $@
这保证了make将在moc编译之前运行foo.cpp。然后你可以把
#include "foo.moc"
在的末尾foo.cpp,该文件中声明的所有类都是完全已知的。
命令行选项
这是moc支持的命令行选项:
您可以明确地告诉Moc不要解析头文件的各个部分。moc定义预处理器符号Q_MOC_RUN。被以下内容包围的任何代码
#ifndef Q_MOC_RUN...
#endif
被跳过moc。
诊断程序
moc会在Q_OBJECT类声明中警告您一些危险或非法的构造。
如果在程序的最终构建阶段遇到链接错误,例如YourClass::className()未定义或YourClass缺少vtable,则说明操作有误。大多数情况下,您忘记编译或#include由moc生成的C ++代码,或者(在前一种情况下)忘记将该对象文件包含在link命令中。如果您使用qmake,请尝试重新运行它以更新您的Makefile。这应该可以解决问题。
局限性
moc不能处理所有的C ++。主要问题是类模板不能具有Q_OBJECT宏。这是一个例子:
class SomeTemplate<int> : public QFrame
{Q_OBJECT...signals:void mySignal(int);
};
以下构造是非法的。所有这些都有我们认为通常比较好的替代方案,因此消除这些限制对我们来说不是一个高度优先事项。
多重继承要求QObject是第一个
如果您使用多重继承,moc假设第一个继承的类是QObject的子类。另外,确保只有第一个继承的类是QObject。
// correct
class SomeClass : public QObject, public OtherClass
{...
};
不支持QObject的虚拟继承。
函数指针不能是信号或插槽参数
在大多数情况下,您会考虑使用函数指针作为信号或插槽参数,我们认为继承是更好的选择。这是非法语法的示例:
class SomeClass : public QObject
{Q_OBJECTpublic slots:void apply(void (*apply)(List *, void *), char *); // WRONG
};
您可以像这样解决此限制:
typedef void (*ApplyFunction)(List *, void *);class SomeClass : public QObject
{Q_OBJECTpublic slots:void apply(ApplyFunction, char *);
};
有时用继承和虚函数替换函数指针可能会更好。
枚举和Typedef必须完全符合信号和插槽参数的要求
检查其参数的签名时,QObject :: connect()会按字面意义比较数据类型。因此,Alignment和Qt :: Alignment被视为两种不同的类型。要解决此限制,请确保在声明信号和插槽以及建立连接时完全限定数据类型。例如:
class MyClass : public QObject
{Q_OBJECTenum Error {ConnectionRefused,RemoteHostClosed,UnknownError};signals:void stateChanged(MyClass::Error error);
};
嵌套类不能有信号或插槽
这是令人反感的结构的示例:
class A
{public:class B{Q_OBJECTpublic slots: // WRONGvoid b();};
};
信号/插槽返回类型不能为引用
信号和插槽可以有返回类型,但返回引用的信号或插槽将被视为返回void。
类的Signals和slot部分中只能出现Signals和slot
如果您试图在类的signals或slot部分中放置signals和slot以外的其他构造,moc会抱怨。
Qt:使用元对象编辑器Moc相关推荐
- Qt的元对象(Meta-Object)系统简介(转)
Qt的元对象系统基于如下三件事情: 1.类:QObject,为所有需要利用原对象系统的对象提供了一个基类. 2.宏:Q_OBJECT,通常可以声明在类的私有段中,让该类可以使用元对象的特性,比如动态属 ...
- 基于Qt5.14.2和mingw的Qt源码学习(三) — 元对象系统简介及moc工具是如何保存类属性和方法的
基于Qt5.14.2和mingw的Qt源码学习(三) - 元对象系统简介及moc工具是如何保存类属性和方法的 一.什么是元对象系统 1.元对象系统目的 2.实现元对象系统的关键 3.元对象系统的其他一 ...
- Qt元对象系统(Meta-Object)(四)、Moc源代码分析
目录 前言 打开源代码 源码追踪解析 总结 前言 前面讲了那么多,Qt的元对象系统是多么多么厉害,多么多么好,那么Moc是具体是怎么工作的,所谓源码面前,了无秘密,下面让我们一探究竟. 打开源代码 ...
- Qt工作笔记-Qt元对象系统解析【2合1】
博文转载地址: https://blog.csdn.net/spwper/article/details/51332187 说Qt信号与槽是一个很好机制,不如说Qt的元对象系统很强大.这也是大家讲Qt ...
- QT Embedded二三事之QObject的元对象
一.元对象 元对象被称做是meta object.在运行时刻(runtime),能够提供对象的运行时信息. 在C++语言发展的早期,C++语言本身没有定义对象的运行时信息,如输出类的名称,父类的名称 ...
- qt中实现息屏开平mousepress_Qt元对象(Meta-Object)系统与反射
前言 给部门内部培训Qt相关的一些注意点用的,我提取出来放到自己的博客上了.欢迎各位大佬吐嘈 原文链接 Qt元对象(Meta-Object)系统与反射 - C++ Programerwww.cryf ...
- 【QT】QT元对象系统
QT元对象系统(Meta-Object-System) 元对象系统 元对象系统是一个基于标准C++的扩展,为QT提供了信号与槽机制.实时类型信息.动态属性系统. 元对象系统的三个基本条件:类必须继承自 ...
- 利用Qt元对象技术防止工厂模式下代码臃肿问题,QT 动态创建对象(第2种方法)
问题的提出: 近来要编写一个仿真液压.电力.机械的软件,如下为液压的: 可以看到液压图中很多液压元器件,这些元器件的id.名称等都是从json配置文件读取的,配置文件格式如下: {"Clas ...
- linux创建自定义组件qt,QT中的元对象系统:创建自定义的QT类型
原创文章,转载请注明出处,谢谢! 作者:清林,博客名:飞空静渡 QVariant可以表示QT中的大部分类型,它和pascal中的variant类型或c中的void类型有点相似,不过它的使用和c中的un ...
- Qt元对象系统:QMetaObject
一.描述 此类包含有关Qt对象的元信息.Qt为应用程序中使用的每个 QObject 子类创建一个 QMetaObject 实例,该实例存储 QObject 子类的所有元信息. 二.静态成员函数 1.Q ...
最新文章
- mac pro下安装gdb和delve调试器
- yii2-wx / 微信二维码接口
- 不是同一个工程的exe与dll,如何调试dll
- IOS之代理文字点击变大变小
- Java Web Jsp
- python until语句_详解Lua中repeat...until循环语句的使用方法
- python画枫叶_python-文件的操作
- 软件工程团队项目Alpha版本产品介绍
- 缺陷定位 | 如何精准效率分析推测BUG定位(二)
- 浏览器中跨域创建cookie的问题
- 【探索PowerShell 】【十二】筛选器 - Filters
- 便利删除_知名便利店凉了?!刚刚道歉
- iis7.5+.net4.5 报404错误
- ibatis中iterate的用法(conjunction=or ,)
- Android-Universal-Image-Loader的工具类封装
- 开源中文分词FudanNLP
- 流水灯程序总结:关于Crol和cror的用法
- 外网登录homeassistant
- 提高团队协作效率就靠它们了!
- python学习---画3d曲线曲面图
热门文章
- win10怎么更新显卡驱动_win10系统AMD显卡驱动安装失败的解决方法
- led灯光衰怎么解决_解决LED灯具光衰办法大全
- 【埋点体系】(一)-埋点的理解
- mysql创建用户并授权语句_MySQL创建用户与授权
- mysql不区分英文字母大小写模糊查询
- 英特尔400系列服务器芯片组,英特尔400系列芯片组似乎还不支持PCIe 4.0
- Tightvncserver 连接树莓派的方法及步骤
- node.js以及Vue的脚手架安装过程
- 专家,除了呼吁涨价你还会干点什么?
- 文本乱码怎么办?教你一招批量修改文本文件的编码格式,轻松解决乱码问题