一、首先來了解一下繼承的基本概念
繼承(inheritance)機制是物件導向程式設計使**可以復用的最重要的手段,它允許程式設計師在保持
原有類特性的基礎上進行擴充套件,增加功能。這樣產生新的類,稱派生類。
繼承可以在原有的基礎上進行增添,不至於每一次使用都要重新寫一遍,避免了不必要的麻煩。
#includeusing namespace std;
class base
~base()
void showbase()
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};class derived :public base
~derived()
void showderived()
private:
int _d_pri;
protected:
int _d_pro;
public:
int _d_pub;
};int main()
執行結果為:
在以上**中base是基類,derived是繼承base產生的派生類,繼承定義格式是:
class deriveclassname(派生類):acess-label(繼承型別)baseclassname(基類名稱)
在主函式中,我分別創了乙個基類的物件和乙個派生類的物件。並將兩個類的大小進行計算,由此可以看出繼承關係中建構函式的呼叫順序:
基類建構函式(按照繼承列表中的順序呼叫)->派生類中物件建構函式(按照在派生類中成員物件宣告順序呼叫)->派生類建構函式體
繼承方式一共三種:
公有繼承,保護繼承,私有繼承
三種繼承方式中成員的變化:
繼承方式
基類的公有成員
基類的保護成員
基類的私有成員
關係變化概括
public繼承
仍為公有成員
仍為保護成員
不可見基類的非私有成員在子類的訪問屬性都不變
protected繼承
變為保護成員
變為保護成員
不可見基類的非私有成員都成為子類的保護成員
private繼承
變為私有成員
變為私有成員
不可見基類的非私有成員都變成子類的私有成員
1.基類的private成員在派生類中是不能被訪問的,如果基類成員不想在類外直接被訪問,但需要在派生類中訪問,就定義為protected。可以看出保護限定成員符是因繼承才出現的。
2.public繼承是乙個介面繼承,保持is-a原則,每個父類可用的成員子類也可以用,因為每個子類物件也都是乙個父類物件。
3.protected/private繼承是乙個實現繼承,基類的部分成員並非完全成為子類介面的一部分,是has-a的關係,所以非特殊情況下不會使用這兩種繼承方式,絕大多數情況都是用公有繼承。私有繼承以為這(是根據什麼實現的)。當乙個派生類需要訪問基類保護成員或需要重定義基類的虛函式時它就是合理的。
4.不管哪種繼承方式,在派生類內部都可以訪問基類的公有成員和保護成員,基類的私有成員存在但是在子類中不可見(不能訪問)。
5.最好寫出繼承方式,class預設private,struct預設public。
6.一般情況下都使用公有繼承。
在派生類中如果沒有定義這六個成員函式編譯系統會預設合成:
建構函式、拷貝建構函式、析構函式、賦值操作符過載、取位址操作符過載、用const修飾的取位址操作符過載
說明:1、基類沒有預設建構函式,派生類必須在初始化列表中顯式給出基類名和引數列表。
2、基類沒有定義建構函式,派生類也可不定義,全部使用預設建構函式。
3、基類定義
了帶有形參表構
造函式,派生類就一定定義建構函式。
[繼承關係中析構函式呼叫過程]
派生類析構函式->派生類包含成員物件析構函式(呼叫順序和成員物件在類中宣告的順序相反)->基類析構函式(呼叫順序和基類在派生列表中宣告順序相反)
多繼承定義兩個基類base1,base2,和派生類derive
則派生類的定義格式為:
class derive:public base1,public base2
{};
繼承體系中的作用域:
1.繼承體系中基類和派生類是兩個不同的作用域
2.子類和父類中有同名成員,子類成員將遮蔽父類成員的直接訪問。(在子類成員函式中,可以使用
基類::基類成員 訪問)--隱藏--重定義
3.注意在實際中在繼承體系中最好不要定義同名的成員
#includeusing namespace std;
class person
private:
string _name;//姓名
int _num;//身份證號
};class student:public person
void displaynum()
protected:
int _num;
};int main()
如圖所示,該程式無法通過編譯,基類和派生類有同名成員,基類不可訪問被子類遮蔽。
[繼承與轉換]
--賦值相容性規則--public繼承
1.子類物件可以賦值給父類物件
2.父類物件不能賦值給子類物件
3.父類的指標/引用可以指向子類成員
4.子類的指標/引用不能指向父類物件(可以通過強制型別轉換實現)
[友元與繼承]
友元關係不能繼承,也就是說基類友元不能訪問子類私有和保護成員。
#includeusing namespace std;
class person
;class student :public person
;void display(person &p, student &s)
void testperson1()
int main()
之後出現錯誤,不能訪問保護和私有成員。
[繼承與靜態成員]
基類定義了static成員,則整個繼承體系中只有乙個這樣的成員。無論派生出多少個子類,都只有乙個static成員例項。
[單繼承&多繼承&菱形繼承]
單繼承:乙個子類只有乙個直接父類時稱這個繼承關係為單繼承
多繼承:乙個子類有兩個及以上直接父類時稱這個繼承關係為多繼承
菱形繼承:
如圖所示:
菱形繼承物件模型
d的物件中有兩份a的成員,菱形繼承存在二義性和資料冗餘的問題
為了解決這個問題,提出了虛擬繼承的方式
1.虛繼承解決了在菱形繼承體系中子類物件包含多份父類物件的資料冗餘和浪費空間的問題。
2.虛繼承體系看起來很複雜,在實際應用中我們通常不會定義如此複雜的繼承體系,一般不到萬不得已都不要定義菱形結構的虛擬繼承體系結構,因為使用虛擬繼承解決資料冗餘問題也帶來了效能上的損耗。
具體操作就是在兩個單繼承的繼承方式public前加上關鍵字virtual
關於c 繼承
如下 所示 最後輸出的是 8,3,7,4 public class apublic virtual void two a a public class b a static void main string args 1 當 a呼叫two方法的時候,傳入進去的四b的例項,這時候就會呼叫b的one方法...
關於C 的多重繼承
今天看設計模式時,書中談到類繼承的用法,就想到在c 中出現這樣一種情況,如果兩個基類有同乙個名字的方法,當乙個類同時繼承這個兩類時該如何呼叫呢?舉書上的例子來說 class task class displayed class satellite public task,public display...
關於C 的private繼承問題
c 有三種繼承方式 公有繼承,私有繼承,保護繼承 這裡只對其中私有繼承做個知識筆記,以防忘記。private 關鍵字意味著除了該型別的建立者和類的內部成員函式之外,物件及子類都不能訪問。這裡注意,即使該類的物件都不能直接訪問哦,只有通過物件的內部成員函式才可以訪問 採用公用繼承方式時,基類的公用成員...