用户_29571846
发布于 2026-06-22 / 2 阅读
0
0

C++ 继承、访问控制、多态基础 virtual 关键字入门

一、前言

继承实现代码复用,提取多个类的公共属性 / 行为到父类,子类直接复用并扩展独有功能;多态让同一函数在不同子类表现不同逻辑,是面向对象三大特性(封装、继承、多态)核心之二。

二、继承基础语法

cpp

运行

class 子类名 : 继承方式 父类名
{
    子类独有成员;
};

三种继承方式:public公有继承、protected保护继承、private私有继承,日常开发优先使用public

公有继承示例:学生子类继承人类父类

cpp

运行

#include <iostream>
#include <string>
using namespace std;
// 父类:人类,公共属性姓名、年龄
class Person
{
protected:
    string name;
    int age;
public:
    void setInfo(string n, int a)
    {
        name = n;
        age = a;
    }
    void showPerson()
    {
        cout << "姓名:" << name << " 年龄:" << age << endl;
    }
};
// 子类:学生,公有继承Person,新增分数属性
class Student : public Person
{
private:
    double score;
public:
    void setScore(double s)
    {
        score = s;
    }
    void showStu()
    {
        showPerson(); // 复用父类函数
        cout << "考试分数:" << score << endl;
    }
};
int main()
{
    Student s;
    s.setInfo("小明", 18); // 调用继承自父类的方法
    s.setScore(92);
    s.showStu();
    return 0;
}

三、三种继承方式权限变化

  1. public公有继承:父类 public→子类 public;父类 protected→子类 protected;父类 private 子类无法访问

  2. protected保护继承:父类 public/protected 全部变为子类 protected

  3. private私有继承:父类 public/protected 全部变为子类 private,仅当前子类可用,孙子类无法继承

四、继承中构造与析构执行顺序

  1. 创建子类对象:先执行父类构造函数 → 再执行子类构造函数

  2. 销毁子类对象:先执行子类析构函数 → 再执行父类析构函数

cpp

运行

class Person
{
public:
    Person(){cout << "父类Person构造" << endl;}
    ~Person(){cout << "父类Person析构" << endl;}
};
class Student:public Person
{
public:
    Student(){cout << "子类Student构造" << endl;}
    ~Student(){cout << "子类Student析构" << endl;}
};
int main()
{
    Student s;
    return 0;
}

输出顺序:父构造→子构造→子析构→父析构

五、子类访问父类私有成员

父类private成员子类无法直接访问,解决方案:

  1. 父类成员改为protected,子类可直接读取修改

  2. 父类提供 public get/set 接口,子类调用接口操作私有数据

六、虚函数 virtual 实现多态

多态核心:父类指针 / 引用指向子类对象,调用同名函数执行子类重写逻辑。

  1. 父类函数添加virtual变为虚函数

  2. 子类重写同名、同参数函数(重写 override)

cpp

运行

#include <iostream>
using namespace std;
// 父类动物
class Animal
{
public:
    // 虚函数
    virtual void speak()
    {
        cout << "动物发出声音" << endl;
    }
};
// 狗子类重写speak
class Dog:public Animal
{
public:
    void speak() override
    {
        cout << "汪汪汪" << endl;
    }
};
// 猫子类重写speak
class Cat:public Animal
{
public:
    void speak() override
    {
        cout << "喵喵喵" << endl;
    }
};
// 多态统一接口
void talk(Animal &a)
{
    a.speak();
}
int main()
{
    Dog d;
    Cat c;
    talk(d); // 输出汪汪汪
    talk(c); // 输出喵喵喵
    return 0;
}

七、虚析构函数(解决继承内存泄漏)

父类析构不加 virtual 时,父类指针释放子类对象,只会执行父类析构,子类堆内存无法释放。

修复方案:父类析构添加virtual

cpp

运行

class Animal
{
public:
    virtual ~Animal()
    {
        cout << "父类虚析构执行" << endl;
    }
};

八、新手避坑

  1. 私有继承后,孙子类无法访问父类任何成员,业务开发几乎不用

  2. 未写 virtual 虚函数,父类指针调用函数只会执行父类逻辑,无多态效果

  3. 继承构造顺序颠倒,子类构造无法直接初始化父类 private 成员

  4. 父类析构非 virtual,堆子类对象释放造成内存泄漏

九、综合实战:员工继承体系(普通员工 / 经理多态)

cpp

运行

#include <iostream>
#include <string>
using namespace std;
// 父类员工
class Staff
{
protected:
    string name;
    int salary;
public:
    Staff(string n, int s):name(n),salary(s){}
    virtual void showInfo()
    {
        cout << "员工:" << name << " 基础薪资:" << salary << endl;
    }
    virtual ~Staff(){}
};
// 普通员工子类
class NormalStaff:public Staff
{
public:
    NormalStaff(string n,int s):Staff(n,s){}
    void showInfo() override
    {
        cout << "普通员工:" << name << " 月薪:" << salary << endl;
    }
};
// 经理子类
class Manager:public Staff
{
private:
    int bonus;
public:
    Manager(string n,int s,int b):Staff(n,s),bonus(b){}
    void showInfo() override
    {
        cout << "经理:" << name << " 底薪:" << salary << " 奖金:" << bonus << endl;
    }
};
void printStaff(Staff &s)
{
    s.showInfo();
}
int main()
{
    NormalStaff a("小张",6000);
    Manager b("王总",10000,5000);
    printStaff(a);
    printStaff(b);
    return 0;
}

十、下期预告

下一篇:C++ string 标准字符串类全套操作详解


评论