Q_OBJECT lanzando ‘referencia indefinida a vtable’ error

Estoy usando Qt Creator 2.0.1 con Qt 4.7.0 (32 bit) en Windows 7 Ultimate 32 bit.

Considere el siguiente código, que es un mínimo para producir el 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; } 

El fragmento de código anterior causa los siguientes errores de enlazador:

En la función `T ‘:

referencia indefinida a `vtable para T ‘

referencia indefinida a `vtable para T ‘

En la función `~ T ‘:

referencia indefinida a `vtable para T ‘

referencia indefinida a `vtable para T ‘

Si comento la línea que contiene Q_OBJECT , comstack bien. Necesito señales y ranuras con QGraphicsItem así que necesito Q_OBJECT .

¿Qué está mal con el código? Gracias.

Es porque la unidad generada por MOC no está incluida en el proceso de vinculación. O tal vez no se genera en absoluto. Lo primero que haría es poner la statement de clase en un archivo de encabezado separado, tal vez el sistema de comstackción no está escaneando archivos de implementación.

Otra posibilidad es que la clase en cuestión una vez no pertenecía al sistema meta objeto Qt (es decir, no tenía Q_OBJECT o tal vez no heredaba QObject en absoluto), por lo que qmake necesita ejecutarse de nuevo para crear el reglas necesarias para MOC. La forma más fácil de forzar qmake a ejecutarse es realizar algunos cambios insignificantes en el archivo de proyecto para actualizar su marca de tiempo, como agregar y luego eliminar un espacio en blanco. O bien, si está utilizando Qt Creator, simplemente seleccione “Ejecutar qmake” en el menú contextual del proyecto.

Si quiere definir una subclase QObject en un archivo fuente, entonces necesita agregar la línea

 #include "file.moc" 

en algún momento después de la definición de su clase donde el nombre del archivo de origen era file.cpp. Necesitarás volver a ejecutar qmake por supuesto, para que la regla apropiada para ejecutar moc se agregue al Makefile.

Solo cuando en un archivo de encabezado la presencia de Q_OBJECT en una definición de clase hace que se invoque Q_OBJECT . Si se trata de un archivo fuente, necesita esta línea adicional para forzar el uso de moc .

Estoy seguro de que se hizo una pregunta similar antes, pero no pude encontrarla.

Coloque sus clases Q_OBJECT en archivos separados. Esa es una .h y una .cpp para cada clase. Las macros de metaobjetos de Qt son bastante exigentes a este respecto.

Además, puede usar QGraphicsObject para su propósito. Le ahorra algo de tiempo allí.

Editar: veo que estás usando el Creador. Utilice su nueva función Clase C ++ en Nuevo archivo o Proyecto para crear el archivo de la “manera correcta” 🙂

Aquí está el código de trabajo agregado con todas las correcciones provistas en otras preguntas (Intenté comstackr limpio y estas reparaciones ayudan):

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

Así que el crédito real para Troubadour y serge_gubenko

hay un par de cosas para mirar:

  1. Agrega QT + = gui en tu archivo pro
  2. Asegúrese de definir sus clases derivadas de QObject únicamente en sus archivos de encabezado (edite: como señaló Troubadour, esto no es obligatorio)
  3. Agregue Q_INTERFACES (QGraphicsItem) a la statement de su clase T

a continuación hay un ejemplo:

th:

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

Intenté comstackr el código anterior y no tuve problemas con él.

espero que esto ayude, saludos