为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C++
杨魅力 2019-07-30 17:06:46
Qt链接器错误:“对vtable的未定义引用”这是我的标题:#ifndef BARELYSOCKET_H#define BARELYSOCKET_H#include <QObject>//! The First Draw of the BarelySocket!class BarelySocket: public QObject{    Q_OBJECTpublic:    BarelySocket();public slots:    void sendMessage(Message aMessage);signals:    void reciveMessage(Message aMessage);private:    //   QVector<Message> reciveMessages;};#endif // BARELYSOCKET_H这是我的班级:#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){}我收到链接器错误:undefined reference to 'vtable for BarelySocket'这意味着我有一个未实现的虚方法。但我班上没有虚拟方法。我评论出矢量认为它是原因,但错误并没有消失。这Message是一个复杂的struct,但即使使用int而不是解决问题
查看完整描述

3 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

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

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


查看完整回答
反对 回复 2019-07-30
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

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

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

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

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

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

virtual const QMetaObject *metaObject() const;

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

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


查看完整回答
反对 回复 2019-07-30
  • 3 回答
  • 0 关注
  • 1352 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信