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)成員訪(fǎng)問(wèn)方式的變化
(1)公有繼承
基類(lèi)的公有成員,子類(lèi)可以繼承為自己的公有成員。在派生類(lèi)可以訪(fǎng)問(wèn),在外部也可以訪(fǎng)問(wèn)。
基類(lèi)的保護(hù)成員,子類(lèi)可以繼承為自己的保護(hù)成員,在派生類(lèi)可以訪(fǎng)問(wèn),在外部不可以訪(fǎng)問(wèn)。
基類(lèi)的私有成員,子類(lèi)不可以訪(fǎng)問(wèn)基類(lèi)的私有成員。
(2)保護(hù)繼承
基類(lèi)公有成員,子類(lèi)中繼承為自己的保護(hù)成員,在派生類(lèi)可以訪(fǎng)問(wèn),在外部不可以訪(fǎng)問(wèn)。
基類(lèi)保護(hù)成員,子類(lèi)中繼承為自己的保護(hù)成員,在派生類(lèi)可以訪(fǎng)問(wèn),在外部不可以訪(fǎng)問(wèn)。
基類(lèi)私有成員,子類(lèi)不可以訪(fǎng)問(wèn)基類(lèi)的私有成員。
(3)私有繼承
基類(lèi)公有成員,子類(lèi)中繼承為自己的私有成員,在派生類(lèi)可以訪(fǎng)問(wèn),在外部不可以訪(fǎng)問(wèn)。
基類(lèi)保護(hù)成員,子類(lèi)中繼承為自己的私有成員,在派生類(lèi)可以訪(fǎng)問(wèn),在外部不可以訪(fǎng)問(wèn)。
基類(lèi)私有成員,子類(lèi)不可以訪(fǎng)問(wèn)基類(lèi)的私有成員。
1.4總結(jié)
(1)基類(lèi)private成員任何方式繼承在派生類(lèi)中都是不可見(jiàn)的。不可見(jiàn)指派生類(lèi)對(duì)象不能去訪(fǎng)問(wèn)它,但是基類(lèi)的私有成員還是被繼承到了派生類(lèi)對(duì)象中。
(2)基類(lèi)的public成員和protected成員任何繼承方式在派生類(lèi)都可以訪(fǎng)問(wèn)。
(3)基類(lèi)pretected成員,派生類(lèi)可以訪(fǎng)問(wèn),類(lèi)外不能訪(fǎng)問(wèn)。
(4)基類(lèi)的其他成員在子類(lèi)的訪(fǎng)問(wèn)方式 == Min(成員在基類(lèi)的訪(fǎng)問(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ì)存在越界訪(fǎng)問(wèn)的問(wèn)題 ps2->_No = 10; }
3.繼承中的作用域
在繼承體系中基類(lèi)和派生類(lèi)都有獨(dú)立的作用域。
子類(lèi)和父類(lèi)中有同名成員,子類(lèi)成員將屏蔽父類(lèi)對(duì)同名成員的直接訪(fǎng)問(wèn),這種情況叫隱藏,也叫重定義。(在子類(lèi)成員函數(shù)中,可以使用 基類(lèi)::基類(lèi)成員 顯示訪(fǎng)問(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)先訪(fǎng)問(wèn)子類(lèi)的,基類(lèi)同名的成員永遠(yuǎn)無(wú)法通過(guò) // 子類(lèi)對(duì)象直接調(diào)用到,相當(dāng)于子類(lèi)同名成員將基類(lèi)的同名成員隱藏了 // 如果想要同名子類(lèi)對(duì)象訪(fǎng)問(wèn)基類(lèi)中同名的成員,只需在成員前加上基類(lèi)名稱(chēng):: // 如果在子類(lèi)成員函數(shù)中,想要訪(fǎng)問(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ù)中,想要訪(fǎng)問(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)先訪(fǎng)問(wèn)子類(lèi)的同名成員變量 不能通過(guò)子類(lèi)對(duì)象直接訪(fǎng)問(wèn)子類(lèi)和父類(lèi)中同名的成員變量,就相當(dāng)與子類(lèi)同名的成員變量將基類(lèi)的同名成員變量隱藏了 */ d._c = 'A'; // d對(duì)象中有兩個(gè)_c // 有些情況下可能需要通過(guò)子類(lèi)對(duì)象訪(fǎng)問(wèn)基類(lèi)中同名的成員變量 d.Base::_c = 'B'; // d.fun(); // 編譯報(bào)錯(cuò) d.fun(10); d.Base::fun(); //如果想要同名子類(lèi)對(duì)象訪(fǎng)問(wèn)基類(lèi)中同名的成員,只需在成員前加上基類(lèi)名稱(chēng):: return 0; }
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C/C++ Qt 基本文件讀寫(xiě)的基本使用(2種實(shí)現(xiàn))
文件的讀寫(xiě)是很多應(yīng)用程序具有的功能,本文主要介紹了兩種實(shí)現(xiàn)方法,第一種使用QFile類(lèi)的IODevice讀寫(xiě)功能直接讀寫(xiě),第二種是利用 QFile和QTextStream結(jié)合起來(lái),用流的方式進(jìn)行文件讀寫(xiě)2021-11-11C++采用openfilename打開(kāi)文件對(duì)話(huà)框用法實(shí)例
這篇文章主要介紹了C++采用openfilename打開(kāi)文件對(duì)話(huà)框用法實(shí)例,是C++文件操作中非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10深入const int *p與int * const p的區(qū)別詳解(常量指針與指向常量的指針)
本篇文章是對(duì)const int *p與int * const p的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06C語(yǔ)言詳細(xì)分析宏定義與預(yù)處理命令的應(yīng)用
宏定義是用宏名來(lái)表示一個(gè)字符串,在宏展開(kāi)時(shí)又以該字符串取代宏名,這只是一種簡(jiǎn)單的替換。字符串中可以含任何字符,可以是常數(shù),也可以是表達(dá)式,預(yù)處理程序?qū)λ蛔魅魏螜z查,如有錯(cuò)誤,只能在編譯已被宏展開(kāi)后的源程序時(shí)發(fā)現(xiàn)2022-07-07程序員都不知道C語(yǔ)言中的這些小細(xì)節(jié)
本文通過(guò)7到實(shí)例題目給大家展示C語(yǔ)言中的一些小細(xì)節(jié),很少有朋友真正的掌握,感興趣的朋友跟隨小編一起看看吧2021-05-05