C++ 中三種繼承方式的理解


一、有繼承(public inheritance)

   1.概念:當類的繼承方式為公有繼承時,基類的 公有成員保護成員訪問屬性在派生類中不變,而基類的 私有成員不可以直接訪問
   
實驗一下:
 
我們用代碼實現對概念的理解,如下:
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A():x(10),y(20){}
 7     A(int x){this->x = x;}
 8     int getx(){return x;}
 9     int gety(){return y;}
10     int getu(){return u;}
11 protected:
12     int y;
13 private:
14     int x;
15     int u;
16 };
17 //class B:public A{   //訪問公有、保護成員
18 //
19 //};
20 class B:public A{     //通過A中的公有成員函數才能訪問A中的私有成員,派生類的成員或者派生類的對象都無法直接訪問基類私有成員
21 public:
22 // int getx(){return x;} //錯誤,直接用派生類的成員訪問基類私有成員 23 // int getx(){return A::getx();}
24     int getx(){return 30;}       //改造基類成員函數
25     void sety(){y = 100;}        //直接調用基類保護成員並修改
26 };
27 int main(){
28     B b;
29     cout<<"原始的x:"<<b.A::getx()<<endl;    //調用基類的同名函數
30     cout<<"改造后的x:"<<b.getx()<<endl;       //調用改造后的函數
31 
32     cout<<"保護成員y:"<<b.gety()<<endl;
33     b.sety();
34     cout<<"在派生類中修改y值:"<<b.gety()<<endl; 35     cout<<"私有成員u:"<<b.getu()<<endl;       //公有繼承可以通過派生類的對象訪問基類繼承的公有成員 36 // cout<<B::x<<endl; //錯誤,無法通過派生類成員訪問基類私有成員 37 // cout<<b.y<<endl; //錯誤, 通過對象無法訪問保護成員
38     return 0;
39 }

執行結果:

 

 理解:

公有繼承方式:

在派生類內部

1、 派生類成員可以直接訪問基類的公有和保護類成員【上面代碼23、25行】

2、 當然,如果想拓展繼承來的函數可以進行改造,改造是可以同名的,

      在接下來用對派生類的對象調用該函數時就會使用改造后的函數【上面代碼24,29行】,

      在后來的調用調用中仍然可以調用基類的未改造的函數【代碼28行】

 

在派生類外部

1、通過派生類的對象可以訪問基類的公有成員(這里只能訪問公有成員,連保護成員都不可以訪問)【上面代碼35、36行】

2、無論是派生類的成員還是對象都無法直接訪問基類私有成員【上面代碼36、37行】     

 

需要注意的是:如果派生類的成員函數與基類的成員函數且你想使用基類的那個函數功能,你需要用  '' 類名::''  這種方式實現。(三種繼承方式都是這樣)

【上面代碼23行】

 

 

 

 

二、私有繼承(private inheritance)

   1.概念:當類的繼承方式為私有繼承時,基類的 公有成員保護成員都以私有成員身份出現在派生類中,而 基類的私有成員在派生類中 不可直接訪問。
 
實驗一下:
 
我們仍然使用代碼來實現對概念的理解,如下:
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A {
 5 public:
 6     A() : x(10), y(20) {}
 7     int getx() { return x; }
 8     int gety() { return y; }
 9     int getu() { return u; }
10 protected:
11     int y;
12 private:
13     int x;
14     int u;
15 };
16 
17 
18 class B : private A {
19 public:                                 //因為基類的公有、保護成員作為派生類的私有成員,派生類的成員不能直接訪問它們,
20     int getx() { return A::getx(); }    //只能通過成員函數調用它們
21 
22     int getyy() { return gety(); } 23 
24     int getyyy(){return y;}             //派生類成員中可以直接訪問基類繼承的公有和保護成員
25 
26 };
27 
28 int main() {
29     B b;
30     cout <<"x的值:" <<b.getx() << endl;
31     cout <<"y的值:"<< b.getyy() << endl;
32     cout<<"y的值:"<<b.getyyy()<<endl;  
33 //    cout<<b.getu()<<endl;           //錯誤,私有繼承無法通過派生類對象訪問基類成員
34     return 0;
35 }

執行結果:

 理解:

私有繼承方式:

在類的內部:

1、由於基類的公有成員和保護成員變成派生類的私有成員,派生類的成員可以直接訪問它們【上面代碼20、24行】

       

