[英]A C++ Program Using Class Template:error LNK2019
I just begin to learn C++ and I am now writing a C++ Program using class template.It realize some easy functions of a queue.But I get an error. 我刚开始学习C ++,现在正在使用类模板编写C ++程序,它实现了一些简单的队列功能,但出现错误。 The program concludes two files:Queue.h and Queue.cpp.Now I post my code.
该程序总结了两个文件:Queue.h和Queue.cpp。现在我发布代码。 Queue.h:
Queue.h:
#ifndef QUEUE_H
#define QUEUE_H
#include <iostream>
#include <cstdlib>
using namespace std;
template <class T> class QueueItem;
//define class template Queue
template <class Type>
class Queue{
public:
Queue():front(0),back(0){}
~Queue();
Type remove();
void add(const Type&);
bool is_empty() const{
return front == 0;
}
friend ostream& operator<<(ostream&,const Queue<Type> &);
private:
QueueItem<Type> *front;
QueueItem<Type> *back;
};
//define class template QueueItem
template <class Type>
class QueueItem{
public:
QueueItem(const Type&t):item(t),next(0){}
friend class Queue<Type>;
friend ostream& operator<<(ostream&,const QueueItem<Type>&);
private:
Type item;
QueueItem *next;
};
template <class Type>
Queue<Type>::~Queue()
{
while(!is_empty())
remove();
}
template <class Type>
void Queue<Type>::add(const Type &val)
{
QueueItem<Type> *pt = new QueueItem<Type>(val);
if (is_empty())
front = back = pt;
else
{
back ->next = pt;
back = pt;
}
}
template <class Type>
Type Queue<Type>::remove()
{
if (is_empty())
{
cerr << "remove() on empty queue!"<<endl;
exit(-1);
}
QueueItem<Type> *pt = front;
front = front ->next;
Type retval = pt ->item;
delete pt;
return retval;
}
template <class Type>
ostream& operator<<(ostream &os,const Queue<Type> &q)
{
os << "<";
QueueItem<Type> *p;
for (p = q .front;p;p = p ->next)
{
os << *p << " ";
}
os << ">";
return os;
}
template <class Type>
ostream& operator<<(ostream &os,const QueueItem<Type> &qi)
{
os << qi.item;
return os;
}
#endif
Queue.cpp: Queue.cpp:
#include "Queue.h"
#include <iostream>
using namespace std;
int main()
{
//Queue<int> *p_qi = new Queue<int>;
Queue<int> p_qi;
cout << p_qi <<endl;
for (int ival = 0;ival < 10;++ival)
{
p_qi .add(ival);
}
cout << p_qi <<endl;
int err_cnt = 0;
for (int ival = 0;ival < 10;++ival)
{
int qval = p_qi .remove();
if (qval != ival)
++err_cnt;
}
cout << p_qi <<endl;
if (!err_cnt)
cout << "!!Queue executed OK!"<<endl;
else
cout << "??Queue errors:"<<err_cnt << endl;
return 0;
}
But I get an error in Visual Studio 2008: 1>Queue.obj : error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class Queue const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Queue@H@@@Z),the symbolic is referenced in function _main 1>G:\\CPPPrimer\\Queue\\Debug\\Queue.exe : fatal error LNK1120: a unresolved external symbol 但是我在Visual Studio 2008中遇到错误:1> Queue.obj:错误LNK2019:未解析的外部符号“类std :: basic_ostream>&__cdecl运算符<<(类std :: basic_ostream>&,类队列const&)”( 6 @ YAAAV?$ basic_ostream @ DU?$ char_traits @ D @ std @@@ std @@ AAV01 @ ABV?$ Queue @ H @@@ Z),符号在函数_main 1> G:\\ CPPPrimer中引用\\ Queue \\ Debug \\ Queue.exe:致命错误LNK1120:无法解析的外部符号
Could anyone tell me why? 谁能告诉我为什么? Thanks a lot.
非常感谢。
I have resolved my problems.This is my code that runs on Visual Studio 2008 correctly: 我已经解决了问题。这是我在Visual Studio 2008上正确运行的代码:
#include <iostream>
#include <cstdlib>
using namespace std;
template <class Type> class QueueItem;
//类模板Queue的定义
template <class Type>
class Queue{
public:
Queue():front(0),back(0){}
~Queue();
Type remove();
void add(const Type&);
bool is_empty() const{
return front == 0;
}
//将输出符号声明为函数模板
template <class T>
friend ostream& operator<<(ostream&,const Queue<T> &);
private:
QueueItem<Type> *front;
QueueItem<Type> *back;
};
//类模板QueueItem的定义
template <class Type>
class QueueItem{
public:
QueueItem(const Type&t):item(t),next(0){}
friend class Queue<Type>;
//将输出符号声明为函数模板
template <class T>
friend ostream& operator<<(ostream&,const QueueItem<T>&);
private:
Type item;
public:
QueueItem *next;
};
template <class Type>
Queue<Type>::~Queue()
{
while(!is_empty())
remove();
}
template <class Type>
void Queue<Type>::add(const Type &val)
{
QueueItem<Type> *pt = new QueueItem<Type>(val);
if (is_empty())
front = back = pt;
else
{
back ->next = pt;
back = pt;
}
}
template <class Type>
Type Queue<Type>::remove()
{
if (is_empty())
{
cerr << "remove() on empty queue!"<<endl;
exit(-1);
}
QueueItem<Type> *pt = front;
front = front ->next;
Type retval = pt ->item;
delete pt;
return retval;
}
template <class Type>
ostream& operator<<(ostream &os,const Queue<Type> &q)
{
os << "<";
QueueItem<Type> *p;
for (p = q .front;p;p = p ->next)
{
os << *p << " ";
}
os << ">";
return os;
}
template <class Type>
ostream& operator<<(ostream &os,const QueueItem<Type> &qi)
{
os << qi.item;
return os;
}
int main()
{
//Queue<int> *p_qi = new Queue<int>;
//ostream& operator<<(ostream &os,const Queue<int>&);
//ostream& operator<<(ostream &os,const QueueItem<int>&);
Queue<int> p_qi;
cout << p_qi <<endl;
for (int ival = 0;ival < 10;++ival)
{
p_qi.add(ival);
}
cout << p_qi <<endl;
int err_cnt = 0;
for (int ival = 0;ival < 10;++ival)
{
int qval = p_qi .remove();
if (qval != ival)
++err_cnt;
}
cout << p_qi <<endl;
if (!err_cnt)
cout << "!!Queue executed OK!"<<endl;
else
cout << "??Queue errors:"<<err_cnt << endl;
return 0;
}
You need to declare your operators first, as such : 您需要首先声明您的运算符,如下所示:
template <typename Type> class Queue;
template <typename Type> class QueueItem;
template <typename Type>
ostream& operator<<(ostream &os,const Queue<Type> &q);
template <typename Type>
ostream& operator<<(ostream &os,const QueueItem<Type> &qi);
And the friend declarations need the template parameter : 并且朋友声明需要template参数:
friend ostream& operator<< <Type>(ostream&,const Queue<Type> &);
friend ostream& operator<< <Type>(ostream&,const QueueItem<Type> &);
This compiles, link and run under gcc and clang. 这将在gcc和clang下进行编译,链接和运行。 Btw, QueueItem needs to have both operators as friend since the code for printing a queue also uses QueueItem members.
顺便说一句,因为打印队列的代码也使用QueueItem成员,所以QueueItem需要同时拥有两个运算符。 On a personal note, I would suggest implementing const accessors and get rid of friends altogther.
就个人而言,我建议实现const访问器,并彻底摆脱朋友。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.