繼承
類/結構可以具有繼承關係。
如果類/ struct B
繼承自類/ struct A
,這意味著 B
具有父 A
。我們說 B
是 A
的派生類/結構,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
關鍵字)和 private
(class
關鍵字)。
甚至可能有一個 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
類私下繼承。私有繼承與聚合的相似性大於公共繼承。
受保護的繼承幾乎從未使用過,並且對它所體現的關係型別沒有普遍的一致意見。