在模板类中输入流">>"和输出流"<<"的重载,若使用友元在类内声明,在类外实现,那么连接时会报错。我们可以采用以下三种方式来实现输出流"<<"和输入流">>"的重载。
《一》将输出流"<<"和输入流“>>”重载的实现写在类中。
下面给出示例的代码:
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; }
《二》既然类外实现相当于重定义了一个函数模板,那么只要它不使用类的私有成员即可,因此重载的函数模板只有通过类的公有成员函数来实现对类的私有成员的操作,这样不必在类内声明它为友元,直接在类外重载即可。
下面给出具体的代码:
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; }