C++深入探究繼承的概念與使用
1、概念及定義
1.1 概念
繼承主要的工作就是-----共性抽取
具體地講:
①繼承機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手段;
②允許程序員在保持原有類特性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加功能。這樣實(shí)現(xiàn)的類稱為派生類/子類?;趯?shí)現(xiàn)該類的原有類稱為基類/父類
③繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu),體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)知過(guò)程。(比如:animal—>dog---->kinds of dogs)
④繼承是類層次設(shè)計(jì)的復(fù)用
1.2 定義
定義方式:class 派生類:繼承方式 基類
繼承方式可以是 public、protected、private三種,他們?cè)诶^承基類時(shí),所具有特性以及表現(xiàn)出的結(jié)果也有所不同,具體如下:
以public的方式繼承基類

結(jié)論:
在public的繼承方式下:
①父類中的成員變量的訪問(wèn)權(quán)限,到子類中不會(huì)發(fā)生改變
②父類中的私有訪問(wèn)權(quán)限的變量在子類中不可見(不能直接被訪問(wèn))
問(wèn)題:類在設(shè)計(jì)的時(shí)候,訪問(wèn)權(quán)限應(yīng)該如何選擇?
應(yīng)該遵循以下3點(diǎn)原則:

以protected的方式繼承基類

結(jié)論:
在protected的繼承方式下:
①基類中public修飾的 成員在子類中訪問(wèn)權(quán)限為protected
②基類中protected修飾的成員在子類中的訪問(wèn)權(quán)限依舊是protected
③父類中的private訪問(wèn)權(quán)限的變量在子類中不可見(不能直接被訪問(wèn))
以private的方式繼承基類

結(jié)論:
在private的繼承方式下:
①基類中public修飾的 成員在子類中訪問(wèn)權(quán)限為private
②基類中protected修飾的成員在子類中的訪問(wèn)權(quán)限為private
③父類中的private訪問(wèn)權(quán)限的變量在子類中不可見(不能直接被訪問(wèn))
上面詳細(xì)分析了每一種個(gè)情況,下面我們針對(duì)上面的結(jié)論進(jìn)行匯總:

注意:
1、基類private成員在派生類中無(wú)論以什么方式繼承都是不可見的。這里的不可見是指基類的私有成員還是被繼承到了派生類對(duì)象中,但是語(yǔ)法上限制派生類對(duì)象不管在類里面還是類外面都不能去訪問(wèn)它。
2、基類private成員在派生類中是不能被訪問(wèn),如果基類成員不想在類外直接被訪問(wèn),但需要在派生類中能訪問(wèn),就定義為protected??梢钥闯霰Wo(hù)成員限定符是因繼承才出現(xiàn)的
3、在實(shí)際運(yùn)用中一般使用都是public繼承,幾乎很少使用protetced/private繼承,也不提倡使用protetced/private繼承,因?yàn)閜rotetced/private繼承下來(lái)的成員都只能在派生類的類里面使用,實(shí)際中擴(kuò)展維護(hù)性不強(qiáng)。
2、class與struct的區(qū)別
主要有以下3點(diǎn)區(qū)別:

3、賦值兼容規(guī)則
前提:一定在public的繼承方式下才滿足
可以直接使用子類對(duì)象給父類對(duì)象賦值,反過(guò)來(lái)不行
這個(gè)很好理解,具體和可以通過(guò)兩個(gè)方面理解:
①子類和父類的關(guān)系是is–a的關(guān)系,因此使用子類給父類賦值時(shí)可以的
②從對(duì)象模型來(lái)說(shuō)。
對(duì)象模型可以簡(jiǎn)單理解為成員變量在內(nèi)存中的布局情況;

可以使用基類的指針指向子類的對(duì)象,反過(guò)來(lái)不行
如果一定要指向,必須強(qiáng)轉(zhuǎn),不推薦,僅僅是能通過(guò)編譯,但是在使用的時(shí)候可能會(huì)造成程序崩潰
分析如下:

可以使用基類的引用去引用子類對(duì)象,反過(guò)來(lái)不行
引用在底層本質(zhì)上就是使用指針實(shí)現(xiàn)的,因此它和指針的理解思路是一致的,這里就不再贅述。
4、繼承中的作用域問(wèn)題
明確:派生類和基類隸屬于不同的作用域
那么,現(xiàn)在有這樣一種情況:
基類和派生類中出現(xiàn)了同名的成員變量或成員方法。這種情況要如何去理解呢? 首先,他一定不是函數(shù)重載,因?yàn)楹瘮?shù)重載的前提必須是在同一作用域。 其實(shí)它就是我們本模塊要介紹的----同名隱藏(重定義)問(wèn)題
基類和派生類中出現(xiàn)同名的成員時(shí),會(huì)有如下問(wèn)題的存在:

