C++中的继承:从基础到复杂

目录

前言

1. 继承的基本概念

2. 继承方式与访问控制

3. 派生类与基类的对象转换

4. 继承中的作用域

5. 派生类的默认成员函数

6. 继承中的特殊关系

6.1 继承与友元

6.2 继承与静态成员

7. 复杂的菱形继承问题

8. 继承与组合的选择

9. 常见面试题

总结


前言

继承是面向对象编程中最重要的概念之一,它允许我们创建新的类(派生类)基于已有类(基类)的特性进行扩展。在C++中,继承机制提供了代码复用的强大手段,同时也带来了许多需要注意的细节和复杂性。本文将全面介绍C++中的继承机制,从基本概念到高级应用,帮助读者深入理解这一重要主题。


1. 继承的基本概念

继承允许派生类复用基类的成员(包括成员变量和成员函数),同时可以添加新的特性或修改现有行为。这种机制体现了面向对象编程中"由简单到复杂"的认知过程。
 

class Person {
public:void Print() {cout << "name:" << _name << endl;cout << "age:" << _age << endl;}
protected:string _name = "peter";int _age = 18;
};class Student : public Person {
protected:int _stuid; // 学号
};


 

在这个例子中,`Student`类通过公有继承获得了`Person`类的所有成员,同时添加了自己的特有成员`_stuid`。

2. 继承方式与访问控制

C++提供了三种继承方式:public、protected和private。不同的继承方式会影响基类成员在派生类中的访问权限。

基类成员/继承方式public继承protected继承private继承
public成员publicprotectedprivate
protected成员protectedprotectedprivate
private成员不可见不可见不可见

重要规则:
1. 基类的private成员在派生类中不可见
2. 成员在派生类中的访问权限 = min(成员在基类的访问权限, 继承方式)
3. class默认private继承,struct默认public继承(但建议显式指定)

3. 派生类与基类的对象转换

派生类对象可以赋值给基类对象/指针/引用,这种现象称为"切片"或"切割"。


 

Student sobj;
Person pobj = sobj;  // 切片
Person* pp = &sobj;  // 指针
Person& rp = sobj;   // 引用


 

但反过来不行,除非使用强制类型转换(需谨慎使用)。

4. 继承中的作用域

基类和派生类有独立的作用域。当派生类与基类有同名成员时,派生类成员会隐藏基类成员(称为"隐藏"或"重定义")。
 

