-- UPDATE --
The problem with the "class type redefinition" seems solved, but the "unresolved externals" is still confusing me. I have used different ways of not reincluding the header file (both #pragma once and using #ifndef/#define, both work), and it's OK. The "unresolved externals" are not related (as far as I can tell). They are relating to a problem I am having with a template defintion. The constructor definition in hashtable.hpp seems correct to me, as does the constructor in hashtable.cpp, but the error I'm getting is:
Severity Code Description Project File Line
Error LNK2019 unresolved external symbol "public: int __thiscall hashtable<class client,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::search(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?search@?$hashtable@Vclient@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@QAEHV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: void __thiscall clienthash::addrec(class rec *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?addrec@clienthash@@QAEXPAVrec@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) תרגיל 2 C:\Users\Yael\Desktop\תרגיל 2\תרגיל 2\clienthash.obj 1
which means, if I understand, that the constructor is not found at link time. Anyone?
I've got a file here that's included in 2 different files. When I remove the pragma once, I get an error "class type redefinition", and when I add it I get 10 "unresolved externals" errors. what should I do? here is the file, titled "rec.h" :
#include "item.h"
class rec
{
string name;
int grade;
string description;
public:
rec(string n, int g, string d) :name(n), grade(g), description(d) {}
~rec() {}
};
EDIT: main.cpp:
#include "workerhash.h"
#include "clienthash.h"
#include "rec.h"
void main()
{
workerhash w(10);
clienthash c(11);//the same thing will happen
string n, p, e;
int num, grade;
cout << "enter 0 to add a worker, 1 to remove a worker, 2 to add a client, 3 to add a recommendation to a worker, 4 to add a recommender's recommendation, 5 to print a workers details, 6 to print a recommendors reccomendations, and 7 to exit\n";
cin >> num;
while(num != 6)
{
switch (num)
{
case 0:
cout << "enter name, phone, and email: ";
cin >> n >> p >> e;
if (w.search(n) == -1)
w.insert(worker(n, p, e));
break;
case 1:
cout << "enter worker's name: ";
cin >> n;
w.remove(n);
break;
case 2:
cout << "enter name, phone, and email: ";
cin >> n >> p >> e;
if (c.search(n) == -1)
c.insert(client(n, p, e));
break;
case 3:
cout << "enter name of recommendee, grade, and description: ";
cin >> n >> grade >> p;
w.addrec(new rec(n, grade, p), n);
break;
case 4:
cout << "enter name of recommender,grade, and description: ";
cin >> n >> grade >> p;
c.addrec(new rec(n, grade, p), n);
break;
case 5:
cout << "enter worker's name: ";
cin >> n;
grade = w.search(n);//really index, just saving memory
cout << "name: " << w.wtable.table[grade].data.name << ", phone: " << w.wtable.table[grade].data.phone << ", email: "
<< w.wtable.table[grade].data.email;
cout << "\n";
}
}
}
client.h:
#pragma once
#include "rec.h"
#include <list>
class client
{
public:
client() {}
client(string n, string p, string e) :name(n), phone(p), email(e) {}
~client() {}
string name;
string phone;
string email;
list<rec *> l;
};
clienthash.h:
#include "client.h"
#include "hashtable.h"
class clienthash
{
public:
clienthash(int size) :ctable(size) {}
~clienthash() {}
hashtable<client, string> ctable;
void insert(client);
void remove(string);
int search (string);
void addrec(rec *,string);
};
hashtable.h:
#pragma once
#include "item.h"
template<class T, class K>
class hashtable
{
public:
hashtable(int size);
~hashtable();
item<T,K> * table;
int size;
int h1(int & k) {return (k % size);}
int h1(string & k);
int h2(int & k) {return (size - (k % size));}
int h2(string & k);
int h(int & k,int i) { return ((h1(k) + i*h2(k)) % size);}
int h(string k, int i) { return ((h1(k) + i*h2(k)) % size); }
int search(K key);
void insert(T data, K key);
void remove(K key);
void print();
int prime(int);
bool isprime(int);
};
item.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
template<class T,class K>
class item
{
public:
item():flag(empty),key(NULL){}
~item() {}
T data;
K key;
enum state {empty=0,full,del};
state flag;
};
worker.h:
#pragma once
#include "rec.h"
#include <list>
class worker
{
public:
worker();
worker(string n, string p, string e) : name(n), phone(p), email(e) {}
~worker();
string name;
string phone;
string email;
list<rec *> l;
};
workerhash.h:
#include "worker.h"
#include "hashtable.h"
class workerhash
{
public:
workerhash(int size):wtable(size) {}
~workerhash() {}
hashtable<worker, string> wtable;
void insert(worker);
void remove(string);
int search(string);
void addrec(rec *, string);
void print(string);
};
clienthash.cpp:
#include "clienthash.h"
#include <string>
void clienthash::insert(client c)
{
ctable.insert(c, c.name);
}
void clienthash::remove(string key)
{
ctable.remove(key);
}
int clienthash::search(string key)
{
return ctable.search(key);
}
void clienthash::addrec(rec * recommendation, string name)
{
int index = ctable.search(name);
if (index != -1)
(ctable.table[index].data).l.push_back(recommendation);
}
hashtable.cpp:
#pragma once
#include "hashtable.h"
template<class T, class K>
int hashtable<T,K>::prime(int size)
{
for (int i = size; ; ++i)
if (isprime(i))
return i;
}
template<class T, class K>
bool hashtable<T,K>::isprime(int num)
{
for (int i = 2; i < num; ++i)
if (num % i == 0 && i != num)
return false;
return true;
}
template<class T, class K>
hashtable<T,K>::hashtable(int size)
{
table = new item[prime(size)];
this->size = prime(size);
}
template<class T, class K>
hashtable<T,K>::~hashtable()
{
delete [] table;
table = NULL;
}
template<class T, class K>
int hashtable<T,K>::search(K key)
{
for (int i = 0; i < size; ++i)
{
if (table[h(key, i)].flag == table[h(key, i)].del && table[h(key, i)].key == key)
return -1;
else if (table[h(key, i)].flag == table[h(key, i)].empty)
return -1;
else if (table[h(key,i)].key == key)
return h(key,i);
}
return -1;
}
template<class T, class K>
void hashtable<T,K>::insert(T data, K key)
{
for (int i = 0; i < size; ++i)
if (table[h(key, i)].flag == table[h(key, i)].empty || table[h(key, i)].flag == table[h(key, i)].del)
{
table[h(key,i)].data = data;
table[h(key, i)].key = key;
table[h(key, i)].flag = table[h(key, i)].full;
return ;
}
}
template<class T, class K>
void hashtable<T,K>::remove(K key)
{
int index = search(key);
if (index != -1)
{
table[index].flag = table[index].del;
}
}
template<class T, class K>
void hashtable<T,K>::print()
{
for (int i = 0; i < size; ++i)
{
if (table[i].flag == table[i].empty)
cout << i << ": empty\n";
else if (table[i].flag == table[i].del)
cout << i << ": del\n";
else cout << i << ": " << table[i].key << "\n";
}
}
template<class T , class K>
int hashtable<T,K>::h1(string & k)
{
unsigned long hash = 5381;
for (string::iterator it = k.begin(); it != k.end(); ++it)
hash = (hash << 5) + hash + int(*it); /* hash * 33 + c */
return hash;
}
template<class T, class K>
int hashtable<T,K>::h2(string & k)
{
char *str;
unsigned long hash = 0;
int c;
for (string::iterator it = k.begin(); it!= k.end(); ++it)
hash = int(*it) + (hash << 6) + (hash << 16) - hash;
return hash;
}
workerhash.cpp:
#include "workerhash.h"
#include <string>
#include <list>
void workerhash::insert(worker w)
{
wtable.insert(w,w.name);
}
void workerhash::remove(string key)
{
wtable.remove(key);
}
int workerhash::search(string key)
{
return wtable.search(key);
}
void workerhash::addrec(rec * recommendation, string name)
{
int index = wtable.search(name);
if (index != -1)
wtable.table[index].data.l.push_back(recommendation);
}
void workerhash::print(string name)
{
int index = wtable.search(name), sum = 0;
for (list<rec *>::iterator it = wtable.table[index].data.l.begin(); it != wtable.table[index].data.l.end(); ++it)
{
//cout<<"recommender: "<<
}
}
UPDATE:
Well, problem solved.
Thanks ventsyv!