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是面向对象的框架,使用特殊 ...
随机推荐
- use MSBuild cmd to build and deploy the database project.
You can use the below command to implement it. SET TargetDBName="Database name" SET DataBa ...
- C#编辑基础笔记
目录 1. .NET .NET Framework是一种多语言的平台,一种技术. 而c#是基于其上面的一种语言. 1 2. Winform 桌面应用程序[从.net平台上面开发的 ...
- 在Windows Server 2008 R2 中架设 SMTP 服务器
安装SMTP服务器 Step 1 在功能里面勾选SMTP 服务器,一路下一步完成安装 Step 2 在IIS6的SMTP属性里面的访问标签点击连接,然后设置本机可访问. (其实可以不用设置) Step ...
- Css静态进度条
图片预览: Css代码: <style> .statusList{width:240px; float:left; line-height:68px;margin:0 2px; text- ...
- BULK SQL
DECLARE TYPE TY_EMP IS TABLE OF EMP%ROWTYPE; --如果是IS TABLE OF行类型(ROWTYPE.RECORD等)就是二维 V_Emp TY_EMP; ...
- codeforces 629D. Babaei and Birthday Cake
题目链接 大意就是给出一个序列, 然后让你从中找出一个严格递增的数列, 使得这一数列里的值加起来最大. 用线段树, 先将数列里的值离散,然后就是线段树单点更新, 区间查询最值. 具体看代码. #inc ...
- day4作业
作业内容:计算器 #!/usr/bin/env python # -*- coding:utf-8 -*- import re,time #加减字符处理函数 def handle_symbol(cal ...
- tf–idf算法解释及其python代码实现(上)
tf–idf算法解释 tf–idf, 是term frequency–inverse document frequency的缩写,它通常用来衡量一个词对在一个语料库中对它所在的文档有多重要,常用在信息 ...
- js获取select默认选中的Option (非当前选中值)
js函数方法: <script> function getDefaultSelectedOption(selectId, valIfNull) { var selectId = selec ...
- javascript模块加载框架seajs详解
SeaJS是一个遵循commonJS规范的javascript模块加载框架,可以实现javascript的模块化开发和模块化加载(模块可按需加载或全部加载).SeaJS可以和jQuery完美集成,使用 ...