那么,該如何解決呢?
只需要在訪問(wèn)的時(shí)候加上 基類名稱和作用域限定符即可,這樣做的目的是明確告訴編譯器被調(diào)用成員所處的作用域

建議:一般情況下,在繼承體系中最好不要定義同名的成員
5、派生類(子類)的默認(rèn)成員函數(shù)
5.1 構(gòu)造函數(shù)
主要取決于基類的情況,分為兩大類進(jìn)行討論:
基類沒有顯式定義任何構(gòu)造函數(shù)
子類可以提供構(gòu)造函數(shù),也可以不提供構(gòu)造函數(shù) 是否提供根據(jù)子類中完成的功能或者具體情況決定
基類顯式定義了構(gòu)造函數(shù)
①基類的構(gòu)造函數(shù)是無(wú)參或者全缺省的
子類可以提供構(gòu)造函數(shù),也可以不提供構(gòu)造函數(shù)
是否提供根據(jù)子類中完成的功能或者具體情況決定
②基類的構(gòu)造函數(shù)是非默認(rèn)構(gòu)造函數(shù)
子類必須要定義自己的構(gòu)造函數(shù)
在子類構(gòu)造函數(shù)初始化列表位置顯式調(diào)用基類的構(gòu)造函數(shù)(完成從基類中繼承下來(lái)的成員的初始化工作)

基類和子類構(gòu)造函數(shù)的調(diào)用先后順序是怎樣的?
把握一點(diǎn):
創(chuàng)建那個(gè)類的對(duì)象,編譯器就會(huì)調(diào)用這個(gè)類的構(gòu)造函數(shù)
例如:創(chuàng)建子類對(duì)象,本質(zhì)上調(diào)用的是子類的構(gòu)造函數(shù),但是在子類的構(gòu)造函數(shù)的初始化列表處會(huì)調(diào)用基類的構(gòu)造方法來(lái)初始化從基類繼承下來(lái)的對(duì)象。然后再去執(zhí)行子類構(gòu)造函數(shù)的函數(shù)體。 因此,從結(jié)果上來(lái)看是基類對(duì)象的構(gòu)造函數(shù)先執(zhí)行完畢,子類構(gòu)造函數(shù)后執(zhí)行完畢。
5.2 拷貝構(gòu)造函數(shù)
取決于基類的情況,主要分為兩類:
基類的拷貝構(gòu)造函數(shù)未定義
子類的拷貝構(gòu)造函數(shù)可定義可不定義,根據(jù)子類的實(shí)際情況決定
基類的拷貝構(gòu)造函數(shù)定義了
子類也需要定義拷貝構(gòu)造函數(shù),并且需要在子類的拷貝構(gòu)造函數(shù)初始化列表的位置顯式調(diào)用基類的拷貝構(gòu)造函數(shù)

5.3 賦值運(yùn)算符重載
1.基類的賦值運(yùn)算符重載未定義
子類可定義可不定義
2.基類的賦值運(yùn)算符重載顯式定義了
子類也需要定義,分為兩個(gè)大的步驟:
①調(diào)用基類的賦值運(yùn)算符重載給基類部分成員賦值base::operator= (d);
②給子類自己新增的部分進(jìn)行賦值
注意:基類的operator= 與子類自己的 operator= 構(gòu)成了同名隱藏,因此要加作用域限定符指定調(diào)用基類的operator=,否則默認(rèn)調(diào)用子類自己的operator=,就會(huì)陷入無(wú)限遞歸
正確示范:

錯(cuò)誤示范:

5.4 析構(gòu)函數(shù)
編譯器將子類的析構(gòu)函數(shù)編譯完成之后,會(huì)自動(dòng)在子類析構(gòu)函數(shù)的最后一條語(yǔ)句之后插入一條調(diào)用基類析構(gòu)函數(shù)的匯編語(yǔ)句call ~Base();!

問(wèn)題:基類和子類析構(gòu)函數(shù)調(diào)用先后順序?

