gpt4 book ai didi

c++ - 使用 CONFIG += staticlib 构建 Qt 应用程序会导致 "undefined reference to vtable"错误

转载 作者:IT老高 更新时间:2023-10-28 22:29:11 33 4
gpt4 key购买 nike

编辑:我对这篇文章进行了大量编辑,以将项目精简到它的本质。我还添加了 Github repository ,包括本文未提及的文件。


我有一个使用 subdirs 模板的 Qt Creator 项目(qmake、Qt 5.2.0、Creator 3.0.0)。共有三个子项目:

  1. Stadium - 配置为 TEMPLATE = libCONFIG += staticlib 的库。
  2. Football - 配置为 TEMPLATE = libCONFIG += staticlib 并使用 Field 库的库。
  3. 服务器 - 一个使用 Stadium 和 Football 库的 QML 应用程序。

我正在 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/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com