C++ 使用CONFIG+;构建Qt应用程序“原因”;未定义对vtable的引用;错误
编辑:我对这篇文章进行了大量的编辑,以将这个项目精简到最基本的部分。我还添加了一个,包括本文中未引用的文件C++ 使用CONFIG+;构建Qt应用程序“原因”;未定义对vtable的引用;错误,c++,linux,qt,gcc,qt-creator,C++,Linux,Qt,Gcc,Qt Creator,编辑:我对这篇文章进行了大量的编辑,以将这个项目精简到最基本的部分。我还添加了一个,包括本文中未引用的文件 我有一个QtCreator项目(qmake,Qt5.2.0,Creator 3.0.0),它使用子目录模板。有三个子项目: 体育场-配置为TEMPLATE=lib和CONFIG+=staticlib的库 足球-配置为TEMPLATE=lib和CONFIG+=staticlib并使用字段的库 服务器-使用体育场和足球库的QML应用程序 我正在Windows8.1(MSVC2012)和Lin
我有一个QtCreator项目(qmake,Qt5.2.0,Creator 3.0.0),它使用
子目录
模板。有三个子项目:
TEMPLATE=lib
和CONFIG+=staticlib
的库TEMPLATE=lib
和CONFIG+=staticlib
并使用字段的库
undefined reference to 'vtable for Stadium::Engine'
#ifndef STADIUM_ENGINE_H
#define STADIUM_ENGINE_H
#include <QObject>
namespace Stadium {
class Engine : public QObject
{
Q_OBJECT
public slots:
virtual void executeCommand() = 0;
};
} // namespace Stadium
#endif // STADIUM_ENGINE_H
我已将此项目重写为一组显示错误的裸文件。您可以在Github上找到它,网址:。请随意克隆它并亲自查看所有错误。661441c
commit解决了问题,而09836f9
commit包含错误
Stadium Engine.h文件是一个抽象类。看起来是这样的:
undefined reference to 'vtable for Stadium::Engine'
#ifndef STADIUM_ENGINE_H
#define STADIUM_ENGINE_H
#include <QObject>
namespace Stadium {
class Engine : public QObject
{
Q_OBJECT
public slots:
virtual void executeCommand() = 0;
};
} // namespace Stadium
#endif // STADIUM_ENGINE_H
我尝试过清理、重新运行qmake、删除构建目录和重建。在Linux中构建此项目的唯一方法是删除Stadium库的.pro文件中的CONFIG+=staticlib
行(当然还有Game.pro中相应的else:unix:PRE\u TARGETDEPS+=$$OUT\u PWD/./Stadium/libstadium.a
行)。这将成功构建项目,并且运行时不会出现问题。但我不明白为什么。我也不明白为什么构造函数定义在哪里很重要
有什么想法吗?您已经内联了虚拟析构函数。
这有时会导致问题。
尝试在.cpp文件中实现析构函数。我还将从析构函数的声明中删除
=0
我看不到您在哪里运行moc编译器。moc创建一个文件,用于解析QObject派生类的其他内容
如果moc正在运行,那么您的命名空间可能就是问题所在。众所周知,moc不能很好地处理名称空间。我喜欢名称空间,但Qt在人们开始到处使用它们之前就已经存在了
如果该类不是绝对必需的,那么移除Q_对象并从QObject派生是另一种解决方案
另一种可能是您的makefile已过时。在这种情况下,您需要强制运行qmake以确保它们正确刷新。您可以查看以下其他问题:
无论如何,您的类继承自QObject,它已经声明并实现了一个非纯虚拟析构函数。纯虚拟析构函数有用吗 好吧,我找到了解决办法。我有三个不同的问题,当更改时,会清除vtable错误。不幸的是,我不知道为什么后两个改变是必要的 1.派生类中的Q_对象 继承上述Stadium::Engine类的类内部有一个额外的Q_对象。当我删除派生类中的第二个Q_对象时,其中一个vtable错误消失了 2.引擎构造器 我不明白为什么,但是当派生类在CPP文件中定义构造函数时,它会给出
vtable
错误。在标题中定义(在类描述中)时,它可以正常工作。构造函数中没有任何内容(DerivedEngine(){}
)。我不明白这有什么关系
3.定义构造函数和虚拟析构函数
要求构造函数和析构函数都在纯抽象类中定义。我不明白为什么。我在类定义之外的标题中添加了以下行:
inline Stadium::Engine::Engine() {}
inline Stadium::Engine::~Engine() {}
这仍然困扰着我。为什么这些改变是必要的?为什么这只发生在gcc/Linux上?这肯定是一个Qt错误,对吗?答案非常简单:库的链接顺序错误。 我查看了调用链接器的命令(链接器错误正上方): 我还研究了代码:Football子项目指的是Stadium子项目,因此库的顺序是错误的,例如,请参见的公认答案以获取解释 事实上,如果我交换Server.pro文件中的两个库(源自commit
09836f9
,为简洁起见,删除了与win32相关的详细信息):
现在,命令行如下所示:
g++ [...] -lFootball [...] -lStadium
它在我的Linux机器上编译并运行得很好。内联析构函数是某个人的建议,他认为它可能会有所帮助。删除它不会影响错误。(编辑时间用完):不幸的是,将析构函数删除到CPP文件(或完全删除)不会改变任何内容。我也试着让它非纯,但没用。当你需要运行qmake时,我看到了这一点again@paulm,是的,但它似乎不起作用。我开始怀疑在构建过程中有一个bug。显示从中继承的代码Engine@paulm,您暗示的建议至少部分正确。:)从引擎继承的代码有一个额外的Q_对象宏(不必要,因为继承的类已经有了这个宏)。奇怪的是,构建过程从未在继承的类中标记错误。我仍在努力弄清楚,在我尝试过的15件事情中,哪些是我帮助过的,但我很快会发布解决方案
g++ [...] -lStadium [...] -lFootball
[...]
SOURCES += main.cpp
LIBS += -L$$OUT_PWD/../Football/ -lFootball
INCLUDEPATH += $$PWD/../Football
DEPENDPATH += $$PWD/../Football
PRE_TARGETDEPS += $$OUT_PWD/../Football/libFootball.a
LIBS += -L$$OUT_PWD/../Stadium/ -lStadium
INCLUDEPATH += $$PWD/../Stadium
DEPENDPATH += $$PWD/../Stadium
PRE_TARGETDEPS += $$OUT_PWD/../Stadium/libStadium.a
g++ [...] -lFootball [...] -lStadium