夥伴函式和成員函式差在哪裡?為什麼輸入/輸出的多載運算子一定要為夥伴函式?如果A類別把B函式當作夥伴,但B函式的參數中沒有A類別,顯然這個B不把A當夥伴,這會造成main()無法找到B函式。
還是很困惑嗎?文章裡有答案喔~😎
雖然friend函式的函式原型宣告在類別中,但它不是成員函式。如果介面和實作是合在一起的話,friend函式是定義在類別外面;而如果介面和實作分開,成員函式必須加上範圍解析子::,但非成員函式不需要,這也包含friend函式。
也就是friend函式的定義是獨立於類別的,並且如果friend函式想要獲得public資料成員的存取權,friend函式不能主動設定,並需類別主動給予friend函式權限。
有些不支持friend函式的原因,覺得friend的機制會破壞OOP的基本原則。
<<, >> 多載時,一定要宣告成friend,因為我們不能動ostream物件的東西,故只能授權ostream能存取新物件的private成員。且傳參考給運算子,也回傳參考(lvalue),這樣就可以連續輸入/輸出,不可以回傳區域參考,不然會消失!這點和指標一樣~
friend類別和friend函式一樣,給予protected, private權限給他。friend類別除了要在類別定義中放上friend類別原型外,如果夥伴類別和授與權限的類別是在不同的檔案中,夥伴類別須向前宣告(forward declaration),不需要#include。例如:stackNode和stack關係非常緊密,
範例:stackNode和stack
// stackNode.h
class Stack; // Forward declarartion
class StackNode {
friend class Stack; // Make stack a friend
public:
...
private:
int data;
StackNode *nextPtr;
};
// stack.h
#include "stackNode.h"
class Stack{
public:
...
private:
StackNode *firstPtr;
StackNode *lastPtr;
};
夥伴的授與是主動的,不能被動授與。因此如果stack想要拿到stackNode的權限,必須stackNode主動授與。要注意的是夥伴關係依舊不是類別的成員關係,因此夥伴函式/類別 (stack)需間接使用授與類別 (stackNode)的成員。也就是stack須先實例化stackNode,再透過stackNode物件去存取其中的protected, private成員。
在作業3當中,會遇到不夠朋友問題。以下程式碼為Complex類別中,宣告friend函式Polar(),可以看到參數列並沒有使用到Complex物件,這就會發生不夠朋友問題。
friend Complex Polar(const double leng, const double arg);
使用在類別中的friend函式時,如果friend函式的參數沒有使用類別本身,則main()就無法偵測到此friend函式,但如果friend函式參數有使用到類別本身,main()就可以偵測到此friend函式。其解決方法:
這就像是我跟你是朋友,但你卻沒有使用到我(傳入的參數),我就不跟你好的概念,C++也是蠻講義氣的(X)。
更多此問題的討論
作業3實作上需要注意一些細節
// Overloading +=
Complex operator+=(Complex& x, const Complex& y){
x = x + y;
return x;
}
// Overloading +=
Complex operator+=(Complex& x, const Complex& y){
const Complex xCopy = x;
x.real = xCopy.real + y.real;
x.imag = xCopy.imag + y.imag;
return x;
}
更多作業細節,請參考AOOP Homework source code
© blink.com.tw