2010-11-24 41 views
16

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.C++ referencia indefinida a vtable

==> BasicMath.h <== 
#ifndef BASIC_MATH_H 
#define BASIC_MATH_H 

#include<string> 
#include<vector>  

class BasicMath { }; 


#endif // BASIC_MATH_H 

==> Operation.h <== 

#ifndef OPERATION 
#define OPERATION 

#include<string> 
#include<vector>  

class Operation { 
public: 
    virtual void perform(std::vector<std::string> vec) = 0; 
}; 


#endif // OPERATION 

==> Sum.h <== 
#ifndef SUM_H 
#define SUM_H 

#include "Operation.h" 

class Sum: public Operation { 
public: 
    void perform(std::vector<std::string> vec); 
}; 

#endif // SUM_H 

==> BasicMath.cpp <== 
#ifndef BASIC_MATH_C 
#define BASIC_MATH_C 

#include <string> 
#include <vector> 
#include <iostream> 
#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 <vector> 
#include <string> 
#include <iostream> 
#include "Sum.h" 

void Sum::perform(std::vector<std::string> vec) { 
    using namespace std; 
    int total = 0; 
    cout << "Total: " << total << "\n"; 
}; 

#endif // SUM_C 

Compilación:

$ 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 95% seguro de que estoy haciendo al menos una cosa tonta aquí - pero mi cerebro se niega a decirme qué.

He visto this pregunta pero no he podido arreglar mi problema.

+1

Nota al margen: definitivamente quiere pasar un std :: vector por referencia, no por valor. – EboMike

+0

Nota al margen 2: las clases con funciones virtuales deben tener un destructor virtual. – EboMike

+0

He agregado la etiqueta g ++, ya que su problema está en cómo hacer que el compilador (más precisamente el enlazador) vincule los archivos del objeto, y eso depende del compilador. –

Respuesta

16

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

+0

bien, eso fue terriblemente fácil. Gracias Noah. Tome los otros puntos sobre pasar por ref, etc. Trabajaré en eso ahora, ahora que he pasado este error. ¡El manual de g ++ sigue en la lista de lectura! – Ben

+0

Correcto, no estaba compilando el archivo 'cpp' de una clase incluida. – zpon

1

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

5

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

Agregaré algo bastante diferente. Solo necesitas guardias de encabezado en tus encabezados. Los ha incluido en sus archivos fuente también, donde realmente no tienen sentido. Por ejemplo, he comentado las líneas que realmente no es necesario (o incluso desea) en sum.cpp:

//#ifndef SUM_C 
//#define SUM_C 
// 
#include <vector> 
#include <string> 
#include <iostream> 
#include "Sum.h" 

void Sum::perform(std::vector<std::string> vec) { 
    using namespace std; 
    int total = 0; 
    cout << "Total: " << total << "\n"; 
}; 

//#endif // SUM_C 

Sólo pedía algo, en lugar de perform, que haría uso de operator():

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

y (obviamente) eso es también lo que se sobrecargaría para Sum. Para usarlo, en lugar de algo como:

Sum op; 
op.perform(); 

que tendría que utilizar algo como:

Sum op; 
op(); 

Esto es particularmente útil cuando se combina su clase con otros (por ejemplo, los 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 pueden usar casi como funciones).

+0

Hola Jerry: agregué los guardias en mi fuente después de revisar algunos de los códigos ACE, que tenían este estilo http://www.cs.wustl.edu/~schmidt/ACE.html. Tal vez esto se requiere para algunos marcos o simplemente está desaparecido? – Ben

1

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

+0

Eso no tiene nada que ver con eso. = 0 significa que su clase será abstracta. Supongo que el problema es que olvidó escribir un cuerpo de función. – EboMike

+0

Gracias, esta respuesta me ayudó. – maharvey67

19

Acabo de encontrar el mismo problema, pero mi problema es que no he escrito el código de destructor en mi archivo .cpp.

class.h:

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

clase.cpp:

MyClass::MyClass() {} 

Me acaba de dar 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 parece a esto:

MyClass::MyClass() {} 
MyClass::~MyClass() {} 
+3

Aparentemente, esto puede ser lo suficientemente común. +1 ... esto me ayudó a resolver el mismo problema. – IAbstract

+0

El segundo bloque de código no es "implementar el destructor (vacío)" como dices, eso es implementar el constructor. – DBedrenko

+1

El segundo bloque de código muestra intencionalmente el estado que produjo el error. Pensé que la oración posterior sería suficiente para la solución, pero agregué el contenido "corregido". –

3

Ese error también ocurre si se le olvida la = 0 para las 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; 
} 

Ningún error:

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

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

Probado en g++ 5.2.1.

+1

chico que me salvaste la vida XD – vivi

Cuestiones relacionadas