6、基類中哪些成員被子類繼承了
6.1 成員變量
普通成員變量,全部被繼承!
這個(gè)我們?cè)诒疚牡?.2 定義這個(gè)模塊已經(jīng)全部驗(yàn)證!
靜態(tài)成員變量也被繼承了
注意:靜態(tài)成員變量在整個(gè)繼承體系中只有一份
驗(yàn)證:通過(guò)靜態(tài)變量來(lái)記錄創(chuàng)建對(duì)象的個(gè)數(shù)
class Base
{
public:
Base(int a,int b)
{
_a = a;
_b = b;
++_count;
}
Base(const Base& b)
{
_a = b._a;
_b = b._b;
++_count;
}
Base& operator=(const Base& b)
{
_a = b._a;
_b = b._b;
return *this;
}
~Base()
{
cout << "Base::~Base()" << endl;
--_count;
}
public:
int _a;
int _b;
static int _count;
};
int Base::_count = 0;
class Derived : public Base
{
public:
Derived()
:Base(1,2)
{
}
Derived(int a,int b,int c)
:Base(a,b)
, _c(c)
{}
Derived(const Derived& d)
:Base(d)
{
_c = d._c;
}
Derived& operator=(const Derived& d)
{
Base::operator=(d);
_c = d._c;
return *this;
}
~Derived()
{
cout << "Derived::~Derived()" << endl;
}
public:
int _c;
};
void Test()
{
cout << &Base::_count << endl;
cout << &Derived::_count << endl;
}
6.2 成員方法
普通成員方法,被子類繼承了。
前面的代碼均有體現(xiàn),這里不再驗(yàn)證~
靜態(tài)成員方法—也被子類繼承了
驗(yàn)證:

7、友元函數(shù)被繼承了嗎
明確:友元函數(shù)不是類的成員函數(shù),他只是在一個(gè)類中進(jìn)行聲明,目的是打破類的封裝性去訪問(wèn)原本外部不可訪問(wèn)的成員。
這個(gè)問(wèn)題很好測(cè)試,我們只需要為子類提供一個(gè)友元函數(shù)去訪問(wèn)父類中的protected訪問(wèn)權(quán)限的成員變量。讓一個(gè)子類繼承自父類,然后測(cè)試在父類中聲明的友元函數(shù)是否能夠訪問(wèn)子類中的protected/private成員變量即可!
如果可以訪問(wèn),那就說(shuō)明 友元函數(shù)也會(huì)被繼承下來(lái)。
如果不可以訪問(wèn),那就說(shuō)明友元函數(shù)不會(huì)被繼承下來(lái)
直接上例子:

Test函數(shù)測(cè)試結(jié)果:

結(jié)論:友元函數(shù)不能被繼承!
本篇文章到這里就結(jié)束了,感覺有所幫助的讀友,可以轉(zhuǎn)發(fā)分享給身邊的朋友并留下你們的足跡!
下篇我們講講C++中一些不同的繼承體系~,我們下篇再見!
到此這篇關(guān)于C++深入探究繼承的概念與使用的文章就介紹到這了,更多相關(guān)C++繼承內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt GUI圖形圖像開發(fā)之QT表格控件QTableView,QTableWidget復(fù)雜表頭(多行表頭) 及凍結(jié)、固定特
這篇文章主要介紹了Qt GUI圖形圖像開發(fā)之QT表格控件QTableView,QTableWidget復(fù)雜表頭(多行表頭) 及凍結(jié)、固定特定的行的詳細(xì)方法與實(shí)例,需要的朋友可以參考下2020-03-03
C語(yǔ)言實(shí)現(xiàn)查詢自動(dòng)售貨機(jī)中的商品價(jià)格【實(shí)例分享】
本文主要介紹了C語(yǔ)言實(shí)現(xiàn)查詢自動(dòng)售貨機(jī)中的商品價(jià)格的相關(guān)資料。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04
C語(yǔ)言實(shí)現(xiàn)計(jì)算雙色球的中獎(jiǎng)率
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言實(shí)現(xiàn)計(jì)算雙色球的中獎(jiǎng)率,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-12-12
boost.asio框架系列之調(diào)度器io_service
這篇文章介紹了boost.asio框架系列之調(diào)度器io_service,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
用C語(yǔ)言求解第N項(xiàng)斐波那契數(shù)列問(wèn)題
這篇文章主要介紹了用C語(yǔ)言求解第N項(xiàng)斐波那契數(shù)列問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
C++實(shí)現(xiàn)打印虛函數(shù)表的地址
對(duì)于存在虛函數(shù)的類,如何打印虛函數(shù)表的地址,并利用這個(gè)虛函數(shù)表的地址來(lái)執(zhí)行該類中的虛函數(shù)呢,下面小編就來(lái)和大家一起簡(jiǎn)單聊聊吧2023-07-07

