Pregunta

Estoy llegando a la vinculación de los errores del siguiente tipo:

El Festival.obj :error LNK2019:símbolo externo sin resolver "público:void __thiscall Árbol::add(Precio de la clase &)" (?agregar@?$Árbol De@VPrice@@@@QAEXAAVPrice@@@Z) que se hace referencia en función de __catch$?AddBand@Festival@@QAE?AW4StatusType@@HHH@Z$0

Yo solía pensar que tiene que ver con try-catch mecanismo, pero ya ha dicho lo contrario.Esta es una versión actualizada de la pregunta.

Estoy utilizando Visual Studio 2008, pero tengo problemas similares en g++.

El código correspondiente:

En Festival.cpp

#include "Tree.h"
#include <exception>

using namespace std;

class Band{
public:
    Band(int bandID, int price, int votes=0): bandID(bandID), price(price), votes(votes){};
...
private:
...

};

class Festival{
public: 
    Festival(int budget): budget(budget), minPrice(0), maxNeededBudget(0), priceOffset(0), bandCounter(0){};
    ~Festival();
    StatusType AddBand(int bandID, int price, int votes=0);
    ...

private: 
    Tree<Band> bandTree;
    ...

};

StatusType Festival::AddBand(int bandID, int price, int votes){
    if ((price<0)||(bandID<0)){
        return INVALID_INPUT;
    }
    Band* newBand=NULL;
    try{
        newBand=new Band(bandID,price-priceOffset,votes);
    }
    catch(bad_alloc&){return ALLOCATION_ERROR;}
    if (bandTree.find(*newBand)!=NULL){
        delete newBand;
        return FAILURE;
    }
bandTree.add(*newBand);
....
}

En El Árbol.h:

template<class T>
class Tree{
public:
    Tree(T* initialData=NULL, Tree<T>* initialFather=NULL);
    void add(T& newData);
....
private:
....
};

Curiosamente no tengo vinculación errores cuando intento usar el Árbol de funciones cuando el tipo T es un tipo primitivo como un int.

¿Fue útil?

Solución

Hay Tree.cpp?Si la hay, tal vez se le olvidó enlace?Donde es la implementación de Árbol::añadir?Además no veo donde usted Árbol de llamadas::add.Supongo que debe estar dentro de la instrucción try, a la derecha después de que el nuevo?

Sólo un recordatorio:

Para la mayoría de los compiladores (es decir,la práctica de compilación independiente) la ejecución de las funciones miembro de una clase de plantilla tiene que ser visible durante la compilación del archivo de código fuente que utiliza la plantilla de clase.Por lo general la gente siga esta regla poniendo la implementación de las funciones miembro dentro del archivo de encabezado.

Tal vez el Árbol::add no está dentro de la cabecera?Entonces, una posible solución en el discutido caso será poner Árbol::agregar aplicación dentro del archivo de encabezado.

La diferencia entre las clases regulares y clases de plantilla existe porque las clases de plantilla no son "reales" de clases - es, así, una plantilla.Si había definido su clase de Árbol como una clase, el compilador podría haber utilizado el código de inmediato.En el caso de una plantilla que el compilador primero ", escribe" para que la clase real, en sustitución de los parámetros de la plantilla con los tipos que se suministra.Ahora, compilador compila archivos cpp uno por uno.Él no es consciente de otros archivos cpp y se puede utilizar nada de otros archivos cpp.Digamos que la implementación de Árbol:añadir parece a esto:

void Tree::add(T& newData)
{
    newData.destroyEverything();
}

Es totalmente legítimo, siempre y cuando su T tiene método destroyEverything.Cuando el compilador compila Class.cpp quiere estar seguro de que no hacer con T algo que no conoce.Por ejemplo Tree<int> no va a funcionar porque int no tiene destroyEverything.El compilador intentará escribir el código con int en lugar de T y se enteran que el código no compila.Pero ya que el compilador "ve" sólo el actual cpp y todo lo que incluye, no va a ser capaz de validar añadir función, ya que es independiente del cpp.

No habrá ningún problema con

void Tree::add(int& newData)
{
    newData.destroyEverything();
}

implementado en un aparte cpp, ya que el compilador sabe que int es el único tipo aceptable y puede contar con el mismo" que cuando él llega a compilar Tree.cpp él se encuentra el error.

Otros consejos

Está usted seguro de que el try/catch no tiene nada que hacer con él?¿Qué sucede si usted simplemente comentar las try y catch líneas, dejar el resto del código, y la generación que?

Puede ser que te estás perdiendo la biblioteca que define Tree::add(class Price &) a partir de la línea de vínculo.

Actualización:el uso de Árbol de funciones con un tipo primitivo no resultar en una vinculación de error.He actualizado mi pregunta a la luz de algunas de las cosas que se dijeron.

