声明:博主原创,未经允许,不得转载
结合所学知识,记录笔记:
(1)将友元函数写在模板的类的内部,不会有什么问题
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> using namespace std; template<typename T> class Complex { public: Complex(){} Complex(T a1,T b1); Complex operator+(const Complex& c); friend Complex mysub(Complex &c1,Complex &c2){ Complex tem(c1.a-c2.a,c1.b-c2.b); return tem; } friend ostream& operator<<(ostream& out,Complex c3){ out<<c3.a<<" + "<<c3.b<<"i"<<endl; return out; } protected: private: T a; T b; }; template<typename T> Complex<T>::Complex(T a1,T b1){ this->a=a1; this->b=b1; } template<typename T> Complex<T> Complex<T>:: operator+(const Complex<T>& c) { Complex cc; cc.a=a+c.a; cc.b=b+c.b; return cc; } void main1() { Complex<int> c1(2,3); Complex<int> c2(4,6); Complex<int> c3,c4; c3=c1+c2; c4=mysub(c1,c2); cout<<c3; cout<<c4; } int main(int args,const char * argv[]){ main1(); cout<<"\n###################"<<endl; return 0; }
结果显示如下:
(2)将友元函数置于模板的类外,在VS2010的dubug下,编译顺利通过,链接时报错。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> using namespace std; template<typename T> class Complex { public: Complex(){} Complex(T a1,T b1); Complex operator+(const Complex& c); friend Complex mysub(Complex &c1,Complex &c2); friend ostream& operator<<(ostream& out,Complex c3); protected: private: T a; T b; }; template<typename T> Complex<T>::Complex(T a1,T b1){ this->a=a1; this->b=b1; } //友元函数放在类体外 template<typename T> Complex<T> mysub(Complex<T> &c1,Complex<T> &c2){ Complex tem(c1.a-c2.a,c1.b-c2.b); return tem; } template<typename T> ostream& operator<<(ostream& out,Complex<T> c3){ out<<c3.a<<" + "<<c3.b<<"i"<<endl; return out; } template<typename T> Complex<T> Complex<T>:: operator+(const Complex<T>& c) { Complex cc; cc.a=a+c.a; cc.b=b+c.b; return cc; } void main1() { Complex<int> c1(2,3); Complex<int> c2(4,6); Complex<int> c3,c4; c3=c1+c2; c4=mysub(c1,c2); cout<<c3; cout<<c4; } int main(int args,const char * argv[]){ main1(); cout<<"\n###################"<<endl; return 0; }
错误提示如下:
main.obj : error LNK2019: 无法解析的外部符号 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<< (class std::basic_ostream<char,struct std::char_traits<char> > &,class Complex<int>) " (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@V?$Complex@H@@@Z), 该符号在函数 "void __cdecl main1(void)" (?main1@@YAXXZ) 中被引用 1>main.obj : error LNK2019: 无法解析的外部符号 "class Complex<int> __cdecl mysub(class Complex<int> &,class Complex<int> &)" (?mysub@@YA?AV?$Complex@H@@AAV1@0@Z),该符号在函数 "void __cdecl main1(void)" (?main1@@YAXXZ) 中被引用 1>C:\Users\Administrator\Desktop\main\Debug\main.exe : fatal error LNK1120: 2 个无法解析的外部命令
(3)如果友元函数用于实现<<或者>>的重载,则解决方案如下
声明改为:friend ostream& operator<<<T>(ostream& out,Complex c3);
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> using namespace std; template<typename T> class Complex { public: Complex(){} Complex(T a1,T b1); Complex operator+(const Complex& c); //friend Complex mysub(Complex &c1,Complex &c2); friend ostream& operator<<<T>(ostream& out,Complex c3); protected: private: T a; T b; }; template<typename T> Complex<T>::Complex(T a1,T b1){ this->a=a1; this->b=b1; } //友元函数放在类体外 //template<typename T> //Complex<T> mysub(Complex<T> &c1,Complex<T> &c2){ // Complex tem(c1.a-c2.a,c1.b-c2.b); // return tem; //} template<typename T> ostream& operator<<(ostream& out,Complex<T> c3){ out<<c3.a<<" + "<<c3.b<<"i"<<endl; return out; } template<typename T> Complex<T> Complex<T>:: operator+(const Complex<T>& c) { Complex cc; cc.a=a+c.a; cc.b=b+c.b; return cc; } void main1() { Complex<int> c1(2,3); Complex<int> c2(4,6); Complex<int> c3,c4; c3=c1+c2; //c4=mysub(c1,c2); cout<<c3; //cout<<c4; } int main(int args,const char * argv[]){ main1(); cout<<"\n###################"<<endl; return 0; }
(4)如果友元函数不是用于实现函数重载(非 << >>)
解决方案如下:
//1)需要在类前增加 类的前置声明 函数的前置声明 template<typename T> class Complex; template<typename T> Complex<T> mysub(Complex<T> &c1, Complex<T> &c2);
//2)类的内部声明 必须写成: friend Complex mysub<T>(Complex &c1,Complex &c2);
//3)友元函数实现 必须写成: template<typename T> Complex<T> mysub(Complex<T> &c1,Complex<T> &c2){ Complex<T> tem(c1.a-c2.a,c1.b-c2.b); return tem; }
//4)友元函数调用必须写成
c4=mysub<int>(c1,c2);
完整代码如下:#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> using namespace std; template<typename T> class Complex; template<typename T> Complex<T> mysub(Complex<T> &c1, Complex<T> &c2); template<typename T> class Complex { public: Complex(){} Complex(T a1,T b1); Complex operator+(const Complex& c); friend Complex mysub<T>(Complex &c1,Complex &c2); friend ostream& operator<<<T>(ostream& out,Complex c3); protected: private: T a; T b; }; template<typename T> Complex<T>::Complex(T a1,T b1){ this->a=a1; this->b=b1; } //友元函数放在类体外 template<typename T> Complex<T> mysub(Complex<T> &c1,Complex<T> &c2){ Complex<T> tem(c1.a-c2.a,c1.b-c2.b); return tem; } template<typename T> ostream& operator<<(ostream& out,Complex<T> c3){ out<<c3.a<<" + "<<c3.b<<"i"<<endl; return out; } template<typename T> Complex<T> Complex<T>:: operator+(const Complex<T>& c) { Complex cc; cc.a=a+c.a; cc.b=b+c.b; return cc; } void main1() { Complex<int> c1(2,3); Complex<int> c2(4,6); Complex<int> c3,c4; c3=c1+c2; c4=mysub<int>(c1,c2); cout<<c3; cout<<c4; } int main(int args,const char * argv[]){ main1(); cout<<"\n###################"<<endl; return 0; }
结果如下: