2012-09-18 155 views
6

可能重複:
why private value of the obj can be changed by class instance?爲什麼==超載可以訪問參數的私有成員

考慮以下(部分)代碼:

class Group { 
    private: 
     int id; 

    public: 
     void set_id(int); 
     int get_id(); 
     bool operator==(const Group&); 
}; 


bool Group::operator==(const Group& g) { 
    if(g.id == this->id) { /* id is private? */ 
      return true; 
    } 

    return false; 
} 

代碼編譯和結果看起來不錯。但是,在運算符重載實現的if部分,我們直接訪問其參數的私有成員 - const Group& g,但是不是這樣的訪問無效嗎?

+1

出了什麼問題'回報g.id ==這個 - > id'? – sbi

+1

在附註中,我認爲用戶名「WeaklyTyped」非常好地匹配了這個問題。 – datenwolf

+1

@sbi - 它有一個不需要的'this->'。 –

回答

16

您的operator==是您的Group類的成員。成員函數可以訪問該類的任何private成員,不僅可以訪問this,也可以訪問它們可以訪問的任何實例。

如果你考慮一下,這種行爲是必須的,否則訪問控制會使兩個或多個實例(swap,複製構造函數,操作符)的交互方法變得不可能,除非對象具有任何成員變量的公共存取器,用於這種方法。從設計的角度來看,這通常是不可取的。此外,它將把訪問控制的標準提高到很高的水平(「如果我只是讓這個成員公開,我就可以免除我的痛苦......」)。

總結這段代碼是完全有效的(雖然我不明白爲什麼if是必要的,比起單純用return g.id == this->id;

+0

謝謝!爲解釋。 – WeaklyTyped

5

不,因爲operator==Group的成員。它正好在函數名稱中。這意味着它可以訪問該類的任何對象的private成員。

如果你試圖把它寫成一個免費的功能,那也不會編譯:

bool areEqual(const Group& g1, const Group& g2) { 
    return g1.id == g2.id; 
} 
13

訪問預選賽不控制在實例級別的訪問,但在類型級別。 T類型實例的任何成員函數都可以訪問同一類型T的任何其他實例的所有私有成員。

由於operator==是一個成員函數,它可以訪問該類的所有實例成員變量成員。

+0

我明白你的觀點,但是如果你能指出爲什麼說明符在類型級別而不是實例級別上運行,我將非常感激。一定有一個原因。 – WeaklyTyped

+1

@ WeaklyTyped如果它們沒有在類型級別上運行,那麼您將無法複製構造或分配,除非所有數據都是公開的,或者每個數據成員都有「getters」。 – juanchopanza

+0

@WeaklyTyped:因爲C++是一種靜態類型檢查語言,不可能靜態確定訪問是否保留在實例中(停止問題)。以成員函數'class T {private:int bar; public:void foo(T * t){t * = t-> bar;} void spam(){foo(this);}' - foo可以從類的「外部」或內部使用'這個'指針。在編譯時,不可能靜態檢查是否發生這種情況。另外juanchopanza說。 – datenwolf