- 更新 -
“类型重新定义”的问题似乎已经解决,但“未解决的外部”仍然让我感到困惑。我已经使用了不同方法来重新包含头文件(#pragma一次和使用#ifndef / #define,两者都工作),这没关系。 “未解决的外部”与此无关(据我所知)。它们与我遇到的模板定义问题有关。 hashtable.hpp中的构造函数定义对我来说似乎是正确的,hashtable.cpp中的构造函数也是如此,但我得到的错误是:
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
这意味着,如果我理解,在链接时找不到构造函数。任何人吗?
我这里有一个文件,包含在2个不同的文件中。当我删除一次编译指示时,我得到一个错误“类类型重新定义”,当我添加它时,我得到10个“未解析的外部”错误。我该怎么办?这是一个名为“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() {}
};
编辑: 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: "<<
}
}
更新:
嗯,问题解决了。
谢谢ventsyv!
答案 0 :(得分:0)
您获得的错误与包含文件或标题保护无关,因为它是链接器错误。
我会截断不重要的东西,使错误更具可读性:
Error LNK2019 unresolved external symbol
public: int __thiscall hashtable::search(class std::basic_string)
referenced in function
public: void __thiscall clienthash::addrec(class rec *,class std::basic_string)
תרגיל 2 C:\Users\Yael\Desktop\תרגיל 2\תרגיל 2\clienthash.obj 1
基本上,在clienthash :: addrec中你调用hashtable :: search(string),但是从不定义该函数(至少根据链接器)。
这是因为该函数是模板化的并且在.cpp文件中定义。 C ++有一个问题(在C ++ 11之前),因为它分别符合每个文件。
最简单的解决方法是在.h文件中移动实现。
如果您需要更详细的说明,请阅读:
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl