为改变Windows编程演练较多而C++中的某些特性用得比较少这一现状,最近在阅读相应典籍以及进行代码实践。以下为近日的一些温习收获:
三、模板类中的操作符重载:
/*************************************************/
#include<iostream>
using namespace std;
template<typename T>
class A;
template<typename T>
ostream& operator << (ostream& out,const A<T>& a);
//进行下面的编码之前,先把声明写好,否则难免会出现一坨乱七八糟的错误提示
/*************************************************/
/*************************************************/
template<typename T>
class A
{
friend ostream& operator << (ostream& out,const A<T>& a)
{
out << a._m;
return out;
}
protected:
T _m;
};
//正确:
//写法一,将操作符实现写在类定义内,安定(注一)的写法。
/*************************************************/
/*************************************************/
template<typename T>
class A
{
friend ostream& operator << (ostream& out,const A<T>& a);
protected:
T _m;
};
template<typename T>
ostream& operator << (ostream& out,const A<T>& a)
{
out << a._m;
return out;
}
//错误:
//写法二,将操作符实现写在类定义外,这样会报链接错误(注二)。
/*************************************************/
/*************************************************/
template<typename T>
class A
{
//friend ostream& operator << (ostream& out,const A<T>& a);
friend ostream& operator << <> (ostream& out,const A<T>& a);//仅修改此处
protected:
T _m;
};
//正确:
//写法三,将操作符实现写在类定义外,同时修改写法二中的“operator <<”为“operator << <>”(注三),即可编译链接成功。
/*************************************************/
注:
一、之所以说是“安定”的写法,是因为在使用模板类时,只要成员函数实现与类定义写在同一个文件内就不会出现错误(具体原因见http://hi.baidu.com/hadoken/blog/item/dfc09e50eaf2aa608435244f.html详述)。若试图将模板类成员函数实现于其他文件(类定义在.h文件、成员函数实现在.cpp文件),则可能会出现编译错误,这与所使用编译器对模板类的编译、实例化机制有关。
二、错误原因是因为链接器没有找到重载的函数实体,也就是重载的流输出模板根本就没有实例化。
三、模板类中声明的函数是函数,而不是模板,如:
template<class Type>
Class1<Type>::Fun1(){}
这里Fun1是属于类Class1<Type>的函数。
而当定义友元时:
template<class Type>
ostream& operator << (...);
这是一个模板,不是函数
ostream& operator << <sometype> (...);
才是一个函数 //此处需注意,在“<<”后加上“<>”表明这是一个函数模板