• 公有繼承(public)
公有繼承在C++中是最常用的一種繼承方式,我們先來看一個示例:
1 #include<iostream> 2 using namespace std; 3 class Father{ 4 public: 5 Father()=default; 6 void Father_show1(){ 7 cout<<"調用Father類的public方法:Father_show1"<<endl; 8 } 9 protected: 10 void Father_show2(){ 11 cout<<"調用Father類的protected方法:Father_show2"<<endl; 12 } 13 private: 14 void Father_show3(){ 15 cout<<"調用Father類的private方法:Father_show3"<<endl; 16 } 17 }; 18 19 class Son:public Father{ 20 public: 21 Son()=default; 22 void Son_fun1(){ 23 cout<<"調用Son類的public方法:Son_fun1"<<endl; 24 Father_show1(); 25 Father_show2(); 26 //Father_show3(); //錯誤:無法調用Father類的private方法 27 } 28 protected: 29 void Son_fun2(){ 30 cout<<"調用Son類的protected方法:Son_fun2"<<endl; 31 Father_show1(); 32 Father_show2(); 33 //Father_show3(); //錯誤:無法調用Father類的private方法 34 } 35 private: 36 void Son_fun3(){ 37 cout<<"調用Son類的private方法:Son_fun3"<<endl; 38 Father_show1(); 39 Father_show2(); 40 //Father_show3();//錯誤:無法調用Father類的private方法 41 } 42 }; 43 44 int main(){ 45 Son s; 46 s.Son_fun1(); //正確,只能調用對象的public方法 47 s.Father_show1(); 48 //s.Son_fun2(); //錯誤:不能調用對象的protected方法 49 //s.Father_show2(); 50 //s.Son_fun3(); //錯誤:不能調用對象的private方法 51 //s.Father_show3(); 52 return 0; 53 }
對公有繼承的理解:
1.三種屬性能力的強弱:public<protected<private
2.在C++的繼承中,子類會繼承父類中除構造函數和析構函數之外的所有成員(正所謂兒子無法繼承父親的生死) 。而公有繼承(public)就相當於先將從父類那里繼承的全部成員放到子類的public部分,如下:
1 class Son:public Father{ 2 /* 從Father類中繼承的所有成員 3 public: 4 public: 5 void Father_show1(){ 6 cout<<"調用Father類的public方法:Father_show1"<<endl; 7 } 8 protected: 9 void Father_show2(){ 10 cout<<"調用Father類的protected方法:Father_show2"<<endl; 11 } 12 private: 13 void Father_show1(){ 14 cout<<"調用Father類的public方法:Father_show1"<<endl; 15 } 16 */ 17 public: 18 Son()=default; 19 void Son_fun1(){ 20 cout<<"調用Son類的public方法:Son_fun1"<<endl; 21 Father_show1(); 22 Father_show2(); 23 //Father_show3();//錯誤:無法調用Father類的private方法 24 } 25 protected: 26 void Son_fun2(){ 27 cout<<"調用Son類的protected方法:Son_fun2"<<endl; 28 Father_show1(); 29 Father_show2(); 30 //Father_show3();//錯誤: 無法調用Father類的private方法 31 } 32 private: 33 void Son_fun3(){ 34 cout<<"調用Son類的private方法:Son_fun3"<<endl; 35 Father_show1(); 36 Father_show2(); 37 //Father_show3();//錯誤: 無法調用Father類的private方法 38 } 39 };
然后根據三種屬性能力的強弱決定成員的屬性在子類中究竟是public、protected還是private:
• Father_show1():在Father類中屬於public方法,繼承到子類Son后放在類的public部分,由於public=public,因此在子類Son中Father_show1()方法仍是public方法
• Father_show2():在Father類中屬於protected方法,繼承到子類Son后放在類的public部分,由於protected>public,因此子類Son中Father_show2()方法是protected方法
• Father_show3():在Father類中屬於private方法,可以理解為“父親的隱私”,繼承到子類Son后放在類的public部分,由於private>public,因此子類Son中Father_show3()方法是private方法。然而正所謂“兒子即使繼承了父親的財產,也無法知曉父親的隱私”,因此不管兒子以何種方式(public/protected/private)繼承父親的“財產”也無法利用父親的“隱私”去進行“交易”,換句話說就是父類的private成員雖然可以被子類繼承,但子類中的任何成員方法都不能在其函數體中調用這些從父類中繼承而來的private成員。因此Son類中的成員方法不管其為與什么部分,都無法調用Father_show3
3.對象只能調用其public部分的成員,而不能調用protected和private部分的成員。因此上例中Son類的對象s可以調用方法Son_fun1()和方法Father_show1(),而無法調用方法Son_fun2()、Son_fun3()、Father_show2()和Father_show3()
• 保護繼承(protected)
將上面的示例改為保護繼承:
1 #include<iostream> 2 using namespace std; 3 class Father{ 4 public: 5 Father()=default; 6 void Father_show1(){ 7 cout<<"調用Father類的public方法:Father_show1"<<endl; 8 } 9 protected: 10 void Father_show2(){ 11 cout<<"調用Father類的protected方法:Father_show2"<<endl; 12 } 13 private: 14 void Father_show3(){ 15 cout<<"調用Father類的private方法:Father_show3"<<endl; 16 } 17 }; 18 19 class Son:protected Father{ 20 public: 21 Son()=default; 22 void Son_fun1(){ 23 cout<<"調用Son類的public方法:Son_fun1"<<endl; 24 Father_show1(); 25 Father_show2(); 26 //Father_show3(); //錯誤:無法調用Father類的private方法 27 } 28 protected: 29 void Son_fun2(){ 30 cout<<"調用Son類的protected方法:Son_fun2"<<endl; 31 Father_show1(); 32 Father_show2(); 33 //Father_show3(); //錯誤:無法調用Father類的private方法 34 } 35 private: 36 void Son_fun3(){ 37 cout<<"調用Son類的private方法:Son_fun3"<<endl; 38 Father_show1(); 39 Father_show2(); 40 //Father_show3(); //錯誤:無法調用Father類的private方法 41 } 42 }; 43 44 int main(){ 45 Son s; 46 s.Son_fun1(); //正確,只能調用對象的public方法 47 //s.Son_fun2(); //錯誤:不能調用對象的protected方法 48 //s.Father_show1(); 49 //s.Father_show2(); 50 //s.Son_fun3(); //錯誤:不能調用對象的private方法 51 //s.Father_show3(); 52 return 0; 53 }
對保護繼承的理解:
1.三種屬性能力的強弱:public<protected<private
2.保護繼承相當於先將從父類繼承的所用成員都放在子類的protected部分:
1 class Son:public Father{ 2 /* 3 protected: 4 public: 5 void Father_show1(){ 6 cout<<"調用Father類的public方法:Father_show1"<<endl; 7 } 8 protected: 9 void Father_show2(){ 10 cout<<"調用Father類的protected方法:Father_show2"<<endl; 11 } 12 private: 13 void Father_show1(){ 14 cout<<"調用Father類的public方法:Father_show1"<<endl; 15 } 16 */ 17 public: 18 Son()=default; 19 void Son_fun1(){ 20 cout<<"調用Son類的public方法:Son_fun1"<<endl; 21 Father_show1(); 22 Father_show2(); 23 //Father_show3();//錯誤:無法調用Father類的private方法 24 } 25 protected: 26 void Son_fun2(){ 27 cout<<"調用Son類的protected方法:Son_fun2"<<endl; 28 Father_show1(); 29 Father_show2(); 30 //Father_show3();//錯誤: 無法調用Father類的private方法 31 } 32 private: 33 void Son_fun3(){ 34 cout<<"調用Son類的private方法:Son_fun3"<<endl; 35 Father_show1(); 36 Father_show2(); 37 //Father_show3();//錯誤: 無法調用Father類的private方法 38 } 39 };
然后和公有繼承一樣,根據三種屬性能力的強弱決定成員的屬性在子類中究竟是public、protected還是private:
• 由於public<protected,因此方法Father_show1()在類Son中是protected方法
• 由於protected=protected,因此方法Father_show2()在類Son中是protected方法
• 就像在公有繼承中分析的那樣,Father_show3()在類Son中雖然是private方法,但Son類中的任何成員方法都不能在其函數體中調用方法Father_show3()
3.對象只能調用public部分的成員,此時方法Father_show1()是對象的protected方法,因此無法像公有繼承那樣再被顯式調用了
• 私有繼承
將上面的示例改為私有繼承:
1 #include<iostream> 2 using namespace std; 3 class Father{ 4 public: 5 Father()=default; 6 void Father_show1(){ 7 cout<<"調用Father類的public方法:Father_show1"<<endl; 8 } 9 protected: 10 void Father_show2(){ 11 cout<<"調用Father類的protected方法:Father_show2"<<endl; 12 } 13 private: 14 void Father_show3(){ 15 cout<<"調用Father類的private方法:Father_show3"<<endl; 16 } 17 }; 18 19 class Son:private Father{ 20 public: 21 Son()=default; 22 void Son_fun1(){ 23 cout<<"調用Son類的public方法:Son_fun1"<<endl; 24 Father_show1(); 25 Father_show2(); 26 //Father_show3(); //錯誤:無法調用Father類的private方法 27 } 28 protected: 29 void Son_fun2(){ 30 cout<<"調用Son類的protected方法:Son_fun2"<<endl; 31 Father_show1(); 32 Father_show2(); 33 //Father_show3(); //錯誤:無法調用Father類的private方法 34 } 35 private: 36 void Son_fun3(){ 37 cout<<"調用Son類的private方法:Son_fun3"<<endl; 38 Father_show1(); 39 Father_show2(); 40 //Father_show3(); //錯誤:無法調用Father類的private方法 41 } 42 }; 43 44 int main(){ 45 Son s; 46 s.Son_fun1(); //正確,只能調用對象的public方法
47 //s.Son_fun2(); //錯誤:不能調用對象的protected方法 48 //s.Son_fun3(); //錯誤:不能調用對象的private方法 49 //s.Father_show1(); 50 //s.Father_show2(); 51 //s.Father_show3(); 52 return 0; 53 }
對私有繼承的理解:
1.三種屬性能力的強弱:public<protected<private
2.私有繼承相當於先將從父類繼承的所用成員都放在子類的private部分:
1 class Son:public Father{ 2 /* 3 private: 4 public: 5 void Father_show1(){ 6 cout<<"調用Father類的public方法:Father_show1"<<endl; 7 } 8 protected: 9 void Father_show2(){ 10 cout<<"調用Father類的protected方法:Father_show2"<<endl; 11 } 12 private: 13 void Father_show1(){ 14 cout<<"調用Father類的public方法:Father_show1"<<endl; 15 } 16 */ 17 public: 18 Son()=default; 19 void Son_fun1(){ 20 cout<<"調用Son類的public方法:Son_fun1"<<endl; 21 Father_show1(); 22 Father_show2(); 23 //Father_show3();//錯誤:無法調用Father類的private方法 24 } 25 protected: 26 void Son_fun2(){ 27 cout<<"調用Son類的protected方法:Son_fun2"<<endl; 28 Father_show1(); 29 Father_show2(); 30 //Father_show3();//錯誤: 無法調用Father類的private方法 31 } 32 private: 33 void Son_fun3(){ 34 cout<<"調用Son類的private方法:Son_fun3"<<endl; 35 Father_show1(); 36 Father_show2(); 37 //Father_show3();//錯誤: 無法調用Father類的private方法 38 } 39 };
然后和公有繼承一樣,根據三種屬性能力的強弱決定成員的屬性在子類中究竟是public、protected還是private:
• 由於public<private,因此方法Father_show1()在類Son中是private方法,但類Son中的成員方法可以在函數體內調用該方法
• 由於private>protected,因此方法Father_show2()在類Son中是prijvate方法,但類Son中的成員方法可以在函數體內調用該方法
• 就像在公有繼承中分析的那樣,Father_show3()在類Son中雖然是private方法,但Son類中的任何成員方法都不能在其函數體中調用方法Father_show3()
3.對象只能調用public部分的成員,此時方法Father_show1()是對象的private方法,因此無法像公有繼承那樣再被顯式調用了
QUESTION:保護繼承(protected)和私有繼承(private)有何不同?
ANSWER:在上面的例子中,我們發現保護繼承方式和私有繼承方式達到的效果完全一樣,難道這兩中繼承方式沒有任何區別嗎?我們先來看一個例子:
1 #include<iostream> 2 using namespace std; 3 class GrandFather{ //祖父類 4 public: 5 GrandFather()=default; 6 void GrandFather_show(){ 7 cout<<"調用GrandFather類的方法:GrandFather_show"<<endl; 8 } 9 }; 10 class Father:protected GrandFather{ //父類 11 public: 12 Father()=default; 13 }; 14 class Son:public Father{ //子類 15 public: 16 Son()=default; 17 void Son_show(){ 18 cout<<"調用Son類的方法:Son_show"<<endl; 19 GrandFather_show(); 20 } 21 }; 22 23 int main(){ 24 Son s; 25 s.Son_show(); 26 return 0; 27 }
我們發現上面的程序可以順利運行。這是因為當Father類以保護方式(protected)繼承GrandFather類時,GrandFather類中的公有方法GrandFather_show()會以protected方法的形式存在於類Father中,當類Son再以公有方式(public)繼承類Father時,方法GrandFather_show()會仍以protected方法的形式存在與類Son中,由於一個類中的成員方法允許在其函數體內調用protected部分的成員,因此系統允許在Son類的成員方法Son_show()調用方法GrandFather_show(),從而使程序順利運行。
現在我們將程序改為Father類以私有繼承的方式繼承GrandFather類:
1 #include<iostream> 2 using namespace std; 3 class GrandFather{ //祖父類 4 public: 5 GrandFather()=default; 6 void GrandFather_show(){ 7 cout<<"調用GrandFather類的方法:GrandFather_show"<<endl; 8 } 9 }; 10 class Father:private GrandFather{ //父類 11 public: 12 Father()=default; 13 }; 14 class Son:public Father{ //子類 15 public: 16 Son()=default; 17 void Son_show(){ 18 cout<<"調用Son類的方法:Son_show"<<endl; 19 GrandFather_show(); 20 } 21 }; 22 23 int main(){ 24 Son s; 25 s.Son_show(); 26 return 0; 27 }
我們發現程序報錯。這是因為當Father類以私有(private)繼承GrandFather類時,GrandFather類中的公有方法GrandFather_show()會以private方法的形式存在於類Father中,換句話說方法GrandFather_show()變成了類Father的“隱私”;當類Son再以公有方式(public)繼承類Father時,由於“兒子無法利用父親的“隱私”進行交易”,因此無法在Son類中的任何成員方法中調用GrandFather_show()方法,包括Son_show()。此時如果我們將類Son中成員函數Son_show()中的語句“GrandFather();"注釋掉,程序便可以重新順利執行。
1 #include<iostream> 2 using namespace std; 3 class GrandFather{ //祖父類 4 public: 5 GrandFather()=default; 6 void GrandFather_show(){ 7 cout<<"調用GrandFather類的方法:GrandFather_show"<<endl; 8 } 9 }; 10 class Father:private GrandFather{ //父類 11 public: 12 Father()=default; 13 }; 14 class Son:public Father{ 15 public: 16 Son()=default; 17 void Son_show(){ 18 cout<<"調用Son類的方法:Son_show"<<endl; 19 //GrandFather_show(); 20 } 21 }; 22 23 int main(){ 24 Son s; 25 s.Son_show(); 26 return 0; 27 }
•總結
父類中的訪問屬性 | 繼承方式 | 子類中的訪問屬性 |
private | public/protected/private | 不允許訪問 |
public | public | public |
public | protected | protected |
public | private | private |
protected | public | protected |
protected | protected | protected |
protected | private | private |