模板类与友元函数:关于LNK1120和LNK2019报错
2017-12-06 22:45
183 查看
因为最近呢开始用清华大学出版社的那本数据结构自学,真正脱离书本写了一个队列,还是出了点问题的。
当我在main中调用输出流的时候,竟然链接器报错!!
我一共只有这两个文件啊,一个头文件,一个main,我也知道模板类声明和实现要一起写的啊,然而,然而。。他就是报错,还linker的错误,又不能调试,又不知道具体问题在哪 ,无比奔溃,查了一个多小时,还和以前程序书上对了个比(我写的和书上略有差异,自己写的是带头节点的),愣是查不出,查报错,又是什么没找到实现,我我我我,我明明一起写了的啊!
在我临近崩坏之际,突然,灵光一闪,我把main中绝大部分代码注释,慢慢恢复注释来编译。yiu!终于最后锁定了问题!输出流函数!
在清华大学出版社数据结构(面向对象方法与C++语言描述)这本书中,它关于友元函数输出流的重载定义是在类声明之外的,同时在此前的例子里,并没有使用过这个输出流,因此我没有发现这个问题,由于模板函数只有实例化才会被编译,因此编译也不会报错。所以,所以,都是你这本书的锅啊啊啊!
然后我查了一下呢,将重载函数的定义甩进类的体内就好了。
***************关于原因**********************
参见英文原参考
怎么说呢,你在某处使用了这只可爱的模板类,友元函数呢也在某处神奇的定义着。在某时,你突然想用这个可爱的友元函数了,那么,在编译时,你的编译器在类定义中看见了这只友元函数,但你的编译器太瞎了,以为它的T实际上是int,而非一个模板函数。因此在你调用这个友元函数的时候,编译器召唤非模板函数,同样瞎瞎的链接器自然报错了啦。
****************解决***************************
除了上面说的直接甩进去之外呢,还可以呢,在类定义前预定义:
哦对,一般模板类是尽可能绝不能加什么友元函数的,除非重载流
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) { // ... }就是这样,谢谢
哦对,一般模板类是尽可能绝不能加什么友元函数的,除非重载流
相关文章推荐
- 关于模板类中友元函数的声明与定义
- 关于类模板的友元函数
- C++模板类内友元(友元函数,友元类)声明的三种情况
- 关于C++中的友元函数的总结
- 关于C++中的友元函数的总结
- 模板类的非约束模板友元函数
- 关于C++中的友元函数的总结
- 关于C++中的友元函数的总结
- 关于模板类中,子类无法访问父类成员问题的解决方法
- STL源码剖析 - 模板类中的友元函数
- 关于C++中的友元函数的总结
- 关于C++中的友元函数的总结
- 模板类和友元函数
- 关于C++中的友元函数的总结
- 模板类中的友元函数写法
- 关于C++中的友元函数的总结
- 在c++ 模板类外写 操作符重载函数,并且是模板类的友元函数
- C++模板类内友元(友元函数,友元类)声明的三种情况
- (选做)-模板类中使用友元函数
- 关于C++中的友元函数的总结