在模板類中輸入流“>>”和輸出流“<<”的重載,若使用友元在類內聲明,在類外實現,那麼連接時將會報錯,但我們可以採用以下三種方式來實現輸出流"<<"和"輸入流>>"的重載。
一、將輸出流"<<"和"輸入流>>"重載的實現寫在類中
#include <iostream>
using namespace std;
template<class T>
class Test
{
public:
Test(const T& t):data(t){}
//---------------------------------------------
friend ostream& operator<<(ostream& out,Test<T>& t) //輸出流重載聲明及實現
{
return out<<"data is "<<t.data;
} //--------------------------------------------
friend istream& operator>>(istream& in,Test<T>& t) //輸入流重載聲明及實現
{
return in>>t.data;
}//---------------------------------------------
private:
T data;
};//-----------------------------------------------------------------
int main()
{
Test<int> b(3);
cout<<b<<'\n';
cin>>b;
cout<<b<<'\n';
return 0;
}
那麼輸入輸出流重載爲什麼不能在類內聲明,類外實現呢??因爲模板比較特殊,若果在模板類外實現重載的話:
ostream& operator<<(ostream& out,Test<T>& t)
{
return out<<"data is "<<t.data;
} //--------------------------------------------
上面正好是函數模板的定義,而我們知道操作符重載函數不是類的成員函數,因此此處相當於定義了一個新的函數模板(不同於類中的friend ostream& operator<<(ostream& out,Test<T>& t) )。但若去掉template<class T> ,函數中的參數Test<T>就不知是什麼類型,所以不能在模板類內聲明,類外實現操作符重載。
二、既然類外實現相當於重定義了一個函數模板,那麼只要他不使用類的私用成員即可,因此重載的函數模板只有通過類的公有成員函數來實現對類的私有成員的操作,這樣不必在類內聲明它爲友元,直接在類外重載即可。
#include <iostream>
using namespace std;
template<class T>
class Test
{
public:
Test(const T& t):data(t){}
T GetData()const{return data;}
void SetData(T &item){data=item;}
private:
T data;
};//-----------------------------------------------------------------
template<class T>
ostream& operator<<(ostream& out,Test<T>& t)
{
return out<<"data is "<<t.GetData();
} //--------------------------------------------
template<class T>
istream& operator>>(istream& in,Test<T>& t)
{
T item;
in>>item;
t.SetData(item);
return in;
}//---------------------------------------------
int main()
{
Test<int> b(3);
cout<<b<<'\n';
cin>>b;
cout<<b<<'\n';
return 0;
}
三、使用過渡函數
#include <iostream>
using namespace std;
template<class T>
class Test
{
public:
Test(const T& t):data(t){}
//---------------------------------------------
template<class CharT,class CharTraits>
basic_ostream<CharT,CharTraits>& Output(basic_ostream<CharT,CharTraits>& out)const //輸出流過渡函數
{
return out<<"data is "<<data;
} //--------------------------------------------
template<class CharT,class CharTraits>
basic_istream<CharT,CharTraits>& Input(basic_istream<CharT,CharTraits>& in) //輸入流過渡函數
{
return in>>data;
}//---------------------------------------------
private:
T data;
};//-----------------------------------------------------------------
template<class T,class CharT,class CharTraits>
basic_ostream<CharT,CharTraits>& operator<<(basic_ostream<CharT,CharTraits>& out,const Test<T>& t) //輸出流重載
{
return t.Output(out);
}//------------------------------------------------------------------
template<class T,class CharT,class CharTraits>
basic_istream<CharT,CharTraits>& operator>>(basic_istream<CharT,CharTraits>& in,Test<T>& t) //輸入流重載
{
return t.Input(in);
}//------------------------------------------------------------------
int main()
{
Test<int> b(4);
cout<<b<<'\n';
cin>>b;
cout<<b<<'\n';
return 0;
}