C++ 继承

在本教程中,我们将借助示例了解 C++ 中的继承。

继承是 C++ 面向对象编程的关键特性之一。它允许我们从现有(基类)创建一个新类(派生类)。

派生类继承了基类的特性,并且可以拥有自己的附加特性。例如,

class Animal {
    // eat() 方法
    // sleep() 方法
};

class Dog : public Animal {
    // bark() 方法
};

在这里, Dog 类是从 Animal 类派生的。由于 Dog 派生自 AnimalDog 就继承了 Animal 的成员(方法和属性)。

Dog 类继承自 Animal 类
C++ 继承

请注意在 DogAnimal 继承时使用了 public 关键字。

class Dog : public Animal {...};

我们也可以使用关键字 privateprotected 代替 public 。我们将在本教程的后面学习 privatepublicprotected 之间的差异。

is-a 关系

继承是一种 is-a 关系。仅当两个类之间存在 is-a 关系时才使用继承。

这里有些例子:

  • 汽车是一种交通工具。
  • 橙子是一种水果。
  • 外科医生是医生。
  • 狗是一种动物。

示例 1:C++ 继承的简单示例

本程序演示了 C++ 中的继承。

#include <iostream>
using namespace std;

// 基类
class Animal {

   public:
    void eat() {
        cout << "I can eat!" << endl;
    }

    void sleep() {
        cout << "I can sleep!" << endl;
    }
};

// 子类
class Dog : public Animal {

   public:
    void bark() {
        cout << "I can bark! Woof woof!!" << endl;
    }
};

int main() {
    Dog dog1;

    // 调用基类中的方法
    dog1.eat();
    dog1.sleep();

    // 调用自己的方法
    dog1.bark();

    return 0;
}

输出

I can eat!
I can sleep!
I can bark! Woof woof!!

这里,dog1 可以访问基类 Animal 的成员。这是因为 Dog 继承自 Animal .

// Calling members of the Animal class
dog1.eat();
dog1.sleep();

C++ protected 成员

当涉及到 C++ 继承时,访问修饰符 protected 尤其重要。

private 成员一样, protected 成员在类之外是不可访问的。但是,它们可以被派生类友元类/函数访问

如果我们想隐藏类的数据,但仍然希望该数据被其派生类继承,我们就需要 protected 成员。

要了解有关 protected 的更多信息,请参阅我们的C++ 访问修饰符教程。

示例 2:C++ protected 成员

本程序演示了 C++ 继承中的受保护成员,演示了 protected 访问修饰符的用法。

#include <iostream>
#include <string>
using namespace std;

// base class
class Animal {

   private:
    string color;

   protected:
    string type;

   public:
    void eat() {
        cout << "I can eat!" << endl;
    }

    void sleep() {
        cout << "I can sleep!" << endl;
    }

    void setColor(string clr) {
        color = clr;
    }

    string getColor() {
        return color;
    }
};

// derived class
class Dog : public Animal {

   public:
    void setType(string tp) {
        type = tp;
    }

    void displayInfo(string c) {
        cout << "I am a " << type << endl;
        cout << "My color is " << c << endl;
    }

    void bark() {
        cout << "I can bark! Woof woof!!" << endl;
    }
};

int main() {
    // Create object of the Dog class
    Dog dog1;

    // Calling members of the base class
    dog1.eat();
    dog1.sleep();
    dog1.setColor("black");

    // Calling member of the derived class
    dog1.bark();
    dog1.setType("mammal");

    // Using getColor() of dog1 as argument
    // getColor() returns string data
    dog1.displayInfo(dog1.getColor());

    return 0;
}

输出

I can eat!
I can sleep!
I can bark! Woof woof!!
I am a mammal
My color is black

这里,变量 typeprotected ,因此可以从派生类 Dog 访问。我们可以看到这一点,因为我们已经使用函数在 Dog 类中的 setType() 方法中进行了 type 初始化。

另一方面,不能在 Dog 中使用 private 变量 color

class Dog : public Animal {

    public:
      void setColor(string clr) {
          // Error: member "Animal::color" is inaccessible
          color = clr;
      }
};

此外,由于 protected 关键字隐藏了数据,我们无法在外部直接访问来自 DogAnimal 类的 type

// Error: member "Animal::type" is inaccessible
dog1.type = "mammal";

C++ 继承中的访问模式

在我们之前的教程中,我们了解了 C++ 访问说明符,例如 publicprivateprotected

到目前为止,我们已经使用 public 关键字从先前存在的基类继承了一个类。但是,我们也可以使用 private and protected 关键字来继承类。例如,

class Animal {
    // code
};

class Dog : private Animal {
    // code
};
class Cat : protected Animal {
    // code
};

我们可以派生类的各种方式被称为访问模式。这些访问模式具有以下效果:

  1. public: 如果派生类是在 public 模式中声明的,那么基类的成员会被派生类继承。
  2. private: 在这种情况下,基类的所有成员都成为派生类的 private 成员。
  3. 保护: 在这种情况下,基类的 public 成员成为派生类的 protected 成员。

基类的private 成员在派生类中总是 private 的。

要了解更多信息,请访问我们的C++ 公共、私有、受保护的继承教程。

继承中的成员函数覆盖

假设基类和派生类具有相同名称和参数的成员函数。

如果我们创建了派生类的对象并尝试访问该成员函数,则会调用派生类中的成员函数而不是基类中的成员函数。

这种情况下,派生类的成员函数覆盖了基类的成员函数。

了解有关C++ 中函数覆盖的更多信息。