C++對於類訪問許可權public,protected,private的深刻理解
阿新 • • 發佈:2019-02-07
本帖轉自網路,查詢不到原作者,如有冒犯,深表歉意!
1 #include <IOSTREAM> 2 using namespace std; 3 4 class A{ 5 public: 6 A(int i_,int j_) 7 { 8 i=i_; 9 j=j_; 10 } 11 void disp(A &a) 12 { 13 cout<<a.i<<endl<<a.j<<endl; 14 } 15 16 private: 17 int i; 18 protected: 19 int j; 20 }; 21 22 int main(int argc, char* argv[]) 23 { 24 A a(123,456); 25 A b(789,543); 26 a.disp(b); 27 b.disp(a); 28 29 return 0; 30 }
訪問修飾符的作用是以類為單位還是以物件為單位?
初看起來,倒是會產生疑問。為什麼會這樣,是否有bug? 仔細考究起來,我們其實可以這樣看待類和物件:類是將資料成員和進行於其上的一系列操作(成員函式)封裝在一起,注意:成員函式可以操作資料成員(可以稱類中的資料成員為泛資料成員)!物件是類的例項化,怎樣理解例項化?其實每一個例項物件都只是對其中的資料成員初始化,記憶體映像中每個物件僅僅保留屬於自己的那份資料成員副本。而成員函式對於整個類而言卻是共享的,即一個類只保留一份成員函式。那麼每個物件怎樣和這些可以認為是“分離”的成員函式發生聯絡,即成員函式如何操作物件的資料成員?記住this指標,無論物件通過(.)操作或者(->)操作呼叫成員函式,編譯時刻,編譯器都會將這種呼叫轉換成我們常見的全域性函式的形式,並且多出一個引數(一般這個引數放在第一個),然後將this指標傳入這個引數。於是就完成了物件與成員函式的繫結(或聯絡).例項化後就得到同一個類的多個不同的物件,既然成員函式共享的,那麼成員函式就可以操作物件的資料成員。 問題是現在有多個物件,成員函式需要知道操作的是哪個物件的資料成員? 比如有物件obj1和obj2,都屬於A類,A類有public成員函式foo()。如果obj1呼叫該函式,編譯時會給foo函式傳入this指標,obj1,foo中操作obj1自身的成員就不用任何修飾,直接訪問,因為其中的資料成員自動根據this指標找到。如果obj1呼叫該函式,同樣可以訪問同類的其他物件的資料成員!那麼你需要做的是讓foo函式知道是同類物件中哪個物件的資料成員,一個解決辦法是傳入同類其他物件的指標或引用,那麼就可以操作同類其他物件的資料成員。 例如:foo(A &obj)這樣定義,然後呼叫:obj1.foo(obj2)就可以在obj1訪問obj2的資料成員,而無論這些資料成員是private還是protected。
總結:C++的訪問修飾符的作用是以類為單位,而不是以物件為單位。通俗的講,同類的物件間可以“互相訪問”對方的資料成員,只不過訪問途徑不是直接訪問。步驟是:通過一個物件呼叫其public成員函式,此成員函式可以訪問到自己的或者同類其他物件的public/private/protected資料資料成員和成員函式(類的所有物件公用),而且還需要指明是哪個物件的資料成員(呼叫函式物件自己的成員不用指明因為有this指標;其他物件的資料成員可以通過引用或指標間接指明。)
誰要控制誰的訪問許可權?
顧名思義,private/public/protected 分別表示 私有/公開/保護,它們是一組用於訪問許可權控制的關鍵字。那麼首先,需要澄清的一個關鍵點是,是要控制誰訪問誰的許可權?這個訪問的主語(施事)是誰?賓語(受事)是誰?
我們經常聽到這樣的說法:
- 一個類友元可以訪問該類的任何成員(包括成員變數及成員方法,下同)。
- private成員只有該類自身可以訪問,protected成員只有該類及其派生類可以訪問,public成員所有的人都可以訪問。