C++ 在头文件中实现Qt moc?

C++ 在头文件中实现Qt moc?,c++,qt,moc,C++,Qt,Moc,可以告诉Qt MOC我想在单个文件中声明并实现该类,而不是将它们拆分为.h和.cpp文件吗?如果您想在cpp文件中声明并实现QObject子类,您必须手动包含MOC文件 例如:(文件main.cpp) 添加#include语句后,您必须重新运行moc(make qmake)。我认为您通常可以在头文件中声明和实现该类,而无需使用任何特殊的语句,例如: #include <QObject> class MyClass : public QObject { Q_OBJECT p

可以告诉Qt MOC我想在单个文件中声明并实现该类,而不是将它们拆分为.h和.cpp文件吗?

如果您想在cpp文件中声明并实现QObject子类,您必须手动包含MOC文件

例如:(文件main.cpp)


添加
#include
语句后,您必须重新运行moc(
make qmake
)。

我认为您通常可以在头文件中声明和实现该类,而无需使用任何特殊的语句,例如:

#include <QObject>

class MyClass : public QObject
{
  Q_OBJECT

  public:
     MyClass(QObject * parent)
     {
        // Constructor Content
     }

     methodExample()
     {
          // Method content
     }
};
#包括
类MyClass:公共QObject
{
Q_对象
公众:
MyClass(QObject*父对象)
{
//构造函数内容
}
方法示例()
{
//方法内容
}
};

在此之后,将头文件添加到pri文件并再次执行qmake,就这样。您有一个继承自qobject的类,该类在.h文件中实现并声明。

我认为这是最好的方法。这就是我现在构造所有对象的方式

Qt 4.8.7

Works.pro:

SOURCES += \
    main.cpp

HEADERS += \
    Window.h \
    MyWidget.h
main.cpp

#include <QtGui>
#include "Window.h"

int main(int argc, char *argv[])
{
    QApplication app(argc,argv);

    Window window;
    window.show();
    return app.exec();
}
#包括
#包括“Window.h”
int main(int argc,char*argv[])
{
QApplication应用程序(argc、argv);
窗口窗口;
window.show();
返回app.exec();
}
窗户

#ifndef WINDOW_H
#define WINDOW_H

#include <QtGui>
#include "MyWidget.h"

class Window : public QWidget
{
    Q_OBJECT

private:
    MyWidget *whatever;

public:
    Window()
    {
        QHBoxLayout *layout = new QHBoxLayout;
        setLayout(layout);

        whatever = new MyWidget("Screw You");
        layout->addWidget(whatever);

    }
};

#include "moc_Window.cpp"

#endif // WINDOW_H
\ifndef窗口
#定义窗口
#包括
#包括“MyWidget.h”
类窗口:公共QWidget
{
Q_对象
私人:
MyWidget*随便什么;
公众:
窗口()
{
QHBoxLayout*布局=新的QHBoxLayout;
设置布局(布局);
whatever=newmywidget(“去你的”);
布局->添加小部件(无论什么);
}
};
#包括“moc_Window.cpp”
#endif//WINDOW\u H
MyWidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QtGui>

class MyWidget : public QLabel
{
    Q_OBJECT

public:
    MyWidget(QString text) : QLabel(text)
    {
        // Whatever
    }
};

#include "moc_MyWidget.cpp"

#endif // MYWIDGET_H
\ifndef MYWIDGET\u H
#定义MYWIDGET_H
#包括
类MyWidget:publicqlabel
{
Q_对象
公众:
MyWidget(QString文本):QLabel(文本)
{
//随便
}
};
#包括“moc_MyWidget.cpp”
#endif//MYWIDGET_H
建造。。。 qmakeworks.pro

使

TL;博士 是的,如果您只谈论您自己编写的文件(与moc生成的文件相反)。你根本不需要做任何特别的事情

如果您希望在编写的文件中明确包含moc输出,则有一种情况下您必须这样做,还有一种情况下您可能希望这样做。假设
MyObject
类在
MyObject.h
中声明,您对它的定义在
MyObject.cpp
中给出:

// MyObject.cpp
#include "MyObject.h"
#include "moc_MyObject.cpp"
...
  • MyObject.moc
    必须包含在
    MyObject.cpp
    iff的末尾,如果您在
    MyObject.cpp
    中声明了任何
    Q\u对象

  • moc\u MyObject.cpp
    可以包含在
    MyObject.cpp
    中的任何位置,以将项目中的翻译单元数量减半。这只是一个构建时优化。如果不这样做,
    moc\u MyObject.cpp
    将单独编译

  • 每次从任何源文件或头文件中添加或删除
    Q_对象
    宏,或在此类文件中添加或删除moc输出的显式包含时,必须重新运行qmake/cmake。

    要在Qt Creator中重新运行qmake/cmake,只需右键单击顶级项目,然后从上下文菜单中选择run qmake或run cmake

    简单的答案 基于qmake的Qt项目示例可能包含三个文件,如下所示:

    # test.pro
    QT       += core
    CONFIG   += console
    CONFIG   -= app_bundle
    TEMPLATE = app
    SOURCES += main.cpp
    HEADERS += myobject.h
    
    // main.cpp
    #include "myobject.h"
    
    int main() {
      MyObject obj;
      obj.staticMetaObject; // refer to a value defined in moc output
      return 0;
    }
    
    // myobject.h
    #ifndef MYOBJECT_H
    #define MYOBJECT_H
    #include <QObject>
    
    class MyObject : public QObject {
       Q_OBJECT
    public:
       MyObject() {}
       Q_SLOT void aSlot() {}
    };
    
    #endif // MYOBJECT_H
    
    // myobject.h
    #ifndef MYOBJECT_H
    #define MYOBJECT_H
    #include <QObject>
    
    class MyObject : public QObject {
       Q_OBJECT
    public:
       MyObject() {}
       Q_SLOT void aSlot() {}
    };
    
    #include "moc_myobject.cpp"
    #endif // MYOBJECT_H
    
    目前,项目仍将编译,似乎实现了您的目标,即只有一个文件定义了整个
    MyObject
    ——您编写的位和moc生成的位,两者都是。但这仅仅是因为一个不太可能令人愉快的环境:
    moc.*.cpp
    的内容仍然只在一个翻译单元中-

    假设现在我们将第二个源文件添加到项目中:

    # test.pro
    QT       += core
    CONFIG   += console
    CONFIG   -= app_bundle
    TEMPLATE = app
    SOURCES += main.cpp test.cpp
    HEADERS += myobject.h
    
    // test.cpp
    #include "myobject.h"
    
    没什么大不了的。它应该会起作用,即使它没什么作用,对吧

    唉,它不会链接。现在,
    moc_myobject.cpp
    的内容是两个翻译单元的一部分。由于
    moc\u myobject.cpp
    的内部充满了独立的类成员定义,这违反了。该规则规定,独立定义只能出现在目标中的一个翻译单元中。作为这条规则的捍卫者,链接者正确地抱怨

    在.cpp文件中包含moc输出时 如TL中所述;DR,在特定情况下,上述任何一项都不排除在源(.cpp)文件中显式包含moc输出

    给定“foo.h”和“foo.cpp”,以及由qmake或cmake管理的项目,构建系统将指导
    moc
    生成最多两个输出:

  • moc_foo.cpp
    来自
    foo.h
    iff
    foo.h
    包含
    Q_对象

  • foo.moc
    来自
    foo.cpp
    iff
    foo.cpp
    包含
    #包括“foo.moc”

  • 让我们详细研究一下为什么要在.cpp文件中包含其中任何一个

    包括xxx.moc 有时,特别是在C++11和Qt5之前的日子里,仅在一个翻译单元(源文件)内声明小型助手QObject类供本地使用非常方便

    当编写用于stackoverflow的单文件、自包含测试用例和示例时,这也很方便

    假设您希望有人在一个文件中演示如何从事件循环调用插槽:

    // main.cpp
    #include <QCoreApplication>
    #include <QTextStream>
    #include <cstdio>
    
    QTextStream out(stdout);
    
    class MyObject : public QObject {
      Q_OBJECT
    public:
      MyObject() {}
      Q_SLOT void mySlot() { out << "Hello from " << __FUNCTION__ << endl; }
    };
    
    int main(int argc, char ** argv) {
      QCoreApplication app(argc, argv);
      MyObject obj;
      QMetaObject::invokeMethod(&obj, Qt::QueuedConnection, "mySlot");
      QMetaObject::invokeMethod(&app, Qt::QueuedConnection, "quit");
      return app.exec();
    }
    
    #include "main.moc"
    

    我想你的意思是
    qmake make
    而不是反过来说:)不,我没有。只需运行一次
    qmake
    即可创建
    Makefile
    s。如果您想在以后重新运行moc,只需运行
    make qmake
    。无法使其工作。。看来我运气不好。无论如何谢谢。对不起,我不知道你指的是一个命令,即
    qmake
    make
    
    // MyObject.cpp
    #include "MyObject.h"
    #include "moc_MyObject.cpp"
    ...