1. 程式人生 > >C++類的繼承與多重繼承的訪問控制

C++類的繼承與多重繼承的訪問控制

在前面的練習中我們一直在使用public的繼承方式,即共有繼承方式,對於protected和private繼承方式,即保護繼承私有繼承方式我們並沒有討論。 
   對於單個類來說,討論保護繼承與私有繼承的區別意義是不大的,他們的區別只在多級繼承的情況中體現。 

   在這裡我宣告一下,對於此章節的內容不太適合用過多的文字進行描述,主要還是看例子,通過例子熟悉之間的關係,過多的文字描述會模糊讀者思路。 


例程如下(重要部分都做了詳細說明): 

//程式作者:管寧 
//站點:www.cndev-lab.com 
//所有稿件均有版權,如要轉載,請務必著名出處和作者 

#include <iostream
using
 namespace std; 

class Base 

public://公有的 
int a1; 
virtual void test() = 0; 
protected://受保護的 
int a2; 
private://私有的 
int a3; 
}; 
//------------------------------------------------------------------------------ 
class ProtectedClass:protected Base//保護繼承 

public
void test() 

a1 = 1;//a1在這裡被轉變為protected 
a2 = 2;//a2在這裡被轉變為protected 

//a3=3;//錯誤,派生類不能訪問基類的私有成員 

}; 
class ControlProtectedClass:public ProtectedClass//以public方式繼承ProtectedClass類 

public
void test() 

a1 = 1;//a1在這裡仍然保持為a1在這裡被轉變為protected 
a2 = 2;//a2在這裡仍然保持為a1在這裡被轉變為protected 
//a3=3;//錯誤,由於Base類成員為私有的,即使是上級父類是保護繼承,也不能改變Base類成員的控制型別 

}; 
//------------------------------------------------------------------------------ 

class PrivateClass:private Base//私有繼承 

public
void test() 

a1 = 1;//a1在這裡被轉變為private 
a2 = 2;//a2在這裡被轉變為private 
//a3=3;//錯誤,基類私有成員對檔案區域與派生類區域都是不可訪問的 

}; 
class ControlPrivateClass:public PrivateClass//以public方式繼承PrivateClass類 

public
void test() 

//a1=1;//錯誤,由於基類PrivateClass為私有繼承,a1已經轉變為private 
//a2=2;//錯誤,由於基類PrivateClass為私有繼承,a1已經轉變為private 
//a3=3;//錯誤,由於Base類成員為私有的,PrivateClass類也為私有繼承 

}; 
//------------------------------------------------------------------------------ 
class PublicClass:public Base//共有繼承有區別與其它方式的繼承,繼承後的各成員不會其改變控制方式 

public
void test() 

a1 = 1;//a1仍然保持public 
a2 = 2;//a2仍然保持protected 
//a3=3;//錯誤,派生類不能操作基類的私有成員 

}; 
class ControlPublicClass:public PublicClass//以public方式繼承PublicClass類 

public
void test() 

a1 = 1;//a1仍然保持public 
a2 = 2;//a2仍然保持protected 
//a3=3;//錯誤,由於Base類成員為私有成員,即使是上級父類是公有繼承,也不能改變Base類成員的控制型別 

}; 
//------------------------------------------------------------------------------ 
int main() 

system("pause"); 



   認真看完了例子,相信細心的讀者對於共有繼承、保護繼承與私有繼承的區別與特點已經瞭解,最後再提醒一下讀者,在繼承關係中,基類的private成員不但對應用程式隱藏,即使是派生類也是隱藏不可訪問的,而基類的保護成員只對應用程式隱藏,對於派生類來說是不隱藏的,保護繼承與私有繼承在實際程式設計工作中使用是極其少見的,他們只在技術理論上有意義。

關於C++中protected的訪問許可權的討論已經是一個很陳舊的話題了,陳舊到大家都不願意去討論,覺得他見到到吃飯睡覺那麼自然。

我再次讀《C++ Primer》的時候,其中關於protected 成員的描述是這樣的:

protected Members

The protected access label can be thought of as a blend of private and public :

  • Like private members, protected members are inaccessible to users of the class.
  • Like public members, the protected members are accessible to classes derived from this class.
  • In addition, protected has another important property:
    A derived object may access the protected members of its base class only through a derived object. The derived class has no special access to the protected members of base type objects.

在沒有繼承的情況下,protected跟private相同。在派生類的時候才出現分化。

