c ++ referencia indefinida a vtable

Estoy aprendiendo C ++. Intento hacer un ejercicio donde defino varias implementaciones de una clase virtual pura con una sola función. Tengo problemas para vincular la clase que usa estas implementaciones.

==> BasicMath.h <== #ifndef BASIC_MATH_H #define BASIC_MATH_H #include #include class BasicMath { }; #endif // BASIC_MATH_H ==> Operation.h <== #ifndef OPERATION #define OPERATION #include #include class Operation { public: virtual void perform(std::vector vec) = 0; }; #endif // OPERATION ==> Sum.h <== #ifndef SUM_H #define SUM_H #include "Operation.h" class Sum: public Operation { public: void perform(std::vector vec); }; #endif // SUM_H ==> BasicMath.cpp <== #ifndef BASIC_MATH_C #define BASIC_MATH_C #include  #include  #include  #include "BasicMath.h" #include "Sum.h" int main(int argc, char* argv[]) { Sum op; } #endif // BASIC_MATH_C ==> Sum.cpp <== #ifndef SUM_C #define SUM_C #include  #include  #include  #include "Sum.h" void Sum::perform(std::vector vec) { using namespace std; int total = 0; cout << "Total: " << total << "\n"; }; #endif // SUM_C 

Comstackcion:

 $ g++ -c Sum.cpp $ g++ -o BasicMath BasicMath.cpp /tmp/cc1VXjNl.o:BasicMath.cpp:(.text$_ZN3SumC1Ev[Sum::Sum()]+0x16): undefined reference to `vtable for Sum' collect2: ld returned 1 exit status 

Estoy seguro de que estoy haciendo al menos una tontería aquí, pero mi cerebro se niega a decirme qué.

He visto esta pregunta pero no he podido solucionar mi problema.

No está incluyendo el archivo de objeto Sum.o en su línea de comstackción y enlace (segundo uso de g ++).

Acabo de encontrar el mismo problema, pero mi problema era que no había escrito el código del destructor en mi archivo .cpp.

class.h:

 class MyClass { public: MyClass(); virtual ~MyClass(); }; 

class.cpp:

 MyClass::MyClass() {} 

Simplemente me dio el mensaje de error vtable, y la implementación del destructor (vacío) resolvió el problema.

[Editar] Por lo tanto, el archivo de clase corregido se ve así:

 MyClass::MyClass() {} MyClass::~MyClass() {} 

Un par de personas ya han señalado la solución al problema que ha visto.

Añadiré algo bastante diferente. Solo necesitas guardias de encabezado en tus encabezados. También los ha incluido en sus archivos de origen , donde realmente no tienen sentido. Por ejemplo, he comentado las líneas que realmente no necesita (o incluso desea) en sum.cpp:

 //#ifndef SUM_C //#define SUM_C // #include  #include  #include  #include "Sum.h" void Sum::perform(std::vector vec) { using namespace std; int total = 0; cout << "Total: " << total << "\n"; }; //#endif // SUM_C 

Solo FWIW, en lugar de perform , usaría operator() :

 class Operation { public: virtual void operator()(std::vector vec) = 0; }; 

y (obviamente) eso es lo que sobrecargarías para Sum . Para usarlo, en lugar de algo como:

 Sum op; op.perform(); 

Utilizarías algo como:

 Sum op; op(); 

Esto es particularmente conveniente cuando combina su clase con otras (por ejemplo, las de la biblioteca estándar) que invocan operaciones como funciones, ya sean funciones, o "funtores" (clases como esta, que sobrecargan operator() por lo que sintácticamente se puede usar casi como funciones).

Ese error también ocurre si olvida el = 0 para funciones virtuales puras

Error:

 class Base { public: virtual void f(); }; class Derived : public Base { public: virtual void f() {} }; int main() { Derived d; Base *b = &d; } 

No hay error:

 class Base { public: virtual void f() = 0; }; 

Esto es porque sin = 0 , C ++ no sabe que es una función virtual pura, lo trata como una statement, esperando una definición posterior.

Probado en g++ 5.2.1.

Simplemente está comstackndo BasicMath.cpp sin Sum.cpp; su vinculador no tiene idea acerca de Sum.cpp. Necesitará comstackrlos juntos, es decir Sum.cpp BasicMath.cpp de una vez, o puede comstackr los archivos .cpp de forma independiente y luego crear el ejecutable llamando a g ++ con ambos archivos .o.

Normalmente encuentro este error cuando accidentalmente olvido el =0 al final de una de mis funciones en una clase virtual pura.