当前位置: 首页 > news >正文

C++ 继承(Inheritance)超详细讲解(含代码+原理+实战)

继承是面向对象三大特性(封装、继承、多态)之一,核心作用是代码复用 + 扩展功能,让子类“继承”父类的属性和行为,同时可以新增或修改自己的特性。

一、继承基础语法

1. 定义格式

class子类名:继承方式 父类名{// 子类新增成员};

2. 三种继承方式(核心)

继承方式决定父类成员在子类中的访问权限,优先级:子类权限 < 继承方式限制

继承方式父类公有成员 → 子类父类保护成员 → 子类父类私有成员 → 子类
公有继承公有保护不可访问
保护继承保护保护不可访问
私有继承私有私有不可访问

继承规则总结

继承方式简单记忆口诀
公有继承不变(public→public, protected→protected)
保护继承全变保护(public/protected→protected)
私有继承全变私有(public/protected→private)

✅ 最常用:公有继承(public) —— 保留父类成员权限,符合“is-a”逻辑(子类是父类的一种)。

二、基础继承代码示例(公有继承)

场景:父类 Person (人类),子类 Student (学生)、 Teacher (教师)

#include<iostream>#include<string>usingnamespacestd;// 父类:人类(公共属性+行为)classPerson{public:// 父类公有成员(子类可直接访问)string name;intage;// 父类公有方法voideat(){cout<<name<<"在吃饭"<<endl;}voidsleep(){cout<<name<<"在睡觉"<<endl;}};// 子类1:学生(公有继承Person)classStudent:publicPerson{public:// 子类新增成员intstu_id;// 学号string major;// 专业// 子类新增方法voidstudy(){cout<<name<<"(学号:"<<stu_id<<")在学"<<major<<endl;}};// 子类2:教师(公有继承Person)classTeacher:publicPerson{public:// 子类新增成员intteach_id;// 工号string course;// 授课科目// 子类新增方法voidteach(){cout<<name<<"(工号:"<<teach_id<<")在教"<<course<<endl;}};intmain(){// 1. 创建子类对象,直接使用父类成员Student stu;stu.name="小明";// 继承父类public成员stu.age=20;// 继承父类public成员stu.stu_id=2024001;// 子类自有成员stu.major="计算机科学";// 调用父类方法stu.eat();stu.sleep();// 调用子类方法stu.study();cout<<"-------------------------"<<endl;// 2. 创建教师对象Teacher tea;tea.name="李老师";tea.age=35;tea.teach_id=1001;tea.course="C++编程";tea.eat();tea.teach();return0;}

运行结果

plaintext

小明在吃饭
小明在睡觉
小明(学号:2024001)在学计算机科学

李老师在吃饭
李老师(工号:1001)在教C++编程

三、继承中的成员访问(protected关键字)

protected 是继承专属权限

  • 类内可访问,类外不可访问;
  • 子类可直接访问,外部代码无法访问。

代码示例(protected成员继承)

#include<iostream>#include<string>usingnamespacestd;classPerson{protected:// 保护成员:子类可访问,外部不可访问string id_card;// 身份证号private:// 私有成员:子类不可访问(只能通过父类方法访问)string password;public:string name;// 父类方法:设置私有成员voidset_password(string pwd){password=pwd;}};classStudent:publicPerson{public:voidset_id_card(string id){id_card=id;// 子类可直接访问父类protected成员}voidshow_info(){cout<<"姓名:"<<name<<",身份证:"<<id_card<<endl;// cout << password << endl; 错误!子类无法访问父类private成员}};intmain(){Student stu;stu.name="小红";stu.set_id_card("3602032000xxxxxx");// 子类方法设置protected成员stu.show_info();// stu.id_card = "xxx"; 错误!外部无法访问protected成员return0;}
四、继承中的构造与析构函数(重点)

1. 调用顺序

  • 构造函数:先调用父类构造 → 再调用子类构造
  • 析构函数:先调用子类析构 → 再调用父类析构(栈规则:先进后出)

2. 子类调用父类有参构造(必须初始化列表)

子类默认调用父类无参构造,如果父类只有有参构造,子类必须用初始化列表显式调用。

#include<iostream>usingnamespacestd;classParent{public:intm_a;// 父类有参构造(无默认无参构造)Parent(inta){m_a=a;cout<<"父类有参构造:"<<m_a<<endl;}~Parent(){cout<<"父类析构"<<endl;}};classChild:publicParent{public:intm_b;// 子类构造:必须用初始化列表调用父类有参构造Child(inta,intb):Parent(a){m_b=b;cout<<"子类有参构造:"<<m_b<<endl;}~Child(){cout<<"子类析构"<<endl;}};intmain(){Childc(10,20);return0;}

运行结果

plaintext

父类有参构造:10
子类有参构造:20
子类析构
父类析构

五、继承中的同名成员处理(隐藏)

子类和父类有同名成员时,子类成员会隐藏父类同名成员,访问父类成员需加 父类名:: 。

代码示例

#include<iostream>usingnamespacestd;classParent{public:intm_a=100;// 父类成员voidfunc(){cout<<"父类func()"<<endl;}};classChild:publicParent{public:intm_a=200;// 子类同名成员(隐藏父类)voidfunc(){cout<<"子类func()"<<endl;}};intmain(){Child c;// 访问子类成员cout<<"子类m_a:"<<c.m_a<<endl;// 200c.func();// 子类func()// 访问父类同名成员(加作用域)cout<<"父类m_a:"<<c.Parent::m_a<<endl;// 100c.Parent::func();// 父类func()return0;}
六、多继承(一个子类继承多个父类)

语法

class子类:继承方式 父类1,继承方式 父类2{...};

代码示例

#include<iostream>usingnamespacestd;// 父类1:外形classShape{public:string color="红色";};// 父类2:价格classPrice{public:intmoney=100;};// 子类:圆形(多继承)classCircle:publicShape,publicPrice{public:intr=5;voidshow(){cout<<"颜色:"<<color<<",价格:"<<money<<",半径:"<<r<<endl;}};intmain(){Circle c;c.show();return0;}

⚠️ 多继承注意:多个父类有同名成员时,必须加 父类名:: 区分,避免歧义。

七、继承的核心作用总结
  1. 代码复用:父类写公共代码,子类直接继承,不用重复编写;
  2. 功能扩展:子类在父类基础上新增成员/方法,不修改父类;
  3. 多态基础:继承是多态的前提(父类指针指向子类对象)。
http://www.jsqmd.com/news/609868/

相关文章:

  • 免费降AI率网站哪个靠谱?2026年18款工具实测对比
  • Java RAG入门基础教程(非常详细),用LangChain4j构建问答系统看这篇就够了!
  • 从设计到仿真:FPGA转置型FIR滤波器的完整开发流程
  • Docker镜像拉取超时?5分钟搞定国内镜像源加速配置(附最新可用镜像列表)
  • STM32 DAC实现高质量音频播放(从8bit到16bit进阶)
  • 【笔记】企业级多智能体系统设计学习
  • 01-17-03 向前兼容的技术手段
  • 从零到一:用BurpSuite插件打造你的第一个HTTP请求“中间人” (基于Montoya API最新版)
  • CSS如何利用Less快速生成颜色渐变背景_使用混合函数生成多样渐变
  • AI 4小时黑进全球最安全系统
  • LangChain深度智能体实战:工作记忆、渐进式技能披露与纵深防御,揭秘高效可靠AI系统的构建秘诀!
  • RuoYi项目部署复盘:除了宝塔,这些配置细节才是稳定运行的关键
  • Claude Code通关手册(三):CLAUDE.md深度实战
  • 基于ESP32与PCM5102的Wi-Fi无损音频传输系统设计与实现
  • 豆包论文降AI最优解:14款工具实测SpeedAI领跑
  • Ovito不止能渲染:5个隐藏技巧帮你从LAMMPS结果中挖掘新发现(团簇分析/边界识别实战)
  • 2025届毕业生推荐的五大AI写作方案解析与推荐
  • 智能手环里的海拔数据准不准?拆解MEMS气压传感器的工作原理与校准
  • 从单容器到生产环境:手把手教你用Docker Compose编排iTop + 独立MySQL
  • 2026信息素养大赛编程题考点全揭秘!Scratch/Python/C++备考必看
  • 2026 比较好的柴油发电机组出租联系方式排行榜,静音型/应急备用/移动拖车式/并机系统/工业级机组厂家选择指南 - 海棠依旧大
  • SVGEdit——打造高效Web图形编辑器的完整指南
  • AI开发-python-langchain框架(--AI 直接生成并执行 Python 代码 )捶
  • 转码半年总结与未来规划
  • 告别杀后台!用UTS插件Ba-KeepAlive-U搞定uniappx安卓保活(附定位/推送/WebSocket实战)
  • LeetCode 删除无效的括号:python 题解瘸
  • SpringBoot 入门
  • 踩坑实录:Cloudflare免费版Bot Fight Mode拦截Webhook——穷鬼开发者的血泪自救指南
  • Keploy实战:基于真实流量的API自动化测试与Mock生成
  • 如何通过Prometheus Operator配置Grafna出图