C++中的继承(一)

文章目录

  • 前言
  • 概念
  • 访问限定符
  • 基类和派生类的赋值转换
  • 继承中的作用域
  • 派生类的默认成员函数
    • 构造函数
  • 拷贝构造
    • 析构函数
  • 继承的其他一些细节

前言

我们之前说过,继承是面向对象的三大特性。

面向对象的三大特性:
封装、继承、多态。

封装在类和对象体现出。

概念

继承是什么?
继承就是一种类层次的复用,复用就是你的就变成我的.

假设我要实现一个管理系统。
如果按照以前类和对象的方式,单独去实现这个类是很坑的.

每个类都有一些信息, 有些类型之间是有一些共性,
每个类都写,那初始化每个类都要写.
在这里插入图片描述

C++创造了一个语法,可以支持继承,支持什么样的继承呢?
把我们公共的属性提取出来,放到一个类里面去,让剩下的类去继承.
在这里插入图片描述

我们也可以有些单独独立的信息.

继承是什么样的呢?
首先有很多类。如果这些类都有一些公共的特征,那我们就可以这些
类里面有些特性提取出来,专门放到一个类里面。这个类我们叫做父类。

我们想用这些特征,以前我们要写到一起,我们现在可以继承它。
怎么继承?

我们看一下它的语法:

 //基类/父类
class Person
{
public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;}private:  string _name = "peter"; // 姓名int _age = 18;  // 年龄
};class Student : public Person
{
protected:int _stuid; // 学号
};

继承方式有三种:
公有继承,私有继承,保护继承。

student这个类看起来啥都没有,其实里面啥都有。
在这里插入图片描述

它怎么来的?就是从它的父类。
stuent这个类的信息除了有学生的信息还有pesorn的信息,因为它继承了person.
继承也就是父类的我也有。

访问限定符

继承有三种访问限定符,但这三种访问限定符又有三种访问限定方式。
它们两两组合。
在这里插入图片描述
这些有什么规律?
它们分成了两组规则。
在这里插入图片描述
1.如果是公有成员和保护成员,就取它们继承方式和它的权限里小的那个。(公有大于保护,保护大于私有)
2.私有成员都是不可见。(不可见就是它在这个地方,你不能用)

演示一下,把父类的成员设置成私有
在子类写一个函数。
在这里插入图片描述
在这里插入图片描述
不可见就是在类里面也用不了,但是它跟私有不一样,私有在类里面可以用。

什么时候我们会定义私有呢?
这东西我不想被子类继承就用私有。

私有和保护在子类才有区别

子类能不能调用父类的函数取访问它?
可以。不可见只是指的是不能直接取访问它,取去调用父类的函数去访问也是可以的。

继承方式也可以像访问限定符一样,可以不写,class默认就是私有继承,struct默认就是公有继承。

实际当中用的最多的,就是这些。
在这里插入图片描述

基类和派生类的赋值转换

这是重点中的重点。这块想说的一个问题是什么?
在这里插入图片描述
这里会发生什么?d可以赋值给i吗?
可以。发生隐式类型转换,中间会产生临时变量,临时变量具有常性。

接着往下看,一个子类对象能不能给父类对象呢?
在这里插入图片描述
可以,但是有没有隐式类型转换的发生呢?
这里只适用于公有继承上,子类可以赋值给父类,这个过程叫做赋值兼容转换。
在这里插入图片描述
在这里插入图片描述
怎么证明呢?
在这里插入图片描述

在这里插入图片描述

子类可以赋值给父类,父类能不能给子类?
默认不可以,子类还有一些专有的属性。

继承中的作用域

基类和派生类都有它们独立的作用域。

既然它们都有独立的作用域,那基类和派生类能不能有同名成员呢?
在这里插入图片描述
派生类能不能也定义一个_num,可以。
我们c语言就规定不同的作用域可以定义同名的变量。

但是这样,我是会报错还是会访问派生类的呢?
在这里插入图片描述
理论上是访问派生类的,根据就近原则。
在这里插入图片描述
但是我就想访问基类,有没有什么办法?
指定作用域就可以了,加上域作用限定符。
在这里插入图片描述

子类和父类有同名成员,这种情况我们叫做隐藏或者重定义。
隐藏指的是默认情况下他会隐藏父类的成员。

