C++學習-繼承中的範圍(10)

來源:互聯網
上載者:User

作者:gzshun. 原創作品,轉載請標明出處!
來源:http://blog.csdn.net/gzshun

在繼承過程中,從基類派生出衍生類別,可能出現重名的成員,包括資料成員或成員函數,這些屬於範圍方面的內容。

一、基類的引用或指標訪問衍生類別

基類的引用或指標只能訪問衍生類別中屬於基類的部分成員,不能訪問衍生類別的部分,否則就會編譯出錯。

 

[cpp] view plaincopy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class CBase  
  6. {  
  7. public:  
  8.     void BasePrint() const  
  9.     {  
  10.         cout << "調用基類的成員函數" << endl;  
  11.     }  
  12. };  
  13.   
  14. class CDerived : public CBase  
  15. {  
  16. public:  
  17.     void DerivedPrint() const  
  18.     {  
  19.         cout << "調用衍生類別的成員函數" << endl;  
  20.     }  
  21. };  
  22.   
  23. int main()  
  24. {  
  25.     CDerived obj;  
  26.     CBase *bObj = &obj;  
  27.     CDerived * dObj = &obj;  
  28.   
  29.     bObj->BasePrint();  
  30. //    bObj->DerivedPrint();//錯誤,基類指標不能調用衍生類別的部分  
  31.     dObj->BasePrint();  
  32.     dObj->DerivedPrint();  
  33.     return 0;  
  34. }  

執行結果:

調用基類的成員函數
調用基類的成員函數
調用衍生類別的成員函數


二、重複的資料成員
有時基類和衍生類別有同名的資料成員,甚至可能在基類和間接基類中都有同名的資料成員。
這種情況一般會出現在:從 由另一個程式員建立的基類中派生自己的類,可能不知道在基類中有什麼私人資料成員,此時自己又建立了與基類當中同名的資料成員。
當然這種情況是不會阻礙繼承的,編譯器做了很多的工作。但這裡主要是介紹如何從衍生類別中調用衍生類別的同名私人成員或者基類的私人成員。
例子:
CBase是CDerived的父類,它們擁有一個同名成員為mVal。
在衍生類別中
1.預設是訪問自己的資料成員mVal;
2.若要訪問基類的mVal,要用這種格式"<類名>::<資料成員>", CBase::mVal

 

[cpp] view plaincopy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class CBase  
  6. {  
  7. public:  
  8.     CBase(int x = 120) : mVal(x) {}  
  9.     int mVal;  
  10. };  
  11.   
  12. class CDerived : public CBase  
  13. {  
  14. public:  
  15.     CDerived(int x = 100) : mVal(x) {}  
  16.     void PrintValue() const  
  17.     {  
  18.         cout << "犀利爹的年齡:" << CBase::mVal << endl  
  19.              << "犀利哥的年齡:" << mVal << endl;  
  20.     }  
  21.     int mVal;  
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     CDerived human;  
  27.     human.PrintValue();  
  28.     return 0;  
  29. }  

執行結果:

犀利爹的年齡:120
犀利哥的年齡:100

三、重複的成員函數
基類與衍生類別若存在重複的成員函數,則有2種情況:
第一種情況:函數名相同,參數列表不同,如果將基類的成員函數的範圍引入衍生類別中,就是重載版本了
第二種情況:函數的所有方面都相同,包括函數名,參數列表與傳回值

第一種情況:
函數名相同,參數列表不同,這跟函數的重載一樣。但這並不是函數的重載,因為函數的重載必須在同一個範圍中定義,而基類和衍生類別定義了不同的範圍。在這裡,可以使用using在衍生類別中聲明基類的函數,將基類的函數的範圍引入衍生類別中的範圍,讓這裡的函數成為重載版本,來個小例子。

 

[cpp] view plaincopy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class CBase  
  6. {  
  7. public:  
  8.     void Print(const char *str)  
  9.     {  
  10.         cout << "調用基類的列印函數: str = " << str << endl;  
  11.     }  
  12. };  
  13.   
  14. class CDerived : public CBase  
  15. {  
  16. public:  
  17.     using CBase::Print;  
  18.     void Print(int val)  
  19.     {  
  20.         cout << "調用衍生類別的列印函數: val = " << val << endl;  
  21.     }  
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     CDerived obj;  
  27.     obj.Print(2);  
  28.     obj.Print("hello");  
  29.     return 0;  
  30. }  

執行結果:

調用衍生類別的列印函數: val = 2
調用基類的列印函數: str = hello

