《C++ primer plus》精炼(OOP部分)——对象和类(8)

news2024/11/23 7:19:00

学习是一项持续的投资,永远不白费——本杰明·富兰克林

文章目录

  • 第13章:类继承
    • 一个基类和派生类
    • 公有继承的逻辑关系:is-a
    • 多态公有继承

第13章:类继承

一个基类和派生类

从一个类派生出另一个类时,原始类称为基类,继承类称为派生类。以下是一个简单的基类:

class Person
{
private:
	string name;
public:
	Person(){name="none";};
	Person(string s)
	{
		name=s;
	}
	~Person(){};
	void show()
	{
		cout<<name;
	}
}

这是一个表示人的简约的类,接下来我们用这个人来派生一个学生类:

class Student:public Person
{
private:
	int grade;
public:
	Student():Person()
	{
		grade=0;
	}
	Student(string s,int g):Person(s)
	{
		grade=g;
	}
	void s_show()
	{
		show();
		cout<<grade;
	}
}
  1. 要使用类继承,在类声明中需要使用如下格式:

class 派生类:public/protected/private 基类

其中public表示公有继承,protected表示保护继承,private表示私有继承,在本章我们只考虑公有继承。

  1. 在继承中,派生类自动包含基类的所有属性和方法,但派生类中的方法不能直接访问基类的私有成员,而要通过基类提供的方法来访问,例如:
Student():Person()
{
	grade=0;
}

这是Student类的默认构造函数。对于派生类和基类的逻辑关系,可以用下面这张图来表示:
在这里插入图片描述
所以当要构造一个Student类的时候,从概念上要先构造出其中的Person类,所以要在构造函数执行到函数体之前将Person类初始化,即必须选用列表初始化语法。而且因为派生类不能直接访问基类的私有属性,因此下面的代码是错误的:

Student():name("none")//不能直接访问name属性
{
	grade=0;
}
  1. 使用时,可以用基类指针来指向派生类:
int main(void)
{
	Person* p[2];
	p[0]=Person();//指向一个Person类对象
	p[1]=Student();//也可以指向一个Student类对象
}

注意,这一规则是单向的,也就是说不能把派生类指针指向基类,这是因为编译器看到Person类指针后,会认为这个指针指向的对象拥有Person类声明的方法和属性,下面的代码显然是错误的:

