公有、私有和受保護的繼承--《C++ primer》筆記
protectedInheritance.cpp
間接繼承和書本描述不一致,書上說因為第一重繼承變private,第二重繼承才無法訪問Base::i~是private,現實是提示Base::i是protected,好像跳過Private_derived類直接找基類了。
繼承對基類的保護,還是普遍規律,只能越來越嚴,不能變鬆。
還有,標號不是限制派生類對基類成員(表達不清楚,是基類成員還是從基類繼承過來的成員?)的訪問,
原話:所有繼承Base的類對Base中的成員具有相同的訪問(指什麼,成員?怎麼理解恰當,派生類包括基類,所以這裡的對基類訪問指對派生類中包含的基類部分訪問?)
標號是限制使用者
//公用、私有和受保護的繼承 #include<iostream> class Base{ public: void basemem(); protected: int i; }; //struct直接繼承class?可以?還有預設訪問級別不同,一個public,一個private,轉換後不要忘了 struct Public_derived : public Base{ int use_base() { return i; }//顧名思義,使用一下base看看 }; struct Protected_derived : protected Base{ int use_base() { return i; } }; struct Private_derived : private Base{ int use_base() { return i; }//也沒問題,儘管private~~~private不是設給它的,是給使用者和下一個派生類的 }; //下一層派生 struct Derived_from_Private : public Private_derived{ int use_base() { return i; } //書上的註釋,Base::i is private in Private_derived, //實際錯誤提示:'int Base::i' is protected,可能說明直接以使用者身份去Base裡找了,是protected,如果間接找,這個提示費勁 }; struct Derived_from_Public : public Public_derived{ int use_base() { return i; }//可以訪問,因為Base::i在Public_derived類中仍然是protected }; int main(){ Base b; Public_derived d1; Protected_derived d3; Private_derived d2; b.basemem();//b物件,肯定能訪問 d1.basemem();//對於d1物件,basemem()還是public //d2.basemem();//basemem()是private,不能訪問 //d3.basemem();//protected當然也不行了 }
介面繼承與實現繼承:
public派生的類與基類有相同的介面。在設計良好的層次中,public派生的類可以用在任何需要基類物件的地方。
非public派生的類不繼承基類的介面,稱為實現繼承,(用基類做它的實現,但不用基類做介面)
using.cpp
經過測試,using的用法和書上差距很大~!!!!!!!!!!!!!!!!!!(mark)
base的protected,用private繼承,結果過用using可以變成public~~~!!!!
另:基類和派生類指標相容與轉換問題也測了一下,結果比較符合我“想當然”的判斷。。
到底派生類的constructor怎麼定義,把基類的成員用using聲明瞭一遍,但是constructor的初始化列表會提示找不到成員n
//派生類使用using宣告恢復繼承成員的訪問級別。
#include<iostream>
class Base{
public:
std::size_t size() const { return n; }
protected:
std::size_t n;
};
class Derived : private Base{//private繼承,全部成員變成私有
public:
using Base::size;
//using Base::n;//神奇了,可以提升為public,直接d1.n就訪問了。神奇的不是Geany編譯器和g++吧
protected:
//using Base::n;
private://宣告成private也行啊。。。到底何謂“不能使訪問級別比基類中原來指定的更嚴格或更寬鬆”
using Base::n;//無論宣告放在protected還是private後邊,d1.n都提示n是protected。但public...
//~小失誤,把基類的n設為private,這種情況到底有何不同~恢復為private也有錯啊?
};
class Public_derived : public Base{//private繼承,全部成員變成私有
public:
//using Base::size;
protected:
//using Base::n;
private:
//using Base::n;
};
int main(){
/*Base b1;
Derived d1;
Public_derived pd1;
//猜測:一個物件的儲存區域是順序存放各類物件的,首地址是基類子物件,其次是派生類多出來的部分,再次是派生類的派生類。。。
Base *bp1 = &d1;//private繼承已經改變了基類的訪問許可權,所以基類指標也不能指向它了~“Base是Derived裡不能訪問的一部分”,因此public繼承是一個前提。
bp1 = &pd1;
Public_derived *pdp1 = bp1; //前提:public。派生類的指標是不能指向基類的物件的,只能向下相容
Derived *dp1 = &b1; //不能向上相容,所以和地址猜想不衝突,這說明很可能就是哪樣排列的,所以不能分。
*/
Derived d1;
std::cout << d1.n;//這提升許可權到public,但是無法初始化,我始終都搞不定派生類的初始化。。。
}
預設繼承保護級別(前邊疑問的class和struct有解了):
default inheritance.cpp
比較簡單的概念,預設不重要,自己可以手動設定
//預設繼承保護級別
class Base{};
struct D1 : Base{}; //public inheritance by default
class D2 : Base{}; //private inheritance by default
//這只是預設的,如果你每次都指定,還是無所謂。。。
//原書:class和struct唯一的不同是預設的成員保護級別和預設的派生保護級別(這倆詞指什麼)
//以下D3和D4的定義兩兩相同
class D3 : public Base{
public:
/*...*/
};
//equivalent definition of D3
struct D3 : Base { //inheritance public by default
/*...*/ //initial number access public by default
};
struct D4 : Base {
private:
/*...*/
};
//equivalent definition of D4
class D4 : Base { //inheritance private by default
/*...*/ //initial member access private by default
};
//tips:因為私有繼承在使用class保留字是預設情況,但因為實踐中使用罕見,所以還要顯式的使用private
int main(){
}
為何可以訪問,卻不可以利用建構函式初始化基類成員,派生類中的基類成員,莫非也用基類的建構函式來完成
class Gif : public Picture_format{
public:
Gif(size_t i = 20) : pixels(i) {}
size_t fcn(){ return pixels; }
};
pe15_11.cpp
弄明白的東西:
繼承來的成員的地位:
派生類的constructor無法在初始化列表中初始化繼承成員,識別不到
對派生類物件來說,繼承的成員也是基類的constructor初始化的,但是派生類能直接讀取它,fcn()中使用pixels
如此說來,基類派生類貌似真是分開的模組
class Picture_format{
public:
Picture_format(size_t i = 10) : pixels(i) {}
protected:
size_t pixels;//畫素
private:
};
class Gif : public Picture_format{
public:
size_t fcn(){ return pixels; }
};
//Gif g();//這個g不算類Gif的類物件,算個函式什麼的吧?!
Gif g;
std::cout << g.fcn() << std::endl;