Подтвердить что ты не робот

Q_OBJECT throwing 'undefined ссылка на ошибку vtable'

Я использую 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 ':

undefined ссылка на `vtable для T '

undefined ссылка на `vtable для T '

В функции `~ T ':

undefined ссылка на `vtable для T '

undefined ссылка на `vtable для T '

Если я прокомментирую строку, содержащую Q_OBJECT, она компилируется отлично. Мне нужен сигнал и слоты с QGraphicsItem, поэтому мне нужно Q_OBJECT.

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

#include "file.moc"

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

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

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

Ответ 3

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

#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

Ответ 4

Поместите классы Q_OBJECT в отдельные файлы. Это один .h и один .cpp для каждого класса. В этом отношении макросы метатега Qt выглядят отвратительными.

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

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

Ответ 5

есть несколько вещей, на которые нужно смотреть:

  • Добавить QT + = gui в свой файл pro
  • Убедитесь, что вы определяете классы, полученные из QObject, только в ваших файлах заголовков (отредактируйте: как указано в Troubadour, это не требуется).
  • Добавить Q_INTERFACES (QGraphicsItem) в объявление вашего класса T
Ниже приведен пример

:

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

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

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