C++中繼承的概念和定義
1.繼承的概念及定義
1.1繼承的概念
繼承機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手段,它允許程序員在保持原有類(lèi)特性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加功能,這樣產(chǎn)生新的類(lèi),稱(chēng)派生類(lèi)。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu),體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)知過(guò)程。以前我們接觸的復(fù)用都是函數(shù)復(fù)用,繼承是類(lèi)設(shè)計(jì)層次的復(fù)用。
1.2繼承的定義格式

1.3繼承基類(lèi)成員訪問(wèn)方式的變化

(1)公有繼承
基類(lèi)的公有成員,子類(lèi)可以繼承為自己的公有成員。在派生類(lèi)可以訪問(wèn),在外部也可以訪問(wèn)。
基類(lèi)的保護(hù)成員,子類(lèi)可以繼承為自己的保護(hù)成員,在派生類(lèi)可以訪問(wèn),在外部不可以訪問(wèn)。
基類(lèi)的私有成員,子類(lèi)不可以訪問(wèn)基類(lèi)的私有成員。
(2)保護(hù)繼承
基類(lèi)公有成員,子類(lèi)中繼承為自己的保護(hù)成員,在派生類(lèi)可以訪問(wèn),在外部不可以訪問(wèn)。
基類(lèi)保護(hù)成員,子類(lèi)中繼承為自己的保護(hù)成員,在派生類(lèi)可以訪問(wèn),在外部不可以訪問(wèn)。
基類(lèi)私有成員,子類(lèi)不可以訪問(wèn)基類(lèi)的私有成員。
(3)私有繼承
基類(lèi)公有成員,子類(lèi)中繼承為自己的私有成員,在派生類(lèi)可以訪問(wèn),在外部不可以訪問(wèn)。
基類(lèi)保護(hù)成員,子類(lèi)中繼承為自己的私有成員,在派生類(lèi)可以訪問(wèn),在外部不可以訪問(wèn)。
基類(lèi)私有成員,子類(lèi)不可以訪問(wèn)基類(lèi)的私有成員。
1.4總結(jié)

