Q_OBJECT抛出'未定义的引用vtable'错误

Don*_*alo 63 c++ qt linker-errors vtable

我在Windows 7 Ultimate 32位上使用Qt Creator 2.0.1和Qt 4.7.0(32位).

请考虑以下代码,这是产生错误的最小代码:

class T : public QObject, public QGraphicsItem
{
    Q_OBJECT

public:
    T() {}

    QRectF      boundingRect() const {return QRectF();}
    void        paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                      QWidget *widget) {}
};

int main()
{
    T t;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码片段导致以下链接器错误:

在函数"T"中:

未定义引用`vtable for T'

未定义引用`vtable for T'

在函数`~T'中:

未定义引用`vtable for T'

未定义引用`vtable for T'

如果我注释掉包含的行Q_OBJECT,它编译得很好.我需要信号和插槽,QGraphicsItem所以我需要Q_OBJECT.

代码有什么问题?谢谢.

Ser*_*nov 124

这是因为MOC生成的单元不包含在链接过程中.或者它可能根本就没有生成.我要做的第一件事是将类声明放在一个单独的头文件中,也许构建系统不是扫描实现文件.

另一种可能性是,有问题的类曾经不属于Qt元对象系统(也就是说,它根本没有Q_OBJECT或者根本没有从QObject继承),所以需要再次运行qmake才能创建MOC的必要规则.强制运行qmake的最简单方法是对项目文件进行一些无关紧要的更改以更新其时间戳,例如添加然后删除一些空白区域.或者,如果您正在使用Qt Creator,则只需从项目上下文菜单中选择"Run qmake".

  • 谢谢你的想法.我清理并重建了项目但是没有用.然后我编辑了*.pro文件并重新编译.它解决了这个问题! (4认同)
  • 现场回答 - 涵盖了我的情况,其中对象最初不属于Qt元对象系统.简单地编辑文件对我来说不起作用.我不得不删除我的.user文件,并按@Donotalo建议触摸*.pro文件.再次运行qMake之后,生活又恢复了良好. (3认同)

Tro*_*our 23

如果要QObject在源文件中定义子类,则需要添加该行

#include "file.moc"
Run Code Online (Sandbox Code Playgroud)

在您的类定义之后的某个时刻,源文件的名称是file.cpp.您qmake当然需要重新运行,以便将运行的相应规则moc添加到Makefile中.

只有在头文件中,才会调用Q_OBJECT类定义中的存在moc.如果它是源文件,则需要使用此额外行来强制moc使用.

我确定以前曾问过类似的问题,但我找不到它.

  • +1真棒,我不知道这个! (2认同)

Ste*_*Chu 8

将您的Q_OBJECT类放在单独的文件中.这是每个班级的一个.h和一个.cpp.Qt的元对象宏在这方面有点挑剔.

此外,您可以将QGraphicsObject用于您的目的.在那里节省你一些时间.

编辑:我看到你正在使用Creator.在New File或Project中使用其New C++ Class函数以"正确的方式"创建文件:)


Tuu*_*oos 6

以下是添加了其他问题中提供的所有修复的工作代码(尝试了清理编译和这些修复帮助):

#include <QGraphicsItem>

class T : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem) //Required.

public:
    T() {}
    QRectF      boundingRect() const {return QRectF();}
    void        paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                      QWidget *widget) {}
};

int main(int argc, char *argv[])
{
    T *t = new T;
    return 0;
}

#include "main.moc" // Required.
Run Code Online (Sandbox Code Playgroud)

所以对Troubadour和serge_gubenko的实际信用