class Person {
protected:int _num = 111; // 身份证号
};class Student : public Person {
public:void Print() {cout << "身份证号:" << Person::_num << endl; // 显式访问cout << "学号:" << _num << endl;}
protected:int _num = 999; // 学号
};


 

5. 派生类的默认成员函数

派生类的6个默认成员函数有其特殊性:

1. 构造函数必须调用基类构造函数初始化基类部分
2. 拷贝构造必须调用基类拷贝构造
3. operator=必须调用基类operator=
4. 析构函数会自动调用基类析构函数(先派生后基类)
5. 对象初始化顺序:先基类构造,再派生类构造
6. 对象析构顺序:先派生类析构,再基类析构

6. 继承中的特殊关系

6.1 继承与友元

友元关系不能继承,基类的友元不能访问派生类的私有和保护成员。

6.2 继承与静态成员

基类定义的静态成员在整个继承体系中只有一个实例,无论派生出多少子类。
 

class Person {
public:static int _count; // 统计人数
};
int Person::_count = 0;class Student : public Person { /*...*/ };
class Graduate : public Student { /*...*/ };// 所有类共享同一个_count


 

7. 复杂的菱形继承问题

菱形继承是多继承的一种特殊情况,会导致数据冗余和二义性问题。


class Person { /*...*/ };
class Student : public Person { /*...*/ };
class Teacher : public Person { /*...*/ };
class Assistant : public Student, public Teacher { /*...*/ };

 

解决方案是使用**虚拟继承**:


 

class Student : virtual public Person { /*...*/ };
class Teacher : virtual public Person { /*...*/ };
class Assistant : public Student, public Teacher { /*...*/ };


 

虚拟继承通过虚基表指针和虚基表解决数据冗余和二义性问题。

8. 继承与组合的选择

- 继承表示"is-a"关系(如BMW是一种Car)
- 组合表示"has-a"关系(如Car有Tire)

设计原则:
1. 优先使用对象组合而非类继承
2. 继承会破坏封装,增加耦合度
3. 组合保持类封装,耦合度低
4. 需要多态时必须使用继承

 

// 继承示例
class BMW : public Car { /*...*/ };// 组合示例
class Car {
protected:Tire _t; // 轮胎
};


 

9. 常见面试题

1. 什么是菱形继承?它的问题是什么?
2. 虚拟继承如何解决数据冗余和二义性?
3. 继承和组合的区别?何时使用它们?


总结

C++的继承机制强大但复杂,特别是多继承和菱形继承。理解继承的各种细节对于编写健壮、可维护的面向对象代码至关重要。在实际开发中,应当谨慎使用多继承,优先考虑组合而非继承,只有在确实需要表达"is-a"关系或实现多态时才使用继承。

通过本文的学习,希望读者能够掌握C++继承的核心概念,理解其底层原理,并能够在实际项目中做出恰当的设计选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92362.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92362.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Eyevinn 彻底改变开源部署模式

该咨询公司借助Akamai云平台&#xff0c;为其创新的开源平台和可持续收益分成模式提供强大支持。 "时间就是金钱&#xff0c;我们通过Akamai云平台快速将开源云平台投入生产。" ——Eyevinn Technology研发副总裁 Jonas Birm实现可持续视频流媒体服务 自2013年以来&…

17day-人工智能-机器学习-分类算法-KNN

1. 什么是knn算法knn算法全名叫做k-近邻算法&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;&#xff0c;看到名字是不是能想到是算距离的&#xff0c;第一个k是指超参数的意思&#xff0c;就是可以认为设置的意思&#xff0c;这里是指最近的k个样本。2. 为什…

12-netty基础-手写rpc-编解码-04

netty系列文章&#xff1a; 01-netty基础-socket02-netty基础-java四种IO模型03-netty基础-多路复用select、poll、epoll04-netty基础-Reactor三种模型05-netty基础-ByteBuf数据结构06-netty基础-编码解码07-netty基础-自定义编解码器08-netty基础-自定义序列化和反序列化09-n…

解决 Windows 下的“幽灵文件”——记一次与带空格的 .gitignore 文件的艰难斗争

引言 你是否遇到过这样的情况&#xff1a;一个文件明明躺在你的文件夹里&#xff0c;ls 或 dir 命令都能清楚地看到它&#xff0c;但无论你用什么方法尝试删除&#xff0c;系统都冷酷地告诉你“找不到文件”&#xff1f; 就在今天&#xff0c;我就遇到了这样一个“幽灵”般的 .…

(易视宝)易视TV is-E4-G-全志A20芯片-安卓4-烧写卡刷工具及教程

&#xff08;易视宝&#xff09;易视TV is-E4-G-全志A20芯片-安卓4-烧写卡刷工具及教程PhoenixCard_V309烧录步骤&#xff1a;1、将TF或SD卡插入计算机&#xff0c;打开软件&#xff1b;2、选择固件所在目录&#xff1b;3、烧写模式选“卡量产”4、点击“烧录”开始量产&#x…

(数据结构)顺序表实现-增删查改

1.线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时…

【面试八股总结】线程/进程同步问题

一、同步与互斥 在线程并发执行的过程中&#xff0c;进程/线程之间存在协作的关系&#xff0c;例如有互斥、同步的关系。为了实现进程/线程间正确的协作&#xff0c;操作系统必须提供实现进程协作的措施和方法&#xff0c;主要的方法有两种&#xff1a; 锁&#xff1a;加锁、解…

大语言模型提示工程与应用:提示工程入门指南

提示工程入门 学习目标 在本课程中&#xff0c;我们将学习提示工程。 相关知识点 提示工程 学习内容 1 提示工程 提示工程是一门新兴学科&#xff0c;专注于设计和优化提示词以高效利用语言模型完成多样化任务。掌握提示工程能帮助开发者更深入理解大语言模型(LLM)的能力…

PostgreSQL 多级依赖血缘系统的设计与落地

一、业务背景&#xff1a;三类指标与四种状态指标类型定义规则依赖关系原子指标单表聚合&#xff08;SELECT WHERE GROUP&#xff09;无派生指标在原子/派生指标上加 WHERE、改 GROUP依赖 1~N 个父指标复合指标多个原子/派生指标做加减运算依赖 1~N 个父指标状态说明已保存草…

阿里云百炼平台创建智能体-上传文档

整体思路是&#xff1a; 1创建ram用户&#xff0c;授权 2上传文件获取FileSession 3调用智能体对话&#xff0c;传入FileSession 接下来每个步骤的细节&#xff1a; 1官方不推荐使用超级管理员用户获得accessKeyId和accessKeySecret&#xff0c;所以登录超级管理员账号创建…

剪映里面导入多张照片,p图后如何再导出多张照片?

剪映普通版本暂时没发现可以批量导出图片。这里采用其他方式实现。先整体导出视频。这里前期要注意设置帧率&#xff0c;一张图片的时长。 参考一下设置&#xff0c;帧率设置为30&#xff0c;图片导入时长设置为1s&#xff0c;这样的话&#xff0c;方便后期把视频切割为单帧。导…

怎么查看Linux I2C总线挂载了那些设备?

1. 根据系统启动查看设备树节点文件&#xff08;系统运行后的&#xff09; 比如&#xff1a;要查看I2C2i2c2: i2cfeaa0000 {compatible "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";reg <0x0 0xfeaa0000 0x0 0x1000>;clocks <&cru CLK_…

bat脚本实现获取非微软官方服务列表

Get-CimInstance -ClassName Win32_Service |Where-Object { $_.State -eq Running -and $_.StartMode -ne Disabled } | ForEach-Object {$isMicrosoft $false$signerInfo 无可执行路径if ($_.PathName) {# 提取可执行文件路径&#xff08;处理带引号/参数的路径&#xff09…

小程序难调的组件

背景。做小程序用到了自定义表单。前后端都是分开写的&#xff0c;没有使用web-view。所以要做到功能对称时间选择器。需要区分datetime, year, day等类型使用uview组件较方便 <template><view class"u-date-picker" v-if"visible"><view c…

从零构建TransformerP2-新闻分类Demo

欢迎来到啾啾的博客&#x1f431;。 记录学习点滴。分享工作思考和实用技巧&#xff0c;偶尔也分享一些杂谈&#x1f4ac;。 有很多很多不足的地方&#xff0c;欢迎评论交流&#xff0c;感谢您的阅读和评论&#x1f604;。 目录引言1 一个完整的Transformer模型2 需要准备的“工…

qt qml实现电话簿 通讯录

qml实现电话簿&#xff0c;基于github上开源代码修改而来&#xff0c;增加了搜索和展开&#xff0c;效果如下 代码如下 #include <QGuiApplication> #include <QQmlApplicationEngine>int main(int argc, char *argv[]) {QCoreApplication::setAttribute(Qt::AA_…

顺序表——C语言

顺序表实现代码解析与学习笔记一、顺序表基础概念顺序表是线性表的一种顺序存储结构&#xff0c;它使用一段连续的内存空间&#xff08;数组&#xff09;存储数据元素&#xff0c;通过下标直接访问元素&#xff0c;具有随机访问的特性。其核心特点是&#xff1a;元素在内存中连…

【Oracle篇】Oracle Data Pump远程备份技术:直接从远端数据库备份至本地环境

&#x1f4ab;《博主主页》&#xff1a;    &#x1f50e; CSDN主页__奈斯DB    &#x1f50e; IF Club社区主页__奈斯、 &#x1f525;《擅长领域》&#xff1a;擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对…

Linux系统--文件系统

大家好&#xff0c;我们今天继续来学习Linux系统部分。上一次我们学习了内存级的文件&#xff0c;下面我们来学习磁盘级的文件。那么话不多说&#xff0c;我们开始今天的学习&#xff1a; 目录 Ext系列⽂件系统 1. 理解硬件 1-1 磁盘、服务器、机柜、机房 1-2 磁盘物理结构…

KUKA库卡焊接机器人氩气节气设备

在焊接生产过程中&#xff0c;氩气作为一种重要的保护气体被广泛应用于KUKA库卡焊接机器人的焊接操作中。氩气的消耗往往是企业生产成本的一个重要组成部分&#xff0c;因此实现库卡焊接机器人节气具有重要的经济和环保意义。WGFACS节气装置的出现为解决这一问题提供了有效的方…