C++ Q_OBJECT 抛出“对 vtable 的未定义引用”错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4774291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:25:48  来源:igfitidea点击:

Q_OBJECT throwing 'undefined reference to vtable' error

c++qtlinker-errorsvtable

提问by Donotalo

I'm using Qt Creator 2.0.1 with Qt 4.7.0 (32 bit) on Windows 7 Ultimate 32 bit.

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

Consider the following code, which is a minimum to produce the error:

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

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;
}

The above code fragment causes the following linker errors:

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

In function `T':

undefined reference to `vtable for T'

undefined reference to `vtable for T'

In function `~T':

undefined reference to `vtable for T'

undefined reference to `vtable for T'

在函数‘T’中:

对‘vtable for T’的未定义引用

对‘vtable for T’的未定义引用

在函数`~T'中:

对‘vtable for T’的未定义引用

对‘vtable for T’的未定义引用

If I comment out the line that contains Q_OBJECT, it compiles fine. I need signal and slots with QGraphicsItemso I need Q_OBJECT.

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

What is wrong with the code? Thanks.

代码有什么问题?谢谢。

回答by Sergei Tachenov

It is because the unit generated by MOC isn't included in the linking process. Or maybe it isn't generated at all. The first thing I'd do is to put the class declaration in a separate header file, perhaps the build system isn't scanning implementation files.

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

Another possibility is that the class in question once didn't belong to Qt meta object system (that is, it had no Q_OBJECT or maybe didn't inherit from QObject at all), so qmake needs to be run again in order to create the necessary rules for MOC. The easiest way to force qmake to be run is to make some insignificant changes to the project file to update its timestamp, like adding and then removing some white space. Or, if you're using Qt Creator, then just select “Run qmake” from the project context menu.

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

回答by Troubadour

If you want to define a QObjectsubclass in a source file then you need to add the line

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

#include "file.moc"

at some point after your class definition where the name of the source file was file.cpp. You will need to re-run qmakeof course so that the appropriate rule to run mocgets added to the Makefile.

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

Only when in a header file does the presence of Q_OBJECTin a class definition cause mocto be invoked. If it's a source file you need this extra line to force mocto be used.

仅当在头文件中时,Q_OBJECT类定义moc中的 才会导致被调用。如果它是源文件,则需要强制moc使用此额外行。

I'm sure a similar question has been asked before but I couldn't find it.

我确定以前有人问过类似的问题,但我找不到。

回答by Stephen Chu

Put your Q_OBJECT classes in separate files. That is one .h and one .cpp for each class. Qt's meta-object macros are kind of picky in this regard.

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

Also, you can use QGraphicsObjectfor your purpose. Saves you some time there.

此外,您可以将QGraphicsObject用于您的目的。为您节省一些时间。

Edit: I see you are using Creator. Use its New C++ Class function in New File or Project to create the file in the "right way" :)

编辑:我看到您正在使用 Creator。在新文件或项目中使用它的新 C++ 类函数以“正确的方式”创建文件:)

回答by Tuukka Lindroos

Here is working code added with all fixes provided in other questions (Tried clean compiling and these fixes help):

这是添加了其他问题中提供的所有修复的工作代码(尝试干净编译,这些修复有帮助):

#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.

So actual credit to Troubadour and serge_gubenko

所以真正归功于 Troubadour 和 serge_gubenko

回答by serge_gubenko

there are couple of thing to look at:

有几件事要看:

  1. Add QT += gui in your pro file
  2. Make sure you define your QObject-derived classes in your header files only (edit: as Troubadour noted, this is not required)
  3. Add Q_INTERFACES(QGraphicsItem) to the declaration of your T class
  1. 在您的 pro 文件中添加 QT += gui
  2. 确保仅在头文件中定义 QObject 派生类(编辑:正如 Troubadour 指出的,这不是必需的)
  3. 将 Q_INTERFACES(QGraphicsItem) 添加到 T 类的声明中

below is an example:

下面是一个例子:

t.h:

日:

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

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

t.cpp:

t.cpp:

T::T() {}

QRectF T::boundingRect() const
{
    return QRectF();
}

void T::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(painter);
    Q_UNUSED(option);
    Q_UNUSED(widget);
}

I've tried compiling the code above and didn't have problems with it.

我试过编译上面的代码并且没有问题。

hope this helps, regards

希望这有帮助,问候