【问题标题】:Undefined reference to already defined interface destructor对已定义的接口析构函数的未定义引用
【发布时间】:2020-02-10 19:14:37
【问题描述】:

我有一个接口QInterruptable如下:

#ifndef QINTERRUPTABLE_H
#define QINTERRUPTABLE_H

class QInterruptable {
public:
    virtual void pause();
    virtual void resume();
    virtual void interrupt();
    virtual ~QInterruptable(){

    }
};

#endif // QINTERRUPTABLE_H

QInterruptable 的一个示例用法是将QThread WorkerObject 子类化为additional functionality

QInterruptable 在我的ThreadWorker 头文件中使用

#ifndef THREADWORKER_H
#define THREADWORKER_H

#include <QObject>
#include <functional>
#include <QWaitCondition>
#include <QMutex>

#include "QInterruptable.h"

class ThreadWorker : public QObject, public QInterruptable
{
    Q_OBJECT

private:
    QMutex mutex;
    QWaitCondition *waitCondition;
    std::function<void ()> runnable;
    bool shouldPause = false;

public:
    explicit ThreadWorker(QObject *parent = nullptr);
    ThreadWorker(std::function<void ()> func);
    ~ThreadWorker();

    void setRunnable(const std::function<void ()> &value);

signals:
    void started();
    void progress(int value);
    void finished();
    void error();

public slots:
    virtual void run();
    virtual void cleanup();

    // QInterruptable interface
public:
    void pause()
    {
        shouldPause = true;
    }
    void resume()
    {
        shouldPause = false;
    }
    void interrupt()
    {

    }

    QMutex& getMutex();
    QWaitCondition *getWaitCondition() const;
    void setWaitCondition(QWaitCondition *value);
    bool getShouldPause() const;

#endif // THREADWORKER_H

编译时遇到这个错误:

debug/threadworker.o: In function `ZN14QInterruptableD2Ev':
C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug/../qMyAwesomeApp/3rd-party/QThreading/QThreading/QInterruptable.h:9: undefined reference to `vtable for QInterruptable'
debug/threadworker.o: In function `ZN14QInterruptableC2Ev':
C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug/../qMyAwesomeApp/3rd-party/QThreading/QThreading/QInterruptable.h:4: undefined reference to `vtable for QInterruptable'
collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: *** [Makefile.Debug:195: debug/MyAwesomeApp.exe] Error 1
mingw32-make: *** [Makefile:38: debug] Error 2
mingw32-make[1]: Leaving directory 'C:/Users/CybeX/QtProjects/build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug'
09:29:08: The process "F:\Qt\Qt5.13.1\Tools\mingw730_32\bin\mingw32-make.exe" exited with code 2.
Error while building/deploying project MyAwesomeApp (kit: Desktop Qt 5.13.1 MinGW 32-bit)
When executing step "Make"

我查看了用于实现 C++ 接口的解决方案以及 undefined references to destructors 的解决方案。我发现 thisthisthis 特别提到了我的问题。

如你所见,我已经尝试用

定义析构函数
virtual ~QInterruptable(){

}

导致上述错误。

如果我像这样使用纯虚拟析构函数:

virtual ~QInterruptable() = 0;

然后我将问题传递给子类,即ThreadWorker,并出现以下错误:

debug/threadworker.o: In function `ZN12ThreadWorkerC2EP7QObject':
C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug/../qMyAwesomeApp/3rd-party/QThreading/QThreading/threadworker.cpp:28: undefined reference to `QInterruptable::~QInterruptable()'
debug/threadworker.o: In function `ZN12ThreadWorkerC2ESt8functionIFvvEE':
C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug/../qMyAwesomeApp/3rd-party/QThreading/QThreading/threadworker.cpp:33: undefined reference to `QInterruptable::~QInterruptable()'
debug/threadworker.o: In function `ZN12ThreadWorkerD2Ev':
C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug/../qMyAwesomeApp/3rd-party/QThreading/QThreading/threadworker.cpp:37: undefined reference to `QInterruptable::~QInterruptable()'
debug/threadworker.o: In function `ZN14QInterruptableC2Ev':
C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug/../qMyAwesomeApp/3rd-party/QThreading/QThreading/QInterruptable.h:4: undefined reference to `vtable for QInterruptable'
collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: *** [Makefile.Debug:195: debug/MyAwesomeApp.exe] Error 1
mingw32-make: *** [Makefile:38: debug] Error 2
mingw32-make[1]: Leaving directory 'C:/Users/CybeX/QtProjects/build-MyAwesomeApp-Desktop_Qt_5_13_1_MinGW_32_bit-Debug'
09:33:51: The process "F:\Qt\Qt5.13.1\Tools\mingw730_32\bin\mingw32-make.exe" exited with code 2.
Error while building/deploying project MyAwesomeApp (kit: Desktop Qt 5.13.1 MinGW 32-bit)
When executing step "Make"

有问题的ThreadWorker.cpp 行在哪里:

[28] ThreadWorker::ThreadWorker(QObject *parent) : QObject(parent)
[29] {
[30]     waitCondition = new QWaitCondition;
[31] }
[32] 
[33] ThreadWorker::ThreadWorker(std::function<void ()> func): runnable(func) {
[34]     waitCondition = new QWaitCondition;
[35] }
[36] 
[37] ThreadWorker::~ThreadWorker()
[38] {
[39]     if(waitCondition != nullptr){
[40]         delete waitCondition;
[41]     }
[42] }

如何解决这个对接口析构函数的未定义引用?

【问题讨论】:

  • 你运行 qmake 了吗?
  • 如果有人想知道这是否是构建问题,我会在每次构建之前清理并重新制作
  • @vahancho 是的,正要发布它。我在 IDE 上设置了每次调用 qmake,会再做一次,为了它的地狱
  • 如果有人愿意看,请在github.com/cybex-dev/QThreading找到它
  • 我的快速猜测是,您应该将 pause resume interrupt 设为纯虚拟(推荐)或提供一些默认定义。同样在c ++ 11中,您可以将析构函数(也是虚拟析构函数)声明为默认值 - 这是告诉编译器为您生成它的显式方式virtual ~QInterruptable() = default;

标签: c++ qt destructor undefined-reference


【解决方案1】:

您对基类的 vtable 有未定义的引用,因为您没有为基类的所有虚拟(bot 不是纯虚拟)方法提供定义,即:pauseresume、@987654324 @。现在,如果您声明这 3 个方法是纯虚拟的,则不需要对它们进行定义。或者,您可以将它们保留为非纯虚拟并编写一些默认定义。请注意,您的析构函数也是一个虚方法,也必须定义,但是您可以通过显式告诉编译器为您生成一个virtual ~QInterruptable() = default 来简化它。 GCC FAQ 中有一条关于它的条目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    相关资源
    最近更新 更多