說實話,我認爲做出這樣一個決定的唯一原因是語法方便和傳統。我會解釋爲什麼通過展示什麼是(而非)兩者之間的差異,以及在做出決定時這些差異如何重要。
非會員朋友功能和公共會員功能有什麼不同?不多。畢竟,成員函數只是一個具有隱藏this
參數的常規函數,並且可以訪問該類的私有成員。
// what is the difference between the two inv functions?
// --- our code ---
struct matrix1x1 { // this one is simple :P
private:
double x;
public:
//... blah blah
void inv() { x = 1/x; }
friend void inv(matrix1x1& self) { self.x = 1/self.x; }
};
matrix1x1 a;
// --- client code ---
// pretty much just this:
a.inv();
// vs this:
inv(a);
void lets_try_to_break_encapsulation(matrix1x1& thingy) {
thingy.x = 42; // oops, error. Nope, still encapsulated.
}
它們都提供相同的功能,並且決不會改變其他功能可以做的事情。相同的內部結構暴露於外部世界:封裝方面沒有區別。其他函數完全可以做不同的事情,因爲有一個修改私有狀態的朋友函數。實際上,大多數函數都可以編寫非會員朋友函數(虛函數和一些重載操作符必須是成員),以提供完全相同的封裝量:用戶不能編寫任何其他朋友函數而不修改除了朋友功能以外,沒有其他功能可以訪問私人成員。我們爲什麼不這樣做?因爲它會違背99.99%的C++程序員的風格,並且沒有很大的優勢可以從中獲益。
不同之處在於功能的性質和您稱之爲的方式。作爲成員函數意味着你可以從它獲得一個指向成員函數的指針,並且作爲一個非成員函數意味着你可以得到一個指向它的函數指針。但這很少相關(特別是使用通用函數包裝器,如std::function
)。
其餘的區別是句法。 D語言的設計者決定統一整個事情,並說你可以直接調用一個成員函數,如inv(a)
,然後調用一個自由函數作爲它的第一個參數的成員,如a.inv()
。沒有任何班級因爲這個或者任何東西而突然被封裝得不好。
要解決問題中的特定示例,inv
應該是成員還是非成員?我可能會讓它成爲一個成員,因爲我上面概述的相似性論點。非風格化,它沒有區別。
。這在C++中不太可能發生,因爲在這一點上,這將是一個突破性改變,因爲沒有實質性的好處。對於一個極端的例子,它會打破我上面寫的matrix1x1
類,因爲它使得兩個調用都不明確。
可能在對象內部有更清晰定義的功能封裝,而不是在不同的朋友功能中傳播。 – PherricOxide
相關http://stackoverflow.com/a/7821482/46642 –
我認爲這裏值得讚揚的答案應該指出成員函數和非成員朋友之間的實際差異,並解釋這些差異如何有助於作出決定,而不是用「因爲它提供更多/更少的封裝」而將所有東西都浪費掉了。 –