1. 程式人生 > >C語言拾遺:公有、私有和受保護的繼承--《C++ primer》筆記

C語言拾遺:公有、私有和受保護的繼承--《C++ primer》筆記

  • 公有繼承:派生類物件可訪問基類中的公有成員,派生類成員可訪問基類中的公有成員與保護成員。
  • 私有繼承:對於派生類物件不可該問基類任何成員。派生類成員可該問基類公有與保護成員。所有基類公有與保護成員變成派生類私有成員,且不可為派生類的子類訪問。基類私有成員對派生類不可見。
  • 保護繼承:派生類物件可訪問基類中的公有成員,派生類成員可訪問基類公有與保護成員。。基類的公有與保護成員變成派生類的保護成員,且不可為派生類的子類訪問。基類私有成員對派生類不可見。

類繼承預設私有繼承。結構體繼承預設公有繼承。

protectedInheritance.cpp

間接繼承和書本描述不一致,書上說因為第一重繼承變private,第二重繼承才無法訪問Base::i~是private

,現實是提示Base::i是protected,好像跳過Private_derived類直接找基類了。

繼承對基類的保護,還是普遍規律,只能越來越嚴,不能變鬆。

還有,標號不是限制派生類對基類成員(表達不清楚,是基類成員還是從基類繼承過來的成員?)的訪問,

原話:所有繼承Base的類對Base中的成員具有相同的訪問(指什麼,成員?怎麼理解恰當,派生類包括基類,所以這裡的對基類訪問指對派生類中包含的基類部分訪問?)

標號是限制使用者派生類的派生類(也當作一種使用者吧?)對派生類(從基類繼承來的)成員的訪問

  1. //公用、私有和受保護的繼承
  2. #include<iostream>
  3. class Base{  
  4. public:  
  5.     void basemem();  
  6. protected:  
  7.     int i;  
  8. };  
  9. //struct直接繼承class?可以?還有預設訪問級別不同,一個public,一個private,轉換後不要忘了
  10. struct Public_derived : public Base{  
  11.     int use_base() { return i; }//顧名思義,使用一下base看看
  12. };  
  13. struct Protected_derived : protected Base{  
  14.     int use_base() { return i; }  
  15. };  
  16. struct Private_derived : private Base{  
  17.     int use_base() { return i; }//也沒問題,儘管private~~~private不是設給它的,是給使用者和下一個派生類的
  18. };  
  19. //下一層派生
  20. struct Derived_from_Private : public Private_derived{  
  21.     int use_base() { return i; }  
  22.     //書上的註釋,Base::i is private in Private_derived,
  23.     //實際錯誤提示:'int Base::i' is protected,可能說明直接以使用者身份去Base裡找了,是protected,如果間接找,這個提示費勁
  24. };  
  25. struct Derived_from_Public : public Public_derived{  
  26.     int use_base() { return i; }//可以訪問,因為Base::i在Public_derived類中仍然是protected
  27. };  
  28. int main(){  
  29.     Base b;  
  30.     Public_derived d1;  
  31.     Protected_derived d3;  
  32.     Private_derived d2;  
  33.     b.basemem();//b物件,肯定能訪問
  34.     d1.basemem();//對於d1物件,basemem()還是public
  35.     //d2.basemem();//basemem()是private,不能訪問
  36.     //d3.basemem();//protected當然也不行了
  37. }  

介面繼承與實現繼承:

public派生的類與基類有相同的介面。在設計良好的層次中,public派生的類可以用在任何需要基類物件的地方。

非public派生的類不繼承基類的介面,稱為實現繼承,(用基類做它的實現,但不用基類做介面)

using.cpp

