繼承

類/結構可以具有繼承關係。

如果類/ struct B 繼承自類/ struct A,這意味著 B 具有父 A。我們說 BA 的派生類/結構,A 是基類/結構。

struct A
{
public:
    int p1;
protected:
    int p2;
private:
    int p3;
};

//Make B inherit publicly (default) from A
struct B : A
{
};

類/結構有 3 種形式的繼承:

  • public
  • private
  • protected

請注意,預設繼承與成員的預設可見性相同:public(如果使用 struct 關鍵字)和 privateclass 關鍵字)。

甚至可能有一個 class 來自 struct(反之亦然)。在這種情況下,預設繼承由子控制,因此從 class 派生的 struct 將預設為公共繼承,而從 struct 派生的 class 將預設具有私有繼承。

public 繼承:

struct B : public A // or just `struct B : A`
{
    void foo()
    {
        p1 = 0; //well formed, p1 is public in B
        p2 = 0; //well formed, p2 is protected in B
        p3 = 0; //ill formed, p3 is private in A
    }
};

B b;
b.p1 = 1; //well formed, p1 is public
b.p2 = 1; //ill formed, p2 is protected
b.p3 = 1; //ill formed, p3 is inaccessible

private 繼承:

struct B : private A
{
    void foo()
    {
        p1 = 0; //well formed, p1 is private in B
        p2 = 0; //well formed, p2 is private in B
        p3 = 0; //ill formed, p3 is private in A
    }
};

B b;
b.p1 = 1; //ill formed, p1 is private
b.p2 = 1; //ill formed, p2 is private
b.p3 = 1; //ill formed, p3 is inaccessible

protected 繼承:

struct B : protected A
{
    void foo()
    {
        p1 = 0; //well formed, p1 is protected in B
        p2 = 0; //well formed, p2 is protected in B
        p3 = 0; //ill formed, p3 is private in A
    }
};

B b;
b.p1 = 1; //ill formed, p1 is protected
b.p2 = 1; //ill formed, p2 is protected
b.p3 = 1; //ill formed, p3 is inaccessible

請注意,雖然允許 protected 繼承,但實際使用它很少。如何在應用程式中使用 protected 繼承的一個例項是部分基類專門化(通常稱為受控多型)。

當 OOP 相對較新時,(公共)繼承經常被稱為模擬“IS-A”關係。也就是說,只有派生類例項也是基類例項時,公共繼承才是正確的。

這後來被改進為 Liskov 替換原則 :只有當/在任何可能的情況下(並且仍然有意義)派生類的例項可以替換基類的例項時,才應該使用公共繼承。

私人繼承通常被認為體現了完全不同的關係:是根據實現的(有時稱為“HAS-A”關係)。例如,Stack 類可以從 Vector 類私下繼承。私有繼承與聚合的相似性大於公共繼承。

受保護的繼承幾乎從未使用過,並且對它所體現的關係型別沒有普遍的一致意見。