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++。最主要的问题是模板类不能用信号或槽。例如:

class SomeTemplate<int> : public QFrame
{
    Q_OBJECT
    ...
 
signals:
    void mySignal(int);
};

次要的是,以下的结构都是非法的。他们都选择了我们认为是更好的,所以去掉这些限制对我们来说并不是优先选择。

MultipleInheritance Requires QObject to Be First

如果使用多继承,moc假定第一个被继承的类是 QObject.的子类。确保只有第一个被继承的类是QObject.。

// correct
class SomeClass : public QObject,public OtherClass
{
    ...
};

不支持对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)的更多相关文章

  1. Qt Meta Object System-元对象系统

    研一的时候开始使用Qt,感觉用Qt开发图形界面比MFC的一套框架来方便的多.后来由于项目的需要,也没有再接触Qt了.现在要重新拾起来,于是要从基础学起. Now,开始学习Qt事件处理机制. 元对象系统 ...

  2. 6、Qt Meta Object system 学习

    原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...

  3. Qt Meta Object system 学习

    原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...

  4. 类classthe Meta-Object Compiler (moc)

    本文是一篇关于类class的帖子 the Meta-Object Compiler (moc) 元对象编译器是处理Qt的C++扩展的程序. moc工具读取C++头文件,如果它找到一个或者多个类声明包含 ...

  5. Lepus经历收获杂谈(二)——QT

    QT简介及相关使用指南 1.QT Qt是1991年奇趣科技开发的一个跨平台的C++图形用户界面应用程序框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框 ...

  6. C++专题 - Qt是什么

    Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程式,也可用于开发非GUI程式,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊的代码生成扩展(称 ...

  7. Qt入门(1)——初识Qt

    Qt是一个跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta ...

  8. 树莓派入门教程——使用Qt开发界面程序

    前言        Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特 ...

  9. QT笔记(1)--QT编程环境搭建

    一.QT简介 Qt  是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊 ...

随机推荐

  1. An Introduction to Interactive Programming in Python

    这是在coursera上面的一门学习pyhton的基础课程,由RICE的四位老师主讲.生动有趣,一共是9周的课程,每一周都会有一个小游戏,经历一遍,对编程会产生很大的兴趣. 所有的程序全部在老师开发的 ...

  2. BZOJ 1634: [Usaco2007 Jan]Protecting the Flowers 护花( 贪心 )

    考虑相邻的两头奶牛 a , b , 我们发现它们顺序交换并不会影响到其他的 , 所以我们可以直接按照这个进行排序 ------------------------------------------- ...

  3. 织梦dedeCMS|系统基本配置标签

    站点根网址:    {dede:global.cfg_basehost/}调出网站的名称:   {dede:field.title/}-{dede:global.cfg_webname/}    网站 ...

  4. python笔记之列表与元组函数和方法使用举例

    在学习列表之前先了解了raw_input和input的区别:(仅适用于版本2,版本3中raw_input和input合并,没有raw_input) input的语法为:input("str& ...

  5. Qt编程中,Ui文件如何被利用

    这两天跟着班级辅导,总有学生感到很疑惑,用ui designer设计出来的ui文件是如何使用的,下面我从一个例子来说明下,希望能对有这样疑惑的同学有帮助. 事实上,现在有了继承设计工具qtcreato ...

  6. Windows Phone 8初学者开发—第14部分:在运行时绑定到真实的数据

    原文 Windows Phone 8初学者开发—第14部分:在运行时绑定到真实的数据 第14部分:在运行时绑定到真实的数据 原文地址: http://channel9.msdn.com/Series/ ...

  7. Android中通过进程注入技术改动广播接收器的优先级

    前言 这个周末又没有吊事,在家研究了怎样通过进程的注入技术改动广播接收器的优先级.关于这个应用场景是非常多的.并且也非常重要.所以就非常急的去fixed了. Android中的四大组件中有一个广播:B ...

  8. Ajax学习(三)——XMLHttpRequest对象的五步使使用方法

        Ajax的核心技术是XMLHttpRequest对象,它能够在不向server提交整个页面的情况下.实现局部更新网页.通过这个对象,Ajax能够像桌面应用程序那样仅仅与server进行数据层的 ...

  9. hdu 4737

    题目链接 直接暴力,或运算只会越来越大 #include <cstdio> #include <cstring> using namespace std; #define N ...

  10. 平实给力的写作指导入门手冊——leo鉴书57

    写作是个体力活儿,须要不断的练习和砥砺.既然是体力劳动,那必定有套路,前人总结.后人学习并加以积累沉积,日久则形成不同的风格和流派有点儿像.相同,写作也有自己的套路和学习路径.初涉写作有必备之书吗?当 ...