在類的外部:

1、派生類外部無法通過對象直接訪問基類的公有成員和保護成員(這是與公有繼承的一個差別)【上面代碼33行】

       

在派生內外部: 都無法直接訪問基類私有成員

 
其實很好理解,基類繼承來的公有、保護成員變成派生類的私有成員,想想普通類對私有成員的使用即可。
 
 
 
 
 
 
 
 

三、保護繼承(protected inheritance)

   1.概念:保護繼承中,基類的 公有成員保護成員以保護成員的身份出現在派生類中,而基類的私有成員不可直接訪問。
   
實驗一下:
 
我們繼續用代碼實現對概念的理解,如下:
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A():x(10),y(20){}
 7     int getx(){return x;}
 8     int gety(){return y;}
 9     int getu(){return u;}
10 protected:
11     int y;
12 private:
13     int x;
14     int u;
15 };
16 class B:protected A{
17 public:
18     int getxx(){return getx();}     //派生類成員可以直接訪問繼承來的公有成員【與公有繼承一樣】
19     int getyy(){return y;}          
20 };
21 int main(){
22     B b;
23     cout<<"x的值:"<<b.getxx()<<endl;
24     cout<<"y的值:"<<b.getyy()<<endl;
25 
26 // cout<<b.getx()<<endl; //通過派生類的對象無法直接訪問基類成員【與私有繼承一樣】 27 // cout<<b.y<<endl;
28 }

執行結果:

 

 

 理解:

保護繼承方式:

在類內部:

1、繼承的公有、保護成員以保護成員存在(存在方式與公有繼承的以公有成員存在方式不同),派生類的其它成員可以直接訪問 

     (這一點與公有、私有繼承一致)。【上面代碼18、19行】

       

在類外部:

1、通過派生類對象無法直接訪問繼承的公有、保護成員【上面代碼26、27行】(與私有繼承一樣)

       

在派生類內外部:基類的私有成員都無法直接訪問

 

!!!實踐上,在直接派生類中,保護繼承的訪問屬性和私有繼承是完全相同的
          但是如果派生類作為新的基類繼續派生時二者區別就出現了,我們用代碼理解 並 對比:
 
首先: 直接繼承時使用保護繼承:
代碼如下:
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A():x(10),y(20){}
 7     int getx(){return x;}
 8     int gety(){return y;}
 9     int getu(){return u;}
10 protected:
11     int y;
12 private:
13     int x;
14     int u;
15 };
16 class B:protected A{                   //直接繼承時 使用保護繼承  再看二次繼承的效果
17 public:
18     int getxx(){return getx();}
19     int getyy(){return y;}
20 };
21 //二次繼承無論是私有還是保護繼承,二次派生類都可以間接訪問初始基類A的公有、保護成員 22 //class C:private B{
23 //public:
24 //    int getA_x(){return getx();}
25 //    int getA_y(){return y;}
26 //};
27 class D:protected B{
28 public:
29     int getA_x(){return getx();}
30     int getA_y(){return y;}
31 };

 

再看:直接繼承時使用私有繼承

代碼如下:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A():x(10),y(20){}
 7     int getx(){return x;}
 8     int gety(){return y;}
 9     int getu(){return u;}
10 protected:
11     int y;
12 private:
13     int x;
14     int u;
15 };
16 class B2:private A{             //直接繼承時 使用私有繼承  再看二次繼承的效果
17 public:
18     int getc_x(){return getx();}
19     int getc_y(){return gety();}
20 };
21 //二次繼承無論時私有還是保護繼承,都無法間接使用初始基類A的成員
22 class C2:private B2{
23 public:
24 // int getA_x(){return getx();} //錯誤,無法間接訪問從初始基類A繼承的成員
25 };
26 class D2:protected B2{
27 public:
28 // int getA_x(){return getx();} //錯誤,無法間接訪問從初始基類A繼承的成員
29 };

 

上面兩塊代碼,我們主要看直接派生類 B&B2 的繼承方式  and   C&C2 、D&D2  能否調用初始基類A的成員

我們發現當直接派生類為私有繼承時,通過它在派生的類無法間接訪問最初基類成員,

而直接派生類為保護繼承時,再通過它派生的成員則可以間接訪問最初基類的公有、保護成員。

 


===============================================================================================================

以上為現階段學習理解,如有錯誤,希望指正:)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM