题
是否可以告诉脱交通部,我谨声明的类而实现它在一个单一文件而不是分裂它们成。h。cpp的文件?
解决方案 4
我相信这是最好的方式。它实际上是我现在该怎么构建我的所有对象。
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中
#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
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
...生成 的qmake Works.pro
请
其他提示
如果你想声明和实现你的cpp文件一个QObject子类,则必须手动包括商务部的文件。
例如:(文件main.cpp中)
struct SubObject : QObject
{
Q_OBJECT
};
//...
#include "main.moc"
您有添加make qmake
语句后重新运行的moc(#include
)。
TL博士
是的,如果你只讨论的文件的编写自己(而不是那些由交通部).你不需要做什么特别的东西。
如果你曾经希望,包括交通部出明确的文件中,你写信,还有一个情况下在其中 必须 做到这一点,一种情况下你 可能会 希望这样做。让我们假设 MyObject
类声明 MyObject.h
和你的定义,它给予在 MyObject.cpp
:
MyObject.moc
必须 包括 在结束 的MyObject.cpp
森林论坛 你的任何声明Q_OBJECT
课程内MyObject.cpp
.moc_MyObject.cpp
可 包括 任何地方 在MyObject.cpp
数减少一半的翻译单位在项目中。这是一个建立时优化只。如果你不这样做,moc_MyObject.cpp
将单独编制。
每次你添加或删除 Q_OBJECT
宏从任何来源头或文件,或者添加或删除的明确的内含物的交通部出在这些文件,必须重新运行qmake/cmake.
重新运行qmake/cmake在建造物主,只是右击顶级项目,并选择 运行qmake 或 运行cmake 从上下文的菜单。
简单的回答
一个例子qmake基建项目可能包括的三个文件,具体如下:
# 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
它没有做多,但它肯定是有效的。除了各图书馆的建立系统的链接我们的项目,有两个具体项目 翻译单位: main.cpp
和 moc_myobject.cpp
.
即使它似乎整个执行情况 MyObject
在该标题的文件,它实际上不是。的 Q_OBJECT
宏宣称,某些位的实施,这将是不确定的,如果不是因为商务部所产生定义。
如何交通部进入画面?项目时首先建立,metabuild工具的任qmake或cmake-扫描的所有C++输入文件的存在 Q_OBJECT
宏。那些包含有它,给予特殊治疗。在这个例子项目, myobject.h
包含 Q_OBJECT
而是处理通过交通部成 moc_myobject.cpp
.后者是列入名单的来源,汇编C++编译器。它是,只有在概念上,因为如果你不得不 SOURCES += moc_myobject.cpp
在 .pro
文件。 你当然应该永远不会添加这样一个线的.亲的文件。
现在注意到 整个 执行情况 MyObject
掌握在两个文件: myobject.h
和 moc_myobject.cpp
. myobject.h
可以包含尽可能多的翻译单位,如你所愿-因为没有出类(独立的)定义中,将违反这一定义的规则。在建立系统的对待 moc_myobject.cpp
作为一个单一的、单独的翻译单元--这是所有的照顾你。
因此你的目标是达到与没有在所有的努力:你有没有什么特别的事情要把整个执行情况 MyObject
-保存的位部产生-进入该标题的文件。它可能延长的编制时间,但否则是无害的。
一规则的违反的方法
它违反了 一个定义的规则, 确切的说,是的,因而产生无效C++的程序。
现在你可能想要获得"聪明"和强制性地包括交通部出入标题的文件。该qmake/cmake/比斯将被收容,并将检测到这一点,并不会单独处理交通部的输出通过编译了,因为你已经做到了。
因此,假设,在该项目上所述,改变了你 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_*.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_myobject.cpp
's的内心是完全的独立类成员的定义,这违反了 一个定义的规则.该规则规定,独立的定义可能只出现在 一个翻译单位 在一目标。连接,被监护人的这条规则,正确地抱怨。
在包括交通部出的。cpp文件
正如TL博士,没有上述的排除了明确包含商业产出的来源(.cpp)的文件,在具体情况。
给予"foo。h"和"foo.cpp"和项目管理的qmake或cmake,建立系统将直接 moc
产生了两个产出:
moc_foo.cpp
从foo.h
, 森林论坛foo.h
包含Q_OBJECT
宏。foo.moc
从foo.cpp
, 森林论坛foo.cpp
包含#include "foo.moc"
.
让我们仔细研究为什么你想要包括两个中的一个。cpp文件。
包括xxx.交通部
有时候,特别是在前几天C++11和脱5,它涉及便利的声明的小助手QObject类为地方内使用一个翻译单元(资料来源文件)。
这也是方便的时候写的单一文件,自包含的测试案例和实例对计算器的使用。
假设你希望有人来证明,在一个文件,如何调用一个插槽从事件循环:
// 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"
由于 MyObject
是一个小类,只使用本地 main.moc
, 它不会有多大意义,把它定义为一个单独的标题的文件。的 #include "main.moc"
行将注意到通过qmake/cmake, main.cpp
将通过交通部,导致 main.moc
.由于 main.moc
限定成员 MyObject
, 它必须包括地方在哪里 MyObject
是的声明。作为《宣言》是在 main.cpp
, 你不能拥有 main.moc
是一个单独的翻译单位:它不会由于汇编 MyObject
是不申报。唯一的地方,它是宣布紧 main.cpp
, 某个地方。这就是为什么它是一个安全的赌注总是包括 foo.moc
在结束 foo.cpp
.
一个精明的读者现在要求:怎么来的 moc_foo.cpp
获取的声明的类成员,它定义了?很简单:它明确地包括对标题的文件,它是产生(这里: foo.h
).当然 foo.moc
不能做到这一点,因为它会破坏一个单一的定义规则,由乘限定的一切 foo.cpp
.
包括moc_xxx.cpp
在特别的大型建项目,可能必须在平均水平的两个文件 和 两个翻译单位的每个类别:
MyObject.h
和MyObject.cpp
是的文件的编写。MyObject.cpp
和moc_MyObject.cpp
是的翻译单位。
它是可能的数减少一半的翻译单位的明确包括 moc_MyObject.cpp
在某个地方 MyObject.cpp
:
// MyObject.cpp
#include "MyObject.h"
#include "moc_MyObject.cpp"
...
我觉得你可以正常申报并实施的头文件中的类,而无需使用任何特殊,例如:
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass(QObject * parent)
{
// Constructor Content
}
methodExample()
{
// Method content
}
};
在此,你的头文件添加到PRI文件,然后再执行qmake的,就是这样。你有一个类从Qobject继承并实现和诠释,他宣称.h文件中。