0

So I'm new to C++ and Visual Studio and I'm trying to implement a hash table using templates. I have four files: main.cpp, HashNode.h, HashTable.h, and HashTable.cpp.

main calls the HashTable constructor with a paramenter (the definition is in HashNode.h, with the implementation in the cpp file), but this throws 2 unresolved external errors: one for the called constructor, and one for what I assume to be the default constructor.

However, main also calls the HashNode constructor with no problems. HashNode has its implementation and declaration all in the HashNode.h file, but moving HashTable's implementation to its .h file didn't clear the error. So I'm very confused lol.

I'm running Visual Studio 2019, fresh install, and using the default build button to build it. It does compile and run other things (like hello world), just not this.

I've also tried adding random garbage into HashTable.cpp to see if the compiler just didn't see that it existed, but that's not the case. It also throws a compilation error then.

HashTable.h:

#pragma once
#include "HashNode.h"

template <typename T>
class HashTable
{
    public:
        void AddItem(int key, T item);
        T* GetItem(int key);
        HashTable(int buckets);
        ~HashTable();
        int print();
    private:
        HashNode<T>** elements;
        int buckets;
};

HashTable.cpp:

#include "HashTable.h"
#include "HashNode.h"
#include <stdexcept>

template<typename T>
HashTable<T>::HashTable(int buckets)
{
    elements = new HashNode<T> * [buckets];
    for (int i = 0; i < buckets; i++)
    {
        elements[i] = nullptr;
    }
    HashTable::buckets = buckets;
}
... //other methods defined below

HashNode.h

#pragma once

template <typename V>
class HashNode
{
public:
    HashNode(int key, const V value) : k(key), v(value), next(nullptr) {}
    int getKey () const { return k; }
    V getValue() const { return v; }
    HashNode* getNext() const { return next; }
    void setNext(HashNode* next) { HashNode::next = next; }
    void appendToChain(HashNode* last)
    {
        HashNode* curr = this;
        while (curr->getNext() != nullptr)
        {
            curr = curr->getNext();
        }
        curr.setNext(last);
    }
private:
    int k;
    V v;
    HashNode* next;
};

Main.cpp:

#include <iostream>
#include "HashTable.h"
#include "HashNode.h"

int main()
{
    std::cout << "Hello World!\n";
    HashNode<int> node(1,1); //works fine
    std::cout << node.getValue() << std::endl; //prints fine
    HashTable<int> table(5); //throws error on compilation
}

It's probably just something stupid or that I'm blind, but here's the errors:

Error   LNK1120 2 unresolved externals  HashTable   D:\C++\HashTable\Debug\HashTable.exe    1   

Error   LNK2019 unresolved external symbol "public: __thiscall HashTable<int>::HashTable<int>(int)" (??0?$HashTable@H@@QAE@H@Z) referenced in function _main    HashTable   D:\C++\HashTable\HashTable\Main.obj 1   

Error   LNK2019 unresolved external symbol "public: __thiscall HashTable<int>::~HashTable<int>(void)" (??1?$HashTable@H@@QAE@XZ) referenced in function _main   HashTable   D:\C++\HashTable\HashTable\Main.obj 1   

Also, please don't hesitate to give me pointers if my code's bad. I've never really programmed anything in C++ before so any help is welcome!

jim-m80
  • 3
  • 3

1 Answers1

1

You need to move the template function definitions into the header file.

A longer answer can be found here.

Buddy
  • 10,874
  • 5
  • 41
  • 58