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

来源:互联网 发布:淘宝食品店铺装修 编辑:程序博客网 时间:2024/06/06 00:31

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

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-declaretemplate<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)  {    // ...  }
就是这样,谢谢

哦对,一般模板类是尽可能绝不能加什么友元函数的,除非重载流