关于类模板重载输入输出流的思考

在模板中输入输出流的重载,若使用友元在类模板中声明,在类模板外实现;那么链接时就会报错,可以使用五种方式来实现输入输出流的重载.

第一种方法:将输入流输出流的重载的实现写在类模板中

template<class T>
class Test
{
public:
  Test(const T& data):m_data(data){}
  friend ostream& operator << (ostream& out, const Test<T>& obj)
  {
     out<<"data is:"<<obj.m_data<<endl;
     return out;  
  }
  friend istream& operator >> (istream& in, Test<T>& obj)
  {
    in>>obj.m_data;
    return in;
  }
  friend const T operator *(const T& lhs, const T& rhs)
  {
    return (lhs.m_data * rhs.m_data);
  }
private:
   T m_data;
};

那么输入输出流重载为什么不能在类内声明,类外实现呢??因为模板比较特殊,如果在类模板中声明友元,在类模板外实现的话:

template<class T>
ostream& operator<<(ostream& out,const Test<T>& t)
{
        out<<"data   is   "<<t.data;

         return out;
} //--------------------------------------------
上面正好是函数模板的定义,而我们知道操作符重载函数不是类的成员函数,因此此处相当于定义了一个新 的函数模板(不同于类中的friend ostream& operator<<(ostream& out,const Test<T>& t) )。但若去掉template<class T> ,函数中的参数Test<T>就不知是什么类型,所以不能在模板类内声明,类外实现操作符重载。

 

第二种方法:既然类外实现相当于重定义了一个函数模板,那么只要他不使用类的私用成员即可,
因此重载的函数模板只有通过类的公有成员函数来实现对类的私有成员的操作,这样不必在类内声明它为友元,直接在类外重载即可。

template<class T>
class Test
{
public:
  Test(const T& data):m_data(data){}
  const T GetData()const;
  void SetData(const Test& rhs);
private:
   T m_data;
};
template<class T>
const T Test<T>::GetData()const
{
  return m_data;
}
template<class T>
void Test<T>::SetData(const Test& rhs)
{
  m_data=rhs.m_data;
}

template<class T>      
ostream& operator << (ostream& out,const Test<T>& obj)   
{
   out<<"data is:"<<obj.GetData();
   return out;   
} 
template<class T>
istream& operator >> (istream& in,Test<T>& obj)     
{
    T item;
    in>>item;
    obj.SetData(item);
    return in;
}

 

第三种方法:将operator <<,operator >> 重载函数定义为函数模板,并声明为Test类模板的友元

template<class T>
class Test
{
public:
	Test(const T& val):m_val(val){}
	template<class Y>
	friend istream& operator >>(istream& is,Test<Y>& obj);
	template<class Y> 
	friend ostream& operator << (ostream& os,const Test<Y>& obj);
private:
	T m_val;
};
template<class Y>
istream& operator >> (istream& is,Test<Y>& obj)
{
	is>>obj.m_val;
	return is;
}
template<class Y>
ostream& operator << (ostream& os,const Test<Y>& obj)
{
	os<<obj.m_val;
	return os;
}


第四种方法:使用输入输出流过渡函数

template<class T>
class Test
{
public:
  Test(const T& data):m_data(data){}
  ostream& Output(ostream& out,const Test& obj);
  istream& Input(istream& in, Test& obj);
private:
   T m_data;
};
template<class T>
ostream& Test<T>::Output(ostream& out,const Test& obj)
{
  out<<m_data<<endl;
  return out;
}
template<class T>
istream& Test<T>::Input(istream& in,Test& obj)
{
  in>>m_data;
  return in;
}
template<class T>
ostream& operator << (ostream& out,const Test<T>& obj)
{
  return obj.Output(out,obj);
}
template<class T>
istream& operator >> (istream& in,Test<T>& obj)
{
  return obj.Input(in,obj);
}

 


第五种方法:使用特殊的方式声明

template<class T>
class Test
{
public:
  Test(const T& data):m_data(data){}
  friend ostream& operator << <T> (ostream& out, const Test<T>& obj);
  friend istream& operator >> <T> (istream& in, Test<T>& obj);
private:
   T m_data;
};
template<class T>
friend ostream& operator << (ostream& out, const Test<T>& obj)
{
     out<<"data is:"<<obj.m_data<<endl;
     return out;  
}
template<class T>
friend istream& operator >> (istream& in, Test<T>& obj)
{
    in>>obj.m_data;
    return in;
}



 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值