69

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

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

在函数“T”中:

未定义对 `vtable for T' 的引用

未定义对 `vtable for T' 的引用

在函数“~T”中:

未定义对 `vtable for T' 的引用

未定义对 `vtable for T' 的引用

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

代码有什么问题?谢谢。

4

5 回答 5

135

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

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

于 2011-01-23T14:33:58.050 回答
26

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

#include "file.moc"

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

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

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

于 2011-01-23T15:45:14.973 回答
8

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

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

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

于 2011-01-23T15:18:02.080 回答
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.

所以真正归功于 Troubadour 和 serge_gubenko

于 2011-01-23T21:14:26.970 回答
4

有几件事要看:

  1. 在您的专业文件中添加 QT += gui
  2. 确保仅在头文件中定义 QObject 派生类(编辑:如 Troubadour 所述,这不是必需的)
  3. 将 Q_INTERFACES(QGraphicsItem) 添加到 T 类的声明中

下面是一个例子:

日:

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

我已经尝试编译上面的代码并且没有遇到问题。

希望这会有所帮助,问候

于 2011-01-23T15:45:12.943 回答