class Person
{
protected:string _name = "小李子"; // 姓名int _num = 111; 		// 身份证号
};class Student : public Person
{
public:void Print(){cout << Person::_num << endl;cout << _num << endl;}protected:int _num = 999; // 学号
};

这里有个很坑的东西,经常出选择题考。
以下程序哪个是对的。
在这里插入图片描述
这道题的杀手锏是A,为什么是A?
函数名相同,参数不同构成函数重载。
那现在有一个问题,vector里的push_back和list里的push_back呢?
记住,函数重载必须在同一个作用域里面。

编译也没有报错。
虽然它们参数不同,但是它们的关系确实是隐藏。

最麻烦的考法是这样的。
下面这个选什么。
在这里插入图片描述
这道题如果是不定向选择,那就是BC.
如果确实要访问A里的fun, 要指定一下作用域

b.A::func();

结论:
如果是成员函数的隐藏,只需要函数名相同就可以构成隐藏。
不需要考虑参数,不需要考虑返回值。

注意在实际中最好不要定义同名的成员,不然自己坑自己。

派生类的默认成员函数

构造函数

派生类的构造函数时怎么玩的呢?
跟我们以前学的有一点点不一样。
在这里插入图片描述

在这里插入图片描述
注意看这个派生类,我什么都没有写.发生了啥?
如果我们不写,子类会自动调用父类的成员。

如果我们写了呢?
在这里插入图片描述
在这里插入图片描述
不可以。为什么呢?

在派生类当中,规定了,父类的成员,必须调父类的构造函数初始化。
你不写它也会调用父类的,你写他也会调用父类的。
在这里插入图片描述
在这里插入图片描述
上面两个都可以编译通过。
你不写他也会调用父类的默认构造,在初始化列表里调。
继承就像子类把父类当作一个自定义类型的整体成员一样。

那如果父类没有默认构造怎么办?
那我们就必须自己写了,自己显示的调用了。

拷贝构造

拷贝构造和前面也是同样的道理。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以,但是你自己不写他会不会调用父类的拷贝构造。
不会,要初始化父类怎么办?调用父类的拷贝构造。但是要求调用父类的拷贝构造,
是不是要传一个父类的对象过去。

只有子类对象没有父类对象,如何把子类对象父类这一部分拿出来啊。
我们可以用我们之前讲到的切片。
在这里插入图片描述
子类对象我也没有父类的那一部分,但是我可以传过去让它自己切就可以了。
在这里插入图片描述

这里回答一下之前遗留下来的一个问题?
如果是子类对象给父类对象,这个地方是怎么给过去的?
在这里插入图片描述
是memcpy拷贝过去还是怎么拷贝。
这里还是调用了拷贝构造,调用了父类的拷贝构造。
在这里插入图片描述
operatro=也是一样的道理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是这里出现了一个栈溢出的问题,是怎么回事呢?
栈溢出一般都是重复调用,这里教大家一个技巧,可以看调用堆栈
在这里插入图片描述
死循环了。为什么?
因为Student类里面的operator=和Person类里面的operator构成隐藏关系。
所以这里自己调用自己了。
在这里插入图片描述
指定作用域就可以了
在这里插入图片描述

在这里插入图片描述

总结一下就是自己干自己的,父类处理父类的。

可不可以不写拷贝构造和赋值呢?
可以,我们之前说过,拷贝构造针对内置类型进行值拷贝或者浅拷贝,
针对自定义类型会调用它的拷贝构造。

析构函数

特点都是先父后子
在这里插入图片描述

在这里插入图片描述

但是有个非常奇怪的现象,我们调用不了析构。为什么?
由于以后多态的原因,析构不会用这个名字,
析构函数会被处理成Destructro,所以它们会构成隐藏的关系。
所以还是指定一下。
在这里插入图片描述
但是这样也不行,父类的析构被调用了两次。
在这里插入图片描述
其它成员函数都可以显示调用,唯独析构函数我们不要显示调用。
它可以自动调用,为什么它可以自动?以为它要保证我们的顺序。
在这里插入图片描述
自己显示写不能保证调用先子后父的顺序。

为什么要先析构子类再析构父类?
因为父类先定义,子类后定义。

先析构父类,再析构子类有可能会出现野指针的问题。
在这里插入图片描述

继承的其他一些细节

