C++标准语言day06

news/2024/4/27 10:46:02/文章来源:https://blog.csdn.net/weixin_61180910/article/details/127250108

一、什么是继承

    1、当遇到问题时,先查看现有的类能否解决一部分问题,如果有则继承该类,在此类的基础上进行扩展来解决最大的问题

        以此可以缩短解决问题的时间(代码复用)

    2、当遇到一个大而复杂的问题时,可以先把复杂的问题拆分成若干个小问题,然后为每个小问题设计一个类进行解决

        最后通过继承的方式把这些类汇总到一个类中,从而解决最终的大问题,以此降低问题的难度

        也可以同时让多个程序员一起工作解决问题

        子类继承父类    派生类继承基类

二、继承的语法

    1、继承表

        class Son : 继承表[继承方式 父类名1,继承方式 父类名2]

        {

            成员变量;

        public: //  访问控制权限

            成员函数;

        };

    2、继承方式

        public

        protected

        private

三、C++继承的特点:

    1、C++中的继承可以有多个父类

    2、子类会继承父类的所有内容

    3、子类对象可以向他的父类类型转换(使用父类类型指针或引用指向子类对象)(可以缩小)

        但是父类对象不能向它的子类类型转换(不能使用子类类型的指针或引用指向父类对象)(不能扩大)

        Base* b = new Son;  true

        Base& b = son;      true

        Son* son = new Base;false

        Son* son = base;    false

    4、子类对隐藏父类的同名成员,在子类中直接使用同名成员时,默认使用的是自己的同名成员

        但是可以通过 父类名::同名成员 的方式指定访问父类的同名成员

    5、子类与父类的同名函数是无法构成重载的,因为不在同一个作用域下,并且子类会隐藏同名的父类成员函数

        因此只能通过域限定符的方式访问父类的同名成员函数

    6、在执行子类的构造函数时,会按照继承表中的顺序执行父类的构造函数,默认执行的是父类的无参构造

        可以在子类的构造函数的初始化列表中显示地调用父类的有参构造,最后才执行子类的构造函数

        Son(int num):Base(参数){}   //  调用Base的有参构造

    7、在子类的析构函数执行结束后,才会调用父类的析构函数,会按照继承表顺序,逆序执行父类的析构函数

    8、当子类执行拷贝构造时,默认也会调用父类的无参构造,但这是有问题的

        此需要在子类的拷贝构造函数初始化列表中显示地调用父类的拷贝构造函数

            Son(Son& that):Base(that) {} // 调用Base的拷贝构造

    9、当子类执行赋值操作时,默认不会调用父类的赋值操作函数,如果需要调用父类的赋值操作函数时

        可以通过域限定符和赋值函数名的方式调用

            void Son::operator=(Son& that)

            {

                父类名::operator=(that);    //调用父类的赋值函数

            }

四、继承方式和访问控制属性

    访问控制属性成员的访问范围:

        public:         可以在任意位置访问

        protected:      只能在类内和子类中访问

        private:        只能在类内访问

    继承方式的影响:

    1、父类的成员是否能在子类中访问,是在设计父类时的访问控制属性决定的,不受继承方式的影响

    2、但是继承方式能够决定父类成员继承后,在子类中变成什么样的访问控制属性,具体情况见表

    3、只有使用public继承父类,父类的指针或引用才能指向子类对象(多态的基础)

五、多重继承和钻石继承

    1、多重继承

        当一个类继承了多个父类时,称为多重继承,会按照继承表的顺序在子类中排列了父类的内容

            当把子类指针对象转换为父类指针时,编译器会自动计算出该父类内容所在的位置,并让指针位置偏移到该位置

            因此,可能会出现转换后的父类指针与转换前子类指针不相同的情况

    2、钻石继承

        假如有一个类A,类B和类C都继承了类A,类D又同时继承了类B和类C,当子类的父类中有共同的祖先时,这种称为钻石继承

        1、类B和类C中都各自有类A的内容

        2、类D继承类B和类C中的所有内容,就会导致类D中有两份类A的内容

        3、当类D对象去访问类A中的成员时,编译器会产生歧义,不确定要使用的是哪份类A中的成员,因此编译不通过

    3、虚继承

        当使用 virtual 关键字去修饰继承表时,此时变成虚继承,此时子类中就会多一个虚指针用于指向父类的内容

            当这个子类被继承时,孙子类中也会继承该虚指针,并且通过虚指针比较是否含有多份相同的祖先类,如果有则只保留一份

        因此:通过虚继承可以在钻石继承中解决子类有多份祖先类成员的问题

   

