Q объект бросает' неопределенная ссылка на vtable ' ошибка [дубликат]


этот вопрос уже есть ответ здесь:

  • Ошибка компоновщика Qt: "неопределенная ссылка на vtable" [дубликат] 9 ответов

Я использую Qt Creator 2.0.1 с Qt 4.7.0 (32 бит) на Windows 7 Ultimate 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.

что не так с кодом? Спасибо.

5 52

5 ответов:

Это связано с тем, что блок, созданный MOC, не включен в процесс связывания. Или, может быть, он вообще не генерируется. Первое, что я бы сделал, это поместить объявление класса в отдельный файл заголовка, возможно, система сборки не сканирует файлы реализации.

другая возможность заключается в том, что рассматриваемый класс когда-то не принадлежал к системе метаобъектов Qt (то есть у него не было Q_OBJECT или, возможно, вообще не наследуется от QObject), поэтому qmake необходимо запустить снова, чтобы создайте необходимые правила для MOC. Самый простой способ заставить qmake быть запущенным-внести некоторые незначительные изменения в файл проекта, чтобы обновить его метку времени, например, добавить, а затем удалить пробел. Или, если вы используете Qt Creator, то просто выберите "Запустить qmake" из контекстного меню проекта.

если вы хотите определить QObject подкласс в исходном файле, то вы должны добавить строку

#include "file.moc"

в какой-то момент после определения класса, где имя исходным файлом был файл.СРР. Вам нужно будет повторно запустить qmake конечно, так что соответствующие правила moc добавляется в файл Makefile.

только когда в заголовочном файле присутствует Q_OBJECT в определении класса причина moc будет вызван. Если это исходный файл, вам это нужно дополнительная линия, чтобы заставить moc использовать.

Я уверен, что подобный вопрос был задан раньше, но я не мог найти его.

поместите классы Q_OBJECT в отдельные файлы. Это одно .ч и одна .cpp для каждого класса. Макросы метаобъектов Qt в этом отношении довольно придирчивы.

кроме того, вы можете использовать QGraphicsObject для ваших целей. Это сэкономит вам немного времени.

Edit: я вижу, вы используете Creator. Используйте свою новую функцию класса C++ в новом файле или проекте, чтобы создать файл "правильным образом":)

вот рабочий код, добавленный со всеми исправлениями, указанными в других вопросах (пробовал чистую компиляцию и эти исправления помогают):

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

Так что реальный кредит Трубадуру и serge_gubenko

есть пара вещей, чтобы посмотреть на:

  1. добавить Qt += gui в ваш pro файл
  2. убедитесь, что вы определяете свои производные от QObject классы только в заголовочных файлах (edit: как отметил Трубадур, это не требуется)
  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);
}

Я пробовал компилировать код выше и никаких проблем с этим не было.

надеюсь, это поможет, с уважением