C++第五章(類的繼承派生)上篇
什麼是繼承?為什麼要有繼承?怎麼繼承?
當我們定義一個類後,
class Student { public : void display() { cout << "num : " << num << endl; cout << "name : " << name << endl; cout << "sex : " << sex << endl; } private : int num; string name; char sex; }
如果學校的某一部門除了需要用到學號,姓名,性別以外,還需要用到年齡,地址等資訊
我們可以重新聲名一個類class Student1
class Student1 { public : void display() { cout << "num : " << num << endl; //重複 cout << "name : " << name << endl; //重複 cout << "sex : " << sex << endl; //重複 cout << "age : " << age << endl; cout << "addr : " << addr << endl; } private : int num; //重複 string name; //重複 char sex; //重複 int age; string addr; }
這時我們定義的很多程式碼 在剛剛我們定義的Student類中 已經定義過了,這時就有一些聰明的小機靈鬼想到,我們是否能夠利用原來宣告的類Student 作為基礎,再加上新的內容即可,減少沒有必要的重複操作。
而我們要學習得繼承就是為了解決這個問題。
以馬為例,“公馬”繼承類全部馬的特徵,再加上雄性的新特徵,“白公馬”又繼承了“公馬”的全部特徵,又加了顏色的特性。公馬是馬派生出來的一個分支,白公馬是公馬派生出來的一個分支。
繼承:就是再一個已存在的類的基礎上建立一個新的類。
基類(Base class),父類(Father class),繼承他們的特性的類叫,派生類(Derived)或子類(Son class)
單繼承:一個派生類只從一個基類派生
多繼承:一個派生類可以從多個基類派生。
一。派生類的聲名方式
class Student1 : public Student //共有繼承 聲名基類是Student
{
public :
void display_1()
{
cout << "age : " << age << endl;
cout << "addr : " << addr << endl;
}
private :
int age; //新增成員函式
string addr; //新增成員函式
}
class 派生類名:【繼承方式】 基類名
{
派生類新增成員。
}
繼承方式有 public (共有) ,private (私有),protected(保護).
二。派生類的構成
(1)從基類接受所有成員,不能只要一部分,但是無法繼承friend函式和建構函式解構函式,new生成的成員。
缺點,有些基類的成員在派生類中是用不到的,但是也必須繼承,這就造成了資料冗餘。
(2)調整從基類接收的成員。就是改變基類成員在派生類中的訪問屬性(通過繼承方式決定)。還可以再派生類中宣告一個與基類成員同名的成員,則派生類中的新成員會覆蓋基類的同名成員,但是應該注意,如果是成員函式,不僅應使函式名相同,而函式的引數表(引數的個數和型別)也應相同。如果不相同就變成的函式過載了,而不是函式的覆蓋。
三。派生類的成員的訪問屬性
共有繼承
公用類在派生類中的訪問屬性 | ||
---|---|---|
在基類中的訪問屬性 | 繼承方式 | 在派生類中的訪問屬性 |
private | public | 不可訪問 |
public | public | public |
protected | public | protected |
派生類無法直接呼叫基類中的私有成員,但是可以通過基類中的public函式或 protected函式來訪問基類中的私有成員
私有繼承
私有基類在派生類中的訪問屬性 | ||
---|---|---|
在基類的訪問屬性 | 繼承方式 | 在派生類中的訪問屬性 |
private | private | 不可訪問 |
public | private | private |
protected | private | private |
既然聲名為私有繼承就表示,將原來能被外界訪問的成員隱藏起來,基類的private還是不能訪問,還是隻能通過基類中的pubic 或 protected 來訪問,而基類中的protected 和 public 中的成員 變成了private 存在了 派生類內。類外就不能訪問了。
(1)不能通過派生類物件引用從私有基類繼承過來的任何成員
(2)派生類的成員函式不能訪問私有基類的私有成員,但是可以訪問私有基類的公有成員。
保護繼承
保護成員不能被類外引用,可以被派生類的成員函式引用。
前面將友元比喻成朋友,可以允許好朋友進入自己的臥室,而保護成員相當與保險箱,任何外人都不能窺視,只有子女才能開啟。
特點:保護基類的共有成員和保護成員在派生類中都成了保護成員,其私有成員仍為基類私有。
保護基類在派生類中的訪問屬性 | ||
基類中的訪問屬性 | 繼承方式 | 派生類中的訪問屬性 |
private | protected | 不可訪問 |
public | protected | protected |
protected | protected | protected |
比較一下私有繼承和保護繼承:
在直接派生類中,以上兩種繼承方式相同:在類外不能訪問任何成員而在派生類中可以通過成員函式訪問基類中的公用成員和保護成員。但是如果繼續派生,在新的派生類中兩種繼承方式的作用就不同了。例如,如果以公用的繼承方式派生出一個新派生類,原來私有基類中的成員在新的派生類中都成了不可訪問的成員,無論在派生類內還是在派生類內都不能訪問,而原來保護基類中的公用成員和保護成員在新派生類中為保護成員,可以被新派生類的成員函式訪問。
派生類中的4中訪問屬性:
(1)公用的,派生類內類外都可以訪問
(2)受保護的,派生類內可以訪問,派生類外不能訪問,其下一層的派生類可以訪問。
(3)私有的,派生類內可以訪問,派生類外不能訪問。
(4)不可訪問的,派生類內外都不能訪問。
派生類中的成員訪問屬性 | |||
---|---|---|---|
派生類中的訪問屬性 | 在派生類中 | 在派生類外 | 在下層派生類中 |
公用 | 可以 | 可以 | 可以 |
保護 | 可以 | 不可以 | 可以 |
私有 | 可以 | 不可以 | 不可以 |
不可訪問 | 不可以 | 不可以 | 不可以 |
然後我們總結一下,這個規律。
誰更厲害: private > protected >public
被繼承之後的許可權 : public > protected > private.
四。多級派生
這時就出現了 直接派生類和間接派生類,直接基類和間接基類。
多類繼承中常採用public
class A
{
public :
int i;
protected :
void f1();
int j;
private :
int k;
};
class B : public A
{
public :
void f2();
protected :
void f3();
private :
int m;
};
class C : protected B
{
public :
void f4();
private :
int n;
};
各成員在不同類中訪問屬性 | |||||||||
i | f1() | j | k | f2() | f3() | m | f4() | n | |
基類A | 公用 | 保護 | 保護 | 私有 | |||||
公用派生類B | 公用 | 保護 | 保護 | 不可訪問 | 公用 | 保護 | 私有 | ||
公用派生類C | 保護 | 保護 | 保護 | 不可訪問 | 保護 | 保護 | 不可訪問 | 公用 | 私有 |
無論哪一種繼承方式,在派生類中是不能訪問基類的私有成員的,私有成員只能被本類的成員函式所訪問,畢竟派生類與基類不是同一類。
如果在多級派生時都採用公用繼承的方式,那麼直到最後一級的派生類都能訪問基類的公用成員和保護成員。
如果是私有繼承方式,經過若干次派生後,基類的所有成員已經變成不可訪問的了。
如果採用保護繼承方式,在派生類外是無法訪問派生類中的任何成員。而且經過多次派生後人們很難記住那些成員可以訪問,哪些不可以訪問。
所以我們多級繼承時常用公用繼承。