這裡如果沒有"using CBase::Print;"的聲明,那麼將會編譯錯誤。

第二種情況:
函數的所有方面都相同,包括函數名,參數列表與傳回值,在衍生類別中,要調用基類的同名成員函數,方法跟同名資料成員的方法一樣,格式是:"<類名>::<成員函數>"。

 

[cpp] view plaincopy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class CBase  
  6. {  
  7. public:  
  8.     void Print()  
  9.     {  
  10.         cout << "調用基類的成員函數" << endl;  
  11.     }  
  12. };  
  13.   
  14. class CDerived : public CBase  
  15. {  
  16. public:  
  17.     void Print()  
  18.     {  
  19.         cout << "調用衍生類別的成員函數" << endl;  
  20.     }  
  21. };  
  22.   
  23. int main()  
  24. {  
  25.     CDerived human;  
  26.     human.Print();  
  27.     human.CBase::Print();  
  28.     return 0;  
  29. }  

執行結果:

調用衍生類別的成員函數
調用基類的成員函數

四、虛函數的範圍
關於虛函數的內容,就會涉及到動態綁定的知識了,這裡先不介紹,主要還是說明類繼承的範圍的問題。在類的繼承過程中,基類中的成員函數是不是虛函數,將會起著非常大的作用,先來看2個虛函數的例子。
1.在基類中沒有使用virtual關鍵字

 

[cpp] view plaincopy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class CBase  
  6. {  
  7. public:  
  8.     void Print() const  
  9.     {  
  10.         cout << "調用CBase::Print()" << endl;  
  11.     }  
  12. };  
  13.   
  14. class CDerived1 : public CBase  
  15. {  
  16. public:  
  17.     void Print() const  
  18.     {  
  19.         cout << "調用CDerived1::Print()" << endl;  
  20.     }  
  21. };  
  22.   
  23. class CDerived2 : public CDerived1  
  24. {  
  25. public:  
  26.     void Print() const  
  27.     {  
  28.         cout << "調用CDerived2::Print()" << endl;  
  29.     }  
  30. };  
  31.   
  32. int main()  
  33. {  
  34.     CBase bobj;  
  35.     CDerived1 d1obj;  
  36.     CDerived2 d2obj;  
  37.     CBase *bp1 = &bobj;  
  38.     CBase *bp2 = &d1obj;  
  39.     CBase *bp3 = &d2obj;  
  40.     bp1->Print();  
  41.     bp2->Print();  
  42.     bp3->Print();  
  43.     return 0;  
  44. }  

執行結果:

調用CBase::Print()
調用CBase::Print()
調用CBase::Print()

2.在基類中使用virtual關鍵字

 

[cpp] view plaincopy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. class CBase  
  6. {  
  7. public:  
  8.     virtual void Print() const  
  9.     {  
  10.         cout << "調用CBase::Print()" << endl;  
  11.     }  
  12. };  
  13.   
  14. class CDerived1 : public CBase  
  15. {  
  16. public:  
  17.     void Print() const  
  18.     {  
  19.         cout << "調用CDerived1::Print()" << endl;  
  20.     }  
  21. };  
  22.   
  23. class CDerived2 : public CDerived1  
  24. {  
  25. public:  
  26.     void Print() const  
  27.     {  
  28.         cout << "調用CDerived2::Print()" << endl;  
  29.     }  
  30. };  
  31.   
  32. int main()  
  33. {  
  34.     CBase bobj;  
  35.     CDerived1 d1obj;  
  36.     CDerived2 d2obj;  
  37.     CBase *bp1 = &bobj;  
  38.     CBase *bp2 = &d1obj;  
  39.     CBase *bp3 = &d2obj;  
  40.     bp1->Print();  
  41.     bp2->Print();  
  42.     bp3->Print();  
  43.     return 0;  
  44. }  

執行結果:

調用CBase::Print()
調用CDerived1::Print()
調用CDerived2::Print()

1,2兩個例子可以看到,一個virtual的關鍵字起著這麼大的作用。當基類的成員函數使用virtual關鍵字修飾的話,基類指標會根據指向的對象的實際類型來尋找相應的類的成員函數的定義。要獲得動態綁定,必須通過基類的引用或指標調用虛成員。
在第二個例子中,將Print函式宣告為虛函數,這樣子編譯器會產生代碼,在運行時基於引用或指標所綁定的對象的實際類型進行調用。bp2指向CDerived1對象,bp3指向CDerived2對象,所以都是調用屬於自己的Print函數版本。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.