Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Zodiak98 en 16 Febrero 2017, 01:59 am



Título: [Error] Tabla Hashing
Publicado por: Zodiak98 en 16 Febrero 2017, 01:59 am
Verán, estoy intentando representar una Tabla Hash, pero por alguna razón me dice que existe un error de enlace o algo así.

Estoy trabajando en Visual Studio 2015, esto es lo que llevo:
Nodo.h
Código
  1. #pragma once
  2.  
  3. template<class T>
  4. class Nodo {
  5. private:
  6. Nodo<T>* siguiente;
  7. Nodo<T>* anterior;
  8. T clave;
  9. public:
  10. inline Nodo();
  11. inline Nodo(T clave);
  12.  
  13. inline Nodo<T>* getSiguiente();
  14. inline Nodo<T>* getAnterior();
  15. inline T getClave();
  16.  
  17. inline void setSiguiente(Nodo<T>* siguiente);
  18. inline void setAnterior(Nodo<T>* anterior);
  19. inline void setClave(T clave);
  20. };
  21.  

Nodo.cpp
Código
  1. #include "Nodo.h"
  2.  
  3. template <class T>
  4. inline Nodo<T>::Nodo() {
  5. siguiente = nullptr;
  6. anterior = nullptr;
  7. clave = 0;
  8. }
  9.  
  10. template <class T>
  11. inline Nodo<T>::Nodo(T clave) {
  12. siguiente = nullptr;
  13. anterior = nullptr;
  14. this->clave = clave;
  15. }
  16.  
  17. template <class T>
  18. inline Nodo<T>* Nodo<T>::getSiguiente() {
  19. return siguiente;
  20. }
  21.  
  22. template <class T>
  23. inline Nodo<T>* Nodo<T>::getAnterior() {
  24. return anterior;
  25. }
  26.  
  27. template <class T>
  28. inline T Nodo<T>::getClave() {
  29. return clave;
  30. }
  31.  
  32. template <class T>
  33. inline void Nodo<T>::setAnterior(Nodo<T>* anterior) {
  34. this->anterior = anterior;
  35. }
  36.  
  37. template <class T>
  38. inline void Nodo<T>::setSiguiente(Nodo<T>* siguiente) {
  39. this->siguiente = siguiente;
  40. }
  41.  
  42. template <class T>
  43. inline void Nodo<T>::setClave(T clave) {
  44. this->clave = clave;
  45. }
  46.  

ListaDoble.h
Código
  1. #pragma once
  2. #include "Nodo.h"
  3.  
  4. template <class T>
  5. class ListaDoble {
  6. private:
  7. Nodo<T>* inicio;
  8. public:
  9. inline ListaDoble();
  10.  
  11. void agregar(Nodo<T>* n);
  12. void eliminar(Nodo<T>* n);
  13. void listar();
  14.  
  15. inline Nodo<T>* getInicio();
  16. };
  17.  

ListaDoble.cpp
Código
  1. #include "ListaDoble.h"
  2.  
  3. template <class T>
  4. inline ListaDoble<T>::ListaDoble() {
  5. inicio = nullptr;
  6. }
  7.  
  8. template <class T>
  9. void ListaDoble<T>::agregar(Nodo<T>* n) {
  10. n->setSiguiente(inicio);
  11.  
  12. if (inicio != nullptr) {
  13. inicio->setAnterior(n);
  14. }
  15.  
  16. n->setAnterior(nullptr);
  17. inicio = n;
  18. }
  19.  
  20. template <class T>
  21. void ListaDoble<T>::eliminar(Nodo<T>* n) {
  22. if (n->getAnterior() != nullptr) {
  23. n->getAnterior()->setSiguiente(n->getSiguiente());
  24. } else {
  25. inicio = n;
  26. }
  27.  
  28. if (n->getSiguiente() != nullptr) {
  29. n->getSiguiente()->setAnterior(n->getAnterior());
  30. }
  31.  
  32. delete n;
  33. }
  34.  
  35. template <class T>
  36. inline Nodo<T>* ListaDoble<T>::getInicio() {
  37. return inicio;
  38. }
  39.  
  40. template <class T>
  41. void ListaDoble<T>::listar() {
  42. for (Nodo<T>* aux = inicio; aux != nullptr; aux = aux->getSiguiente()) {
  43. cout << "Clave: " << aux->getClave() << endl;
  44. }
  45. }
  46.  

TablaHash.h
Código
  1. #pragma once
  2. #include "ListaDoble.h"
  3.  
  4. #define TAM 701
  5.  
  6. template <class T>
  7. class TablaHash {
  8. private:
  9. ListaDoble<T>* H[TAM];
  10. public:
  11. TablaHash();
  12.  
  13. void agregar(Nodo<T>* n);
  14. void eliminar(Nodo<T>* n);
  15. Nodo<T>* buscar(T clave);
  16.  
  17. inline int h(int clave);
  18.  
  19. void listar();
  20. };
  21.  

