Qt链接器错误:"对vtable的未定义引用"

Tho*_*mas 60 c++ qt linker-errors vtable qobject

这是我的标题:

#ifndef BARELYSOCKET_H
#define BARELYSOCKET_H

#include <QObject>
//! The First Draw of the BarelySocket!

class BarelySocket: public QObject
{
    Q_OBJECT

public:
    BarelySocket();
public slots:
    void sendMessage(Message aMessage);
signals:
    void reciveMessage(Message aMessage);

private:
    //   QVector<Message> reciveMessages;
};

#endif // BARELYSOCKET_H
Run Code Online (Sandbox Code Playgroud)

这是我的班级:

#include <QTGui>
#include <QObject>
#include "type.h"
#include "client.h"
#include "server.h"

#include "barelysocket.h"

BarelySocket::BarelySocket()
{
    //this->reciveMessages.clear();
    qDebug("BarelySocket::BarelySocket()");
}

void BarelySocket::sendMessage(Message aMessage)
{
}

void BarelySocket::reciveMessage(Message aMessage)
{
}
Run Code Online (Sandbox Code Playgroud)

我收到链接器错误:

undefined reference to 'vtable for BarelySocket'
Run Code Online (Sandbox Code Playgroud)
  • 这意味着我有一个未实现的虚方法.但我班上没有虚拟方法.
  • 我评论出矢量认为它是原因,但错误并没有消失.
  • Message是一个复杂的struct,但即使使用int而不是解决问题.

Mic*_*ael 140

每次向Q_OBJECT宏添加新调用时,都需要再次运行qmake.您所指的vtable问题与此直接相关.

只需运行qmake,您应该好好假设您的代码中没有其他问题.

  • 在QT Creator中,使用Build菜单中的qmake运行. (27认同)
  • 谢谢!从命令行,只使用`make`通常也会更新一些与qmake相关的东西,但显然还不够.确实需要明确地运行`qmake`. (2认同)

Seb*_*edl 42

我已经看到很多方法来解决这个问题,但没有解释为什么会发生这种情况,所以这里就是这样.

当编译器看到具有虚函数的类(直接声明或继承)时,它必须为该类生成vtable.由于类通常在头文件中定义(因此出现在多个翻译单元中),因此问题在于放置vtable的位置.

通常,可以通过在定义类的每个TU中生成vtable来解决问题,然后让链接器消除重复.由于ODR在每次出现时要求类定义相同,因此这是安全的.但是,它也会降低编译速度,膨胀对象文件,并要求链接器执行更多工作.

因此,作为优化,编译器将在可能的情况下选择一个特定的TU来放入vtable.在通用的C++ ABI中,这个TU 是实现类的关键功能的那个,其中关键功能是第一个在类中声明但未定义的虚拟成员函数.

在Qt类的情况下,它们通常以Q_OBJECT宏开头,并且该宏包含声明

virtual const QMetaObject *metaObject() const;
Run Code Online (Sandbox Code Playgroud)

因为它是宏中的第一个虚函数,所以它通常是该类的第一个虚函数,因此也是它的关键函数.因此,编译器不会在大多数TU中发出vtable,只会执行实现的vtable metaObject.此函数的实现moc在处理标头时自动写入.因此,您需要moc处理标头以生成新的.cpp文件,然后在编译中包含.cpp文件.

因此,当您有一个定义了一个QObject派生类的新标头时,您需要重新运行qmake以便它更新您的makefile以moc在新标头上运行并编译生成的.cpp文件.

  • 很棒的写作.我正在使用CMake而不是qmake,我经常看到这个错误; 理解基本的C++ vtable信息并且仍然无法弄清楚出了什么问题,这是非常令人沮丧的.谢谢! (7认同)

Dav*_*vid 15

我在一个小的"main.cpp"文件中创建了一个小类后,我遇到了这个错误.

经过一个小时左右的训练后,我终于将该课程从main.cpp移到了一个独立的hpp文件中,更新了.pro(项目)文件,然后项目构建得非常好.这可能不是问题,但我认为无论如何它都是有用的信息.


Ron*_*del 11

从经验来看:经常是qmake && make clean && make help.我个人认为有时候改变发现/缓存效果/不管怎么说 - 我不知道xxxxx.我不能说为什么,但这是我遇到这种错误时做的第一件事.

顺便说一句.有一个错误> recive <

您忘记在构造函数中调用QObject构造函数(在初始化列表中).(虽然它没有解决错误)

  • 当文件存在但在运行qmake时没有任何Q_OBJECT引用时,这尤其有用.qmake然后不相信它需要运行moc并且你最终得到vtable错误.make clean并不总是必要的,但是当进行某些结构变化时. (5认同)
  • 还要确保barelysocket.h位于pro文件的HEADERS部分. (4认同)

lst*_*kov 6

对我来说,我从构建日志中注意到没有调用 moc。Clean All 没有帮助。所以我删除了 .pro.user,重新启动了 IDE,它就成功了。