經過測試,using的用法和書上差距很大~!!!!!!!!!!!!!!!!!!(mark

base的protected,用private繼承,結果過用using可以變成public~~~!!!!

另:基類和派生類指標相容與轉換問題也測了一下,結果比較符合我“想當然”的判斷。。

到底派生類的constructor怎麼定義,把基類的成員用using聲明瞭一遍,但是constructor的初始化列表會提示找不到成員n

  1. //派生類使用using宣告恢復繼承成員的訪問級別。
  2. #include<iostream>
  3. class Base{  
  4. public:  
  5.     std::size_t size() const { return n; }  
  6. protected:  
  7.     std::size_t n;  
  8. };  
  9. class Derived : private Base{//private繼承,全部成員變成私有
  10. public:  
  11.     using Base::size;  
  12.     //using Base::n;//神奇了,可以提升為public,直接d1.n就訪問了。神奇的不是Geany編譯器和g++吧
  13. protected:  
  14.     //using Base::n;
  15. private://宣告成private也行啊。。。到底何謂“不能使訪問級別比基類中原來指定的更嚴格或更寬鬆”
  16.     using Base::n;//無論宣告放在protected還是private後邊,d1.n都提示n是protected。但public...
  17.     //~小失誤,把基類的n設為private,這種情況到底有何不同~恢復為private也有錯啊?
  18. };  
  19. class Public_derived : public Base{//private繼承,全部成員變成私有
  20. public:  
  21.     //using Base::size;
  22. protected:  
  23.     //using Base::n;
  24. private:  
  25.     //using Base::n;
  26. };  
  27. int main(){  
  28.     /*Base b1; 
  29.     Derived d1; 
  30.     Public_derived pd1; 
  31.     //猜測:一個物件的儲存區域是順序存放各類物件的,首地址是基類子物件,其次是派生類多出來的部分,再次是派生類的派生類。。。 
  32.     Base *bp1 = &d1;//private繼承已經改變了基類的訪問許可權,所以基類指標也不能指向它了~“Base是Derived裡不能訪問的一部分”,因此public繼承是一個前提。 
  33.     bp1 = &pd1; 
  34.     Public_derived *pdp1 = bp1; //前提:public。派生類的指標是不能指向基類的物件的,只能向下相容 
  35.     Derived *dp1 = &b1;         //不能向上相容,所以和地址猜想不衝突,這說明很可能就是哪樣排列的,所以不能分。 
  36.     */
  37.     Derived d1;  
  38.     std::cout << d1.n;//這提升許可權到public,但是無法初始化,我始終都搞不定派生類的初始化。。。
  39. }  

預設繼承保護級別(前邊疑問的class和struct有解了):

default inheritance.cpp

比較簡單的概念,預設不重要,自己可以手動設定

  1. //預設繼承保護級別
  2. class Base{};  
  3. struct D1 : Base{};     //public inheritance by default
  4. class D2 : Base{};      //private inheritance by default
  5. //這只是預設的,如果你每次都指定,還是無所謂。。。
  6. //原書:class和struct唯一的不同是預設的成員保護級別和預設的派生保護級別(這倆詞指什麼)
  7. //以下D3和D4的定義兩兩相同
  8. class D3 : public Base{  
  9. public:  
  10.     /*...*/
  11. };  
  12. //equivalent definition of D3
  13. struct D3 : Base {      //inheritance public by default
  14.     /*...*///initial number access public by default
  15. };  
  16. struct D4 : Base {  
  17. private:  
  18.     /*...*/
  19. };  
  20. //equivalent definition of D4
  21. class D4 : Base {   //inheritance private by default
  22.     /*...*///initial member access private by default
  23. };  
  24. //tips:因為私有繼承在使用class保留字是預設情況,但因為實踐中使用罕見,所以還要顯式的使用private
  25. int main(){  
  26. }  

為何可以訪問,卻不可以利用建構函式初始化基類成員,派生類中的基類成員,莫非也用基類的建構函式來完成
  1. class Gif : public Picture_format{  
  2. public:  
  3.     Gif(size_t i = 20) : pixels(i) {}  
  4.     size_t fcn(){ return pixels; }  
  5. };  
pe15_11.cpp

弄明白的東西:

繼承來的成員的地位:

派生類的constructor無法在初始化列表中初始化繼承成員,識別不到

對派生類物件來說,繼承的成員也是基類的constructor初始化的,但是派生類能直接讀取它,fcn()中使用pixels

如此說來,基類派生類貌似真是分開的模組

  1. class Picture_format{  
  2. public:  
  3.     Picture_format(size_t i = 10) : pixels(i) {}  
  4. protected:  
  5.     size_t pixels;//畫素
  6. private:  
  7. };  
  8. class Gif : public Picture_format{  
  9. public:  
  10.     size_t fcn(){ return pixels; }  
  11. };  
  12.     //Gif g();//這個g不算類Gif的類物件,算個函式什麼的吧?!
  13.     Gif g;  
  14.     std::cout << g.fcn() << std::endl;  

相關推薦

C語言拾遺公有私有保護繼承--《C++ primer筆記

公有繼承:派生類物件可訪問基類中的公有成員,派生類成員可訪問基類中的公有成員與保護成員。私有繼承:對於派生類物件不可該問基類任何成員。派生類成員可該問基類公有與保護成員。所有基類公有與保護成員變成派生類私有成員,且不可為派生類的子類訪問。基類私有成員對派生類不可見。保護繼

公有私有保護繼承--《C++ primer筆記

protectedInheritance.cpp 間接繼承和書本描述不一致,書上說因為第一重繼承變private,第二重繼承才無法訪問Base::i~是private,現實是提示Base::i是protected,好像跳過Private_derived類直接找基類了。 繼

使用公共私有保護等訪問指示符的java概述

5.2 Java訪問指示符 針對類內每個成員的每個定義,Java訪問指示符poublic,protected以及private都置於它們的最前面——無論它們是一個數據成員,還是一個方法。每個訪問指示符都只控制著對那個特定定義的訪問。這與C++存在著顯著不同。在

C++繼承公有私有保護

公有繼承(public)、私有繼承(private)、保護繼承(protected)是常用的三種繼承方式。 1. 公有繼承(public) 公有繼承的特點是基類的公有成員和保護成員作為派生類的成員時,它們都保持原有的狀態,而基類的私有成員仍然是私有的,不能被這個派生類的子類所訪問。 2. 私有繼承(

C語言中的__FILE____LINE__#line用法

C語言中的__FILE__用以指示本行語句所在原始檔的檔案。 例如: #include <stdio.h>int main(){printf("%s\n",__FILE__);} 在g

c語言基礎陣列指標

-----------------------------------------------------------------------------------------------------------------------------------------------------------

C語言中的__FILE____LINE____func__等預定義跟蹤除錯

標準C語言預處理要求定義某些物件巨集,每個預定義巨集的名稱一兩個下劃線字元開頭和結尾,這些預定義巨集不能被取消定義(#undef)或由程式設計人員重新定義。下面預定義巨集表,被我抄了下來。 __LIN

C++知識積累過載隱藏重寫的區別

基本概念: 過載:是指同一可訪問區內被宣告的幾個具有不同引數列(引數的型別,個數,順序不同)的同名函式,根據引數列表確定呼叫哪個函式,過載不關心函式返回型別。 示例: class A{ public: void test(int a); void test(double a)

C語言中的__FILE____LINE__#line(用於列印當前函式及行數)

C語言中的__FILE__用以指示本行語句所在原始檔的檔名,舉例如下(test.c):#include <stdio.h>int main(){printf("%s\n",__FILE__);}在gcc編譯生成a.out,執行後輸出結果為:test.

C語言規範C89C90C95C99

本文轉載 【K&R C】 1978 年,Dennis Ritchie 和 Brian Kernighan 合作推出了《The C Programming Language》的第一版(按照慣例,經典著作一定有簡稱,該著作簡稱為 K&R),書末的參考指南

C語言中關鍵字staticexternauto的作用總結

1、首先說一下auto自動儲存型別,一般我們很少在程式中顯示申明變數為auto型別。因為程式碼塊中的變數預設情況下就是這種型別,這種型別的變數存放於堆疊中,也就是說只有程式執行這些程式碼塊(一對{}之間的語句)時這種自動變數才會被建立,程式碼塊執行結束後自動變數便被釋放。

JavaFutureCallableFutureTask原理解析(學習筆記

Future表示一個任務的生命週期,並提供了方法來判斷是否已經完成或取消,以及獲取任務的結果和取消任務等。Future介面: public interface Future<V> { boolean cancel(boolean mayInterruptIfRunni

C++繼承型別公有保護私有虛擬

公有繼承(public)、保護繼承(protected)、私有繼承(private)是常用的三種繼承方式,除了這些繼承型別外還有一種虛擬繼承。 公有繼承(public) 公有繼承的特點是基類的公有成員和保護成員作為派生類的成員時,它們都保持原有的狀態,即基類的公有成員在派生類中還是公有

C++中繼承派生詳解(公有私有保護繼承的區別)

繼承和派生概述: 繼承和派生是同一個過程從不同角的度看 保持已有類的特性而構造新類的過程稱為繼承。 在已有類的基礎上新增自己的特性而產生新類的過程稱為派生。 被繼承的已有類稱為基類(或父類)。 派生出的新類稱為派生類(

命令列選項解析函式(C語言)getopt()getopt_long()getopt_long_only

上午在看原始碼專案 webbench 時,剛開始就被一個似乎挺陌生函式 getopt_long() 給卡住了,說實話這函式沒怎麼見過,自然不知道這哥們是幹什麼的。於是乎百度了一番,原來是處理命令列選項引數的,的確,正規點的大型程式一般第一步就是處理命令列引數

C++繼承公有私有保護(轉)

情況 pre mes 派生類 它的 保持 ++ col ble 公有繼承(public)、私有繼承(private)、保護繼承(protected)是常用的三種繼承方式。 1. 公有繼承(public) 公有繼承的特點是基類的公有成員和保護成員作為派生類的成員時,它們都保持

C 函數中保存狀態registryreferenceupvalues

targe 閉包 一個 兩個 table chang detail chan 這樣的 在C函數中保存狀態:registry、reference和upvalues C函數能夠通過堆棧來和Lua交換數據,但有時候C函數須要在函數體的作用域之外保存某些Lua數

一起talk C栗子吧(第一百二十三回C語言實例--顯示變量函數的地址)

調試 ora 部分 example 多線程 ear red 語言 help 各位看官們,大家好,上一回中咱們說的是多線程的樣例。這一回咱們說的樣例是:顯示變量和函數的地址。閑話休提,言歸正轉。讓我們一起talk C栗子吧! 在編敲代碼時,有時候須

iOS開發核心語言Objective C —— 面向對象思維settergetter方法及點語法

才幹 各路 alt .net 行為 變量的作用域 fadein 格式 讀取 本分享是面向有意向從事iOS開發的夥伴們。或者已經從事了iOS的開發人員。假設您對iOS開發有極高的興趣,能夠與我一起探討iOS開發。一起學習,共同進步。假設您是零基礎,建議您先

(轉)C語言之原碼反碼補碼

計算機 進制 情況下 class 正數 去掉 都是 OS 原碼 原碼、反碼和補碼 1).數據在內存中存儲的時候都是以二進制的形式存儲的. int num = 10; 原碼、反碼、補碼都是二進制.只不過是二進制的不同的表現形式. 數據是以補碼