友元关系不能被继承。
比如一个类,一个函数是你父类的友元,那是不是你子类的友元呢?
不是。
在这里插入图片描述
但是我就是想访问怎么办?
再定义一个友元就可以了。

class Person
{
public:friend void Display(const Person& p, const Student& s);
//protected:string _name; // 姓名
};
class Student : public Person
{friend void Display(const Person& p, const Student& s);
protected:int _stuNum; // 学号
};void Display(const Person& p, const Student& s)
{cout << p._name << endl;cout << s._stuNum << endl;
}void main()
{Person p;Student s;Display(p, s);
}

静态成员是怎么走的?
在这里插入图片描述
在这里插入图片描述

父类继承有一个_count,子类继承会不会也友一个_count呢?
不会。但是从域的角度,子类可以访问它。

无论你继承多少次,都只有一个_count
静态成员变量属于整个类,它不仅属于父类也属于子类。但是只有同一个。

证明一下:
父类当中的_name和子类当中的_name是不是同一个。
不是,它们的地址是不一样的。
但是_count是同一个。

把父类protected:去掉
在这里插入图片描述

下一个问题,这里Peron或者以Peson为继承的子类对象总共创建了多少个对象?
怎么算呢?这里有一个非常巧妙的东西。在父类的构造函数++_count就可以,为什么?
因为子类对象必须调用父类对象去初始化
在这里插入图片描述>

静态的成员所有继承的派生类共享。

实现一个不能被继承的类,如何实现?
最简单的方式就是把它的构造函数私有化,或者析构函数私有化。为什么?
因为构造函数私有了,继承了以后创建不了对象,为什么?
因为子类的构造函数必须去调用父类的构造函数,而父类的构造函数私有,子类调用不了。
在这里插入图片描述
A的构造函数私有,B是无论如何也调用不了。
A怎么调用呢?A是有办法的。

class A
{
public:static A CreateObj(){return A();}
private:A(){}
};
class B : public A
{};
int main()
{
//要调用函数首先要创建对象
//我们可以用静态成员函数,就可以直接用类去调用它A::CreateObj();return 0;
}

友元是能不用就不用。

其实C++正常的继承学到这里也差不多了,但是还有一个大坑,我们留到下篇文章

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

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

相关文章

2043杨辉三角(C语言)

目录 一&#xff1a;题目 二&#xff1a;思路分析 三&#xff1a;代码 一&#xff1a;题目 二&#xff1a;思路分析 1.通过杨辉三角&#xff0c;不难发现中间的数等于肩头两个数之和 2.但是当我们的输出结果&#xff0c;与杨辉三角的形式有所不同&#xff0c;但是我们可以找…

Freemarker基本语法与案例讲解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《SpringBoot》。&#x1f3af;&#x1f3af; &…

python接口自动化测试-unittest-批量用例管理

我们日常项目中的接口测试案例肯定不止一个&#xff0c;当案例越来越多时我们如何管理这些批量案例&#xff1f;如何保证案例不重复&#xff1f;如果案例非常多&#xff08;成百上千&#xff0c;甚至更多&#xff09;时如何保证案例执行的效率&#xff1f;如何做&#xff08;批…

利用n_gram进行情感分析

一、思路 二、关键步骤实现 1、利用tf-idf进行特征提取 详见利用tf-idf对特征进行提取-CSDN博客 2、利用svm进行模型训练 详见​​​​​​​​​​​​​​利用svm进行情感分析-CSDN博客

搞懂这6 个持续集成工具,领先80%测试人!

开发人员喜欢把写的代码当成自己的孩子&#xff0c;他们会被当成艺术品一样呵护。作为家长&#xff0c;总是会认为自己的孩子是最好的&#xff0c;也会尽全力给自己的孩子最好的&#xff0c;就算有时候会超出自己的能力范围。 最终&#xff0c;孩子会走出去&#xff0c;和其他…

HarmonyOS云开发基础认证考试满分答案(100分)【全网最全-不断更新】【鸿蒙专栏-29】

系列文章&#xff1a; HarmonyOS应用开发者基础认证满分答案&#xff08;100分&#xff09; HarmonyOS应用开发者基础认证【闯关习题 满分答案】 HarmonyOS应用开发者高级认证满分答案&#xff08;100分&#xff09; HarmonyOS云开发基础认证满分答案&#xff08;100分&#xf…

