一、基本概念
1、類的繼承,是新的類從已有類那裡得到已有的特性。或從已有類產生新類的過程就是類的派生。原有的類稱為基類或父類,產生的新類稱為派生類或子類。
2、派生類的宣告:
class 派生類名:繼承方式 基類名1, 繼承方式 基類名2,...,繼承方式 基類名n
;3、乙個派生類可以同時有多個基類,這種情況稱為多重繼承,派生類只有乙個基類,稱為單繼承。直接派生,間接派生。
4、繼承方式規定了如何訪問基類繼承的成員。繼承方式有public, private, protected。如果不顯示給出繼承方式,預設為private繼承。繼承方式指定了派生類成員以及類外物件對於從基類繼承來的成員的訪問許可權。
5、派生類繼承基類中除構造和析構函式以外的所有成員。
6、派生類生成:
吸收基類成員(除構造析構函式以外的所有成員);
改造基類成員(根據繼承方式調整基類成員的訪問,函式在子類中的覆蓋,以及虛函式在子類中的覆蓋);
新增新的成員;
7、公有繼承
當類的繼承方式為公有繼承時,基類的公有和保護成員的訪問屬性在派生類中不變,而基類的私有成員不可訪問。即基類的公有成員和保護成員被繼承到派生類中仍作為派生類的公有成員和保護成員。派生類的其他成員可以直接訪問它們。無論派生類的成員還是派生類的物件都無法訪問基類的私有成員。
8、私有繼承
當類的繼承方式為私有繼承時,基類中的公有成員和保護成員都以私有成員身份出現在派生類中,而基類的私有成員在派生類中不可訪問。基類的公有成員和保護成員被繼承後作為派生類的私有成員,派生類的其他成員可以直接訪問它們,但是在類外部通過派生類的物件無法訪問。無論是派生類的成員還是通過派生類的物件,都無法訪問從基類繼承的私有成員。通過多次私有繼承後,對於基類的成員都會成為不可訪問。因此私有繼承比較少用。
9、保護繼承
保護繼承中,基類的公有成員和私有成員都以保護成員的身份出現在派生類中,而基類的私有成員不可訪問。派生類的其他成員可以直接訪問從基類繼承來的公有和保護成員,但是類外部通過派生類的物件無法訪問它們,無論派生類的成員還是派生類的物件,都無法訪問基類的私有成員。
二、派生類的建構函式和析構函式
1、派生類中由基類繼承而來的成員的初始化工作還是由基類的建構函式完成,然後派生類中新增的成員在派生類的建構函式中初始化。
2、派生類建構函式的語法:
派生類名::派生類名(引數總表):基類名1(參數列1),基類名(引數名2)....基類名n(引數名n),內嵌子物件1(參數列1),內嵌子物件2(參數列2)....內嵌子物件n(參數列n)
注:建構函式的初始化順序並不以上面的順序進行,而是根據宣告的順序初始化。
3、如果基類中沒有不帶引數的建構函式,那麼在派生類的建構函式中必須呼叫基類建構函式,以初始化基類成員。
4、派生類建構函式執行的次序:
呼叫基類建構函式,呼叫順序按照它們被繼承時宣告的順序(從左到右);
呼叫內嵌成員物件的建構函式,呼叫順序按照它們在類中宣告的順序;
派生類的建構函式體中的內容。
例子:#include
#include
using namespace std;
class b1
private:
b1 memberb1;
b2 memberb2;
b3 memberb3;
};int main()
輸出結果為:
constructing b2 2
constructing b1 1
constructing b3
constructing b1 3
constructing b2 4
constructing b3
5、析構函式
派生類的析構函式的功能是在該物件消亡之前進行一些必要的清理工作,析構函式沒有型別,也沒有引數。析構函式的執行順序與建構函式相反。
例子:#include
#include
using namespace std;
class b1
private:
b1 memberb1;
b2 memberb2;
b3 memberb3;
};int main()
輸出結果為:
constructing b2 2
constructing b1 1
constructing b3
constructing b1 3
constructing b2 4
constructing b3
destructing b3
destructing b2
destructing b1
destructing b3
destructing b1
destructing b2
三、派生類成員的標識和訪問
1、派生類成員屬性劃分為四種:
不可訪問的成員;私有成員;保護成員;公有成員;
2、作用域分辨
形式為:基類名::成員名;基類名::成員名(參數列);
如果某派生類的多個基類擁有同名的成員,同時,派生類又新增這樣的同名成員,在這種情況下,派生類成員將覆蓋所有基類的同名成員。這就需要這樣的呼叫方式才能呼叫基類的同名成員。
例子:多繼承同名
#include
#include
using namespace std;
class b1
輸出結果為:
member of d1 1
member of b1 2
member of b2 3
以上通過作用域分辨符,解決了訪問基類中被遮蔽的同名成員。
3、如果某個派生類的部分或全部直接基類是從另乙個共同的基類派生而來,在這些直接基類中,從上一級基類繼承來的成員就擁有相同的名稱,因此派生類中也就會產生同名現象,對這種型別的同名成員也要使用作用域分辨符來唯一標識,而且必須用直接基類進行限定。
例子:#include
#include
using namespace std;
class b0
;class b2:public b0
;class d1:public b1, public b2
輸出結果為:
member of b0 2
member of b0 3
在這種情況下,派生類物件在記憶體中就同時擁有成員nv及fun的兩份拷貝。但是很多情況下,我們只需要這樣乙個這樣的資料拷貝,同一成員的多份拷貝增加了記憶體的開銷。可以通過虛函式來解決這個問題。
4、虛基類
為了解決前面提到的多重拷貝的問題,可以將共同基類設定為虛基類,這時從不同的路徑繼承過來的同名資料成員在記憶體中就只有乙個拷貝,同乙個函式也只有乙個對映。
虛基類的宣告是在派生類的宣告過程,其語法形式為:
class 派生類名::virtual 繼承方式 基類名;
例子:#include
#include
using namespace std;
class b0
;class b2:virtual public b0
;class d1:public b1, public b2
輸出結果為:
member of b0 2
5、虛基類及其派生類的建構函式
一般而言,派生類只對其直接基類的建構函式傳遞引數,但是在虛基類中,不管是直接或間接虛基類的所有派生類,都必須在建構函式的成員初始化列表中列出對虛基類的初始化。
例子:#include
#include
using namespace std;
class b0
int nv;
void fun()
int nv1;
};class b2:virtual public b0
int nv2;
};class d1:public b1, public b2
int nvd;
void fund()
以上例子看上去b0的建構函式好像被呼叫了三次,但是實際上只有d1類中的d1(int a):b0(a), b1(a), b2(a)
才是真正的呼叫了b0建構函式。
四、賦值相容規則
1、賦值相容規則是指在需要基類物件的任何地方都可以使用公有派生類的物件來替代。
2、賦值相容規則中所指的替代包括:
派生類的物件可以賦值給基類物件;
派生類的物件可以初始化基類的引用;
派生類物件的位址可以賦給指向基類的指標。
在替代之後,派生類物件就可以作為基類的物件使用,但只能使用從基類繼承的成員。
例子:#include
#include
using namespace std;
class b0
int main()
輸出結果為:
b0::display()
b0::display()
b0::display()
通過這種賦值相容後,每次呼叫的同名函式都是基類的同名函式,如果想呼叫派生類的,則需要使用虛函式。
C 類的繼承與派生
1.乙個包含多級派生 構造 析構函式的綜合例項 include using namespace std class a a 析構函式,關於析構函式只做簡單介紹 void f1 int i protected void f2 int j private int k class b public a 定...
C 類的繼承與派生
繼承是物件導向程式設計中最重要的乙個概念。繼承允許我們根據乙個類來定義另乙個類,達到了 功能重用效果。當建立乙個類時,如果待建立的類與另乙個類存在某些共同特徵,程式設計師不需要全部重新編寫成員變數和成員函式,只需指定繼承另乙個類即可,被繼承的類稱為基類或父類,新建的類稱為派生類或子類。定義乙個派生類...
C 類的繼承與派生
繼承是物件導向程式設計中最重要的乙個概念。繼承允許我們根據乙個類來定義另乙個類,達到了 功能重用效果。當建立乙個類時,如果待建立的類與另乙個類存在某些共同特徵,程式設計師不需要全部重新編寫成員變數和成員函式,只需指定繼承另乙個類即可,被繼承的類稱為基類或父類,新建的類稱為派生類或子類。定義乙個派生類...