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