int main(void)
{
	Student* s[2];
	s[0]=Student();//可以通过编译
	s[1]=Person();//不能通过编译
	s[0]->s_show();//因为s[0]指向的是一个Student类对象,自然可以调用这个方法
	s[1]->s_show();//但s[1]指向一个Person对象,因此显然是不行的

另外,如果用Person类指针指向了Student类对象,也只能用对象中从Person类继承下来的方法:

int main(void)
{
	Person* p[2];
	p[0]=Person();//指向一个Person类对象
	p[1]=Student();//也可以指向一个Student类对象
	p[1]->s_show();//错误,不能通过编译,即使指向一个Studnet类对象
}

对于形参为指向基类的指针的函数,也可以用派生类的地址作为实参,因此也可以用派生类对象来初始化基类对象(实际上是使用了复制构造函数),实际效果为将派生类对象中的基类部分拷贝到新的基类对象上。

公有继承的逻辑关系:is-a

当派生类is a基类时,适合使用公有继承,这就是公有继承的逻辑关系,例如在上面的例子中,Student is a Person.
在这里插入图片描述

多态公有继承

在弄清Person类和Student类的关系后,我们可以把这种关系扩展到其他职业:
在这里插入图片描述
同样的,因为teacher is a person,headmaster is a person,也可以使用公有继承。可以试着自己写一写代码,笔者的代码如下:

class Person
{
private:
	string name;
public:
	Person(){name="none";};
	Person(string s)
	{
		name=s;
	}
	virtual ~Person(){};
	virtual void show()
	{
		cout<<name;
	}
}

class Student:public Person
{
private:
	int grade;
public:
	Student():Person()
	{
		grade=0;
	}
	Student(string s,int g):Person(s)
	{
		grade=g;
	}
	virtual void show()
	{
		Person::show();
		cout<<grade;
	}
}

class Teacher:public Person
{
private:
	int number;//负责哪个班级的班号,简单即可
public:
	Teacher():Person()
	{
		number=0;
	}
	Teacher(string s,int n):Person(s)
	{
		number=n;
	}
	virtual void show()
	{
		Person::show();
		cout<<number;
	}
}

class HeadTeacher:public Person
{
private:
	int s_number;//负责哪个学校的代号
public:
	HeadTeacher():Person()
	{
		number=0;
	}
	HeadTeacher(string s,int n):Person(s)
	{
		s_number=n;
	}
	virtual void show()
	{
		Person::show();
		cout<<s_number;
	}
}

这里需要注意的就是virtual关键字。被virtual关键字当要将基类的方法在派生类中重写时,可以使用这个关键字。当使用这个关键字时,如果一个对象由指针引用,那么这个对象调用函数时,所调用的函数由这个对象的实际类决定。另外,因为进行了函数重写,因此在调用基类的方法时需要使用::运算符。下面是这四个类的测试代码:

Person* p[4];
p[0]=Person();
p[1]=Student();
p[2]=Teacher();
p[3]=HeadTeacher();

p[0]->show();//调用Person类中的show函数
p[1]->show();//调用Student类中的show函数
p[2]->show();//调用Teacher类中的show函数
p[3]->show();//调用HeadTeacher类中的show函数

另外,如果将函数的声明和定义分开,那么virtual关键字只在类声明的时候加上即可。
用一个基类指针的数组指向不同派生类的对象,当执行同样的代码时,实际行为会随被执行的对象类型而变化,这就是多态。多态保证了代码的重用性,使得程序员不需要频繁修改测试代码,所以多态也是继封装和继承后OOP中第三个重要的思想。
最后,在Person类中的构造函数也被声明为虚函数,这是因为如果不这样声明,那么编译器会按照指针类型而非实际对象类型来析构数组p所指向的对象,这会导致内存泄漏,所以即使Person类析构函数不进行任何操作,也要声明为虚函数。
请添加图片描述
我是霜_哀,在算法之路上努力前行的一位萌新,感谢你的阅读!如果觉得好的话,可以关注一下,我会在将来带来更多更全面的知识讲解!

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

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

相关文章

SLAM简要介绍

过去二十年&#xff0c;计算机视觉和机器学习领域都取得了很多进步。这一切都归功于硬件的改进&#xff0c;这使得研究人员和工程师能够设计和训练更复杂和更准确的模型&#xff0c;同时以以前难以想象的规模处理和分析数据。随着硬件的这些改进&#xff0c;未知环境的映射已经…

基于Java的学校固定资产管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

vue 使用 创建二维数组响应数据 渲染 echarts图标

目前我遇到的情况就是用动态的二维数组数据渲染echarts图标&#xff0c;我们从后端收到的接口一般是个一维数组&#xff0c;需要手动构建并且保证响应式。接下来我做了个案例 一、案例总逻辑 1. 先创建一个vue项目 2. 添加 echarts依赖 3. 模拟数据请求&#xff0c;构建二维数组…

支付宝2023年收单外包服务机构评级启动,截止11月15日

9月22日消息&#xff0c;支付宝近日发布公告称&#xff0c;已启动2023年收单外包服务机构评级工作。支付宝表示&#xff0c;收单外包服务机构评级工作是金融监管部门规范引导收单外包服务市场的重要举措&#xff0c;其结果将会向社会公示&#xff0c;直接关系到外包机构的业务开…

QT 之数据库 QSqlQuery CURD 实战

零、参考文档 https://doc.qt.io/archives/qt-6.0/qsqldatabase.html 一、开发环境 Ubuntu 20.04 QT6.0 Microsoft SQL Server 2022 Developer Edition (64-bit) 先修改 /etc/odbc.ini 的数据源配置&#xff0c;指定连接数据库 vdb&#xff0c; sudo vim /etc/odbc.ini[mss…

《发现的乐趣》作者费曼(读书笔记)

目录 一、书简介 二、作者理查德•费曼 费曼式思维 教育与传承 三、个人思考 四、笔记 科学家眼中的花之美 关于偏科 父亲教育我的方式 知道一个概念和真正懂得这个概念有很大区别 我没有义务去成全别人对我的期望 诺贝尔奖——够格吗&#xff1f; 探究世界的游戏规…

基于SpringBoot的商品物品产品众筹平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

内网综合扫描工具-fscan的安装和使用

简介 一款内网综合扫描工具&#xff0c;方便一键自动化、全方位漏扫扫描。 支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。相当强大&#xff01;&…

JavaSE | 初始Java(九) | 包的使用

包 包是对类、接口等的封装机制的体现&#xff0c;是一种对类或者接口等的很好的组织方式&#xff0c;比如&#xff1a;一个包中的类不想被其他包中的类使用。包还有一个重要的作用&#xff1a;在同一个工程中允许存在相同名称的类&#xff0c;只要处在不同的包中即可。 可以…

【Spring】Spring 创建和使用

Spring 创建和使用 一. 创建 Spring 项目1. 创建⼀个 Maven 项目2. 添加 Spring 框架⽀持3. 添加启动类 二. 存储 Bean 对象1. 创建 Bean2. 将 Bean 注册到容器 三. 获取并使⽤ Bean 对象1. 创建 Spring 上下文2. 获取指定的 Bean 对象3. 使用 Bean Spring 就是⼀个包含了众多⼯…

HDF5文件数据读取

1、HDF5文件说明 HDF 是用于存储和分发科学数据的一种自我描述、多对象文件格式。HDF 是由美国国家超级计算应用中心(NCSA)创建的,以满足不同群体的科学家在不同工程项目领域之需要。HDF 可以表示出科学数据存储和分布的许多必要条件。HDF 被设计为: 自述性:对于一个HDF …

Koa学习4:密码加密、验证登录、颁发token、用户认证

请求体 这里遇到了个问题&#xff0c;ctx.request.body 的值是一个字符串。明明已经使用了koa-body中间件 查了一下原因是&#xff1a; ctx.request.body的值可能是一个对象或一个字符串&#xff0c;取决于请求的Content-Type和请求体的格式。 当使用koa-body中间件时&#x…

专业PDF编辑阅读工具PDF Expert mac中文特点介绍

PDF Expert mac是一款专业的PDF编辑和阅读工具。它可以帮助用户在Mac、iPad和iPhone等设备上查看、注释、编辑、填写和签署PDF文档。 PDF Expert mac软件特点 PDF编辑&#xff1a;PDF Expert提供了丰富的PDF编辑功能&#xff0c;包括添加、删除、移动、旋转、缩放、裁剪等操作…

基于Java的老年人体检管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

JDBC学习笔记(1)

连接数据库 下载mysql-connector-java&#xff0c;这里我是看的这个连接mysql-connector-java下载。 下载后并且导入了Idea中的lib文件下。 导入成功后&#xff0c;为了验证可以通过CTRLn来搜索Driver看看有没有添加进来。 随后在MySQL中创建一个数据库&#xff0c;我这里直…

小狐狸ChatGPT付费创作系统V2.0.4智能问答小程序,修复一个pc版的bug

狸GPT付费体验系统是一款基于ThinkPHP框架开发的AI问答小程序&#xff0c;是基于国外很火的ChatGPT进行开发的Ai智能问答小程序。 当前全民热议ChatGPT&#xff0c;流量超级大&#xff0c;引流不要太简单&#xff01;一键下单即可拥有自己的GPT&#xff01;无限多开、免费更新不…

Vue中如何进行多语言处理

Vue中的多语言处理 在开发多语言Web应用程序时&#xff0c;处理文本翻译和国际化是一个重要的任务。Vue.js提供了多种方法来实现多语言处理&#xff0c;以确保您的应用程序能够支持不同语言的用户。本文将深入探讨在Vue中进行多语言处理的方法&#xff0c;并提供示例代码来帮助…

基于SpringBoot的高校实习管理系统设计与实现(亮点:多角色、功能全、进可攻退可守)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

2023年中国家用智能投影市场发展趋势分析

2023年上半年&#xff0c;连续多年保持高速增长态势的家用智能投影行业&#xff0c;首次半年度出现同比负增长态势。2023年上半年&#xff0c;中国家用智能投影市场全渠道推总销量为323.0万台&#xff0c;同比下降2.6 %&#xff1b;销售额61.0亿元&#xff0c;同比下降2.9%&…

SLAM面试笔记(7) — Linux面试题

目录 问题1&#xff1a;Linux系统基本组件&#xff1f; 问题2&#xff1a;Linux和Unix有什么区别&#xff1f; 问题3&#xff1a;Linux下编译程序 问题4&#xff1a;gcc基本格式和常用指令 问题5&#xff1a;用什么命令查找内存和交换使用情况&#xff1f; 问题6&#xf…