在C++中,可重用性是通過繼承這一機(jī)制來實(shí)現(xiàn)的,因此,繼承是C++中一個(gè)重要的部分。
成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的衢州網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!1.派生類的聲明
聲明一個(gè)派生類的一般格式為:
class 派生類名:繼承方式 基類名 { //派生類新增的數(shù)據(jù)成員和成員函數(shù) };
從已有類派生出新類時(shí),可以在派生類內(nèi)完成以下功能:
(1)可以增加新的數(shù)據(jù)成員
(2)可以增加新的成員函數(shù)
(3)可以對基類的成員進(jìn)行重定義
(4)可以改變基類成員在派生類中的訪問屬性
2.基類成員在派生類中的訪問屬性
從基類繼承來的成員在派生類中的訪問屬性是由繼承方式控制的,下面我們來看看類的繼承方式。
類的繼承方式有public(公有繼承),protected(保護(hù)繼承),private(私有繼承)3種,不同的繼承方式導(dǎo)致不同訪問屬性的基類成員在派生類中的訪問屬性也不同。
(1)公有繼承的訪問規(guī)則
基類成員 | 私有成員 | 公有成員 | 保護(hù)成員 |
類內(nèi)訪問 | 不可訪問 | 可訪問 | 可訪問 |
對象訪問 | 不可訪問 | 可訪問 | 不可訪問 |
(2)保護(hù)繼承的訪問規(guī)則
基類成員 | 私有成員 | 公有成員 | 保護(hù)成員 |
類內(nèi)訪問 | 不可訪問 | 可訪問 | 可訪問 |
對象訪問 | 不可訪問 | 不可訪問 | 不可訪問 |
(3)私有繼承的訪問規(guī)則
基類成員 | 私有成員 | 公有成員 | 保護(hù)成員 |
類內(nèi)訪問 | 不可訪問 | 可訪問 | 可訪問 |
對象訪問 | 不可訪問 | 不可訪問 | 不可訪問 |
根據(jù)上面三個(gè)表格我們不難看出:
a.基類中的私有成員:
無論哪種繼承方式,都不允許派生類繼承,即在派生類中是不可以直接訪問的。
b.基類中的公有成員:
公有繼承時(shí),基類中的所有公有成員在派生類中仍以公有成員的身份出現(xiàn)
私有繼承時(shí),基類中的所有公有成員在派生類中都是以私有成員的身份出現(xiàn)
保護(hù)繼承時(shí),基類中的所有公有成員在派生類中都是以保護(hù)成員的身份出現(xiàn)
c.基類中的保護(hù)成員:
公有繼承時(shí),基類中的所有公有成員在派生類中仍以保護(hù)成員的身份出現(xiàn)
私有繼承時(shí),基類中的所有公有成員在派生類中都是以私有成員的身份出現(xiàn)
保護(hù)繼承時(shí),基類中的所有公有成員在派生類中都是以保護(hù)成員的身份出現(xiàn)
下面我們通過實(shí)例來看看公有繼承:
#includeusing namespace std; class B { public: void geta(int a1) { a = a1; } void showa() { cout << "a=" << a << endl; } private: int a; }; class D :public B { public: void getab(int a1, int b1) { geta(a1); b = b1; } void showab() { cout << "a=" << a << endl;//錯(cuò)誤,a在類中為不可直接訪問成員 cout << "b=" << b << endl; } private: int b; }; void Funtest() { D d; d.getab(10, 24); d.showa(); d.showab(); } int main() { Funtest(); system("pause"); return 0; }
上面程序中在D內(nèi)訪問了a是錯(cuò)誤的,在這里再次說明:派生類公有繼承了基類,但是不代表派生類可以訪問基類私有成員,企圖訪問是非法的。
3.派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù):
我們先通過一個(gè)例子來看看派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用順序吧:
#includeusing namespace std; class B { public: B(int n) { cout << "B()" << endl; i = n; } ~B() { cout << "~B()" << endl; } void showi() { cout << i << endl; } private: int i; }; class D :public B { public: D(int n, int m) :B(m) { cout << "D()" << endl; j = n; } ~D() { cout << "~D()" << endl; } void showj() { cout << j << endl; } private: int j; }; void Funtest() { D d(50, 60); d.showi(); d.showj(); } int main() { Funtest(); system("pause"); return 0; }
大家分析一下這段代碼的結(jié)果是什么呢?
從結(jié)果中可以看到:
當(dāng)創(chuàng)建派生類對象時(shí),首先調(diào)用基類的構(gòu)造函數(shù),然后再調(diào)用派生類的構(gòu)造函數(shù),當(dāng)撤銷派生類對象時(shí),則先調(diào)用派生類的析構(gòu)函數(shù),隨后調(diào)用基類的析構(gòu)函數(shù)。
那么為什么調(diào)用析構(gòu)函數(shù)時(shí)順序是相反的呢?
對于析構(gòu)函數(shù)來說,基類的構(gòu)造函數(shù)并不了解子類的結(jié)構(gòu),所以子類必須先于基類完成清理工作,一步一步向上推進(jìn)。
4.派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)
在上面的程序中我們可以看到派生類內(nèi)有自定義的構(gòu)造函數(shù),并且?guī)Я藚?shù)。派生類不能繼承基類中的構(gòu)造函數(shù)和析構(gòu)函數(shù)。當(dāng)基類含有帶參數(shù)的構(gòu)造函數(shù)時(shí),派生類必須定義構(gòu)造函數(shù),以提供把參數(shù)傳遞給基類構(gòu)造函數(shù)的途徑。
C++中,派生類構(gòu)造函數(shù)的一般格式為:
派生類名(參數(shù)總表):基類名(參數(shù)表)
{
//派生類新增數(shù)據(jù)成員的初始化語句
}
基類構(gòu)造函數(shù)的參數(shù)通常來源于派生類構(gòu)造函數(shù)的參數(shù)總表
說明:
(1)基類沒有缺省的構(gòu)造函數(shù),派生類必須要在初始化列表中顯式給出基類名和參數(shù)列表
(2)基類沒有定義構(gòu)造函數(shù),則派生類也可以不用定義,全部使用缺省構(gòu)造函數(shù)
(3)基類定義了帶有形參表的構(gòu)造函數(shù),派生類就一定定義構(gòu)造函數(shù)(可以看上面那段程序幫助理解哦)
5.繼承體系中的作用域
(1)在繼承體系中基類和派生類是兩個(gè)不同的作用域(這也是為什么基類的私有成員無論被哪種方式繼承時(shí)都不可以在派生類中直接訪問的原因)
(2)派生類和基類中有同名成員時(shí),派生類成員將屏蔽基類對成員的直接訪問。在派生類成員函數(shù)中,可通過下面這種方式訪問:
基類::基類成員
(3)當(dāng)然,在實(shí)際中,我們最好不要使用同名成員來定義對象
6.賦值兼容規(guī)則:
(1)子類對象賦值給父類對象:
Base b; Derived d; b=d;
(2)子類對象可初始化父類對象的引用:
B &br = d;
(3)父類指針可以指向子類對象:
B *pb = &d;
(4)若函數(shù)形參為父類對象或?qū)ο蟮囊脮r(shí),調(diào)用函數(shù)時(shí)可以用子類對象作實(shí)參
class B { public: int i; //…… }; class D:public B { }; void fun(B &bb) { cout<7.友元與繼承
友元關(guān)系不能繼承,即基類友元不能訪問派生類私有和保護(hù)成員
8.單繼承、多繼承、菱形繼承、
(1)單繼承:一個(gè)子類只有一個(gè)直接父類時(shí)稱這個(gè)繼承關(guān)系為單繼承
(2)多繼承:一個(gè)子類有兩個(gè)或以上直接父類時(shí)稱這個(gè)繼承關(guān)系為多繼承
多重繼承的一般形式為:
class類名l:訪問控制類名2,訪問控制類名3,…訪問控制類名n
(
…//定義派生類自己的成員
};多繼承構(gòu)造函數(shù)的調(diào)用順序與單繼承構(gòu)造函數(shù)的調(diào)用順序相同,也是遵循先調(diào)用基類的構(gòu)造函數(shù),再調(diào)用對象成員的構(gòu)造函數(shù),最后調(diào)用派生類構(gòu)造函數(shù)的原則。
(3)菱形繼承
例如,B為類C1、C2的直接父類,C1、C2又同時(shí)是D的父類。
因?yàn)榱庑卫^承存在二義性和數(shù)據(jù)冗余的問題,所以引出了下面的虛擬繼承
9.虛擬繼承
虛擬繼承是多重繼承中特有的概念。虛擬基類是為解決多重繼承而出現(xiàn)的。如:類D繼承自類C1、C2,而類C1、C2都繼承自類B,因此在類D中兩次出現(xiàn)類B中的變量和函數(shù)。為了節(jié)省內(nèi)存空間,可以將C1、C2對B的繼承定義為虛擬繼承,而B就成了虛擬基類。
虛基類的聲明:
class 派生類名:virtual 繼承方式 類名
{
// ……
}
說明:關(guān)鍵字virtual與繼承方式關(guān)鍵字的先后順序無關(guān),它只是說明是“虛擬繼承”。
下面我們通過例子來深度理解一下虛擬繼承是怎么一回事:
#includeusing namespace std; class B { public: B() { a = 1; cout << "B a = " << a << endl; } protected: int a; }; class B1 :public B { public: B1() { a += 10; cout << "B1 a = " << a << endl; } }; class B2 :public B { public: B2() { a += 20; cout << "B2 a = " << a << endl; } }; class D :public B1, public B2 { public: D() { cout << "B1::a = " << B1::a << endl; cout << "B2::a = " << B2::a << endl; } }; void Funtest() { D d; } int main() { Funtest(); system("pause"); return 0; } 程序運(yùn)行結(jié)果如下:
由于在類D中同時(shí)存在著類B1、B2的數(shù)據(jù)成員a,因此在D中的構(gòu)造函數(shù)中輸出a時(shí)必須加上“類名::”,指出是哪一個(gè)數(shù)據(jù)成員a,否則就會(huì)出現(xiàn)二義性。如果將上面的子類D改成下面形式便會(huì)出錯(cuò):
class D :public B1, public B2 { public: D() { cout << "D a = " << a << endl;//錯(cuò)誤 } };下面使用關(guān)鍵字來看這個(gè)程序:
#includeusing namespace std; class B { public: B() { a = 1; cout << "B a = " << a << endl; } protected: int a; }; class B1 : virtual public B { public: B1() { a += 10; cout << "B1 a = " << a << endl; } }; class B2 :virtual public B { public: B2() { a += 20; cout << "B2 a = " << a << endl; } }; class D :public B1, public B2 { public: D() { cout << "D a = " << a << endl; //cout << "B1::a = " << B1::a << endl; //cout << "B2::a = " << B2::a << endl; } }; void Funtest() { D d; } int main() { Funtest(); system("pause"); return 0; } 程序結(jié)果運(yùn)行如下:
上述程序中使用了關(guān)鍵字,這樣的話,從B1、B2派生出的類D指繼承基類B一次,就是說基類B的數(shù)據(jù)成員a只保留一份。
虛擬繼承解決了在菱形繼承體系里面子類對象包含多份父類對象的數(shù)據(jù)冗余和空間浪費(fèi)的問題。
這是我對于繼承的理解,如有不足,還請各位多多指教
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
本文名稱:C++類的繼承-創(chuàng)新互聯(lián)
鏈接分享:http://weahome.cn/article/ddhjcd.html