1. 继承的基本概念

继承是面向对象编程的核心特性之一,允许我们基于已有类创建新类,实现代码重用和建立类之间的层次关系。

基本语法

class 派生类名 : 继承方式 基类名 {
    // 派生类成员
};

2. 继承方式

C++支持三种继承方式:

2.1 公有继承(public)

class Animal {
public:
    void eat() { cout << "Eating..." << endl; }
protected:
    int age;
private:
    int id;
};
 
class Dog : public Animal {  // 公有继承
public:
    void bark() { 
        eat();        // 可以访问public成员
        age = 5;      // 可以访问protected成员
        // id = 10;   // 错误!不能访问private成员
    }
};

访问权限变化:

  • 基类的 public → 派生类的 public
  • 基类的 protected → 派生类的 protected
  • 基类的 private → 派生类中不可访问

2.2 保护继承(protected)

class Dog : protected Animal {
    // 基类的public和protected成员都变为protected
};

2.3 私有继承(private)

class Dog : private Animal {
    // 基类的public和protected成员都变为private
};

3. 构造函数和析构函数

3.1 调用顺序

class Base {
public:
    Base() { cout << "Base构造" << endl; }
    ~Base() { cout << "Base析构" << endl; }
};
 
class Derived : public Base {
public:
    Derived() { cout << "Derived构造" << endl; }
    ~Derived() { cout << "Derived析构" << endl; }
};
 
int main() {
    Derived d;
    // 输出顺序:
    // Base构造
    // Derived构造
    // Derived析构
    // Base析构
}

3.2 向基类构造函数传递参数

class Person {
protected:
    string name;
    int age;
public:
    Person(string n, int a) : name(n), age(a) {}
};
 
class Student : public Person {
private:
    string school;
public:
    // 使用初始化列表调用基类构造函数
    Student(string n, int a, string s) 
        : Person(n, a), school(s) {}
};

4. 函数重写(Override)

4.1 普通函数重写

class Shape {
public:
    void draw() {
        cout << "Drawing shape" << endl;
    }
};
 
class Circle : public Shape {
public:
    void draw() {  // 隐藏基类的draw函数
        cout << "Drawing circle" << endl;
    }
};

4.2 虚函数和多态

class Shape {
public:
    virtual void draw() {  // 虚函数
        cout << "Drawing shape" << endl;
    }
    
    virtual double area() = 0;  // 纯虚函数
};
 
class Rectangle : public Shape {
private:
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    
    void draw() override {  // C++11 override关键字
        cout << "Drawing rectangle" << endl;
    }
    
    double area() override {
        return width * height;
    }
};

5. 多重继承

C++支持一个类继承多个基类:

class Vehicle {
public:
    void start() { cout << "Vehicle starting" << endl; }
};
 
class Flyable {
public:
    void fly() { cout << "Flying" << endl; }
};
 
class FlyingCar : public Vehicle, public Flyable {
public:
    void travel() {
        start();  // 从Vehicle继承
        fly();    // 从Flyable继承
    }
};

5.1 菱形继承问题

class Animal {
public:
    int age;
};
 
class Mammal : public Animal {};
class Bird : public Animal {};
class Bat : public Mammal, public Bird {};  // 菱形继承
 
// 解决方案:虚继承
class Mammal : virtual public Animal {};
class Bird : virtual public Animal {};
class Bat : public Mammal, public Bird {};  // 现在只有一份Animal

6. 完整示例:员工管理系统

#include <iostream>
#include <vector>
#include <memory>
using namespace std;
 
// 基类
class Employee {
protected:
    string name;
    int id;
    double baseSalary;
    
public:
    Employee(string n, int i, double s) 
        : name(n), id(i), baseSalary(s) {}
    
    virtual ~Employee() {}  // 虚析构函数很重要!
    
    // 虚函数,计算工资
    virtual double calculateSalary() const {
        return baseSalary;
    }
    
    virtual void displayInfo() const {
        cout << "姓名: " << name 
             << ", ID: " << id 
             << ", 工资: " << calculateSalary() << endl;
    }
};
 
// 派生类:经理
class Manager : public Employee {
private:
    double bonus;
    
public:
    Manager(string n, int i, double s, double b)
        : Employee(n, i, s), bonus(b) {}
    
    double calculateSalary() const override {
        return baseSalary + bonus;
    }
    
    void displayInfo() const override {
        cout << "经理 - ";
        Employee::displayInfo();  // 调用基类版本
    }
};
 
// 派生类:销售人员
class SalesPerson : public Employee {
private:
    double commission;
    double sales;
    
public:
    SalesPerson(string n, int i, double s, double c, double sal)
        : Employee(n, i, s), commission(c), sales(sal) {}
    
    double calculateSalary() const override {
        return baseSalary + (sales * commission);
    }
    
    void displayInfo() const override {
        cout << "销售 - ";
        Employee::displayInfo();
    }
};
 
int main() {
    vector<unique_ptr<Employee>> employees;
    
    employees.push_back(make_unique<Manager>("张三", 1001, 8000, 3000));
    employees.push_back(make_unique<SalesPerson>("李四", 1002, 5000, 0.1, 50000));
    employees.push_back(make_unique<Employee>("王五", 1003, 6000));
    
    cout << "员工信息:" << endl;
    for (const auto& emp : employees) {
        emp->displayInfo();  // 多态调用
    }
    
    return 0;
}

7. 继承的最佳实践

7.1 设计原则

  • 优先使用组合而非继承
  • 使用public继承表示”is-a”关系
  • 基类析构函数应该是虚函数或protected
  • 不要继承非接口类(如STL容器)

7.2 注意事项

class Base {
public:
    virtual ~Base() = default;  // 虚析构函数
    Base(const Base&) = default;  // 拷贝构造
    Base& operator=(const Base&) = default;  // 赋值运算符
};
 
class Derived : public Base {
    // 编译器会自动生成合适的版本
};

继承是C++中强大但复杂的特性,正确使用可以提高代码的可维护性和复用性,但过度使用会导致代码难以理解和维护。