TablaHash.cpp
Código
  1. #include "TablaHash.h"
  2.  
  3. template<class T>
  4. TablaHash<T>::TablaHash() {
  5. for (int h = 0; h < TAM; h++) {
  6. H[h] = nullptr;
  7. }
  8. }
  9.  
  10. template<class T>
  11. inline int TablaHash<T>::h(int clave) {
  12. return (clave % TAM);
  13. }
  14.  
  15. template<class T>
  16. void TablaHash<T>::agregar(Nodo<T>* n) {
  17. int slot = h((int)n->getClave());
  18.  
  19. if (H[slot] == nullptr) {
  20. H[slot] = new ListaDoble<T>;
  21. }
  22.  
  23. H[slot]->agregar(n);
  24. }
  25.  
  26. template <class T>
  27. Nodo<T>* TablaHash<T>::buscar(T clave) {
  28. int slot = h((int)clave);
  29.  
  30. if (H[slot] != nullptr) {
  31. for (Nodo<T>* aux = H[slot]->getInicio(); aux != nullptr; aux = aux->getSiguiente()) {
  32. if (aux->getClave() == clave) {
  33. return aux;
  34. }
  35. }
  36. }
  37.  
  38. return nullptr;
  39. }
  40.  
  41. template <class T>
  42. void TablaHash<T>::eliminar(Nodo<T>* n) {
  43. int slot = h((int)n->getClave());
  44. Nodo<T>* aux = buscar(n->getClave());
  45.  
  46. if (aux != nullptr) {
  47. H[slot]->eliminar(aux);
  48. }
  49.  
  50. if (H[slot]->getInicio() == nullptr) {
  51. H[slot] = nullptr;
  52. delete H[slot];
  53. }
  54. }
  55.  
  56. template <class T>
  57. void TablaHash<T>::listar() {
  58. for (int i = 0; i < TAM; i++) {
  59. if (H[i] != nullptr) {
  60. H[i]->listar();
  61. }
  62. }
  63. }
  64.  

main.cpp
Código
  1. #include <iostream>
  2. #include "TablaHash.h"
  3.  
  4. using namespace std;
  5.  
  6. int main() {
  7. TablaHash<int> myHashTable;
  8.  
  9. Nodo<int>* nodo1 = new Nodo<int>(25);
  10. Nodo<int>* nodo2 = new Nodo<int>(35);
  11. Nodo<int>* nodo3 = new Nodo<int>(45);
  12.  
  13.  
  14. return 0;
  15. }
  16.  

El error que me da es el siguiente:
Código:
- Error	LNK2019	unresolved external symbol "public: __thiscall TablaHash<int>::TablaHash<int>(void)" (??0?$TablaHash@H@@QAE@XZ) referenced in function _main	
- Error LNK2019 unresolved external symbol "public: __thiscall Nodo<int>::Nodo<int>(int)" (??0?$Nodo@H@@QAE@H@Z) referenced in function _main

- Error LNK1120 2 unresolved externals

Supongo que tiene algo que ver con las cabeceras, ¿alguien podría decirme que estoy haciendo mal?

Gracias de antemano. :)


Título: Re: [Error] Tabla Hashing
Publicado por: engel lex en 16 Febrero 2017, 02:03 am
tienes un error del linker

no tu puedo ayudar mucho, pero estas son posibles soluciones

https://msdn.microsoft.com/en-us/library/799kze2z.aspx


Título: Re: [Error] Tabla Hashing
Publicado por: Zodiak98 en 16 Febrero 2017, 02:35 am
Gracias por responder, aún no he logrado solucionarlo. Verifiqué algunas de esas posibles soluciones y nada de nada.

-- EDIT --
Si cambio en el main el include del header para incluir el .cpp, sí funciona. O sea, por alguna razón no me está reconociendo los .cpp donde están las definiciones de los .h


Título: Re: [Error] Tabla Hashing
Publicado por: ivancea96 en 16 Febrero 2017, 18:32 pm
No puedes definir templates en un .cpp y usarlos desde fuera.
El cpp se compila antes que el main. Por tanto, los templates que no uses ahí (TablaHash<int>, por ejemplo), no se va a compilar.

Tendrás que pioner esos templates en el hpp, sin el cpp.


Título: Re: [Error] Tabla Hashing
Publicado por: Zodiak98 en 17 Febrero 2017, 03:45 am
¿Podrías explicarte un poco mejor, por favor? Aún no me ha quedado del todo claro.

Yo creé los templates en el hpp, y luego le di cuerpo a esas clases en archivos .cpp, ¿eso no es válido? Sólo estoy dándole cuerpo a los métodos de esas clases.

¿Te refieres a que sólo debo crear el .hpp y darle cuerpo donde tengo el main (cuando hago uso de plantillas)?


Título: Re: [Error] Tabla Hashing
Publicado por: ivancea96 en 17 Febrero 2017, 09:30 am
El cuerpo debes dárselo en el hpp.

Los templates se compilan por cada combinación de tipos que le des. Si no se le da ningun tipo (como ocurre en el .cpp, por ejemplo), no se compila. Entonces, cuando compilas el main, no encuentra el template <int> en ningún lado (porque no ha sido compilado).

Poniéndolo en el .hpp se compila en cada lugar en que hagas el include, y por tanto, se compila todo lo que se necesita.


Título: Re: [Error] Tabla Hashing
Publicado por: Zodiak98 en 17 Febrero 2017, 17:53 pm
Oh, wow. Ojalá mi profesor de la universidad fuese como tú. Jajajaj Muchas gracias.  ;D ;D