六、虚函数和覆盖

    1、虚函数

        当成员函数前加 virtual 修饰后,这样的函数称为虚函数

        该类也会像虚继承一样多了一个虚指针

    2、虚函数表

        虚指针指向一张表格的首地址,该表格中记录的是该类中所有虚函数的首地址  

        ((void(*)(void))(*(int*)*(int*)b))();   //  相当于调用了虚函数表中的第一个函数      

    3、覆盖(重写)

        当使用virtual关键字修饰父类的成员函数,此时父类中多了一个虚指针(虚表指针),子类会把父类的虚指针一起继承过来

        当子类中有与父类虚函数同名的成员函数时,编译器会比较两个函数的格式,如果格式完全相同

            则会把子类的同名函数的的地址覆盖掉虚函数表中父类的同名虚函数的原地址

        此时使用父类的指针或引用指向子类对象时,调用虚函数则会调用被覆盖的虚函数表中所指向的子类的同名且格式相同的成员函数

    4、构成覆盖的条件:

        1、必须式发生在父子类,并且一定为public继承

        2、要被覆盖的父类的函数必须为虚函数 virtual 修饰

        3、子类中必须有与父类虚函数同名,且返回值、参数列表、常属性都必须完全相同的函数,才能覆盖

        4、覆盖要求返回值类型相同,或者子类函数的返回值可以向父类虚函数的返回值类型做隐式转换且有继承关系时,也可以构成覆盖

    常见面试题:重载、覆盖、隐藏、重写的区别?

        隐藏:

            1、如果同名但格式不同,无论是否加virtual,在子类中都会隐藏父类同名成员函数

            2、子类中如果同名且格式相同,不加virtual,子类也会隐藏父类的同名成员函数

            总结:父子类中,同名成员函数那么构成覆盖,要么构成隐藏

七、多态

    什么是多态:

        是指同一个事物、指令可以有多种形态,当调用同一个指令时,它会根据参数、环境的不同会做出不同的相应操作

            这种模式称为多态

        C++中根据确定执行操作的时间,多态分为编译时多态、运行时多态

        编译时多态:

            当调用重载过的函数时,编译器会根据参数的不同,在编译时就能确定执行哪个版本的重载函数,这种叫做编译时多态

                还有模板技术

        运行时多态:

            在父子类中,当子类覆盖了父类的同名虚函数,然后用父类指针或引用访问虚函数时,它既可能调用父类的虚函数

            也可能调用子类的同名函数,具体调用哪个取决于该父类指针或引用指向的目标是谁

            而这个目标的确定需要在运行时才能确定下来,这种情况叫做运行时多态

   

    构成运行时多态的条件:

        1、父子类之间且有构成覆盖关系的同名函数

        2、子类是以public继承父类(让父类指针、引用指向子类对象)

        3、通过父类指针或引用访问被覆盖的虚函数

    思考:构造函数和析构函数能否是虚函数?为什么?

八、虚析构和虚构造

    虚构造:

        构造函数不能设置为虚函数,假如构造函数可以设置为虚函数,子类的构造函数会自动覆盖父类的构造函数

        当创建子类对象时,子类执行自己的构造函数之前执行父类的构造函数,但是此时父类的构造函数已经被覆盖成了子类的构造函数

            这样就形成了死循环,因此编译器不允许把构造函数声明为虚函数

    虚析构:

        析构函数可以设置为虚函数,当使用类多态时,通过父类指针或引用释放子类对象是,

            默认情况下不加虚构是不会调用子类的析构函数,如果子类析构函数中要释放的资源时,就可能构成内存泄漏

        只有把父类的析构函数定义为虚析构(子类的析构函数会自动覆盖父类的析构函数),

            当通过父类指针或引用释放子类对象时,会先调用覆盖后的子类析构函数,而且之后还会自动调用父类的析构函数

            这样就不会有内存泄漏了

        总结:

            当使用多态且子类的构造函数中有申请内存,此时父类的析构函数一定要设置为虚析构

