- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
编辑:我对这篇文章进行了大量编辑,以将项目精简到它的本质。我还添加了 Github repository ,包括本文未提及的文件。
我有一个使用 subdirs
模板的 Qt Creator 项目(qmake、Qt 5.2.0、Creator 3.0.0)。共有三个子项目:
TEMPLATE = lib
和 CONFIG += staticlib
的库。TEMPLATE = lib
和 CONFIG += staticlib
并使用 Field
库的库。我正在 Windows 8.1 (MSVC2012) 和 Linux (gcc 4.8.1) 上构建此应用程序。 它在 Windows 上运行没有问题,但 Linux 版本的行为很奇怪。
我得到的错误如下所示:
undefined reference to 'vtable for Stadium::Engine'
我已将此项目重写为一组显示错误的裸文件。你可以在 Github 上找到它:Football .随意克隆它并自己查看所有错误。 661441c
提交解决了问题,09836f9
提交包含错误。
Stadium Engine.h 文件是一个抽象类。它看起来像这样:
#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
这里是 Football Engine.h 文件,它继承自上面的 Stadium Engine.h 文件:
#ifndef FOOTBALL_ENGINE_H
#define FOOTBALL_ENGINE_H
#include <QObject>
#include "../Stadium/Engine.h"
namespace Football
{
class Engine : public Stadium::Engine
{
Q_OBJECT
public:
Engine();
~Engine() {}
public slots:
void executeCommand();
};
} // namespace Football
#endif // FOOTBALL_ENGINE_H
还有 Football Engine.cpp 文件:
#include "Engine.h"
#include <QDebug>
Football::Engine::Engine()
{
qDebug() << "[Football::Engine] Created.";
}
void Football::Engine::executeCommand()
{
qDebug() << "[Football::Engine] The command was executed.";
}
如果我将构造函数定义从 cpp 移动到头文件中,它会正确构建。
下面是 Server.pro 文件。它表示我所有其他专业文件,因为静态链接描述(由 Qt Creator 自动生成)看起来相同。
QT += core
QT -= gui
TARGET = Server
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Stadium/release/ -lStadium
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Stadium/debug/ -lStadium
else:unix: LIBS += -L$$OUT_PWD/../Stadium/ -lStadium
INCLUDEPATH += $$PWD/../Stadium
DEPENDPATH += $$PWD/../Stadium
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/release/libStadium.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/debug/libStadium.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/release/Stadium.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Stadium/debug/Stadium.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../Stadium/libStadium.a
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Football/release/ -lFootball
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Football/debug/ -lFootball
else:unix: LIBS += -L$$OUT_PWD/../Football/ -lFootball
INCLUDEPATH += $$PWD/../Football
DEPENDPATH += $$PWD/../Football
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/release/libFootball.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/debug/libFootball.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/release/Football.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../Football/debug/Football.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../Football/libFootball.a
我尝试过清理、重新运行 qmake、删除构建目录和重建。在 Linux 中构建此项目的唯一方法是删除 Stadium 库的 .pro 文件中的 CONFIG += staticlib
行(以及相应的 else:unix: PRE_TARGETDEPS += $当然,Game.pro 中的 $OUT_PWD/../stadium/libstadium.a
行也是如此)。这成功地构建了项目并且运行没有问题。但我就是不明白为什么。我也不明白为什么定义构造函数的地方很重要。
有什么想法吗?
最佳答案
答案非常简单:这些库的链接顺序错误。
我查看了调用链接器的命令(就在链接器错误上方):
g++ [...] -lStadium [...] -lFootball
我还查看了代码:Football 子项目是指 Stadium 子项目,因此库的顺序错误,例如,请参阅 GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()' 的接受答案解释一下。
确实,如果我交换 Server.pro 文件中的两个库(源自提交 09836f9
,为简洁起见,删除了无关的 win32 特定细节):
[...]
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
它可以在我的 Linux 机器上编译和运行。
关于c++ - 使用 CONFIG += staticlib 构建 Qt 应用程序会导致 "undefined reference to vtable"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21512077/
我是一名优秀的程序员,十分优秀!