1. 程式人生 > >C++學習筆記——繼承與派生

C++學習筆記——繼承與派生

繼承與派生是同一過程從不同角度的描述:

  • 保持已有類的特性而構造新類的過程稱為繼承。
  • 在已有類的基礎上新增自己的特性而產生新類的過程稱為派生

被繼承的已有類稱為基類(或父類)。

派生出的新類稱為派生類(或子類)。

直接參與派生出某類的基類稱為直接基類

基類的基類甚至更高層的基類稱為間接基類

繼承的目的:實現設計與程式碼的重用。

派生的目的:當新的問題出現,原有程式無法解決(或不能完全解決)時,需要多原有程式進行改造。

單繼承時派生類的定義:

class 派生類名:繼承方式 基類名
{
    成員宣告;
}

//例子
class Derived:public Base
{
public:
    Derived();
    ~Derived();
}

多繼承時派生類的定義:

!!!每一個“繼承方式”,只用於限制對緊隨其後的基類的繼承

class 派生類名:繼承方式1 基類名1, 繼承方式2 基類名2,...
{
    成員宣告;
}

//例子
class Derived:public Base1, private Base2
{
public:
    Derived();
    ~Derived();
}

派生類的構成:

  • 吸收基類成員
    • 預設情況下派生類包含了全部基類中除構造和解構函式之外的所有成員。
  • 改造基類成員
    • 如果派生類宣告一個和某基類成員同名的新成員,派生的新成員就隱藏或覆蓋了外層同名成員。
  • 新增新的成員

不同繼承方式的影響主要體現在:

  • 派生類成員對基類成員的訪問許可權;
  • 通過派生類物件對基類成員的訪問許可權

三種繼承方式

  • 公有繼承(public)
    • 繼承的訪問控制
      • 基類的public和protected成員:訪問屬性在派生類保持不變;
      • 基類的private成員:不可直接訪問。
    • 訪問許可權
      • 派生類中的成員函式:可以直接訪問基類中的public和protected成員,但不能直接訪問基類的private成員;
      • 通過派生類的物件:只能訪問public成員。
  • 私有繼承(private)
    • 繼承的訪問控制
      • 基類的public和protected成員:都以private身份出現在派生類中;
      • 基類的private成員:不可直接訪問。
    • 訪問許可權
      • 派生類的成員函式:可以直接訪問基類中的public和protected成員,但不能直接訪問基類的private成員;
      • 通過派生類的物件:不能直接訪問從基類繼承的任何成員。
  • 保護繼承(protected)
    • 繼承的訪問控制
      • 基類的public和protected成員:都以protected身份出現在派生類中;
      • 基類的private成員:不可直接訪問。
    • 訪問許可權
      • 派生類中的成員函式:可以直接訪問基類中的public和protected成員,但不能直接訪問基類的private成員;
      • 通過派生類的物件:不能直接訪問從基類繼承過來的任何成員。

protected成員的特點與作用

  • 對建立其所在類物件的模組來說,它與private成員的性質相同。
  • 對於其派生類來說,它與public成員的性質相同。
  • 即實現了資料隱藏,又方便繼承,實現程式碼重用。

型別轉換

  • 公有派生類物件可以被當作基類的物件使用,反之則不可。
    • 派生類的物件可以隱含轉換為基類物件;
    • 派生類的物件可以初始化基類的引用;
    • 派生類的指標可以隱含轉化為基類的指標。
  • 通過基類物件名、指標只能使用從基類繼承的成員。

派生類的建構函式

  • 預設情況下,基類的建構函式不被繼承,派生類需要定義自己的建構函式。
  • C++11規定:可用using語句繼承基類建構函式,但只能初始化從基類繼承的成員。語法形式:using B::B;

如果不繼承基類的建構函式

  • 派生類新增成員:派生類定義建構函式初始化;
  • 繼承來的成員:自動呼叫基類建構函式進行初始化;
  • 派生類的建構函式需要給基類的建構函式傳遞引數。

單繼承時建構函式的定義語法:

派生類名::派生類名(基類所需的形參, 本類成員所需的形參):
    基類名(引數表),本類成員初始化列表
{
    //其他初始化;}

多繼承時建構函式的定義語法:

派生類::派生類名(引數表)
    基類名1(基類1初始化引數表),
    基類名2(基類2初始化引數表),
    ...
    基類名n(基類n初始化引數表),
    本類成員初始化列表
{
    //其他初始化;
}

派生類與基類的建構函式

  • 當基類有預設建構函式時
    • 派生類建構函式可以不向基類建構函式傳遞引數。
    • 構造派生類物件時,基類的預設建構函式將被呼叫。
  • 如需執行基類中帶引數的建構函式
    • 派生類建構函式應為基類建構函式提供引數。

多繼承且有物件成員時派生的建構函式定義語法:

派生類名:派生類名(形參表):
    基類名1(引數),基類名2(引數),...,基類名n(引數),
    本類成員(含物件成員) 初始化列表
{
    //其他初始化
};

建構函式的執行順序

  • 呼叫基類建構函式。
    • 順序按照它們被繼承時宣告的順序(從左向右)。
  • 對初始化列表中的成員進行初始化。
    • 順序按照它們在類中定義的順序。
    • 物件成員初始化時自動呼叫其所屬類的建構函式。(由初始化列表提供引數)
  • 執行派生類的建構函式體中的內容。