在类模板中使用友元函数的问题


声明:博主原创,未经允许,不得转载

结合所学知识,记录笔记:

(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;
}

结果如下:

关注微信公众号

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com