您的位置:首页 > 其它

模板类与友元函数:关于LNK1120和LNK2019报错

2017-12-06 22:45 183 查看
因为最近呢开始用清华大学出版社的那本数据结构自学,真正脱离书本写了一个队列,还是出了点问题的。

template <typename T>
class LQueue
{
public:
LQueue();
~LQueue();
bool EnQueue(const T& x);
bool DeQueue(T& x);
int getSize() const;
bool getHead(T& x) const;
bool IsEmpty() const{ return head->link == NULL; }
void makeEmpty();
friend ostream& operator<< (ostream& out, LQueue<T>& Q);
private:
LinkNode<T>* rear, * head;
};

template <typename T>
ostream& operator<< (ostream& out, LQueue<T>& Q){
LinkNode<T>* current = Q.head->link;
int i = 0;
while (current != NULL){
i++;
out << "#" << i << ":" << current->data << endl;
current = current->link;
}
return out;
};


当我在main中调用输出流的时候,竟然链接器报错!!

我一共只有这两个文件啊,一个头文件,一个main,我也知道模板类声明和实现要一起写的啊,然而,然而。。他就是报错,还linker的错误,又不能调试,又不知道具体问题在哪 ,无比奔溃,查了一个多小时,还和以前程序书上对了个比(我写的和书上略有差异,自己写的是带头节点的),愣是查不出,查报错,又是什么没找到实现,我我我我,我明明一起写了的啊!

在我临近崩坏之际,突然,灵光一闪,我把main中绝大部分代码注释,慢慢恢复注释来编译。yiu!终于最后锁定了问题!输出流函数!

在清华大学出版社数据结构(面向对象方法与C++语言描述)这本书中,它关于友元函数输出流的重载定义是在类声明之外的,同时在此前的例子里,并没有使用过这个输出流,因此我没有发现这个问题,由于模板函数只有实例化才会被编译,因此编译也不会报错。所以,所以,都是你这本书的锅啊啊啊!

然后我查了一下呢,将重载函数的定义甩进类的体内就好了。

***************关于原因**********************

参见英文原参考

怎么说呢,你在某处使用了这只可爱的模板类,友元函数呢也在某处神奇的定义着。在某时,你突然想用这个可爱的友元函数了,那么,在编译时,你的编译器在类定义中看见了这只友元函数,但你的编译器太瞎了,以为它的T实际上是int,而非一个模板函数。因此在你调用这个友元函数的时候,编译器召唤非模板函数,同样瞎瞎的链接器自然报错了啦。

****************解决***************************

除了上面说的直接甩进去之外呢,还可以呢,在类定义前预定义:

template<typename T> class LQueue;  // pre-declare
template<typename T> ostream& operator<< (std::ostream& out, const LQueue<T>& Q);
类定义里面的呢这么写(注意中间加了一对尖括号,好奇用途原理中)

friend ostream& operator<< <> (ostream& out, const LQueue<T>& Q);
实现直接就好了
ostream& operator<< (ostream& out, const LQueue<T>& Q)
{
// ...
}
就是这样,谢谢

哦对,一般模板类是尽可能绝不能加什么友元函数的,除非重载流
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  友元函数 模板 LNK