Como otros han dicho que usted necesita para mostrar la implementación de Treee::add() y dinos cómo eres de la vinculación.

En una relación de punto, si usted está utilizando construcciones como:

  Band* newBand=NULL;
    try{
        newBand=new Band(bandID,price-priceOffset,votes);
    }
    catch(bad_alloc&){return ALLOCATION_ERROR;}

en todo el código, que son francamente perdiendo su tiempo.Las posibilidades de llegar a un punto de agotamiento de la memoria en un sistema operativo moderno son a distancia y la posibilidad de hacer algo útil después de que haya sucedido son aproximadamente cero.Usted será mucho mejor simplemente diciendo:

Band * newBand = new Band ( bandID, price - priceOffset, votes );

ot posiblemente:

Band newBand( bandID, price - priceOffset, votes );

y olvidar el manejo de excepciones en este caso.

Usted escribió en un comentario:

Yo consideraba esto, pero la función es la parte del Árbol.h, y yo sí lo incluyen.La función definida es:plantilla de vacío Árbol::add(T& nuevosdatos);La llamamos de la siguiente manera:priceTree.agregar(*newPriceNode);mientras que priceTree es el Árbol, ambos de los cuales están definidos en el archivo cpp en cuestión.

en lugar de:

priceTree.add(*newPriceNode);

probar:

priceTree.add(newPriceNode); //no "*" before "newPriceNode"

agregar() toma una referencia a un nodo, no un puntero a un nodo (según su definición de Árbol).

Usted está recibiendo la vinculación de los errores, no de errores del compilador.Esto nos dice que el compilador sabía qué tipo de función Tree::add() es pero que no tiene una definición.En El Árbol.h, veo una declaración de la función add() de la función, pero no una definición.Parece extraño para mí;¿alguien sabe dónde Árbol.h proviene?

Generalmente una clase de plantilla viene con la función de miembro de definiciones en el archivo de inclusión, ya que las funciones tienen que ser instanciado en algún lugar, y la cosa más simple es que el compilador para crear una instancia cuando se utiliza y dejar que el enlazador algo.Si las definiciones son en Árbol.h, me gustaría esperar que todo funcione según lo planeado.

Así que, voy a salir en una extremidad y sugieren que las definiciones están en un archivo independiente, no vinculado, y que hay disposiciones de otros lugares para crear instancias de tipos básicos como Tree<int>.Esto es probablemente para simplificar la compilación, ya que normalmente estas cosas se compilan en varios lugares, y eso lleva tiempo.

Lo que usted necesita hacer en este caso es encontrar donde Tree<int> se crea una instancia, y añadir una instancia de su clase.

Yo podría estar muy lejos de la base aquí, pero mi explicación no se ajusta a los hechos que has dado.

Editar después de los primeros comentarios:

Las plantillas son un poco más complicado de lo que a funciones comunes, que generalmente no es un problema real.Si las definiciones de todas las llamadas eran en forma de Árbol.h, entonces Festival.cpp sería capaz de crear instancias de Tree<Band> y todo estaría bien.Esa es la técnica más habitual, y usted está corriendo en este problema porque no la estés utilizando.

Cuando se escribe una función, no se compila, y el enlazador se va a encontrar.Cualquier rutina de llamar a la función que se necesita conocer el prototipo de la función, así que sé cómo llamarlo.Cuando usted escribe una plantilla, no estás escribiendo algo que va a ir directamente en el programa, pero cualquier uso de la plantilla cuenta como escribir en todas las funciones.

Por lo tanto, no tiene que ser el uso de algunos Tree<Band> en algún lugar en su programa, para que haya un Tree<Band>::add() la función de compilar.La definición de Tree<T>::add tiene que estar disponible para el compilador cuando Tree<Band> se crea una instancia, porque de lo contrario el compilador no tiene idea de lo que compilar.En este caso, es la generación de la llamada a la función, seguros de que tendrá que asegurarse de que la función está compilado en otros lugares.

Por lo tanto, usted tiene que crear una instancia Tree<Band> dentro de un archivo que tiene acceso tanto a las definiciones de Tree<T> y Band.Esto probablemente significa que un archivo que es, o incluye, Tree.cpp e incluye el Festival.h.

El vinculador ya está utilizando Tree.cpp pero Tree.cpp no tiene Tree<Band> en él se definen, por lo que no tiene sentido para el enlazador.Las plantillas son útiles únicamente para el compilador y el enlazador sólo opera en lo que el compilador genera a partir de plantillas.

La manera rápida de solucionar este problema es tomar las definiciones de Tree.cpp y ponerlos en el Árbol.h.Que será el probable incremento de compilación y enlace veces, por desgracia.La otra técnica es instanciar todos plantilla utiliza en Tree.cpp, de modo que van a ser compilados allí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top