I've been given some source code (as part of an assignment) that I'm supposed to modify, but I can't get the unmodified version of the code to compile and I'm tearing my hair out. (To be clear - this code is for a school assignment on hash tables, these compile errors are not part of the assignment)
I'm using visual studio 2010 to compile. I've been working on this all day and getting absolutely nowhere!
I'm getting a series of "LNK2005" errors:
1>------ Build started: Project: Assignment10, Configuration: Debug Win32 ------
1> hashmain.cpp
1>e:\google drive\cpsc 1160\labs\projects\assignment10\assignment10\hashtable.cpp(40): warning C4018: '<' : signed/unsigned mismatch
1>hashtable.obj : error LNK2005: "public: __thiscall HashTableSavitch::HashTable::HashTable(void)" (??0HashTable#HashTableSavitch##QAE#XZ) already defined in hashmain.obj
1>hashtable.obj : error LNK2005: "public: virtual __thiscall HashTableSavitch::HashTable::~HashTable(void)" (??1HashTable#HashTableSavitch##UAE#XZ) already defined in hashmain.obj
1>hashtable.obj : error LNK2005: "private: static int __cdecl HashTableSavitch::HashTable::computeHash(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?computeHash#HashTable#HashTableSavitch##CAHV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) already defined in hashmain.obj
1>hashtable.obj : error LNK2005: "public: bool __thiscall HashTableSavitch::HashTable::containsString(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)const " (?containsString#HashTable#HashTableSavitch##QBE_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) already defined in hashmain.obj
1>hashtable.obj : error LNK2005: "public: void __thiscall HashTableSavitch::HashTable::put(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?put#HashTable#HashTableSavitch##QAEXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) already defined in hashmain.obj
1>E:\Google Drive\CPSC 1160\Labs\Projects\Assignment10\Debug\Assignment10.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Here is the code I was given:
hashmain.cpp
// Program to demonstrate use of the HashTable class
#include <string>
#include <iostream>
#include "listtools.cpp" // Your compiler may compile separately
#include "hashtable.h"
#include "hashtable.cpp" // Your compiler may compile separately
using std::string;
using std::cout;
using std::endl;
using HashTableSavitch::HashTable;
int main()
{
HashTable h;
cout << "Adding dog, cat, turtle, bird" << endl;
h.put("dog");
h.put("cat");
h.put("turtle");
h.put("bird");
cout << "Contains dog? "
<< h.containsString("dog") << endl;
cout << "Contains cat? "
<< h.containsString("cat") << endl;
cout << "Contains turtle? "
<< h.containsString("turtle") << endl;
cout << "Contains bird? "
<< h.containsString("bird") << endl;
cout << "Contains fish? "
<< h.containsString("fish") << endl;
cout << "Contains cow? "
<< h.containsString("cow") << endl;
return 0;
}
hashtable.h
// This is the header file hashtable.h. This is the interface
// for the class HashTable, which is a class for a hash table
// of strings.
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include "listtools.h"
using LinkedListSavitch::Node;
using std::string;
namespace HashTableSavitch
{
const int SIZE = 10;
class HashTable
{
public:
HashTable(); // Initialize empty hash table
// Normally a copy constructor and overloaded assignment
// operator would be included. They have been omitted
// to save space.
virtual ~HashTable(); // Destructor destroys hash table
bool containsString(string target) const;
// Returns true if target is in the hash table,
// false otherwise
void put(string s);
// Adds a new string to the hash table
private:
Node<string> *hashArray[SIZE];
static int computeHash(string s); // Compute hash value for string
}; // HashTable
} // HashTableSavitch
#endif // HASHTABLE_H
hashtable.cpp
// This is the implementation file hashtble.cpp.
// This is the implementation of the class HashTable.
#include <string>
#include "listtools.h"
#include "hashtable.h"
using LinkedListSavitch::Node;
using LinkedListSavitch::search;
using LinkedListSavitch::headInsert;
using std::string;
namespace HashTableSavitch
{
HashTable::HashTable()
{
for (int i = 0; i < SIZE; i++)
{
hashArray[i] = NULL;
}
}
HashTable::~HashTable()
{
for (int i=0; i<SIZE; i++)
{
Node<string> *next = hashArray[i];
while (next != NULL)
{
Node<string> *discard = next;
next = next->getLink( );
delete discard;
}
}
}
int HashTable::computeHash(string s)
{
int hash = 0;
for (int i = 0; i < s.length( ); i++)
{
hash += s[i];
}
return hash % SIZE;
}
bool HashTable::containsString(string target) const
{
int hash = this->computeHash(target);
Node<string>* result = search(hashArray[hash], target);
if (result == NULL)
return false;
else
return true;
}
void HashTable::put(string s)
{
int hash = computeHash(s);
if (search(hashArray[hash], s)==NULL)
{
// Only add the target if it's not in the list
headInsert(hashArray[hash], s);
}
}
} // HashTableSavitch
listtools.h
//This is the header file listtools.h. This contains type definitions and
//function declarations for manipulating a linked list to store data of any type T.
//The linked list is given as a pointer of type Node<T>* which points to the
//head (first) node of the list. The implementation of the functions are given
//in the file listtools.cpp.
#ifndef LISTTOOLS_H
#define LISTTOOLS_H
namespace LinkedListSavitch
{
template<class T>
class Node
{
public:
Node(const T& theData, Node<T>* theLink) : data(theData), link(theLink){}
Node<T>* getLink( ) const { return link; }
const T& getData( ) const { return data; }
void setData(const T& theData) { data = theData; }
void setLink(Node<T>* pointer) { link = pointer; }
private:
T data;
Node<T> *link;
};
template<class T>
void headInsert(Node<T>*& head, const T& theData);
//Precondition: The pointer variable head points to
//the head of a linked list.
//Postcondition: A new node containing theData
//has been added at the head of the linked list.
template<class T>
void insert(Node<T>* afterMe, const T& theData);
//Precondition: afterMe points to a node in a linked list.
//Postcondition: A new node containing theData
//has been added after the node pointed to by afterMe.
template<class T>
void deleteNode(Node<T>* before);
//Precondition: The pointers before point to nodes that has
//at least one node after it in the linked list.
//Postcondition: The node after the node pointed to by before
//has been removed from the linked list and its storage
//returned to the freestore.
template<class T>
void deleteFirstNode(Node<T>*& head);
//Precondition: The pointers head points to the first
//node in a linked list; with at least one node.
//Postcondition: The node pointed to by head has been removed
//for the linked list and its storage returned to the freestore.
template<class T>
Node<T>* search(Node<T>* head, const T& target);
//Precondition: The pointer head points to the head of a linked list.
//The pointer variable in the last node is NULL. head (first) node
//head (first) node has been defined for type T.
//(== is used as the criterion for being equal).
//If the list is empty, then head is NULL.
//Returns a pointer that points to the first node that
//is equal to the target. If no node equals the target,
//the function returns NULL.
}//LinkedListSavitch
#endif //LISTTOOLS_H
listtools.cpp
//This is the implementation file listtools.cpp. This file contains
//function definitions for the functions declared in listtools.h.
#include <cstddef>
#include "listtools.h"
namespace LinkedListSavitch
{
template<class T>
void headInsert(Node<T>*& head, const T& theData)
{
head = new Node<T>(theData, head);
}
template<class T>
void insert(Node<T>* afterMe, const T& theData)
{
afterMe->setLink(new Node<T>(theData, afterMe->getLink( )));
}
template<class T>
void deleteNode(Node<T>* before)
{
Node<T> *discard;
discard = before->getLink( );
before->setLink(discard->getLink( ));
delete discard;
}
template<class T>
void deleteFirstNode(Node<T>*& head)
{
Node<T> *discard;
discard = head;
head = head->getLink( );
delete discard;
}
//Uses cstddef:
template<class T>
Node<T>* search(Node<T>* head, const T& target)
{
Node<T>* here = head;
if (here == NULL) //if empty list
{
return NULL;
}
else
{
while (here->getData( ) != target && here->getLink( ) != NULL)
here = here->getLink( );
if (here->getData( ) == target)
return here;
else
return NULL;
}
}
}//LinkedListSavitch
I think that this is way out of my depth, I've poured over similar problems/solutions here and anywhere else I could find on google, but I'm completely stumped.
Edit:
As per the request of Arcinde, I commented out #include "hashtable.cpp" in hashmain.cpp like so:
#include <string>
#include <iostream>
#include "listtools.cpp" // Your compiler may compile separately
#include "hashtable.h"
//#include "hashtable.cpp" // Your compiler may compile separately
using std::string;
using std::cout;
using std::endl;
using HashTableSavitch::HashTable;
which produces the following errors:
1>------ Build started: Project: Assignment10, Configuration: Debug Win32 ------
1> hashmain.cpp
1>hashtable.obj : error LNK2019: unresolved external symbol "class LinkedListSavitch::Node<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > * __cdecl LinkedListSavitch::search<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class LinkedListSavitch::Node<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$search#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###LinkedListSavitch##YAPAV?$Node#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###0#PAV10#ABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) referenced in function "public: bool __thiscall HashTableSavitch::HashTable::containsString(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)const " (?containsString#HashTable#HashTableSavitch##QBE_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z)
1>hashtable.obj : error LNK2019: unresolved external symbol "void __cdecl LinkedListSavitch::headInsert<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class LinkedListSavitch::Node<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > * &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$headInsert#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###LinkedListSavitch##YAXAAPAV?$Node#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###0#ABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) referenced in function "public: void __thiscall HashTableSavitch::HashTable::put(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?put#HashTable#HashTableSavitch##QAEXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z)
1>E:\Google Drive\CPSC 1160\Labs\Projects\Assignment10\Debug\Assignment10.exe : fatal error LNK1120: 2 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
It looks like the root of your problems was that you were instantiating template functions without an implementation (your .h was attempting to declare, and your .cpp was attempting to define them).
You have two options to resolve your issue:
Move everything from listtools.cpp into listtools.h, thus moving both the template instantiation and implementation to the same place
Move everything from listtools.cpp into a new file (listtoolssupport.h) and remove the declarations from listtools.h.
Using option 1, I moved all the implementations of listtools.cpp into listtools.h using #n0rd's and # Arcinde's instructions. I then completely removed the listtools.cpp as it now did nothing and removed the #includes of the .cpp.
listtools.h now looks like:
//This is the header file listtools.h. This contains type definitions and
//function declarations for manipulating a linked list to store data of any type T.
//The linked list is given as a pointer of type Node<T>* which points to the
//head (first) node of the list. The implementation of the functions are given
//in the file listtools.cpp.
#ifndef LISTTOOLS_H
#define LISTTOOLS_H
#include <cstddef>
namespace LinkedListSavitch
{
template<class T>
class Node
{
public:
Node(const T& theData, Node<T>* theLink) : data(theData), link(theLink) { }
Node<T>* getLink() const { return link; }
const T& getData() const { return data; }
void setData(const T& theData) { data = theData; }
void setLink(Node<T>* pointer) { link = pointer; }
private:
T data;
Node<T> *link;
};
template<class T>
void headInsert(Node<T>*& head, const T& theData)
{
head = new Node<T>(theData, head);
}
//Precondition: The pointer variable head points to
//the head of a linked list.
//Postcondition: A new node containing theData
//has been added at the head of the linked list.
etc etc etc...
The "Unresolved External Symbol" is basically saying that, when it goes to link, it cannot find a symbol for Node.
In your hashmain.cpp file
// Program to demonstrate use of the HashTable class
#include <string>
#include <iostream>
//#include "listtools.cpp" // Your compiler may compile separately
#include "hashtable.h"
//#include "hashtable.cpp" // Your compiler may compile separately
using std::string;
using std::cout;
using std::endl;
using HashTableSavitch::HashTable;
Try uncommenting the two commented lines.
It is wrong that include source code file name, so you should commented them.
Related
I'm trying to build a simple heap data structure for practice. When I build the version for double it works fine.
class heapt {
public:
heapt();
heapt(std::initializer_list<double> lst);
void print_heapt();
private:
int size;
int length;
double* elem; //points to root
};
Its constructors works perfectly and the heap is printed as it should. But when I try to generalize it with
template< typename Elem>
as:
template<typename Elem>
class heapt {
public:
heapt();
heapt(std::initializer_list<Elem> lst);
void print_heapt();
private:
int size;
int length;
Elem* elem; //points to root
};
for the class definition and as:
template<typename Elem>
heapt<Elem>::heapt(std::initializer_list<Elem> lst) :
size{ static_cast<int>(lst.size()) },
elem{new Elem[lst.size()]}
{
std::copy(lst.begin(), lst.end(), elem);//Now heaptify elem
build_heapt(elem, lst.size());
}
for one of the constructors used in the main function.
I get two linking errors:
LNK2019 unresolved external symbol "public: void __thiscall heapt::print_heapt(void)" (?print_heapt#?$heapt#H##QAEXXZ) referenced in function _main
LNK2019 unresolved external symbol "public: __thiscall heapt::heapt(class std::initializer_list)" (??0?$heapt#H##QAE#V?$initializer_list#H#std###Z) referenced in function _main
The main function is:
{
heapt<int> hh{ 27,12,3,13,2,4,14,5 };
std::cout << "Hello" << '\n';
hh.print_heapt();
}
EDIT: The heapt class is in the "heap.h" file and the definition for the constructor heapt<Elem>::heapt(std::initializer_list<Elem> lst) is in the "heap.cpp" class, which has #include"heap.h" as a header file. The int main function is in a file named "InSo.cpp", which also has #include"heap.h" as a header file.
In your templated class declaration you are using heapt(std::initializer_list<double> lst); but in your definition you are using std::initializer_list<Elem>. You should change the declaration to heapt(std::initializer_list<Elem> lst);
You are still missing definitions for print_heapt and build_heapt but otherwise it should compile.
EDIT: In light of you clarifying how your source files are set up, see WhozCraig's comment on your initial post. You can either include the definition of the templated class functions in a heap.hpp file, for example, and include it at the end of your heap.h, or just put them all together in one file, e.g.
// heap.h
#ifndef HEAP_H
#define HEAP_H
#include <initializer_list>
template<typename Elem>
class heapt {
public:
heapt();
heapt(std::initializer_list<Elem> lst);
void print_heapt();
private:
int size;
int length;
Elem* elem; //points to root
};
#include "heap.hpp"
#endif
//heap.hpp
#ifndef HEAP_HPP
#define HEAP_HPP
#include "heap.h"
#include <algorithm>
template<typename Elem>
heapt<Elem>::heapt(std::initializer_list<Elem> lst) :
size{ static_cast<int>(lst.size()) },
elem{ new Elem[lst.size()] }
{
std::copy(lst.begin(), lst.end(), elem);//Now heaptify elem
//build_heapt(elem, lst.size());
}
#endif
This question already has answers here:
Why do I get "unresolved external symbol" errors when using templates? [duplicate]
(3 answers)
Closed 3 years ago.
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!
You need to move the template function definitions into the header file.
A longer answer can be found here.
I am trying to create a custom List in c++.
I've defined it this way:
List.h:
#include "ListItem.h"
#pragma once
template<class T> class List
{
private:
ListItem<T>* first;
public:
T* GetAt(int);
ListItem<T>* GetLastListItem();
void Add(T*);
void Clear();
};
List.cpp:
#include "stdafx.h"
#include "List.h"
template<class T> T* List<T>::GetAt(int index)
{
if (!first)
return 0;
ListItem<T>* current = first;
for (int i = 1; i < index; i++)
{
current = current->GetNext();
}
return current->GetItem();
}
template<class T> L...
main:
List<TestItem> liste;
TestItem ti; //just a int inside.
liste.Add(&ti);
I am getting the following errors:
1>ConsoleApplication1.obj : error LNK2019: unresolved external symbol ""public: void __thiscall List::Add(class TestItem *)" (?Add#?$List#VTestItem####QAEXPAVTestItem###Z)" in function"_main".
I just started using template.
I want to create a linked list class which stores the address of Type (could be an object). Here is the layout of my project:
linkedlist.h
node.h
node.cpp
linkedlist.cpp
main.cpp
Node.h
template <class Type> struct Node
{
public:
Node<Type>();
Node<Type>(Type* x = 0, Node* pNext = 0);
Type* data;
Node* next;
};
Node.cpp
#include "node.h"
template<class Type> Node<Type>::Node()
{
next = 0;
data = 0;
}
template<class Type> Node<Type>::Node(Type* item, Node* ptrNext)
{
next = ptrNext;
data = item;
}
linkedlist.h
#include "node.h"
template <class Type> class LinkedList
{
private:
Node<Type>* root;
public:
LinkedList<Type>();
~LinkedList<Type>();
void insert(Type*);
void remove(Type*);
};
linkedlist.cpp
#include "linkedlist.h"
template <class Type> LinkedList<Type>::LinkedList()
{
root = 0;
}
template <class Type> LinkedList<Type>::~LinkedList()
{
Node* p;
while(p = root)
{
root = p->next;
delete p;
}
}
// many more....
In main.cpp, I have the following:
int main()
{
int *ptrA, *ptrB;
int a = 100, b = 10;
ptrA = &a;
ptrB = &b;
LinkedList<int>myList;
myList.insert(ptrA);
return 0;
}
and compiler threw linker errors:
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall LinkedList<int>::~LinkedList<int>(void)" (??1?$LinkedList#H##QAE#XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall LinkedList<int>::insert(int *)" (?insert#?$LinkedList#H##QAEXPAH#Z) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall LinkedList<int>::LinkedList<int>(void)" (??0?$LinkedList#H##QAE#XZ) referenced in function _main
Attempted Solution:
I called LinkedListmyList() instead. This can resolve the linker error, but I will not be able to call any member function.
myList.insert(ptrA) will say "Error: Expression must have a class type" if I put ().
So clearly this is not working.
What's the problem? I think the whole implementation has problems....
Thanks for your time.
Move the stuff from linkedlist.cpp .. to linkedlist.h
As it's declaring a 'template for making code' the machine code doesn't actually exist until you give the compiler the type you want to use.
For example, as long as all the template code is visible to the compiler, as soon as you go: LinkedList<int>myList the compiler creates the solid real class that makes a linkedlist of ints. In your case, the compiler can't see the template code, so isn't able to generate the machine code.
in c++11 you can say 'extern template': http://en.wikipedia.org/wiki/C%2B%2B11#Extern_template
in the header file, then implement the 'int' version in your linkeList.cpp file .. and it'll be available in main.cpp when it tries to use it.
This gives the advantage of the compiler not having to generate the machine code in every .cpp file where the template is used and makes compiling faster.
It can be done in c++98 too .. but it's a bit more tricky and not 100% portable as I understand it .. easier to just generate the code everywhere. Here's a good blurb on it for gnu gcc: http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html
Im new to programming, in our c++ course, we have to build a stack class and using template, I followed the book and tried to put it together but still a lot of error. So I hope the experts here can help point me to the right direction.
StackType.h:
class FullStack
{};
class EmptyStack
{};
template<class ItemType>
class StackType
{
public:
StackType(int max);
/*
* Function: constructor
* Precondition: none
* Postcondition: Stack has been initialized
*/
bool IsEmpty() const;
/*
* Function: Determines whether the stack is empty
* Precondition: Stack has been initialized
* Postcondition: Function value = (stack is empty)
*/
bool IsFull() const;
/*
* Function: Determines whether the stack is full
* Precondition: Stack has been initialized
* Postcondition: Function value = (stack is full)
*/
void Push(ItemType item);
/*
* Function: Add new item to the top of the stack
* Precondition: Stack has been initialized
* Postcondition: If (stack is full), exception FullStack is thrown,
* else new item is at the top of the stack
*/
void Pop();
/*
* Function: Remove top item from the stack
* Precondition: Stack has been initialized
* Postcondition: If (stack is empty), exception EmptyStack is thrown,
* else top item has been removed from stack
*/
ItemType Top() const;
/*
* Function: Returns value of the top item from the stack
* Precondition: Stack has been initialized
* Postcondition: If (stack is empty), exception EmptyStack is thrown,
* else value of the top item is returned
*/
~StackType(void);
/*
* Function: destructor
* Precondition: Stack has been initailized
* Postcondition: deallocate memory
*/
private:
int maxStack;
ItemType* item;
int top;
};
StackType.cpp:
#include "StackType.h"
#include <iostream>
#include <string>
using namespace std;
template<class ItemType>
StackType<ItemType>::StackType(int max)
{
maxStack = max;
top = -1;
item = new ItemType[maxStack];
}
template<class ItemType>
bool StackType<ItemType>::IsEmpty() const
{
return (top == -1);
}
template<class ItemType>
bool StackType<ItemType>::IsFull() const
{
return (top == maxStack - 1);
}
template<class ItemType>
void StackType<ItemType>::Push(ItemType newItem)
{
if(IsFull())
throw FullStack();
top++;
item[top] = newItem;
}
template<class ItemType>
void StackType<ItemType>::Pop()
{
if(IsEmpty())
throw EmptyStack();
top--;
}
template<class ItemType>
ItemType StackType<ItemType>::Top() const
{
if(IsEmpty())
throw EmptyStack();
return item[top];
}
template<class ItemType>
StackType<ItemType>::~StackType()
{
delete []item;
}
Thanks everyone in advanced :)
Update:
Looks like the class is built and all is fine. But when I build a client code to test it, I get these errors:
1>client_code.obj : error LNK2019: unresolved external symbol "public: __thiscall StackType::~StackType(void)" (??1?$StackType#H##QAE#XZ) referenced in function _main
1>client_code.obj : error LNK2019: unresolved external symbol "public: void __thiscall StackType::Push(int)" (?Push#?$StackType#H##QAEXH#Z) referenced in function _main
1>client_code.obj : error LNK2019: unresolved external symbol "public: __thiscall StackType::StackType(int)" (??0?$StackType#H##QAE#H#Z) referenced in function _main
1>C:\Users\Alakazaam\Desktop\Stack\Debug\Stack.exe : fatal error LNK1120: 3 unresolved externals
main.cpp
#include <iostream>
#include <string>
#include "StackType.h"
using namespace std;
int main()
{
int num;
StackType<int> stack(4);
for(int i = 0; i < 4; i++)
{
cin >> num;
stack.Push(num);
}
return 0;
}
Update:
I got the solution, that StackType.h and StackType.cpp have to be in the same header file StackType.h (StackType.cpp is not needed bc Im using Template. So whatever supposed to be in the StackType.cpp, just go to the bottom of StackType.h)
Thanks everyone for helping :)
Change this:
template <class ItemType>
class FullStack
{};
class EmptyStack
{};
class StackType
Should be:
class FullStack
{};
class EmptyStack
{};
template <class ItemType>
class StackType
// This tells the compiler StackType is a template that uses ItemType internally.
Note 1: The use of class ItemType is correct but because ItemType may be a non class type I prefer to use the typename form:
template<typename ItemType>
class StackType
Note 2: Because of the way templates work. It is usally best to put the method definition in the header file (along with the class). It can work it the cpp file but it takes extra work. The simplist solution for you is:
Rename "StackType.cpp" to "StackType.tpp"
Add "#include <StackType.tpp>" to the end of "StackType.h"
Note 3: using namespace std; is bad practice (All the books do it to save space in the long run you will find it better not too). It is not difficult to prefix std objects with std::
You should put this code on http://codereview.stackexchange.com .