C++设计模式-Builder 构建器

通过“对象创建” 模式绕开new&#xff0c;来避免对象创建&#xff08;new&#xff09;过程中所导致的紧耦合&#xff08;依赖具体类&#xff09;&#xff0c;从而支持对象创建的稳定。它是接口抽象之后的第一步工作。 一、动机 在软件系统中&#xff0c;有时候面临着“一个复…

Spark基础入门

spark基础入门 环境搭建 localstandlonespark ha spark code spark corespark sqlspark streaming 环境搭建 准备工作 创建安装目录 mkdir /opt/soft cd /opt/soft下载scala wget https://downloads.lightbend.com/scala/2.13.12/scala-2.13.12.tgz -P /opt/soft解压scala…

单元测试计划、用例、报告、评审编制模板

单元测试支撑文档编制模板&#xff0c;具体文档如下&#xff1a; 1. 单元测试计划 2. 单元测试用例 3. 单元测试报告 4. 编码及测试评审报告 软件项目相关资料全套获取&#xff1a;软件项目开发全套文档下载-CSDN博客 1、单元测试计划 2、单元测试用例 3、单元测试报告 4、编码…

FastSAM 分割一切 速度可以比 SAM 快 50 倍

一、FastSAM 在自然语言处理领域有 ChatGPT 通用大语言模型系列&#xff0c;但是在图像领域好像一直没有通用领域模型&#xff0c;但MetaAI 提出能够 分割一切 的视觉基础大模型 SAM 可以做到很好的分割效果&#xff0c;并且不限于场景、不限于目标&#xff0c;为探索视觉大模…

四. 基于环视Camera的BEV感知算法-BEVDet

目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第四章——基于环视Cam…

Java系列-HashMap构造方法

1.无参 只初始化了loadFactor public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {final float loadFactor;public HashMap() {this.loadFactor DEFAULT_LOAD_FACTOR; // all other fields defaulted} }2…

Android动画

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、动画实现3.1 帧动画资源文件中实现…

【MySQL】触发器trigger / 事件

文章目录 1. 触发器 trigger1.1 触发器命名1.2 new和old关键字1.3 案例&#xff1a;insert 触发器1.4 练习&#xff1a;delete 触发器1.5 查看触发器 show triggers1.6 使用触发器记录对表的操作 2 事件2.1 打开 / 关闭事件调度器2.2 创建事件 create event2.3 查看&#xff0c…

软件设计师——数据结构(二)

&#x1f4d1;前言 本文主要是【数据结构】——软件设计师——数据结构的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

5个免费、跨平台的SQLite数据库可视化工具

前言 SQLite是一个轻量级的嵌入式关系型数据库&#xff0c;目前最新的版本是 SQLite3。今天推荐5个实用的SQLite数据库可视化工具(GUI)&#xff0c;帮助大家更好的管理SQLite数据库。 什么是SQLite&#xff1f; SQLite是一个轻量级的嵌入式关系型数据库&#xff0c;它以一个…

dp中最短编辑距离的笔记(分析dp)

dp分析往往就是看最后一步的变化。 分析&#xff1a; 设a串长度为i&#xff0c;b串长度为j。题目要求为通过三种操作将a字符串转化为b字符串的最少次数。 删除操作&#xff1a; 把a[i]删除后a[1~i]和b[1~j]匹配&#xff0c;所以可以得到f[i - 1][j] 1&#xff0c;在此之前要先…

连锁管理系统是什么?有哪些功能?

连锁管理系统帮助门店实现POS收银管理、门店管理、采购订货管理、线上商城搭建、供应链管理一体化管理系统&#xff0c;快速提高门店管理效率&#xff0c;无论你的门店有多少&#xff0c;连锁总部都能通过系统随时洞察监管门店的所有运营数据。 连锁管理系统由&#xff1a;1个…

Eslint 要被 Oxlint替换了吗

什么是 Oxlint 由于最近的rust在前端领域的崛起,基于rust的前端生态链遭到rust底层重构,最近又爆出OxLint,是一款基于Rust的linter工具。Oxlint在国外前端圈引起热烈讨论,很多大佬给出了高度评价。 事实上,Oxlint 是 Oxc 项目旗下的一款产品,专为 JavaScript 和 TypeSc…

Java解决不同路径问题

Java解决不同路径问题 01 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少…