上面那段英文前兩條都很好理解,基類物件不能訪問基類的protected成員,派生類中可以訪問基類的protected成員。也就是說private成員是不能被繼承的,只有public,protected的成員才可以被繼承。

就是最後一條有些迷惑人,派生類物件如果要訪問基類protected成員只有通過派生類物件,派生類不能訪問基類物件的protected成員。

請注意 drived class和drived object:派生類和派生類物件。第一點和第二點都是針對派生類來說的。

對於第三點總結一句話:只有在派生類中才可以通過派生類物件訪問基類的protected成員。

舉一個簡單的例子:

  1. #include <iostream>
  2. usingnamespace std;  
  3. class Base  
  4. {  
  5. public:  
  6.     Base(){};  
  7.     virtual ~Base(){};  
  8. protected:  
  9.     int int_pro;  
  10. };  
  11. class A : public Base  
  12. {  
  13. public:  
  14.     A(){};  
  15.     A(int da){int_pro = da;}  
  16.     void Print(A &obj){obj.int_pro = 24;}  
  17.     void PrintPro(){cout << "The proteted data is " << int_pro <<endl;}  
  18. };  
  19. int main()  
  20. {  
  21.     A aObj;  
  22.     A aObj2(5);  
  23.     aObj2.PrintPro();  
  24.     aObj.Print(aObj2);  
  25.     aObj2.PrintPro();  
  26.          //註釋1
  27.          //aObj.int_pro = 8;
  28. }  

編譯執行結果如下:

The protected data is 5

The protected data is 24

可見,在派生類內部直接訪問protected成員和訪問派生類物件基類的protected成員都是可行的。

但是若果解開註釋1.就會編譯報錯。

很多書上都說有派生類的情況下protected的訪問許可權同public。這種說法是不對的,類內部直接訪問沒什麼區別,但是訪問物件基類的protected成員只能是在該類的內部。

我這裡只列舉了只有一層繼承的情況,如果有多重繼承的情況,比如三層。那麼。中間層的類的內部還可以訪問第三層類物件的基類成員,但是不能訪問第三層類自己的protected的成員。


C++:protected訪問說明符

2009-01-23 20:40jackheroes8383 | 瀏覽 15825 次  C++
protected只能被類的成員函式和類的友元函式訪問

那子類能不能訪問啊?

JAVA的protected是專門設計為讓子類訪問.
private也可以被類的成員函式和類的友元函式訪問 
這個protected到底是為哪種情況設計的啊?
哈哈 protected專門就是為繼承(子類)設計的 
用public繼承 那麼基類所有的訪問標識在子類不變 
protected還是protected 
protected只有類本身 和類的子類可以訪問,物件是無法訪問的! 

除了在繼承上 他跟private沒有任何區別! 
private 子類也將不能訪問!

跟你說了啊~~~  只是在繼承上不同 其他都一樣的
private無法繼承 也就是說子類也不能用基類的 private...
但是protected就是可以的~

明白嗎? pravite 只對本類可見 
protected 對本類和繼承類可見
提問者評價
感謝
評論(4) | 95 0

牛比的琭琭 | 七級 採納率35%

擅長: 電腦/網路 商業/理財

為您推薦:

<iframe src="http://entry.baidu.com/rp/home?di=u2115503&amp;rsi0=450&amp;rsi1=25&amp;type=pageembed&amp;version=1&amp;titff=sans-serif%2Ctahoma%2C%22MicrosoftYaHei%22&amp;titfs=14&amp;rss2=%232d64b3&amp;rss3=%232d64b3&amp;title=C%2B%2B%3Aprotected%E8%AE%BF%E9%97%AE%E8%AF%B4%E6%98%8E%E7%AC%A6_%E7%99%BE%E5%BA%A6%E7%9F%A5%E9%81%93&amp;ltu=http%3A%2F%2Fzhidao.baidu.com%2Fquestion%2F83373888.html%3Ffr%3Diks%26word%3DC%252B%252B%2Bprotected%26ie%3Dgbk&amp;ref=http%3A%2F%2Fzhidao.baidu.com%2Fsearch%3Fct%3D17%26pn%3D0%26tn%3Dikaslist%26rn%3D10%26word%3DC%252B%252B%2520protected%26fr%3Dwwwt&amp;pageWidth=1808&amp;pageHeight=846&amp;t=1442672803005&amp;iframeWidth=1808&amp;iframeHeight=846" align="center,center" marginwidth="0" marginheight="0" class="BAIDU_SS_HHIFRAME" scrolling="no" frameborder="0" allowtransparency="true" style="width: 450px; height: 25px; background-color: transparent;"></iframe>按預設排序 | 按時間排序

