面向对象三大特性之一:继承(C++)
目錄
繼承的定義
基類對象和派生類對象的賦值轉換
繼承中的作用域
派生類與基類中成員的關系
派生類與默認成員函數的關系
繼承與友元的關系
繼承與靜態成員的關系
面向對象的三大特性:封裝,繼承,多態。
繼承作為三大特性之一,是使代碼可以復用的最重要的手段,它允許程序員在保持原有類特性的基礎上進行擴展,增加功能。繼承呈現了面向對象程序設計的層次結構,繼承是類設計層次的復用。
繼承的定義
格式的定義:
//A類為基類 class A{ public:int a; };// B 繼承于 A class B : public A { public:int b; };class B : public A 這句中? :其中B類為派生類,也叫子類;A類為基類,也叫父類;public為繼承方式。
注意:繼承后父類(A類)的成員(成員函數+成員變量)都會變成子類(B類)的一部分,B類也有自己的數據和方法。這里體現出了B類復用了A類的成員。B類對象可以訪問到這些數據和方法,但也要有權限問題。
舉個例子:
//Person類為基類 class Person{ public:string name;int age;void Print(){cout << name << " " << age << endl;} };//Student類繼承了Person class Student : public Person{ private:int stuid: // 學號 };//Teacher類繼承了Person class Teacher : public Person{ private:int jobid;//教師職工號 };Student類和Teacher類繼承Person類,這兩個類繼承了Person類中的數據 ( name和age ) 和方法 ( Print() ) 。
通過復用,兩個派生類都可以使用基類的數據和方法,不用再寫聲明相同的數據和方法,節省了代碼量。
?
上面提到了繼承的方式為public,其實還有private繼承方式和protected繼承方式。
下圖為繼承方式和訪問限定符的關系圖:
總結如下:
1、基類private成員在派生類中是不可見的。不可見是指基類的私有成員還是被繼承到了派生類對象中,但是語法上限制派生類對象不管在類里還是類外都不能去訪問它。?
2、若基類成員不想在類外直接被訪問,但想要在派生類中訪問,就定義為protected。protected限定符是因繼承才出現的。
3、class中默認為private繼承,struct中默認為public繼承。但最好顯示的寫出繼承方式。
4、public繼承最為常用,private/protected繼承只能在類中訪問,作用不大。在實際運用中一般使用都是public繼承,幾乎很少使用protetced/private繼承,也不提倡使用protetced/private繼承。這也是C++面向對象的較坑的一點。
?
基類對象和派生類對象的賦值轉換
基類與派生類之間的賦值轉換只能發生在公有繼承中。
1、派生類賦值給基類
派生類對象可以賦值給 基類的對象/基類的指針/基類的引用。
這個行為我們可以把它叫做 切片,意思就是把派生類中基類的那部分切分開賦值給基類。如下圖所示
class A { public:int a;int b;int c; };class B : public A { public:int d = 4; //B中繼承了A的a b c };int main() {B b;b.a = 1;b.b = 2;b.c = 3;//下面的過程叫切片//子類對象可以賦值給父類對象/指針/引用A a1 = b; A* a2 = &b; A& a3 = b; // 注意a3不是b的別名,而是其中父類部分的別名//a對象中的成員變量a b c分別等于1 2 3 return 0; }對象間的賦值,是將派生類從基類繼承來的數據復制一份給基類對象。
指針間的賦值,是將基類的指針指向派生類的對象,但所指的范圍只包括基類的數據。
引用間的賦值,引用在底層也是一個指針,所以原理指針賦值的原理基本相同。
2、基類 無法 賦值給派生類
b = a; //這是錯的3、基類的指針可以通過強制類型轉換賦值給派生類的指針
基類的指針必須是指向派生類對象地址才是安全的。
//a:基類 b:派生類 A *a = &b; B *b1 = (B*)a; //這樣可以 //a:基類 b:派生類 A a1 = b //切片 A *a2 = &a1; B *b1 = (B*)a2; //這種情況轉換時雖然可以,但會存在越界訪問的問題。//只能訪問到基類的數據,無法訪問派生類數據,是亂碼。?
繼承中的作用域
- 繼承體系中,基類和派生類都有自己獨立的作用域。
- 若子類和父類中有同名的成員,子類成員將屏蔽對父類中同名的成員的直接訪問,這種行為叫隱藏,也叫重定義。若想訪問父類同名成員,則要使用? 基類::基類成員 的格式顯示訪問。
- 若是成員函數的隱藏,只需讓函數名相同就可以。
- 但在繼承體系中,最好不要定義同名的成員。
?
派生類與基類中成員的關系
派生類與默認成員函數的關系
- 派生類的構造函數調用基類的構造函數來初始化繼承字基類中的數據。如果基類中沒有默認的構造函數,就在派生類構造的初始化列表階段進行顯示的調用。
- 派生類對象初始化先調用基類構造再調派生類構造。
- 派生類對象析構清理先調用派生類析構再調基類的析構。派生類的析構與基類的析構構成了隱藏(由于繼承中多態的原因),析構函數不顯示調用,由編譯器自己調用。
- 派生類的拷貝構造調用基類的拷貝構造完成對基類數據的拷貝。
- 派生類的operator=調用基類的operator=完成對基類數據的賦值。
?
繼承與友元的關系
友元關系不能繼承(基類友元不能訪問子類私有和保護成員)
繼承與靜態成員的關系
- 基類定義了static靜態成員,則整個繼承體系里面只有一個這樣的成員。無論派生出多少個子類,都只有一 個static成員實例。
- 所有子類對靜態成員的操作都只是在同一個靜態成員之上。
?
?
總結
以上是生活随笔為你收集整理的面向对象三大特性之一:继承(C++)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ 中的 IO流
- 下一篇: s3c2440移植MQTT