1. 程式人生 > >C++對於類訪問許可權public,protected,private的深刻理解

C++對於類訪問許可權public,protected,private的深刻理解

本帖轉自網路,查詢不到原作者,如有冒犯,深表歉意!

 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 分別表示 私有/公開/保護,它們是一組用於訪問許可權控制的關鍵字。那麼首先,需要澄清的一個關鍵點是,是要控制誰訪問誰的許可權?這個訪問的主語(施事)是誰?賓語(受事)是誰?
    我們經常聽到這樣的說法:
  1. 一個類友元可以訪問該類的任何成員(包括成員變數及成員方法,下同)。
  2. private成員只有該類自身可以訪問,protected成員只有該類及其派生類可以訪問,public成員所有的人都可以訪問。
賓語(受事)是誰這一點很明確,是類的成員(包括成員變數及成員方法)。主語(施事)是誰?這是讓大家發生混淆的關鍵點。也是這個說法中含糊不清的地方。
想清楚一點,其實主語(施事)指的是一個函式,而不是(當然更不是變數)。private/public/protected要控制的是一個函式(施事)對一個類的成員(包括成員變數及成員方法)的訪問許可權。因此比較完整的說法是: 1)一個類友元(包含友元函式或者友元類的所有成員函式)可以訪問該類的任何成員(包括成員變數及成員方法)。 2)除去友元外,private成員只有該類自身的成員函式可以訪問,protected成員只有該類的成員函式及其派生類的成員函式可以訪問,public成員則所有的函式都可以訪問。 也就是說,當我們說一個類可以訪問XXX,其實暗指這個類的成員函式可以訪問XXX。瞭解了這一點,外加一條顯而易見的規則,上面的問題就不難回答了。這條規則是: 3)派生類在繼承時可削弱成員的訪問許可權(通過protected/private修飾)。例如上面的例子class P : protected O {…}; 那麼某個函式通過類P訪問O中成員時,該函式對類O中的public成員只有protected許可權。