继承

类/结构可以具有继承关系。

如果类/ 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 类私下继承。私有继承与聚合的相似性大于公共继承。

受保护的继承几乎从未使用过,并且对它所体现的关系类型没有普遍的一致意见。