C++: 繼承和多型(一)三種繼承方式與許可權
繼承
在C++中,我們常要對某個函式進行多次複用,例如: 資訊管理系統中,對於教師、學生、教務人員等"類"而言,有部分資訊是通用的:姓名,性別,年齡,聯絡方式等。如果為每一種角色都編寫一個"類",會有不少重複的程式碼,造成效率上的浪費。
C++ 的“繼承”機制就能避免上述浪費,減少程式碼複用
- 在 C++ 中,從一個類派生出另一個類的寫法如下
class 派生類名: 繼承方式說明符 基類名{
...
};
繼承方式可以宣告為: protect (保護繼承),public(公有繼承),private(私有繼承)
- 派生類物件佔用的儲存空間大小,等於基類物件佔用的儲存空間大小加上派生類物件自身成員變數佔用的儲存空間大小。
class Base { int a; int b; }; class Derived :public Base { int c; }; int main() { cout<<"Base:"<<sizeof(Base)<<endl; // 8 cout<<"Derived"<<sizeof(Derived)<<endl; //12 system("pause"); return 0; }
Protected 保護繼承
引入:基類的成員本來就是派生類的成員,因此對於那些出於隱藏的目的不宜設為公有,但又確實需要在派生類的成員函式中經常訪問的基類成員,將它們設定為保護成員,既能起到隱藏的目的,又避免了派生類成員函式要訪問它們時只能間接訪問所帶來的麻煩。
許可權:能訪問成員的地方就能訪問公有成員
保護成員擴大的訪問範圍表現在:基類的保護成員可以在派生類的成員函式中被訪問。
class Student { public: char name[20]; int age; protected: int id; private: int sex; }; class Mstudent :public Student { void show() { name[20]='jack'; //可以訪問 age = 10; //可以訪問 id = 001;//可以訪問 sex = 0; //error: 不能訪問基類的私有成員 Student A; A.id //error ,A不是函式所作用的物件,不能訪問其保護成員 Mstudent B; B.id = 002; B.sex = 0; //error :不能訪問基類的私有成員 } }; int main() { Mstudent C; int n; n=C.age; // ok int m ; m=C.id ; //error 不在派生類成員函式內,不能訪問基類保護成員 system("pause"); return 0; }
注意以下三點:
- 在類的成員函式外部,不能訪問物件的私有成員和保護成員。
- 派生類的成員函式中不能訪問基類的私有成員。
- 派生類的成員函式中可以訪問基類的保護成員。
三種繼承方式的訪問許可權如下表
繼承方式 | 基類的訪問許可權 | 派生類的訪問許可權 | 外部的訪問許可權 |
public | public | public | Yes |
protected | protected | No | |
private | 不可訪問 | No | |
protected | public | public | No |
protected | protected | No | |
private | 不可訪問 | No | |
private | public | private | No |
protected | private | No | |
private | 不可訪問 | No |
基類的公有成員經過私有派生後,在派生類中變為私有成員。(以此類推)
不可訪問: 指的是類的成員函式內部也不能訪問的成員。
Base中的private成員,在Derived中的成員函式中不能訪問,但是它依然是派生類的成員。
C++派生類和賦值運算子
如果基類過載了賦值運算子
=
而派生類沒有,那麼在派生類物件之間賦值,或用派生類物件對基類物件進行賦值時,其中基類部分的賦值操作是呼叫被基類過載的=
完成的。
同名成員的訪問方式:
- 過載
在基類或者派生類同一個類作用域當中的
函式名相同,引數列表不同
- 隱藏
方法分佈在基類和派生類中
方法名字相同,就說派生類的同名方法把基類的同名方法給隱藏了
- 覆蓋
方法分佈在基類和派生類中
基類的方法是虛擬函式,派生類的方法和基類的虛擬函式,返回值相同,函式名相同,
引數列表也相同,那麼此時派生類的這個函式自動處理成虛擬函式,和基類的函式成為
覆蓋關係, 在虛擬函式表中進行覆蓋!<虛擬函式表以及虛擬函式在《C++ 繼承和多型(二)中有詳細講解》>
問題:
【1】如果不寫繼承方式,如何訪問?
- 取決於類的定義為struct / class struct 預設為公有繼承 class 預設為私有繼承
【2】派生類物件如何構造?
- 在派生類建構函式的初始化列表中,指定基類成員的構造方式