友元函式的來由和使用套路

2021-07-25 15:32:55 字數 1531 閱讀 6244

來由

class_a = class_b * 2.75;

這裡的 * 運算子過載我們可以通過成員函式實現,但是像這樣的語句:

class_a = 2.75 * class_b;

就不能了。從概念上說,2.75 * class_b 應與 class_b * 2.75 相同,但第乙個表示式不對應於成員函式,因為2.75不是time型別的物件。左側運算元應是呼叫物件,但2.75不是物件。因此,

編譯器不能使用成員函式呼叫來替換該表示式。

解決這個難題的一種方式是,告知每個人(包括程式設計師自己),只能按 class_b * 2.75 這種格式編寫,不能寫成 2.75 * class_b 。這是一種對伺服器友好-客戶警惕的(server-friendly, client-beware)解決方案,與oop無關。

然而,還有另一種解決方式——非成員函式(記住,大多數運算子都可以通過成員或非成員函式來過載)。非成員函式不是由物件呼叫的,它使用的所有值(包括物件)都是顯式引數。這樣,

編譯器能夠將表示式 class_a = 2.75 * class_b; 與 class_a = operator*(2.75, class_b) 非成員函式呼叫匹配。

對於非成員函式過載運算子來說,運算子表示式左邊的運算元對應於運算子函式的第乙個引數(

這裡的函式特徵標有順序!),運算子表示式右邊的運算元對應於運算子函式的第二個引數。而原來的成員函式則按相反的順序處理運算元,也就是說,double值乘以time值。

使用非成員函式可以按所需的順序獲得運算元,但是這裡有個問題,非成員函式不能直接訪問類的私有資料,所以,就引出了我們的

友元函式。

套路

始終記住一點,友元函式是是非成員函式,所以不能使用域限定符 : : 對友元函式進行操作。但是同時,友元函式的訪問許可權又與成員函式相同。

實際上,我們經常採用在友元函式定義中呼叫成員函式的方式(這裡有**重用的思想,因為我們已經實現了time值乘以double值,區別只是在於引數的順序不同,所以可以直接呼叫該成員函式而不是重新實現一遍):

time operator*(double m, const time & t)

乙個經驗就是,如果要為類過載運算子,並將非類的項作為第乙個運算元,則可以

用友元函式來反轉運算元的順序。

過載《運算子,一般使用如下模式(因為返回值為ostream物件,可以在乙個語句中多次呼叫):

ostream & operator<<(ostream & os, const c_name & obj)

過載乙個運算子,如果它的功能是計算得到乙個新的類物件,則應考慮是否可以使用類建構函式來完成這種工作。這樣做不僅可以避免麻煩,而且可以確保新的物件是按照正確的方式建立的(方便,高效,安全)。例如:

vector vector::operator+(const vector & v) const

將加法定義為友元函式可以讓程式更容易適應自動型別轉換,原因在於,兩個運算元都成為函式引數,因此與函式原型匹配。

友元 友元函式 友元類和友元成員函式 C

有些情況下,允許特定的非成員函式訪問乙個類的私有成員,同時仍阻止一般的訪問,這是很方便做到的。例如被過載的操作符,如輸入或輸出操作符,經常需要訪問類的私有資料成員。友元 frend 機制允許乙個類將對其非公有成員的訪問權授予指定的函式或者類,友元的宣告以friend開始,它只能出現在類定義的內部,友...

友元 友元函式 友元類和友元成員函式 C

有些情況下,允許特定的非成員函式訪問乙個類的私有成員,同時仍阻止一般的訪問,這是很方便做到的。例如被過載的操作符,如輸入或輸出操作符,經常需要訪問類的私有資料成員。友元 frend 機制允許乙個類將對其非公有成員的訪問權授予指定的函式或者類,友元的宣告以friend開始,它只能出現在類定義的內部,友...

C 友元 友元函式 友元類和友元成員函式

有些情況下,允許特定的非成員函式訪問乙個類的私有成員,同時仍阻止一般的訪問,這是很方便做到的。例如被過載的操作符,如輸入或輸出操作符,經常需要訪問類的私有資料成員。友元 frend 機制允許乙個類將對其非公有成員的訪問權授予指定的函式或者類,友元的宣告以friend開始,它只能出現在類定義的內部,友...