繼承 (僅限 C++)

繼承 是重複使用及延伸現有類別而不修改它們的機制,因此會在它們之間產生階層式關係。

繼承幾乎就像將物件內嵌在類別中。 假設您在 B的類別定義中宣告類別 A 的物件 x 。 因此,類別 B 將有權存取類別 A的所有公用資料成員及成員函數。 不過,在類別 B中,您必須透過物件 x存取類別 A 的資料成員及成員函數。 下列範例示範:
#include <iostream>
using namespace std;

class A {
   int data;
public:
   void f(int arg) { data = arg; }
   int g() { return data; }
};

class B {
public:
   A x;
};

int main() {
   B obj;
   obj.x.f(20);
   cout << obj.x.g() << endl;
//   cout << obj.g() << endl;
}
在 main 函數中,物件透過其資料成員 B::x 使用陳述式 obj.x.f(20) obj 存取函數 A::f() 。 物件 obj 會以與陳述式 obj.x.g()類似的方式存取 A::g() 。 編譯器不容許陳述式 obj.g() ,因為 g() 是類別 A而非類別 B的成員函數。

繼承機制可讓您在上述範例中使用類似 obj.g() 的陳述式。 為了使該陳述式合法, g() 必須是 B類別的成員函數。

繼承可讓您併入另一個類別成員的名稱和定義作為新類別的一部分。 您要將其成員併入新類別的類別稱為 基礎類別。 您的新類別是從基礎類別 衍生 。 新類別包含基礎類別類型的 子物件 。 下列範例與前一個範例相同,不同之處在於它使用繼承機制,將類別 B 存取權提供給類別 A的成員:
#include <iostream>
using namespace std;

class A {
   int data;
public:
   void f(int arg) { data = arg; }
   int g() { return data; }
};

class B : public A { };

int main() {
   B obj;
   obj.f(20);
   cout << obj.g() << endl;
}
類別 A 是類別 B的基礎類別。 類別 A 的成員名稱及定義包含在類別 B的定義中; 類別 B 會繼承類別 A的成員。 類別 B 衍生自類別 A。 類別 B 包含 A類型的子物件。

您也可以將新的資料成員及成員函數新增至衍生類別。 您可以置換新衍生類別中的基礎類別成員函數或資料,以修改現有成員函數或資料的實作。

您可以從其他衍生類別衍生類別,從而建立另一個繼承層次。 下列範例示範:
struct A { };
struct B : A { };
struct C : B { };
類別 BA的衍生類別,但也是 C的基礎類別。 繼承的層次數目僅受資源限制。

多重繼承 可讓您建立從多個基礎類別繼承內容的衍生類別。 由於衍生類別會繼承其所有基礎類別的成員,因此可能會產生不明確。 例如,如果兩個基礎類別具有同名的成員,則衍生類別無法隱含地區分兩個成員。 請注意,當您使用多重繼承時,對基礎類別名稱的存取權可能不明確。 如需詳細資訊,請參閱 多重繼承 (僅限 C++)

直接基礎類別 是在其衍生類別的宣告中直接顯示為基本指定元的基礎類別。

間接基礎類別 是一種基礎類別,不會直接出現在衍生類別的宣告中,但可透過其其中一個基礎類別供衍生類別使用。 對於給定類別,非直接基礎類別的所有基礎類別都是間接基礎類別。 下列範例示範直接及間接基礎類別:
class A {
  public:
    int x;
};
class B : public A {
  public:
    int y;
};
class C : public B { };

類別 BC的直接基礎類別。 類別 AB的直接基礎類別。 類別 AC的間接基礎類別。 (類別 Cxy 作為其資料成員。)

多型函數 是可套用至多種類型物件的函數。 在 C++ 中,多型函式有兩種實現方式:
  • 在編譯時期會靜態連結超載函數。
  • C++ 提供虛擬函數。 虛擬函數 是可以針對透過衍生相關的許多不同使用者定義類型呼叫的函數。 在執行時期會動態連結虛擬函數。 它們在 虛擬函數 (僅限 C++)中有更詳細的說明。