繼承的引出
概念:
繼承(inheritance)機制是面向對象程序設計使代碼可以復用的最重要的手段,它允許程序員在保持原有類特 性的基礎上進行擴展,增加功能,這樣產生新的類,稱派生類。繼承呈現了面向對象程序設計的層次結構, 體現了由簡單到復雜的認知過程。以前我們接觸的復用都是函數復用,繼承是類設計層次的復用。
例子:
-
網頁 有很多公共部分
-
導致實現時候有很多重復的代碼
-
引出繼承,基類(父類)公共網頁
-
具體子類(派生類),實現不同的內容
-
語法 class 子類 :繼承方式 父類
#include<iostream>using namespace std;//class News//{//public:// void header()// {// cout << "公共的頭部" << endl;// }//// void footer()// {// cout << "公共底部" << endl;// }// void left()// {// cout << "左側列表" << endl;// }// void content()// {// cout << "新聞播報:白百合.." << endl;// }//};//class Yule//{//public:// void header()// {// cout << "公共的頭部" << endl;// }//// void footer()// {// cout << "公共底部" << endl;// }// void left()// {// cout << "左側列表" << endl;// }// void content()// {// cout << "新聞播報:白百合.." << endl;// }//};/*void test01(){//新聞類News news;news.header();news.footer();news.left();news.content();//娛樂類Yule y1;y1.header();y1.footer();y1.left();y1.content();}*///繼承寫法//抽象一個 基類的網頁 重復的代碼都寫到這個網頁上class BasePage{public:void header(){cout << "公共的頭部" << endl;}void footer(){cout << "公共底部" << endl;}void left(){cout << "左側列表" << endl;}void content(){cout << "新聞播報:白百合.." << endl;}};class News :public BasePage //繼承 News類繼承 BasePage類{public:void content(){cout << "新聞播報" << endl;}};class YULE :public BasePage{public:void content(){cout << "白百合.." << endl;}};class Game :public BasePage{public:void content(){cout << "kpl直播" << endl;}};void test02(){cout << "新聞網頁內容:" << endl;News news;news.header();news.footer();news.left();news.content();cout << "娛樂網頁內容:" << endl;YULE y1;y1.header();y1.footer();y1.left();y1.content();cout << "游戲網頁內容:" << endl;Game y2;y2.header();y2.footer();y2.left();y2.content();}//繼承 減少代碼重復內容//BasePage 基類 (父類) News 派生類 (子類)int main(){test02();system("pause");return 0;}
繼承的方式
- 不管公有繼承 ,保護,還是私有,基類中的私有屬性,都不可以繼承下去
- 公有繼承 父類中的protected在子類中是protected,父類中的public在子類中還是public
- 保護繼承,父類中的protected在子類中是protected,父類中的public在子類中是protected
- 私有繼承,父類中的protected在子類中是private,父類中的public在子類中是prviate
注意:
-
基類private成員在派生類中無論以什么方式繼承都是不可見的。這里的不可見是指基類的私有成員還是 被繼承到了派生類對象中,但是語法上限制派生類對象不管在類里面還是類外面都不能去訪問它。
-
. 基類private成員在派生類中是不能被訪問,如果基類成員不想在類外直接被訪問,但需要在派生類中能 訪問,就定義為protected。可以看出保護成員限定符是因繼承才出現的。
-
實際上面的表格我們進行一下總結會發現,基類的私有成員在子類都是不可見。基類的其他成員在子類 的訪問方式 == Min(成員在基類的訪問限定符,繼承方式),public > protected > private。
-
使用關鍵字class時默認的繼承方式是private,使用struct時默認的繼承方式是public,不過最好顯示的 寫出繼承方式。
-
在實際運用中一般使用都是public繼承,幾乎很少使用protetced/private繼承,也不提倡使用 protetced/private繼承,因為protetced/private繼承下來的成員都只能在派生類的類里面使用,實際中 擴展維護性不強。
#include<iostream> using namespace std;class Base1 { public:int m_A; protected:int m_B; private:int m_C;};//公有繼承 class Son1 : public Base1 { public:void func(){//cout << m_C << endl;//基類中私有屬性 不可繼承cout << m_A << endl; //基類中公有屬性可繼承還是publiccout << m_B << endl;//基類中保護屬性 可繼承 還是protected} };void testSon1() {Son1 s1;s1.m_A;//s1.m_B; 類外訪問不了protected屬性 }//--------------------------保護繼承-------------class Base2 { public:int m_A; protected:int m_B; private:int m_C;};class Son2 :protected Base2 { public:void func(){//cout << m_C << endl;//基類中私有屬性 不可繼承cout << m_A << endl; //基類中公有屬性可繼承還是protectedcout << m_B << endl;//基類中保護屬性 可繼承 還是protected} }; void func2() {Son2 s;//s.m_A;//保護繼承類外不可訪問} //--------------------------私有繼承------------- class Base3 { public:int m_A; protected:int m_B; private:int m_C; };class Son3 :private Base3 { public:void func(){//cout << m_C << endl;//基類中私有屬性 不可訪問cout << m_A << endl;//基類中公有屬性 可繼承 還是private} };class GrandSon3 :public Son3 { public:void myFunc(){;//cout << m_A << endl;//孫子類中 訪問不到m_A,因為在Son3中m_A已經是私有屬性了} };int main() {system("pause");return 0;}
繼承中的對象模型
-
子類中會繼承父類中所有的內容,包括了私有屬性
-
只是我們訪問不到,編譯器給隱藏了
#include<iostream>using namespace std;class Base{public:int m_A;protected:int m_B;private:int m_C;};//子類中 會繼承父類的私有成員 只是被編譯器給隱藏起來,訪問不到私有成員class Son :public Base{public:int m_D;};void test01(){cout << sizeof(Son) << endl;//大小為16,基類中的私有成員也在子類中被繼承,只是無權訪問}int main(){test01();system("pause");return 0;}