# 继承的基本语法

URL: https://caijiao.org/cpp/oop/inheritance
Source: docs/cpp/oop/inheritance.md
Description: 本节介绍 C++ 中继承的基本语法。继承是面向对象编程的重要特性之一，它允许一个类继承另一个类的属性和方法，从而实现代码的复用和扩展。

在 C++ 中，继承是面向对象编程的核心特性之一。通过继承，一个类可以继承另一个类的属性和方法，从而实现代码的复用和扩展。继承的基本语法包括类的声明、继承方式（公有继承、私有继承、保护继承）等。

## 基本语法

继承的基本语法如下：

```cpp
class DerivedClass : accessSpecifier BaseClass {
    // DerivedClass 特有成员和方法
};
````

* **`DerivedClass`**：派生类，继承自基类 `BaseClass`。
* **`BaseClass`**：基类，提供公共的属性和方法供派生类使用。
* **`accessSpecifier`**：继承的访问控制类型，决定基类成员在派生类中的访问权限，通常是 `public`、`private` 或 `protected`。

## 继承方式

在 C++ 中，继承的访问控制类型决定了派生类对基类成员的访问权限，常见的继承方式有三种：

1. **公有继承 (`public`)**：派生类可以访问基类的公有和保护成员，但不能访问基类的私有成员。派生类的公有成员保持不变，保护成员保持不变。
2. **私有继承 (`private`)**：派生类将基类的公有和保护成员都变为私有成员。外部无法访问派生类的基类成员，但派生类内部仍可以访问。
3. **保护继承 (`protected`)**：派生类将基类的公有和保护成员变为保护成员。外部无法访问派生类的基类成员，只有派生类及其子类可以访问。

## 示例：公有继承

```cpp
#include <iostream>
using namespace std;

class Animal {
public:
    void speak() {
        cout << "Animal speaks" << endl;
    }
};

class Dog : public Animal {  // 公有继承
public:
    void bark() {
        cout << "Dog barks" << endl;
    }
};

int main() {
    Dog dog;
    dog.speak();  // 派生类可以访问基类的公有成员
    dog.bark();   // 派生类可以访问自己的成员
    return 0;
}
```

### 输出：

```
Animal speaks
Dog barks
```

在这个例子中，`Dog` 类通过公有继承继承了 `Animal` 类的 `speak()` 方法，因此 `Dog` 类的对象可以访问 `Animal` 类的 `speak()` 方法。

## 示例：私有继承

```cpp
#include <iostream>
using namespace std;

class Animal {
public:
    void speak() {
        cout << "Animal speaks" << endl;
    }
};

class Dog : private Animal {  // 私有继承
public:
    void bark() {
        cout << "Dog barks" << endl;
    }

    void speakDog() {
        speak();  // 派生类内部可以访问基类的公有成员
    }
};

int main() {
    Dog dog;
    dog.bark();  // 访问派生类成员
    dog.speakDog();  // 通过派生类的成员函数访问基类的成员
    // dog.speak();  // 错误：外部无法访问基类的成员
    return 0;
}
```

### 输出：

```
Dog barks
Animal speaks
```

在私有继承中，`Dog` 类的对象无法直接访问基类的 `speak()` 方法，因为基类的公有成员变成了派生类的私有成员。但派生类内部仍然能够访问基类的成员。

## 示例：保护继承

```cpp
#include <iostream>
using namespace std;

class Animal {
public:
    void speak() {
        cout << "Animal speaks" << endl;
    }
};

class Dog : protected Animal {  // 保护继承
public:
    void bark() {
        cout << "Dog barks" << endl;
    }

    void speakDog() {
        speak();  // 派生类内部可以访问基类的公有成员
    }
};

int main() {
    Dog dog;
    dog.bark();  // 访问派生类成员
    dog.speakDog();  // 通过派生类的成员函数访问基类的成员
    // dog.speak();  // 错误：外部无法访问基类的成员
    return 0;
}
```

### 输出：

```
Dog barks
Animal speaks
```

在保护继承中，`Dog` 类的对象无法直接访问基类的 `speak()` 方法，但派生类内部可以访问。

## 继承中的构造函数和析构函数

在继承中，派生类对象的创建顺序是先调用基类的构造函数，然后调用派生类的构造函数；析构函数的调用顺序是先调用派生类的析构函数，再调用基类的析构函数。

### 示例：构造函数和析构函数的顺序

```cpp
#include <iostream>
using namespace std;

class Base {
public:
    Base() {
        cout << "Base class constructor" << endl;
    }

    ~Base() {
        cout << "Base class destructor" << endl;
    }
};

class Derived : public Base {
public:
    Derived() {
        cout << "Derived class constructor" << endl;
    }

    ~Derived() {
        cout << "Derived class destructor" << endl;
    }
};

int main() {
    Derived derivedObj;
    return 0;
}
```

### 输出：

```
Base class constructor
Derived class constructor
Derived class destructor
Base class destructor
```

从输出可以看出，先调用基类的构造函数，再调用派生类的构造函数；先调用派生类的析构函数，再调用基类的析构函数。

## 总结

* 继承是面向对象编程的重要特性，C++ 中的继承可以通过 `public`、`private` 或 `protected` 关键字来指定继承方式。
* 公有继承允许派生类访问基类的公有成员，私有继承和保护继承则限制了外部对基类成员的访问。
* 继承不仅涉及成员的继承，还影响构造函数和析构函数的调用顺序。
