友元函數和運算符重載


友元
一個常規的成員函數聲明描述了三件在邏輯上相互不同的事情
①該函數能訪問類聲明中的私用部分
②該函數位於作用域之中
③該函數必須經由一個對象去激活(有一個this指針)
通過將函數聲明為static,可以讓他只有前兩種性質
通過將一個函數聲明為友元可以使他只具有第一種性質
單(++,--)、雙目運算符(+,-,*,/,%,|,&,+=,-=,*=,/=)的重載(雙目重載絕大多數只考慮對象與對象進行的操作),輸入輸出運算符作為友元函數的重載。
//Test1.h
#include<iostream>
using namespace std;
class INT
{
	friend INT operator+(int a, const INT &t);
	friend ostream& operator<<(ostream &out, const INT &t);
	friend istream& operator>>(istream &in, INT &t);
private:
	int a;
	long b;
public:
	INT(int _a=0,long _b=0):a(_a),b(_b)
	{
		this->a=_a;
		this->b=_b;
	}
	INT(INT &t)
	{
		this->a = t.a;
		this->b = t.b;
	}
	~INT(){}
	INT& operator=(const INT &t);
	INT operator+(const INT &t);
	INT operator+(int i);
	INT operator-(const INT &t);
	INT operator*(const INT &t);
	INT operator/(const INT &t);
	INT operator%(const INT &t);
	INT operator&(const INT &t);
	INT operator|(const INT &t);
	INT& operator+=(const INT &t);//因為結果返回本身,因此使用引用更快捷
	INT& operator-=(const INT &t);
	INT& operator*=(const INT &t);
	INT& operator/=(const INT &t);
	INT& operator%=(const INT &t);
	INT& operator++();//++a引用返回this就不用拷貝構造了
	INT operator++(int);//后++比前++多一個參數//a++
	INT& operator--();
	INT operator--(int);
};
INT& INT::operator%=(const INT &t)
{
	this->a %= t.a;
	this->b %= t.b;
	return *this;
}
INT& INT::operator/=(const INT &t)
{
	if(t.a != 0)
	{
		this->b /= t.b;
		this->a /= t.a;
		return *this;
	}
	exit(0);  
}
INT& INT::operator*=(const INT &t)
{
	this->a *= t.a;
	this->b *= t.b;
	return *this;
}
INT& INT::operator-=(const INT &t)
{
	this->a -= t.a;
	this->b -= t.b;
	return *this;
}
INT& INT::operator+=(const INT &t)
{
	this->a += t.a; 
	this->b += t.b;
	return *this;
}
INT INT::operator|(const INT &t)
{
	return(this->a|t.a, this->b|t.b);
}
INT INT::operator&(const INT &t)
{
	return(this->a&t.a, this->b&t.b);
}
INT INT::operator%(const INT &t)
{
	return(this->a%t.a, this->b%t.b);
}
INT INT::operator/(const INT &t)
{
	if(t.a != 0)
		return(this->a/t.a,this->b/t.a);
	exit(0);
}
INT INT::operator*(const INT &t)
{
	return (this->a*t.a, this->b*t.b);
}
INT INT::operator++(int)
{
	INT tmp(this->a,this->b);
	++this->a;
	++this->b;
	return tmp;
}
INT& INT::operator++()
{
	++this->a;
	++this->b;
	return *this;
}
INT INT::operator--(int)
{
	INT tmp(this->a);
	--this->a;
	--this->b;
	return tmp;
}
INT& INT::operator--()
{
	--this->a;
	--this->b;
	return *this;
}
INT INT::operator+(const INT &t)
{
	return(this->a+t.a,this->b+t.b);;//將(this->a+t.a)隱式轉換為一個無名的臨時對象。
}
INT INT::operator+(int i)
{
	INT tmp(this->a+i,this->b);
	return tmp;
}
INT INT::operator-(const INT &t)
{
	return(this->a-t.a,this->b-t.b);
}
INT& INT::operator=(const INT &t)
{
	if(this != &t)
	{
		this->a = t.a;
		this->b = t.b;
	}
	return *this;
}
INT operator+(int a, const INT &t)
{
	INT tmp(a+t.a,t.b);//此處使用臨時對象的原因是防止直接返回無名臨時對象時其私有數據被初始化
	return tmp;
}
ostream& operator<<(ostream &out, const INT &t)
{
	out<<"("<<t.a<<", "<<t.b<<")";
	return out;
}

istream& operator>>(istream &in, INT &t)
{
	in>>t.a>>t.b;
	return in;
}
友元函數
1.友源函數不是類的成員函數,在函數體中訪問對象的成員,必須用對象名加運算符“.”加對象成員名。但是
友源函數可以訪問類中的所有成員,一般函數只能訪問類中的公有成員。
2.友源函數不受類中的訪問權限關鍵字限制,可以把它放在類的公有、私有、保護成分,但結果一樣。
3.某類的友元函數的作用域並非該類作用域,如果該友元函數是另一類的成員函數,其作用域為另一類的作用域,否則與一般函數相同。
//Test.cpp
#include<iostream> #include"Test1.h" using namespace std; void main() { INT a(5); INT b(2); INT c = a&b; INT d = a|b; INT s; c += d; c -= d; c *= d; d = INT(10,15); c /= d; c %= d; cout<<c<<endl; cin>>s; a = 10 + a; a = a + 10; }

 關於加法的函數有三個分別解決:對象與對象相加、 對象與數字相加(這兩個是類的成員函數),數字與對象相加(友元函數)

輸入輸出運算符均被重載為友元函數,但是輸出運算符可以被重載為類的成員函數只不過調用那時有些不符合正常習慣

#include<iostream>
using namespace std;
class Test
{
private:
	int a;
	int b;
public:
	Test(int _a=0, int _b=0):a(_a),b(_b)
	{
		this->a = _a;
		this->b = _b;
	}
	~Test(){}
	ostream& operator<<(ostream &out)
	{
		out<<this->a<<", "<<this->b;
		return out;
	}
};
void main()
{
	Test st(10,20);
	st<<cout<<endl;//聲明為成員函數則必須讓對象在運算符前面,這樣才能產生類似st.operator(out)的效果
}

效果如下

友元類
整個類可以是另一個類的友元。友元類得每個成員函數都是另一個類的友元函數,都可以訪問另一個類中的保護
或私有數據成員


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM