2012-02-23 25 views
25

Archivo AhC++ Indefinido referencia a VTABLE y la herencia

#ifndef A_H_ 
#define A_H_ 

class A { 
public: 
    virtual ~A(); 
    virtual void doWork(); 
}; 

#endif 

Archivo Child.h

#ifndef CHILD_H_ 
#define CHILD_H_ 

#include "A.h" 

class Child: public A { 
private: 
    int x,y; 
public: 
    Child(); 
    ~Child(); 
    void doWork(); 
}; 
#endif 

Y Child.cpp

#include "Child.h" 

Child::Child(){ 
    x = 5; 
} 

Child::~Child(){...} 

void Child::doWork(){...}; 

El compilador dice que hay una referencia indefinida a vtable para A. He intentado muchas cosas diferentes y, sin embargo, ninguna ha funcionado.

Mi objetivo es que la clase A sea una interfaz, y separar el código de implementación de los encabezados.

+4

Debe definir cada función virtual no pura que declare. No necesita definir una función no virtual que declare pero no use. –

Respuesta

60

¿Por qué el error & cómo resolverlo?

es necesario proporcionar definitions para todas las funciones virtuales en class A. Solo las funciones virtuales puras no tienen definiciones.

es decir: En class A los dos métodos:

virtual ~A(); 
virtual void doWork(); 

deben definirse (debería tener un cuerpo)

por ejemplo:

a.cpp

void A::doWork() 
{ 
} 
A::~A() 
{ 
} 

Advertencia:
si desea que su class A para actuar como una interfaz (a.k.a Abstract class en C++), entonces usted debe hacer que el método virtual pura.

virtual void doWork() = 0; 

Buena lectura:

What does it mean that the "virtual table" is an unresolved external?
When building C++, the linker says my constructors, destructors or virtual tables are undefined.

+0

¿Qué quieres decir? – rjmarques

+0

@ user1227351: actualizó la respuesta para explicar mejor. Lea los enlaces para obtener una explicación más detallada. –

+0

Tener Virtual ~ A(); virtual void doWork() = 0; todavía da error de vtable = /. Pero sin el destructor funciona bien. Sin embargo, sin él, si hago algo como: A * a = new Child(); eliminar a; obviamente no llamará a Child :: ~ Child(). ¿Hay alguna solución? – rjmarques

6

Mi objetivo es que A sea una interfaz, y para separar el código de implementación de las cabeceras.

En ese caso, hacen la función de miembro tan puro virtual en la clase A.

class A { 
    // ... 
    virtual void doWork() = 0; 
}; 
+0

Eso elimina el error si también elimino el destructor. En ese caso si lo hago: A a = new Child(); borrar a; ¿a qué destructor llamaría? – rjmarques

+0

La destrucción se realiza siempre en orden inverso a la construcción. En este caso, el destructor de la clase 'A' debe ser virtual, lo que exige que el destructor' Child' se llame primero seguido de 'A' destructor. Si el destructor de clase 'A' no es virtual, entonces el comportamiento no está definido. – Mahesh

+0

Llamará al destructor del niño ya que ha hecho virtual destructor de clase primaria. Después de eso, el destructor de la clase padre. – Izza

1

asegúrese de eliminar todos los archivos "* .gch" si ninguna de las otras respuestas le ayude.