C++中的友元

ZhiboZhao 發表於 2021-07-05
C++

前面提到過,在類的封裝中,私有的成員變數和成員函式無法在類外訪問,但是總有那麼一些情況需要給類外的物件賦予一定的訪問許可權。比如在家裡面,客廳是公共訪問許可權,而每個人的臥室是私有訪問許可權,對大多數人來說不可訪問,但是自己的好朋友可以。同樣的道理,在C++中實現這種功能需要藉助友元的機制。簡單來說就是如果某個類外的物件需要訪問類內的私有成員,在類內宣告為友元型別即可。

一、全域性函式做友元

在本例中,首先構造了一個 house 類,需要在類內宣告全域性函式 Friend 為友元方能訪問類內的私有成員:

class house
{
	friend void Friend(house& p_house);	// friend 是友元的關鍵字
public:
	string livingroom;
private:
	string bedroom;
public:
	house()		// 定義建構函式給成員變數賦值
	{
		livingroom = "客廳";
		bedroom = "臥室";
	}
};

void Friend(house& p_house)
{
	// 可以在類外正常訪問類內的公有成員
	cout << "Friend 正在訪問:" << p_house.livingroom << endl;

	// 將Friend函式宣告為友元方可訪問私有成員
	cout << "Friend 正在訪問:" << p_house.bedroom << endl;
}
int main(void)
{
	house p;	// 例項化house物件
	Friend(p);	// 呼叫友元函式Friend
}

輸出結果如下所示:

Friend 正在訪問:客廳
Friend 正在訪問:臥室

二、類做友元

想象一下,如果你某天需要出遠門,需要一個朋友定期去你家裡面進行打掃,這個時候你就需要給他一定的許可權讓他能夠訪問到家裡面的任何地方。其實類做友元跟函式做友元一樣,如下例所示:

class house{
    // 將 friend_house 類宣告為house的友元后,該類例項化的物件能夠訪問 house 類物件的所有成員
	friend class friend_house;
public:
	string livingroom;
private:
	string bedroom;
public:
	house()		// 定義建構函式給成員變數賦值
	{
		livingroom = "客廳";
		bedroom = "臥室";
	}
	void show()	// 顯示類內的變數內容
	{
		cout << "livingroom:" << livingroom << endl;
		cout << "bedroom:" << bedroom << endl;
	}
};

class friend_house{
public:
	void visit(house& p_House)
	{
		cout << "friend 正在訪問:" << p_House.livingroom << endl;
        // 將類friend_house 宣告為house的友元后,不僅可以訪問house的公有成員,也能訪問私有成員
		cout << "friend 正在訪問:" << p_House.bedroom << endl;

		p_House.livingroom = "整理後的客廳";	// 由於傳進來的引數是引用型別,可以修改原來house物件的值
		p_House.bedroom = "整理後的臥室";
	}
};
int main(void)
{
	house p;	// 例項化house物件
	friend_house p_friend;	// 
	p_friend.visit(p);	// 訪問並修改house類物件p的成員
	p.show();
}

輸出結果如下:

friend 正在訪問:客廳
friend 正在訪問:臥室
livingroom:整理後的客廳
bedroom:整理後的臥室

三、成員函式做友元

其實無論什麼做友元都是一樣的目的,只是友元的宣告格式不同,比如:

  1. 全域性函式的宣告:friend void Friend(house& p_house); // friend 是友元的關鍵字
  2. 友元類的宣告:friend class friend_house;
  3. 成員函式的宣告:friend void goodGay::visit1();
class Building;
class goodGay
{
public:
	goodGay();
	void visit1();
	void visit2();
 
private:
	Building * building;
};
//類內宣告,類外實現;
class Building
{
	//讓成員函式visit1做友元函式:
	friend void goodGay::visit1();
public:
	Building();
public:
	string m_sittingroom;	//客廳
private:
	string m_bedroom;		//臥室
};
Building::Building()
{
	this->m_bedroom = "臥室";
	this->m_sittingroom = "客廳";
}
goodGay::goodGay()
{
	building = new Building;
}
void goodGay::visit1()
{
	cout << "基友正在" << this->building->m_sittingroom << endl;
	//要訪問私有屬性的元素;
	//在Building 類中定義友元類:friend class goodGay;
	cout << "基友正在" << this->building->m_bedroom << endl;
 
}
void goodGay::visit2()
{
	cout << "基友正在" << this->building->m_sittingroom << endl;
	//要訪問私有屬性的元素;
	//在Building 類中定義友元類:friend class goodGay;
	//cout << "基友正在" << this->building->m_bedroom << endl;
}
int main()
{
	goodGay g1;
	g1.visit1();
	return 1;
}

輸出結果為:

基友正在客廳
基友正在臥室