C++ 继承与派生

一、继承与派生的核心概念

继承是 C++ 实现代码复用多态的基础:

  • 基类(父类):被继承的类,定义了通用的属性和方法。
  • 派生类(子类):从基类继承而来的类,可复用基类的成员,也可扩展新的成员或重写基类方法。你可以把继承理解为 "特殊化"------ 派生类是基类的一种特殊形式(例如:学生是人的特殊形式)。

二、继承的基本语法

1. 定义派生类

语法格式:

cpp

运行

复制代码
class 派生类名 : 继承方式 基类名 {
    // 派生类新增的成员(属性/方法)
};

继承方式有三种(核心是控制基类成员在派生类中的访问权限):

继承方式 基类 public 成员 基类 protected 成员 基类 private 成员
public public protected 不可访问
protected protected protected 不可访问
private private private 不可访问
👉 最常用的是 public 继承,也是符合 "is-a" 逻辑的继承方式。
2. 基础示例(public 继承)

cpp

运行

复制代码
#include <iostream>
#include <string>
using namespace std;

// 基类:人类
class Person {
public:
    // 构造函数
    Person(string n, int a) : name(n), age(a) {}
    
    // 公有方法
    void ShowInfo() {
        cout << "姓名:" << name << ",年龄:" << age << endl;
    }
    
    // 可被派生类重写的方法
    void SayHello() {
        cout << "我是一个普通人" << endl;
    }

protected:
    // 保护成员:派生类可访问,外部不可访问
    string name;
private:
    // 私有成员:仅基类自身可访问
    int age;
};

// 派生类:学生(public继承Person)
class Student : public Person {
public:
    // 派生类构造函数:必须先调用基类构造函数初始化基类成员
    Student(string n, int a, int id) : Person(n, a), studentId(id) {}
    
    // 新增方法
    void ShowStudentInfo() {
        // 可访问基类的protected成员name
        cout << "姓名:" << name << ",学号:" << studentId << endl;
        // age是private,此处访问会报错:error: 'int Person::age' is private
        // cout << age << endl; 
    }
    
    // 重写基类方法(覆盖)
    void SayHello() {
        cout << "我是学生,姓名:" << name << endl;
    }

private:
    // 新增私有成员
    int studentId;
};

int main() {
    // 创建派生类对象
    Student stu("张三", 18, 2025001);
    
    // 调用继承自基类的方法
    stu.ShowInfo(); // 输出:姓名:张三,年龄:18
    
    // 调用派生类新增方法
    stu.ShowStudentInfo(); // 输出:姓名:张三,学号:2025001
    
    // 调用重写后的方法
    stu.SayHello(); // 输出:我是学生,姓名:张三
    
    return 0;
}

三、继承中的核心规则

1. 构造函数与析构函数
  • 构造顺序 :先调用基类构造函数 → 再调用派生类构造函数。

  • 析构顺序 :先调用派生类析构函数 → 再调用基类析构函数。

  • 派生类构造函数必须显式 / 隐式初始化基类: cpp

    运行

    复制代码
    // 显式调用基类构造函数(推荐)
    Student(string n, int a, int id) : Person(n, a), studentId(id) {}
    
    // 隐式调用:如果基类有默认构造函数(无参),可省略
    class Person {
    public:
        Person() {} // 默认构造函数
    };
    class Student : public Person {
    public:
        Student(int id) : studentId(id) {} // 隐式调用Person()
    };
2. 方法重写(覆盖)
  • 派生类可以重写基类的非 private 方法,但需注意:
    • 默认情况下,重写不会形成多态(需结合virtual关键字,见下文)。
    • 重写的方法签名(返回值、参数、const)必须与基类完全一致。
3. 多态(虚函数)

如果希望通过基类指针 / 引用调用派生类的重写方法(动态多态),需将基类方法声明为virtual

cpp

运行

复制代码
// 基类:将SayHello声明为虚函数
class Person {
public:
    virtual void SayHello() { // 虚函数
        cout << "我是一个普通人" << endl;
    }
};

// 派生类:重写虚函数
class Student : public Person {
public:
    void SayHello() override { // override关键字显式声明重写(C++11+)
        cout << "我是学生" << endl;
    }
};

int main() {
    Person* p = new Student(); // 基类指针指向派生类对象
    p->SayHello(); // 输出:我是学生(动态多态)
    delete p;
    return 0;
}
4. 继承的特殊形式
  • 单继承:一个派生类只继承一个基类(上文示例),最常用。

  • 多继承 :一个派生类继承多个基类(C++ 特有,需谨慎使用):

    cpp

    运行

    复制代码
    // 基类1
    class A { public: void FuncA() { cout << "A" << endl; } };
    // 基类2
    class B { public: void FuncB() { cout << "B" << endl; } };
    // 多继承
    class C : public A, public B {
    public:
        void FuncC() { cout << "C" << endl; }
    };
    
    int main() {
        C c;
        c.FuncA(); // 输出A
        c.FuncB(); // 输出B
        c.FuncC(); // 输出C
        return 0;
    }

    ❗ 多继承易引发 "菱形继承" 问题(两个基类继承同一个基类,派生类继承这两个基类),需用virtual继承解决。

四、继承的典型应用场景

  1. 代码复用:将多个类的通用属性 / 方法抽离为基类,派生类直接继承,避免重复代码。

  2. 多态设计 :通过基类指针 / 引用统一管理不同派生类对象,例如:

    cpp

    运行

    复制代码
    // 基类:图形
    class Shape {
    public:
        virtual double GetArea() = 0; // 纯虚函数(抽象方法)
    };
    // 派生类:圆形
    class Circle : public Shape {
    private:
        double r;
    public:
        Circle(double r) : r(r) {}
        double GetArea() override { return 3.14 * r * r; }
    };
    // 派生类:矩形
    class Rectangle : public Shape {
    private:
        double w, h;
    public:
        Rectangle(double w, double h) : w(w), h(h) {}
        double GetArea() override { return w * h; }
    };
    
    // 统一计算面积
    void PrintArea(Shape* s) {
        cout << "面积:" << s->GetArea() << endl;
    }
    
    int main() {
        PrintArea(new Circle(5)); // 输出:面积:78.5
        PrintArea(new Rectangle(4, 5)); // 输出:面积:20
        return 0;
    }
  3. 分层设计:例如框架中的基类定义核心接口,派生类实现具体业务逻辑。

总结

  1. 继承核心 :派生类通过public/protected/private继承基类,复用基类成员并扩展自身功能,构造先基后派、析构先派后基。
  2. 访问控制:public 继承是最常用的方式,基类 public/protected 成员在派生类中保持原有访问权限,private 成员不可访问。
  3. 多态关键 :基类方法声明为virtual,派生类用override重写,可通过基类指针 / 引用实现动态多态,这是继承的核心价值之一。
相关推荐
Boilermaker19925 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
MM_MS5 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
꧁Q༒ོγ꧂6 小时前
LaTeX 语法入门指南
开发语言·latex
njsgcs6 小时前
ue python二次开发启动教程+ 导入fbx到指定文件夹
开发语言·python·unreal engine·ue
alonewolf_996 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
古城小栈6 小时前
Rust 迭代器产出的引用层数——分水岭
开发语言·rust
ghie90906 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab
恋爱绝缘体16 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit
wuk9986 小时前
VSC优化算法MATLAB实现
开发语言·算法·matlab
AI小怪兽7 小时前
基于YOLOv13的汽车零件分割系统(Python源码+数据集+Pyside6界面)
开发语言·python·yolo·无人机