繼承是c++中的三大特性之一。
繼承機制是物件導向程式設計使**可以復用的最重要的手段,它允許程式設計師在保持原有類特性的基礎上進行擴充套件,增加功能。
這樣產生新的類,叫做派生類。
繼承定義的格式:class deriveclassname(派生類名):asecc-label(繼承型別) baseclassname(基類名)
我們已知的繼承型別有三種,分別為:public(共有繼承),protected(保護繼承)和private(私有繼承)
這三種繼承在三種繼承方式之下產生的結果如下圖:
繼承方式
基類的public成員
基類的protected成員
基類的private成員
繼承引起的訪問控制關係
public繼承
仍為public成員
仍為protected成員
不可見基類的非私有成員在子類的訪問屬性都不變
protected繼承
變為protected成員
變為protected成員
不可見基類的非私有成員都成為子類的保護成員
private繼承
變為private成員
變為private成員
不可見基類的非私有成員都成為子類的私有成員
總結:1. 基類的private成員在派生類中是不能被訪問的,如果基類成員不想在類外直接被訪問,但需要
在派生類中能訪問,就定義為protected。可以看出保護成員限定符是因繼承才出現的。
2. public繼承是乙個介面繼承,保持is-a原則,每個父類可用的成員對子類也可用,因為每個子類
物件也都是乙個父類物件。
3. protetced/private繼承是乙個實現繼承,基類的部分成員並非完全成為子類介面的一部分,
是 has-a 的關係原則,所以非特殊情況下不會使用這兩種繼承關係,在絕大多數的場景下使用的
都是公有繼承。
4. 不管是哪種繼承方式,在派生類內部都可以訪問基類的公有成員和保護成員,基類的私有成員存
在但是在子類中不可見(不能訪問)。
5. 使用關鍵字class時預設的繼承方式是private,使用struct時預設的繼承方式是public,不過最
好顯示的寫出繼承方式。
6. 在實際運用中一般使用都是public繼承,極少場景下才會使用protetced/private繼承.
那麼在繼承關係中,當派生類中如果沒有顯示這六個成員函式,編譯系統會預設合成這六個成員函式。
需要注意的是:
1、基類沒有預設建構函式,派生類必須要在初始化列表中顯式給出基類名和引數列表。
2、基類沒有定義建構函式,則派生類也可以不用定義,全部使用預設建構函式。
3、基類定義了帶有形參表建構函式,派生類就一定定義建構函式。
那麼對於以下**:
class test1
~test1 ()
};class test2
~test2 ()
};class base1
~base1 ()
protected:
int _data;
};class base2
~base2 ()
protected:
int _data2;
};class derive: public base1, public base2
public:
//derive(): base1(0), base2(1),t1(3), t2(4)
//derive(): base2(0), base1(1),t2(3), t1(4)
//derive(): t1(3), t2(4), base1(0), base2(1)
derive()
: t2 (3)
, t1 (4)
, base2 (0)
, base1(1 )
~derive ()
protected:
test1 t1;
test2 t2;
};我們執行得到的結果如下圖所示:
由結果我們可以得到類和派生類以及基類它們的建構函式以及析構函式的呼叫順序。
我們可以知道派生類繼承了base1以及base2,而且派生類中定義了兩個類物件分別為t1和t2;
我們看到編譯器先呼叫類兩個基類的建構函式,之後呼叫了兩個test類物件的建構函式,最後呼叫了派生類的建構函式,而析構函式的呼叫與之相反,從先到後析構;
我們發現t1和t2在呼叫建構函式的時候與派生類構造函式引數列表中給出的順序無關,而是按照派生類中定義類的順序呼叫。
我們用了不同的引數列表驗證,結果和圖中所示相同。
注意同名隱藏問題:
1. 在繼承體系中基類和派生類是兩個不同作用域。
2. 子類和父類中有同名成員,子類成員將遮蔽父類對成員的直接訪問。(在子類成員函式中,可以使用 基類::基類成員 訪問)--隱藏 --重定義
3. 注意在實際中在繼承體系裡面最好不要定義同名的成員。
繼承與轉換--賦值相容規則--public繼承
1. 子類物件可以賦值給父類物件
2. 父類物件不能賦值給子類物件
3. 父類的指標/引用可以指向子類物件
4. 子類的指標/引用不能指向父類物件(可以通過強制型別轉換完成)
友元關係不能繼承,也就是說基類友元不能訪問子類私有和保護成員。
基類定義了static成員,則整個繼承體系裡面只有乙個這樣的成員。無論派生出多少個子類,都只有
乙個static成員例項。
例如:class person
我們可以看到,自始至終我們定義的靜態成員變數_count都是公用的,每一次呼叫派生類從而呼叫基類的建構函式時,_count都會++。
單繼承&多繼承&菱形繼承
乙個子類只有乙個直接父類時稱這個繼承關係為單繼承。
乙個子類有兩個或以上直接父類時稱這個繼承關係為多繼承。
而菱形繼承基於多繼承的基礎。它使兩個派生類繼承自乙個基類,又使這兩個派生類作為基類,有另乙個派生類繼承它們。
菱形繼承存在二義性以及資料冗餘的問題,我們可以通過虛繼承來解決。
而有關虛繼承以及虛函式的知識我會在下一章有關c++多型的部落格中寫到。
C 中的繼承
一 繼承 什麼是繼承 繼承是允許重用現有類去建立新類的過程。分類的原則是乙個類派生出來的子類具有這個類的所有非私有的屬性。1 繼承c 中的類 c 不支援多重繼承,c 類始終繼承自乙個基類 如果未在宣告中指定乙個基類,則繼承自 system.object 派生類繼承基類的語法如下 using syst...
C 中的繼承
繼承,資料抽象和動態繫結是物件導向程式設計的核心思想。使用繼承,可以定義相似的型別並對其相似關係進行建模。通過繼承聯絡在一起的類構成一種層次關係,通常在層次關係的根部有乙個基類,其他類則直接或間接地從基類繼承而來,這些繼承得到的類稱為派生類。下面就讓我們一起來 繼承中的一些常見問題。1.繼承方式cl...
C 中的繼承
先看一下下面的例子 file1 cbase.h include using namespace std class cbase virtual cbase void 如果乙個類被用來作為基類的時候,最好把析構函式寫成虛函式。這樣做是為了當用 乙個基類的指標刪除乙個派生類的物件時,派生類的析構函式會被...