the Meta-Object Compiler (moc)
the Meta-Object Compiler (moc)
元对象编译器是处理Qt的C++扩展的程序。
moc工具读取C++头文件,如果它找到一个或者多个类声明包含Q_OBJECT宏。它生为那些类成一个包含元对象代码的C++源文件。元对象代码是信号与槽机制,运行时信息和动态属性系统所必需的。
moc生成的C++源文件在类的实现过程中必需进行编译和连接。
如果你用qmake创建makefiles,包含的创建规则在需要的时候调用moc,所以你不用直接使用moc。
Usage
moc典型的用法,输入文件包含的类声明:
class MyClass : publicQObject
{
Q_OBJECT
public:
MyClass(QObject*parent =0);
~MyClass();
signals:
void mySignal();
publicslots:
void mySlot();
};
除了以上显示的信号与槽机制外,moc实现对象属性如下例子。Q_PROPERTY()宏声明了一个对象属性, Q_ENUMS()在类中声明了一个枚举类型,可以用在属性系统中。
在下面的例子,我们声明了一个枚举属性,一个获取属性的方法priority() 和设置属性的方法setPriority().。
class MyClass : public QObject
{
Q_OBJECT
Q_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(), 允许你给类的元对象添加额外的name/value对信息。
class MyClass : public QObject
{
Q_OBJECT
Q_CLASSINFO("Author","Oscar Peterson")
Q_CLASSINFO("Status","Active")
public:
MyClass(QObject *parent =0);
~MyClass();
};
moc生成的文件必须和程序中的其他C++源文件一样进行编译和链接;否则,在在生成的链接阶段将失败。如果你使用qmake,这将会自动完成。当qmake允许起来,它解析工程的头文件和生成创建规则以为那些包含 Q_OBJECT宏的文件进行调用moc。
如果类在myclass.h中声明,moc生成 的文件为moc_myclass.cpp。这个文件一样进行编译,在windows上生成的目标文件moc_myclass.obj。这个目标文件在程序生成过程都需要进行连接的。
Writing Make Rules for Invoking moc
为了简单的测试程序,建议自动运行moc。通过添加规则到程序的makefile,可以在需要的时候很好的运行moc和处理moc的生成文件。
我们建议使用qmake 的makefile生成工具创建makefile。这个工具生成moc需要的所有操作的makefile。
如果你想创建自己的makefile,这里有一些如何包含moc操作的提示。
对于头文件中 Q_OBJECT宏声明,如果你只用GNU make这里有一个很有用的makefile规则:
moc_%.cpp: %.h
moc $(DEFINES) $(INCPATH) $<-o $@
如果你想写的更灵活,你可以用如下的单独的规则格式:
moc_foo.cpp: foo.h
moc $(DEFINES) $(INCPATH) $<-o $@
你必须记得添加moc_foo.cpp到你的SOURCES 变量和moc_foo.o 或moc_foo.obj到你的OBJECTS 变量。
所有的例子都假设$(DEFINES) 和 $(INCPATH) 展开到传递到C++编译器的define和include路径选项。这些都是moc在进行源文件的预处理时需要的。
我们喜欢把源文件命名为.cpp。其实也可以用其他扩展,如.c,.cc,.CC,.cxx和.c++。
对于.cpp文件中的r Q_OBJECT宏声明,我们建议makefile规则如下:
foo.o: foo.moc
foo.moc: foo.cpp
moc $(DEFINES) $(INCPATH) -i $<-o $@
这保证了在编译foo.cpp之前允许moc,你可以把:
#include "foo.moc"
放在foo.cpp的末尾。所有类声明都已完全可知的地方。
Command-Line Options
以下是moc支持命令行选项:
|
Option |
Description |
|
-o<file> |
Write output to <file> rather than to standard output. |
|
-f[<file>] |
Force the generation of an #include statement in the output. This is the default for header files whose extension starts with H or h. This option is useful if you have header files that do not follow the standard naming conventions. The <file> part is optional. |
|
-i |
Do not generate an #include statement in the output. This may be used to run the moc on on a C++ file containing one or more class declarations. You should then #include the meta-object code in the .cpp file. |
|
-nw |
Do not generate any warnings. (Not recommended.) |
|
-p<path> |
Makes the moc prepend <path>/ to the file name in the generated #include statement. |
|
-I<dir> |
Add dir to the include path for header files. |
|
-E |
Preprocess only; do not generate meta-object code. |
|
-D<macro>[=<def>] |
Define macro, with optional definition. |
|
-U<macro> |
Undefine macro. |
|
@<file> |
Read additional command-line options from <file>. Each line of the file is treated as a single option. Empty lines are ignored. Note that this option is not supported within the options file itself (i.e. an options file can't "include" another file). |
|
-h |
Display the usage and the list of options. |
|
-v |
Display moc's version number. |
|
-Fdir |
Mac OS X. Add the framework directory dir to the head of the list of directories to be searched for header files. These directories are interleaved with those specified by -I options and are scanned in a left-to-right order (see the manpage for gcc). Normally, use -F /Library/Frameworks/ |
你可以显示的告诉moc不要解析头文件中的某些部分。moc定义了预处理宏 Q_MOC_RUN. 。
以下代码将被moc忽略。
#ifndef Q_MOC_RUN
...
#endif
Diagnostics
在 Q_OBJECT 类声明中,moc会给出一些危险或者非法的创建的警告。
如果在程序生成的最后阶段发生连接错误,说YourClass::className() 没有定义或YourClass缺少虚函数表vtable。一定是出现了某些错误。最可能的是,你忘记编译或 #include包含了moc生成的C++源文件,或者在连接命令忘记包含目标文件。如果你用qmake,试着重新运行更新makefile,这就行了。
Limitations
moc不能处理所有的C++。最主要的问题是模板类不能用信号或槽。例如:
次要的是,以下的结构都是非法的。他们都选择了我们认为是更好的,所以去掉这些限制对我们来说并不是优先选择。
MultipleInheritance Requires QObject to Be First
如果使用多继承,moc假定第一个被继承的类是 QObject.的子类。确保只有第一个被继承的类是QObject.。
不支持对QObject的虚拟继承。
FunctionPointers Cannot Be Signal or Slot Parameters
在大部分情况,你可以考虑使用函数指针作为信号或槽的参数,我们觉得继承是一个号的替代选择。如下例子有语法错误:
class SomeClass : public QObject
{
Q_OBJECT
publicslots:
void apply(void (*apply)(List *, void *), char *); // WRONG
};
我们可以进行如下变通:
typedef void (*ApplyFunction)(List *, void *);
class SomeClass : public QObject
{
Q_OBJECT
publicslots:
void apply(ApplyFunction, char *);
};
最好还是用继承或虚函数替代函数指针。
Enumsand Typedefs Must Be Fully Qualified for Signal and Slot Parameters
当检查参数的签名时, QObject::connect() 逐字地的进行比较数据类型。因此, Alignment和 Qt::Alignment 被当成不同的类型。为了解决这个问题,当声明信号和槽,或者建立connection时,确保取得数据类型的完全资格。
class MyClass : public QObject
{
Q_OBJECT
enum Error {
ConnectionRefused,
RemoteHostClosed,
UnknownError
};
signals:
void stateChanged(MyClass::Error error);
};
NestedClasses Cannot Have Signals or Slots
这是个结构不好的例子:
class A
{
public:
class B
{
Q_OBJECT
publicslots: // WRONG
void b();
};
};
Signal/Slotreturn types cannot be references
信号和槽可以有返回类型,但是信号或槽返回引用会被当成返回void。
Only Signals and Slots May Appear in the signals and slots Sections of aClass
moc会抱怨,如果你试图将信号和槽意外的结构放在信号和槽段。
http://blog.csdn.net/hai200501019/article/details/9157149
the Meta-Object Compiler (moc)的更多相关文章
- Qt Meta Object System-元对象系统
研一的时候开始使用Qt,感觉用Qt开发图形界面比MFC的一套框架来方便的多.后来由于项目的需要,也没有再接触Qt了.现在要重新拾起来,于是要从基础学起. Now,开始学习Qt事件处理机制. 元对象系统 ...
- 6、Qt Meta Object system 学习
原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...
- Qt Meta Object system 学习
原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...
- 类classthe Meta-Object Compiler (moc)
本文是一篇关于类class的帖子 the Meta-Object Compiler (moc) 元对象编译器是处理Qt的C++扩展的程序. moc工具读取C++头文件,如果它找到一个或者多个类声明包含 ...
- Lepus经历收获杂谈(二)——QT
QT简介及相关使用指南 1.QT Qt是1991年奇趣科技开发的一个跨平台的C++图形用户界面应用程序框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框 ...
- C++专题 - Qt是什么
Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程式,也可用于开发非GUI程式,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊的代码生成扩展(称 ...
- Qt入门(1)——初识Qt
Qt是一个跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta ...
- 树莓派入门教程——使用Qt开发界面程序
前言 Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特 ...
- QT笔记(1)--QT编程环境搭建
一.QT简介 Qt 是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊 ...
随机推荐
- CodeForces 443B Kolya and Tandem Repeat
题目:Click here 题意:给定一个字符串(只包含小写字母,并且最长200)和一个n(表示可以在给定字符串后面任意加n(<=200)个字符).问最长的一条子串长度,子串满足前半等于后半. ...
- ARM简介(科普文)
ARM简介[1] 1. ARM只卖知识产权,不卖(物理的,实质的)产品. 全世界100多家公司购买了ARM授权,包括三星,Freescale.NXP Semiconductors.STMicro ...
- [转载]CSS 创作指南(Beta)(css规范)
当年还在纠结各种规范的时候,不知道从哪里翻到这个,就让我脱离了css这个规范的苦海了... 反正就是团队和项目合作说的算,选择合适的进行使用就可以了,见到合适的文章,我也会转载过来的 来源 https ...
- oracle 集合变量以及自定义异常的用法
oracle 集合变量以及自定义异常的用法, 在过程 record_practice 有record变量和自定义异常的用法实例.具体在3284行. CREATE OR REPLACE Package ...
- 关于java中强制转换
在百度上遇到一个问题,描述如下: 在java中,定义两个变量 byte x = (byte) 128; byte y = (byte)-129; 输出后,为什么结果是-128和128? 借此机会,自己 ...
- known good die( KGD) /确认好裸芯片,合格芯片
英文:known good die( KGD) / 中文:确认好裸芯片,合格芯片 完工的晶圆上有许多晶片存在,其单一品质有好有坏,经过老化试验后,其确知电性能良好的晶片即称为己知好晶片.不过,已知好晶 ...
- VC6中创建Qt工程的创建
文章来源:http://blog.sina.com.cn/s/blog_64d015c10100sf1o.html 本文主要介绍怎么创建可以在VC6中编译的QT工程.本文所采用环境为VC++6.0+Q ...
- Windows 8.1 RTM初体验
Windows 8.1正式发布在10月17日,现在可以在MSDN/TechNet进行订阅下载. 操作系统版本号和Windows Server 2012 R2保持一致. 开始屏幕动态磁贴现在有4种尺寸可 ...
- poj 3281 Dining 网络流-最大流-建图的题
题意很简单:JOHN是一个农场主养了一些奶牛,神奇的是这些个奶牛有不同的品味,只喜欢吃某些食物,喝某些饮料,傻傻的John做了很多食物和饮料,但她不知道可以最多喂饱多少牛,(喂饱当然是有吃有喝才会饱) ...
- uva - The Lottery(容斥,好题)
10325 - The Lottery The Sports Association of Bangladesh is in great problem with their latest lotte ...