(1)基類(lèi)private成員任何方式繼承在派生類(lèi)中都是不可見(jiàn)的。不可見(jiàn)指派生類(lèi)對(duì)象不能去訪問(wèn)它,但是基類(lèi)的私有成員還是被繼承到了派生類(lèi)對(duì)象中。
(2)基類(lèi)的public成員和protected成員任何繼承方式在派生類(lèi)都可以訪問(wèn)。
(3)基類(lèi)pretected成員,派生類(lèi)可以訪問(wèn),類(lèi)外不能訪問(wèn)。
(4)基類(lèi)的其他成員在子類(lèi)的訪問(wèn)方式 == Min(成員在基類(lèi)的訪問(wèn)限定符,繼承方式)。public > protected > private。
(5)使用關(guān)鍵字class時(shí)默認(rèn)的繼承方式是private,使用struct時(shí)默認(rèn)的繼承方式是public,不過(guò)最好顯示的寫(xiě)出繼承方式。
class Derived : public Base //指明繼承方式是public class Derived : Base //沒(méi)寫(xiě)的情況下是private struct Derived : Base //沒(méi)寫(xiě)的情況下是public
(6)在實(shí)際運(yùn)用中一般使用都是public繼承,幾乎很少使用protetced/private繼承,實(shí)際中
擴(kuò)展維護(hù)性不強(qiáng)。
2.基類(lèi)和派生類(lèi)對(duì)象賦值轉(zhuǎn)換
派生類(lèi)對(duì)象可以賦值給基類(lèi)的對(duì)象 / 基類(lèi)的指針 / 基類(lèi)的引用。
基類(lèi)對(duì)象不能賦值給派生類(lèi)對(duì)象
基類(lèi)的指針可以通過(guò)強(qiáng)制類(lèi)型轉(zhuǎn)換賦值給派生類(lèi)的指針。但是必須是基類(lèi)的指針是指向派生類(lèi)對(duì)象時(shí)才是安全的。
class Person //基類(lèi)/父類(lèi)
{
protected :
string _name; // 姓名
string _sex; // 性別
int _age; // 年齡
};
class Student : public Person //派生類(lèi)/子類(lèi)
{
public :
int _No ; // 學(xué)號(hào)
};
void Test ()
{
Student sobj ; //創(chuàng)建子類(lèi)對(duì)象sobj
// 1.子類(lèi)對(duì)象可以賦值給父類(lèi)對(duì)象/指針/引用
Person pobj = sobj ;
Person* pp = &sobj;
Person& rp = sobj;
//2.基類(lèi)對(duì)象不能賦值給派生類(lèi)對(duì)象
sobj = pobj; //錯(cuò)誤
// 3.基類(lèi)的指針可以通過(guò)強(qiáng)制類(lèi)型轉(zhuǎn)換賦值給派生類(lèi)的指針
pp = &sobj
Student* ps1 = (Student*)pp; // 這種情況轉(zhuǎn)換時(shí)可以的。
ps1->_No = 10;
pp = &pobj;
Student* ps2 = (Student*)pp; // 這種情況轉(zhuǎn)換時(shí)雖然可以,但是會(huì)存在越界訪問(wèn)的問(wèn)題
ps2->_No = 10;
}
3.繼承中的作用域
在繼承體系中基類(lèi)和派生類(lèi)都有獨(dú)立的作用域。
子類(lèi)和父類(lèi)中有同名成員,子類(lèi)成員將屏蔽父類(lèi)對(duì)同名成員的直接訪問(wèn),這種情況叫隱藏,也叫重定義。(在子類(lèi)成員函數(shù)中,可以使用 基類(lèi)::基類(lèi)成員 顯示訪問(wèn))
需要注意的是如果是成員函數(shù)的隱藏,只需要函數(shù)名相同就構(gòu)成隱藏。
注意在實(shí)際中在繼承體系里面最好不要定義同名的成員。
// B中的fun和A中的fun不是構(gòu)成重載,因?yàn)椴皇窃谕蛔饔糜?
// B中的fun和A中的fun構(gòu)成隱藏,成員函數(shù)滿(mǎn)足函數(shù)名相同就構(gòu)成隱藏。
class A //基類(lèi)
{
public:
void fun()
{
cout << "func()" << endl;
}
};
class B : public A //派生類(lèi)
{
public:
void fun(int i)
{
A::fun();
cout << "func(int i)->" <<i<<endl;
}
};
void Test()
{
B b;
b.fun(10);
};
//如果通過(guò)子類(lèi)對(duì)象調(diào)用相同名稱(chēng)的成員時(shí),優(yōu)先訪問(wèn)子類(lèi)的,基類(lèi)同名的成員永遠(yuǎn)無(wú)法通過(guò)
// 子類(lèi)對(duì)象直接調(diào)用到,相當(dāng)于子類(lèi)同名成員將基類(lèi)的同名成員隱藏了
// 如果想要同名子類(lèi)對(duì)象訪問(wèn)基類(lèi)中同名的成員,只需在成員前加上基類(lèi)名稱(chēng)::
// 如果在子類(lèi)成員函數(shù)中,想要訪問(wèn)基類(lèi)同名的成員,只需在基類(lèi)成員前加上基類(lèi)名稱(chēng)::
class Base //基類(lèi)
{
public:
void SetBase(int b)
{
_b = b;
}
void fun()
{
cout << "Base::fun()" << endl;
}
public:
int _b;
char _c;
};
class Derived : public Base //派生類(lèi)
{
public:
void SetDeirved(int b, int d)
{
_c = 100;
Base::_c = 100; //如果在子類(lèi)成員函數(shù)中,想要訪問(wèn)基類(lèi)同名的成員,只需在基類(lèi)成員前加上基類(lèi)名稱(chēng)::
__super::_c = 100;
SetBase(b);
_d = d;
}
void fun(int a)
{
cout << "Derived::fun(int)" << endl;
}
public:
int _d;
int _c;
};
int main()
{
Base b;
b.SetBase(10);
Derived d;
d.SetDeirved(100, 200);
/*
如果子類(lèi)和基類(lèi)中具有相同名稱(chēng)的成員變量時(shí),不管成員變量的類(lèi)型是否相同,
都優(yōu)先訪問(wèn)子類(lèi)的同名成員變量
不能通過(guò)子類(lèi)對(duì)象直接訪問(wèn)子類(lèi)和父類(lèi)中同名的成員變量,就相當(dāng)與子類(lèi)同名的成員變量將基類(lèi)的同名成員變量隱藏了
*/
d._c = 'A'; // d對(duì)象中有兩個(gè)_c
// 有些情況下可能需要通過(guò)子類(lèi)對(duì)象訪問(wèn)基類(lèi)中同名的成員變量
d.Base::_c = 'B';
// d.fun(); // 編譯報(bào)錯(cuò)
d.fun(10);
d.Base::fun(); //如果想要同名子類(lèi)對(duì)象訪問(wèn)基類(lèi)中同名的成員,只需在成員前加上基類(lèi)名稱(chēng)::
return 0;
}
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
淺析C/C++中的可變參數(shù)與默認(rèn)參數(shù)
C支持可變參數(shù)的函數(shù),這里的意思是C支持函數(shù)帶有可變數(shù)量的參數(shù),最常見(jiàn)的例子就是我們十分熟悉的printf()系列函數(shù)。我們還知道在函數(shù)調(diào)用時(shí)參數(shù)是自右向左壓棧的2013-09-09
C++探索構(gòu)造函數(shù)私有化會(huì)產(chǎn)生什么結(jié)果
C++的構(gòu)造函數(shù)的作?:初始化類(lèi)對(duì)象的數(shù)據(jù)成員。即類(lèi)的對(duì)象被創(chuàng)建的時(shí)候,編譯系統(tǒng)對(duì)該對(duì)象分配內(nèi)存空間,并?動(dòng)調(diào)?構(gòu)造函數(shù),完成類(lèi)成員的初始化。構(gòu)造函數(shù)的特點(diǎn):以類(lèi)名作為函數(shù)名,?返回類(lèi)型2022-05-05
C/C++?Qt?運(yùn)用JSON解析庫(kù)的實(shí)例代碼
這篇文章主要介紹了C/C++?Qt?運(yùn)用JSON解析庫(kù)的相關(guān)知識(shí),通過(guò)代碼依次解析這個(gè)json文件中的每一個(gè)參數(shù),代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01
C++?AVL樹(shù)的兩單旋和兩雙旋的項(xiàng)目實(shí)踐
本文主要介紹了C++?AVL樹(shù)的兩單旋和兩雙旋的項(xiàng)目實(shí)踐,根據(jù)節(jié)點(diǎn)插入位置的不同,AVL樹(shù)的旋轉(zhuǎn)分為四種,下面就來(lái)介紹一下,感興趣的可以了解一下2024-03-03
解讀C++編程中派生類(lèi)的構(gòu)成和創(chuàng)建
這篇文章主要介紹了解讀C++編程中派生類(lèi)的構(gòu)成和創(chuàng)建,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09
C++實(shí)現(xiàn)飛機(jī)訂票系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)飛機(jī)訂票系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
C語(yǔ)言實(shí)現(xiàn)手寫(xiě)Map(數(shù)組+鏈表+紅黑樹(shù))的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言實(shí)現(xiàn)手寫(xiě)Map(數(shù)組+鏈表+紅黑樹(shù)),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定借鑒價(jià)值,需要的可以參考一下2022-09-09