其他1條回答

2009-01-23 20:48lostman250 | 六級有這麼一條原則:在繼承的時候,無論用什麼方式(public.protected.private),子類隨時都可以訪問父類的非private變數或函式。 
所以可以的!

看看這個例程就明白了:http://tech.163.com/05/0407/17/1GOJ25N500091589.html

C++中,類的protected究竟有什麼作用?

 軟體軟體開發程式語言專業回答  電子產品技術支援 技術部工程師2015-07-05 11:35  protected專門就是為繼承(子類)設計的 用public繼承,基類所有的訪問標識在子類不變, protected還是protected 。
  C++程式設計思想中是這麼說的,public意味著隨後的定義對所有人都適用;private意味著除了該型別的建立者和該型別的內部成員函式之外,任何人都無法訪問這些定義;而protected是繼承的類可以訪問protected的成員,但不能訪問private的成員。本回答專業性由電腦網路分類達人 劉瑋認證

為您推薦:

<iframe src="http://entry.baidu.com/rp/home?di=u2115503&amp;rsi0=450&amp;rsi1=25&amp;type=pageembed&amp;version=1&amp;titff=sans-serif%2Ctahoma%2C%22MicrosoftYaHei%22&amp;titfs=14&amp;rss2=%232d64b3&amp;rss3=%232d64b3&amp;title=C%2B%2B%E4%B8%AD%EF%BC%8C%E7%B1%BB%E7%9A%84protected%E7%A9%B6%E7%AB%9F%E6%9C%89%E4%BB%80%E4%B9%88%E4%BD%9C%E7%94%A8%EF%BC%9F_%E7%99%BE%E5%BA%A6%E7%9F%A5%E9%81%93&amp;ltu=http%3A%2F%2Fzhidao.baidu.com%2Fquestion%2F574257523.html%3Ffr%3Diks%26word%3DC%252B%252B%2Bprotected%26ie%3Dgbk&amp;ref=http%3A%2F%2Fzhidao.baidu.com%2Fsearch%3Fct%3D17%26pn%3D0%26tn%3Dikaslist%26rn%3D10%26word%3DC%252B%252B%2520protected%26fr%3Dwwwt&amp;pageWidth=1808&amp;pageHeight=846&amp;t=1442673004018&amp;iframeWidth=1808&amp;iframeHeight=846" align="center,center" marginwidth="0" marginheight="0" class="BAIDU_SS_HHIFRAME" scrolling="no" frameborder="0" allowtransparency="true" style="width: 450px; height: 25px; background-color: transparent;"></iframe>
錯了,不管何種繼承,基類的private成員派生類都無法訪問,當然也就出現了protected成員,集合了public成員(對派生類) 和 private成員(對外部訪問)的特點。
追問:
子類不是可以呼叫基類public成員麼,然後public再呼叫private, 這樣不就呼叫了基類private了?
 
那基類怎樣訪問自己的protected呢
追答:
呵呵,public直接呼叫private的話,所有外部訪問全部都能”訪問“private了,那private存在的意義是什麼?
基類自己的所有資料自己訪問是無限制的。
 
OOD的最大特點就是封裝和繼承,封裝也就是外界無法直接訪問private和protected成員,只給外界留出了public介面,藉由public介面來訪問private和proteced成員,用以限制外部訪問,就好像你只需要一個遙控器就能控制整個空調的開關,溫度的升降而不用去管其內部細節。
而protected存在的意義是當我不想向外部暴露某個函式或者成員變數,但是我又想讓派生類知道和訪問這個成員,就將其用protected標誌,就好比
你爹有兩筆存款,一筆是他養老用的,一筆是留給你買房的,養老用的這部分錢你肯定不能拿而且大概你也不知道有多少錢,但是給你買房用的你就可以隨便拿,如果你連養老用的這部分錢都拿了那你就是不肖子了,但是你爹可以隨便動給你買房的錢(因為錢是他賺的)。當然,不管是養老用的錢還是給你買房用的錢,外人都不能動而且也不知道。
追問:
暈啊 您確定您說的是對的?剛剛有人說,子類是可以間接來訪問基類private的
追答:
呵呵,我說的是 “外界無法直接訪問private和protected成員” 啊,再把上面的看看吧,這理解起來確實有些困難,可能第一段有誤解吧,我只是調侃的說法,意思是你說法中的”呼叫“和“public呼叫”是完全不一樣的概念,public呼叫是介面呼叫,而正常呼叫是直接呼叫資料成員。