在模板类中输入流">>"和输出流"<<"的重载,若使用友元在类内声明,在类外实现,那么连接时会报错。我们可以采用以下三种方式来实现输出流"<<"和输入流">>"的重载。
《一》将输出流"<<"和输入流“>>”重载的实现写在类中。
下面给出示例的代码:
template<typename Type>
class Test;
template<typename Type>
ostream& operator<<(ostream &out,const Test<Type> &t);
template<typename Type>
class Test
{
friend ostream& operator<<(ostream &out,const Test<Type> &t)
{
cout << *(t.ptr);
return out;
}
public:
Test(Type * p = 0):ptr(p)
{}
Test(const Test<Type> &p):ptr(p.ptr)
{}
~Test()
{
delete ptr;
cout << "des!" << endl;
}
Test<Type>& operator=(Test<Type>& t)
{
if(this != &t){
delete ptr;
ptr = t.ptr;
t.ptr = NULL;
}
return *this;
}
Type& operator*()const
{
return *ptr;
}
private:
Type *ptr;
};
int main(int argc,char**argv)
{
Test<int> t(new int(10));
Test<int> t1(new int(100));
cout << "t = " << *t<<endl;
cout << "t1 = " << *t1 <<endl;
t = t1;
cout << "t = " << t <<endl;
return 0;
}
其执行结果如下:
下面我们来说明为什么输出流的重载不能在类外实现呢?
template<typename Type>
ostream& operator<<(ostream& out,Test<Type>& t)
{
cout << *(t.ptr);
return out;
}
上面正是函数模板的定义,而我们知道操作符重载函数不是类的成员函数,因此此处相当于定义了一个新的函数模板(不同于类中的friend ostream& operator<<(ostream& out,Test<Type>& t))。但若去掉template<tapename Type>,函数中的参数就不知道Test<Type>是什么类型,所以不能在模板类声明,类外实现操作符重载。
《二》既然类外实现相当于重定义了一个函数模板,那么只要它不使用类的私有成员即可,因此重载的函数模板只有通过类的公有成员函数来实现对类的私有成员的操作,这样不必在类内声明它为友元,直接在类外重载即可。
下面给出具体的代码:
template<typename Type>
class Test
{
public:
Test(Type * p = 0):ptr(p)
{}
Test(const Test<Type> &p):ptr(p.ptr)
{}
~Test()
{
delete ptr;
cout << "des!" << endl;
}
Test<Type>& operator=(Test<Type>& t)
{
if(this != &t){
delete ptr;
ptr = t.ptr;
t.ptr = NULL;
}
return *this;
}
Type& operator*()const
{
return *ptr;
}
public:
Type& GetData()const
{return *ptr;}
void SetData(const Type*& t)
{
ptr = t;
}
private:
Type *ptr;
};
template<typename Type>
ostream& operator<<(ostream& out,Test<Type>& t)
{
cout << t.GetData();
return out;
}
int main(int argc,char**argv)
{
Test<int> t(new int(10));
Test<int> t1(new int(100));
cout << "t = " << *t<<endl;
cout << "t1 = " << *t1 <<endl;
t = t1;
cout << "t = " << t <<endl;
return 0;
}
程序的执行结果:
《三》使用过渡函数:
下面给出具体的代码:
template<typename Type>
class Test
{
public:
Test(Type * p = 0):ptr(p)
{}
Test(const Test<Type> &p):ptr(p.ptr)
{}
~Test()
{
delete ptr;
cout << "des!" << endl;
}
Test<Type>& operator=(Test<Type>& t)
{
if(this != &t){
delete ptr;
ptr = t.ptr;
t.ptr = NULL;
}
return *this;
}
Type& operator*()const
{
return *ptr;
}
public:
//输出过渡函数
template<typename CharT,typename CharTraits>
basic_ostream<CharT,CharTraits>& Output(basic_ostream<CharT,CharTraits>& out)const
{
out << *ptr;
return out;
}
//输入过渡函数
template<typename CharT,typename CharTraits>
basic_istream<CharT,CharTraits>& Iutput(basic_istream<CharT,CharTraits>& in)
{
in >> ptr;
return in;
}
private:
Type *ptr;
};
//输出流重载
template<typename Type,typename CharT,typename CharTraits>
basic_ostream<CharT,CharTraits>& operator<<(basic_ostream<CharT,CharTraits>& out,const Test<Type>& t)
{
return t.Output(out);
}
//输入流重载
template<typename Type,typename CharT,typename CharTraits>
basic_istream<CharT,CharTraits>& operator>>(basic_istream<CharT,CharTraits>& in,Test<Type>& t)
{
return in.Input(in);
}
int main(int argc,char**argv)
{
Test<int> t(new int(10));
Test<int> t1(new int(100));
cout << "t = " << *t<<endl;
cout << "t1 = " << *t1 <<endl;
t = t1;
cout << "t = " << t <<endl;
return 0;
}
程序执行结果: