2012-09-11 88 views
2

我想知道什麼樣的類成員訪問friend函數和static成員函數具有類對象。具體而言,差異是什麼以及爲什麼要使用這兩者之一。我的理解是,聲明爲friend的函數或static成員都可以訪問該類的任何實例的私有成員。朋友和靜態成員函數有什麼樣的成員訪問?

我會舉一個快速示例來說明爲什麼它們看起來和我很相似。 operator<MyClass::lessThan這兩個函數似乎都具有相同的訪問權限,並且可以執行完全相同的操作。

class MyClass { 
    friend bool operator<(const MyClass &left, const MyClass &right); 
public: 
    MyClass(int pub, int priv) : m_pub(pub), m_priv(priv) {} 
    static bool lessThan(const MyClass &left, const MyClass &right); 
    int m_pub; 
private: 
    int m_priv; 
}; 

bool operator<(const MyClass &left, const MyClass &right) { 
    return ((left.m_pub < right.m_pub) && (left.m_priv < right.m_priv)); 
} 

bool MyClass::lessThan(const MyClass &left, const MyClass &right) { 
    return ((left.m_pub < right.m_pub) && (left.m_priv < right.m_priv)); 
} 

int main(int argc, const char* argv[]) { 
    MyClass a(1, 2), 
     b(3, 4), 
     c(-1, 1); 
    cout << "a < b  = " << (a<b) << endl; 
    cout << "a lessThan b = " << MyClass::lessThan(a,b) << endl; 
    cout << "a < c  = " << (a<c) << endl; 
    cout << "a lessThan c = " << MyClass::lessThan(a,c) << endl; 
} 

顯然,這是一個簡單的例子,但我想我的問題是由兩部分組成:

  1. 什麼是關於成員訪問的朋友和靜態函數之間的區別是什麼?
  2. 什麼樣的事情應該考慮在決定使用哪一種?
+1

「朋友」的重點是給其他功能/類私人訪問。至於使用哪個,靜態函數不能訪問實例成員。他們的本意就是你可以在沒有物體的情況下打電話。 – chris

+0

另外:'operator <(a,b)'編譯,而'lessThan(a,c)'不。 –

+0

chris - 謝謝,這是我忘記的一個重要區別。然而,像這裏給出的例子那樣,靜態函數可以訪問實例成員,因爲實例被作爲參數傳遞了嗎? – Ayelix

回答

2

請記住,雖然原型朋友功能出現在一個類定義,朋友功能無法正常工作的成員。 A 朋友功能已定義遠離班級,但朋友功能已接入非公開成員。有人認爲「友誼」破壞了信息隱藏。有時朋友功能用於製造測試儀類。

靜態數據成員用於對象類應共享一個變量的唯一副本。因此,當所有類成員只有一個副本足夠時,您必須使用靜態數據成員來保存存儲。

對於靜態成員函數,你可以看看下面:When to use static member function?

+0

朋友絕對不會破壞信息隱藏。它增強了它。它擴展了類的接口,代價是將朋友與類緊密耦合在一起http://programmers.stackexchange.com/q/99589/12917這比將所有代碼緊密耦合到您的類更好。 –

+0

謝謝,結果在發佈之前沒有在我的搜索中出現。從該問題鏈接的「可能的重複」特別有用:[你會在哪裏使用朋友函數vs靜態函數?](http://stackoverflow.com/questions/2315166/where-would-you-use-a-交友功能VS-一個靜態函數) – Ayelix

1

它們是不同的概念:

如果一個類,方法或函數是類X的朋友,那類,函數或方法有權訪問被聲明爲private類X的成員,因此通常無法訪問類

class A{ 
    private: 
    int x; 
    friend void foo(A& a); 

}; 

void foo(A& a){ 
    a.x = 3; //Access okay, foo is a friend of A 
} 

void bar(A& a){ 
    a.x = -1; // Compiler will complain A::x is private 
} 

外靜態構件既可以是類的所有對象實例之間共享的數據成員,或者一個可以在沒有這個類的實例對象調用的方法。

class B{ 

    private: 
    static int y; 

    public: 
    static void printY(); 
    void alterY(); 

} 

int B::y=3; 

void B::printY(){ 
    cout<<y; 
} 

void B::alterY(){ 
    y++; 
    cout<<y; 
} 


B b1,b2; 
B::printY();// will output 3 
b1.alterY();// will output 4 
b2.alterY();// will output 5 
1

靜態方法可以調用而不需要通過類的實例,所以他們沒有任何直接訪問,它們就像全局函數,但嵌套在類的命名空間。但是,如果您將該類的實例作爲參數提供給它們,則它們將能夠訪問成員變量,而無需像訪問非靜態方法那樣通過訪問器。就像靜態方法一樣,如果你給它們一個他們作爲參數的朋友的類的實例,它們就可以直接訪問成員變量。

+0

我想我不清楚。我的意思是說他們不能訪問「他們自己」的成員變量,因爲靜態方法不是通過類的實例調用的。但是,如果你給他們一個該類的實例作爲參數,它會起作用。 – Borgleader

+0

澄清我的答案。 – Borgleader

+0

你讓它聽起來像朋友和靜態之間的區別。似乎沒有任何。在他們可以訪問任何成員之前,他們都需要傳遞對象的引用。 –

1
  1. 他們都可以訪問類的所有成員,包括私立學校
  2. 你需要決定如果一個函數在邏輯上屬於類訪問成員,其中需要,或者如果它屬於另一個階級或根本沒有階級。在第一種情況下(邏輯上屬於該類的一個函數)使該函數靜態;在第二種情況下,根據您的設計,將它作爲朋友,並添加到其邏輯所屬的類或名稱空間中。
0

什麼是關於成員訪問的朋友和靜態函數之間的區別是什麼?

無。他們都擁有完整的訪問權限。

決定使用哪種東西時應該考慮哪些事情?

它完全依賴於上下文,是什麼使代碼更易於閱讀。

在你上面的例子中,我肯定更喜歡bool operator<()而不是MyClass::lessThan(),因爲它使代碼更直觀。