九、纯虚函数和纯抽象类

    纯虚函数的格式

        virtual 返回值 成员函数名(参数列表) = 0;

    1、纯虚函数可以只声明不实现(一般没必要去实现它)

    2、父类中如果有纯虚函数,子类九必须覆盖父类的纯虚函数,否则无法创建对象

    3、有纯虚函数的类是无法创建对象的,因为这样的话纯虚函数没有被覆盖

    4、纯虚函数的目的就是为了强制子类去覆盖父类的纯虚函数,为了强制子类实现某些功能

    5、有纯虚函数的类称为抽象类

    6、析构函数可以是纯虚的,但纯虚析构函数必须有定义体,因为析构函数的调用是在子类中隐含的

   

    纯抽象类:

        所有的成员函数都是纯虚函数的类,叫做纯抽象类,这种类一般设置功能的接口,也称为接口类

    工厂模式:

        了解什么是工场模式,尝试实现一个简单的工厂模式例子

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

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

相关文章

12个小细节让普源示波器使用更加高效(上)

俗话说细节决定成败,示波器作为电子测量的第一工具,虽然使用简单,但并不是每个人都能注意到细节。运用好细节,可以使你的示波器使用更加的便捷。以下由安泰测试带来普源示波器测量相关的12个小细节可作为示波器常识快速自检的小文…

Spring Boot(4):@Import注解和@Conditional注解

说明:基于atguigu学习笔记。 在了解spring boot自动配置原理前,再来了解下两个注解Import注解和Conditional注解。 Import Import注解主要用于导入某些特殊的Bean,这些特殊的Bean和Bean Definitaion 有关。 主要用于导入Configuration 类…

Python实现桌面挂件,做一只可爱的桌面宠物~

文章目录嗨嗨,大家好 ~ 我是小圆相关文件开发工具相关模块:环境搭建安装原理简介1.初始化一个窗口组件:效果2.设置一下窗口的属性:随机导入一张图片,看效果随机导入一个宠物的所有图片的函数代码3.宠物随机出现在桌面上…

服务端渲染的探索与实践

服务端渲染(SSR)近两年炒得很火热,相信各位同学对这个名词多少有所耳闻。本节我们将围绕“是什么”(服务端渲染的运行机制)、“为什么”(服务端渲染解决了什么性能问题 )、“怎么做”(服务端渲染的应用实例与使用场景)这三个点,对服务端渲染进行探索。 服务端渲染是一…

GOM引擎登录器的研究,逆向技术在这款GOM20151108引擎上是一个大舞台

最近遇到一个逆向类课题,是关于GOM20151108版本对应登录器研究。刚接触传奇的时候是2002年,那时候网吧玩SF,都是手动用IP直接连接,当时的一款 联创传奇 很好玩,有传送戒子,木域戒指,土域戒指&am…

不会 Vue,但不影响我学 diff 算法

前言 现在社会各行各业大都面临着寒冬,互联网行业最近还出现了裁员潮,导致前端是越来越卷,普通学校的应届生不仅要跟985、211毕业的学生以及研究生进行竞争,甚至还需要和最近刚被裁的、有了几年工作经验的程序员竞争,…

page.json

uni-app需要给page.json文件需要进行配置路由,否则会不报错,也跳转不过去

【数模/启发式算法】蚁群算法

文章目录简介符号说明核心思想流程图文章使用到的测试函数基本步骤蚁群算法代码简介 蚁群算法是一种用来寻找优化路径的概率型算法。它由Marco Dorigo于1992年在他的博士论文中提出,其灵感来源于蚂蚁在寻找食物过程中发现路径的行为。 这种算法具有分布计算、信息正…

