the Meta-Object Compiler (moc)
2016-02-01 19:49
447 查看
theMeta-ObjectCompiler(moc)
元对象编译器是处理Qt的C++扩展的程序。
moc工具读取C++头文件,如果它找到一个或者多个类声明包含Q_OBJECT宏。它生为那些类成一个包含元对象代码的C++源文件。元对象代码是信号与槽机制,运行时信息和动态属性系统所必需的。
moc生成的C++源文件在类的实现过程中必需进行编译和连接。
如果你用qmake创建makefiles,包含的创建规则在需要的时候调用moc,所以你不用直接使用moc。
classMyClass:publicQObject
{
Q_OBJECT
public:
MyClass(QObject *parent=0);
~MyClass();
signals:
voidmySignal();
publicslots:
voidmySlot();
};
除了以上显示的信号与槽机制外,moc实现对象属性如下例子。Q_PROPERTY()宏声明了一个对象属性,Q_ENUMS()在类中声明了一个枚举类型,可以用在属性系统中。
在下面的例子,我们声明了一个枚举属性,一个获取属性的方法priority()和设置属性的方法setPriority().。
Q_FLAGS()宏声明一个可以用作标记的枚举值。另外一个宏Q_CLASSINFO(),允许你给类的元对象添加额外的name/value对信息。
moc生成的文件必须和程序中的其他C++源文件一样进行编译和链接;否则,在在生成的链接阶段将失败。如果你使用qmake,这将会自动完成。当qmake允许起来,它解析工程的头文件和生成创建规则以为那些包含Q_OBJECT宏的文件进行调用moc。
如果类在myclass.h中声明,moc生成的文件为moc_myclass.cpp。这个文件一样进行编译,在windows上生成的目标文件moc_myclass.obj。这个目标文件在程序生成过程都需要进行连接的。
我们建议使用qmake的makefile生成工具创建makefile。这个工具生成moc需要的所有操作的makefile。
如果你想创建自己的makefile,这里有一些如何包含moc操作的提示。
对于头文件中Q_OBJECT宏声明,如果你只用GNUmake这里有一个很有用的makefile规则:
如果你想写的更灵活,你可以用如下的单独的规则格式:
你必须记得添加moc_foo.cpp到你的SOURCES变量和moc_foo.o或moc_foo.obj到你的OBJECTS变量。
所有的例子都假设$(DEFINES)和$(INCPATH)展开到传递到C++编译器的define和include路径选项。这些都是moc在进行源文件的预处理时需要的。
我们喜欢把源文件命名为.cpp。其实也可以用其他扩展,如.c,.cc,.CC,.cxx和.c++。
对于.cpp文件中的rQ_OBJECT宏声明,我们建议makefile规则如下:
这保证了在编译foo.cpp之前允许moc,你可以把:
放在foo.cpp的末尾。所有类声明都已完全可知的地方。
你可以显示的告诉moc不要解析头文件中的某些部分。moc定义了预处理宏Q_MOC_RUN.。
以下代码将被moc忽略。
Q_OBJECT类声明中,moc会给出一些危险或者非法的创建的警告。
如果在程序生成的最后阶段发生连接错误,说YourClass::className()没有定义或YourClass缺少虚函数表vtable。一定是出现了某些错误。最可能的是,你忘记编译或#include包含了moc生成的C++源文件,或者在连接命令忘记包含目标文件。如果你用qmake,试着重新运行更新makefile,这就行了。
次要的是,以下的结构都是非法的。他们都选择了我们认为是更好的,所以去掉这些限制对我们来说并不是优先选择。
QObject.的子类。确保只有第一个被继承的类是QObject.。
不支持对QObject的虚拟继承。
我们可以进行如下变通:
最好还是用继承或虚函数替代函数指针。
QObject::connect()逐字地的进行比较数据类型。因此,Alignment和Qt::Alignment被当成不同的类型。为了解决这个问题,当声明信号和槽,或者建立connection时,确保取得数据类型的完全资格。
http://blog.csdn.net/hai200501019/article/details/9157149
元对象编译器是处理Qt的C++扩展的程序。
moc工具读取C++头文件,如果它找到一个或者多个类声明包含
moc生成的C++源文件在类的实现过程中必需进行编译和连接。
如果你用qmake创建makefiles,包含的创建规则在需要的时候调用moc,所以你不用直接使用moc。
Usage
moc典型的用法,输入文件包含的类声明:classMyClass:public
{
Q_OBJECT
public:
MyClass(
~MyClass();
signals:
voidmySignal();
publicslots:
voidmySlot();
};
除了以上显示的信号与槽机制外,moc实现对象属性如下例子。
在下面的例子,我们声明了一个枚举属性,一个获取属性的方法priority()和设置属性的方法setPriority().。
classMyClass:publicQObject
{
Q_OBJECT
Q_PROPERTY(PrioritypriorityREADpriorityWRITEsetPriority)
Q_ENUMS(Priority)
public:
enumPriority{High,Low,VeryHigh,VeryLow};
MyClass(QObject *parent=0);
~MyClass();
voidsetPriority(Prioritypriority){m_priority=priority;}
Prioritypriority()const{returnm_priority;}
private:
Prioritym_priority;
};
classMyClass:publicQObject
{
Q_OBJECT
Q_CLASSINFO("Author","OscarPeterson")
Q_CLASSINFO("Status","Active")
public:
MyClass(QObject *parent=0);
~MyClass();
};
moc生成的文件必须和程序中的其他C++源文件一样进行编译和链接;否则,在在生成的链接阶段将失败。如果你使用qmake,这将会自动完成。当qmake允许起来,它解析工程的头文件和生成创建规则以为那些包含
如果类在myclass.h中声明,moc生成的文件为moc_myclass.cpp。这个文件一样进行编译,在windows上生成的目标文件moc_myclass.obj。这个目标文件在程序生成过程都需要进行连接的。
WritingMakeRulesforInvokingmoc
为了简单的测试程序,建议自动运行moc。通过添加规则到程序的makefile,可以在需要的时候很好的运行moc和处理moc的生成文件。我们建议使用qmake的makefile生成工具创建makefile。这个工具生成moc需要的所有操作的makefile。
如果你想创建自己的makefile,这里有一些如何包含moc操作的提示。
对于头文件中
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
foo.o:foo.moc
foo.moc:foo.cpp
moc$(DEFINES)$(INCPATH)-i$<-o$@
这保证了在编译foo.cpp之前允许moc,你可以把:
#include"foo.moc"
放在foo.cpp的末尾。所有类声明都已完全可知的地方。
Command-LineOptions
以下是moc支持命令行选项:Option | Description |
-o<file> | Writeoutputto<file>ratherthantostandardoutput. |
-f[<file>] | Forcethegenerationofan#includestatementintheoutput.ThisisthedefaultforheaderfileswhoseextensionstartswithHorh.Thisoptionisusefulifyouhaveheaderfilesthatdonotfollowthestandardnamingconventions.The<file>partisoptional. |
-i | Donotgeneratean#includestatementintheoutput.ThismaybeusedtorunthemocononaC++filecontainingoneormoreclassdeclarations.Youshouldthen#includethemeta-objectcodeinthe.cppfile. |
-nw | Donotgenerateanywarnings.(Notrecommended.) |
-p<path> | Makesthemocprepend<path>/tothefilenameinthegenerated#includestatement. |
-I<dir> | Adddirtotheincludepathforheaderfiles. |
-E | Preprocessonly;donotgeneratemeta-objectcode. |
-D<macro>[=<def>] | Definemacro,withoptionaldefinition. |
-U<macro> | Undefinemacro. |
@<file> | Readadditionalcommand-lineoptionsfrom<file>.Eachlineofthefileistreatedasasingleoption.Emptylinesareignored.Notethatthisoptionisnotsupportedwithintheoptionsfileitself(i.e.anoptionsfilecan't"include"anotherfile). |
-h | Displaytheusageandthelistofoptions. |
-v | Displaymoc'sversionnumber. |
-Fdir | MacOSX.Addtheframeworkdirectorydirtotheheadofthelistofdirectoriestobesearchedforheaderfiles.Thesedirectoriesareinterleavedwiththosespecifiedby-Ioptionsandarescannedinaleft-to-rightorder(seethemanpageforgcc).Normally,use-F/Library/Frameworks/ |
以下代码将被moc忽略。
#ifndefQ_MOC_RUN
...
#endif
Diagnostics
在如果在程序生成的最后阶段发生连接错误,说YourClass::className()没有定义或YourClass缺少虚函数表vtable。一定是出现了某些错误。最可能的是,你忘记编译或#include包含了moc生成的C++源文件,或者在连接命令忘记包含目标文件。如果你用qmake,试着重新运行更新makefile,这就行了。
Limitations
moc不能处理所有的C++。最主要的问题是模板类不能用信号或槽。例如:classSomeTemplate<int>:publicQFrame
{
Q_OBJECT
...
signals:
voidmySignal(int);
};
次要的是,以下的结构都是非法的。他们都选择了我们认为是更好的,所以去掉这些限制对我们来说并不是优先选择。
MultipleInheritanceRequiresQObjecttoBeFirst
如果使用多继承,moc假定第一个被继承的类是//correct
classSomeClass:publicQObject ,publicOtherClass
{
...
};
不支持对
FunctionPointersCannotBeSignalorSlotParameters
在大部分情况,你可以考虑使用函数指针作为信号或槽的参数,我们觉得继承是一个号的替代选择。如下例子有语法错误:classSomeClass:publicQObject
{
Q_OBJECT
publicslots:
voidapply(void(*apply)(List*,void*),char*);//WRONG
};
我们可以进行如下变通:
typedefvoid(*ApplyFunction)(List*,void*);
classSomeClass:publicQObject
{
Q_OBJECT
publicslots:
voidapply(ApplyFunction,char*);
};
最好还是用继承或虚函数替代函数指针。
EnumsandTypedefsMustBeFullyQualifiedforSignalandSlotParameters
当检查参数的签名时,classMyClass:publicQObject
{
Q_OBJECT
enumError{
ConnectionRefused,
RemoteHostClosed,
UnknownError
};
signals:
voidstateChanged(MyClass::Errorerror);
};
NestedClassesCannotHaveSignalsorSlots
这是个结构不好的例子:classA
{
public:
classB
{
Q_OBJECT
publicslots://WRONG
voidb();
};
};
Signal/Slotreturntypescannotbereferences
信号和槽可以有返回类型,但是信号或槽返回引用会被当成返回void。OnlySignalsandSlotsMayAppearinthesignalsandslotsSectionsofaClass
moc会抱怨,如果你试图将信号和槽意外的结构放在信号和槽段。相关文章推荐
- The Meta-Object System
- QThread 与 QObject的关系(QObject可以用于多线程,可以发送信号调用存在于其他线程的slot函数,但GUI类不可重入)
- WPF输入框Paste时出错,IDataObject的GetData抛出OutOfMemoryException
- java基础之 超类Object
- Swift学习之Objective-C 与 Swift 混用(1)
- The DataWindows Object not find。。。。错误提示-----------运维日志19
- json中jobject
- 使用Objective-C解压缩ZIP文件教程
- Objective Foundations
- objective-zip解压带密码的文件
- 2 类与对象
- embed区别object
- Uncaught Error: Error calling method on NPObject的几种解决方案
- windows 上用Sublime Text编译objective-c
- Objective-C简介
- Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id)等
- Objective-C多个UIButton同时点击问题
- commonJS — 对象操作(for Object)
- scala伴生对象companion object
- Js中Prototype、__proto__、Constructor、Object、Function关系介绍