Arduino播放声音

玩软件有点虚无,没有实际东西,所以接下来要体验下硬件与软件结合。 1 Arduino Arduino是一种包含硬件(各种型号的Arduino板)和软件(Arduino IDE)的开源电子平台。硬件部分是可以用来做电路连接的Arduino电…

小白学习Java第四十三天

Git概述 (一)什么是Git Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一…

设计模式学习笔记(五) - 观察者模式 Observer

目录 观察者模式 Observer 一、背景描述 Version 1 (面向过程) Version 2 (面向对象) Version 3 (单个观察者) Version 4 (多个观察者) Version 5 (分离观察者与被观察者) 二、不同事件下的观察者模式 三、事件本身也可以形成继承体系 四、观察者常用场景 观察者模式…

Selenium基础 — 鼠标操作

1、鼠标事件介绍 前面例子中我们已经学习到可以用click()来模拟鼠标的单击操作,而我们在实际的web产品测试中发现,有关鼠标的操作,不单单只有单击,有时候还要用到右击,双击,拖动等操作,这些操作…

【Nginx】认识与基本使用 Nginx 实现反向代理、配置负载均衡

文章目录1. Nginx 概述1.1 Nginx 介绍1.2 Nginx 下载和安装1.3 Nginx 目录结构2. Nginx 命令3. Nginx 配置文件结构4. Nginx 具体应用4.1 部署静态资源4.2 反向代理4.2.1 介绍4.2.2 配置反向代理4.3 负载均衡4.3.1 介绍4.3.2 配置负载均衡4.3.3 负载均衡策略1. Nginx 概述 1.1…

Ubuntu开机界面出现“error found when loading /root/.profile”

原因 今天一开始按照一篇文章,想把普通用户的权限提高到最高权限,修改了**/etc/passwd**文件,然后重启,发现之前的用户进不去了,一开机就出现如下信息 解决方法 1、重启虚拟机进入recovery模式(长按shi…

计算机网络-第一章 | 王道考研

目录 一、基本介绍 定义 功能 组成 分类 标准化工作 标准的分类 标准化工作相关组织 二、性能指标 ※ 速率 带宽 ※吞吐量 时延 时延带宽积 往返时延RTT 利用率 三、分层结构 ※ 分层基本规则 正式认识分层 7层OSI参考模型 怎么来的 怎么分的 怎么传的…

<特殊类设计与单例模式>——《C++高阶》

目录 1.请设计一个类,不能被拷贝 2. 请设计一个类,只能在堆上创建对象 3. 请设计一个类,只能在栈上创建对象 4. 请设计一个类,不能被继承 5. 请设计一个类,只能创建一个对象(单例模式) 后记:●由于…

GD32F307VC+WIN10+VSCODE+GCC+JLINK环境build

为了构建Cortex M系列单片机免费开源的开发环境,网络上了解来看VSCODEGCCJLINK是一套比较高效的组合方式,下面记录环境搭建的流程。 我这边的PC环境为 WIN10专业版64bit。 工具准备 1. arm-none-eabi-gcc下载及安装 官网下载链接:Downloa…

c++数据结构:数组和向量

线性表: 在数据元素的非空有限集中 存在唯一的一个被叫做“第一个”的数据元素存在唯一的一个被叫做“最后一个”的数据元素除第一个之外,集合中的每个数据元素均只有一个前驱除最后一个之外,每个集合元素均只有一个后继数据结构中线性结构指…

文字识别检测入门(1)

CTPN 优点:对水平文字检测效果超级好 缺点:对扭曲的文字不好 RRPN 在faster的基础上改进 RPN改为RRPN ROI pooling改进为RROI pooling 能解决旋转,但是解决不了弯曲的曲面问题 EAST Anchor free 特征合并,检测不同尺度文本 检测各…

刷爆leetcode第三期 0007~0010

刷爆leetcode第三期 0007~0010 题目一 反转链表解法一解法二题目二 链表的中间节点题目三 链表的倒数第K个节点题目四 合并两个有序链表题目一 反转链表 解法一 给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。 示例 1&#xff1a…