【c++】类和对象7—继承
文章目录
- 关于继承
- 继承与非继承的对比
- 继承方式
- 继承中的对象模型
- 继承中的构造和析构顺序
- 继承同名成员处理方式
- 继承同名静态成员处理方式
- 多继承语法
- 菱形继承
关于继承
我们发现,定义一些类时,下级别的成员处理拥有上一级的共性,还有自己的特性。
这时候我们就可以考虑利用继承的技术,减少重复代码。
继承的好处:减少重复代码
语法:
class 子类 : 继承方法 父类;
如:class A:public B;
A类称为子类或派生类
B类称为父类或基类
派生类中的成员包含两大部分:
一类是从基类继承过来的,一类是自己增加的成员。
从基类继承过来的表现其共性,而新增的成员体现了其个性。
继承与非继承的对比
非继承方式实现:
#include<iostream>
using namespace std;//Java页面
class Java
{
public:void header(){cout << "首页、公开课、登录...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共分类列表)" << endl;}void content(){cout << "Java学科视频" << endl;}
};//Python页面
class Python
{
public:void header(){cout << "首页、公开课、登录...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共分类列表)" << endl;}void content(){cout << "Python学科视频" << endl;}
};//C++页面
class Cpp
{
public:void header(){cout << "首页、公开课、登录...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共分类列表)" << endl;}void content(){cout << "C++学科视频" << endl;}
};void test()
{//Java页面cout << "Java下载视频页面如下:" << endl;Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "-----------" << endl;//Python页面cout << "Python下载视频页面如下:" << endl;Python py;py.header();py.footer();py.left();py.content();cout << "-----------" << endl;//C++页面cout << "C++下载视频页面如下:" << endl;Cpp cp;cp.header();cp.footer();cp.left();cp.content();
}int main()
{test();system("pause");return 0;
}
继承方式实现:
#include<iostream>
using namespace std;//公共页面
class BasePage
{
public:void header(){cout << "首页、公开课、登录...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共分类列表)" << endl;}
};//Java页面
class Java :public BasePage
{
public:void content(){cout << "Java学科视频" << endl;}
};//Python页面
class Python :public BasePage
{
public:void content(){cout << "Python学科视频" << endl;}
};//C++页面
class Cpp :public BasePage
{
public:void content(){cout << "C++学科视频" << endl;}
};void test()
{//Java页面cout << "Java下载视频页面如下:" << endl;Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "-----------" << endl;//Python页面cout << "Python下载视频页面如下:" << endl;Python py;py.header();py.footer();py.left();py.content();cout << "-----------" << endl;//C++页面cout << "C++下载视频页面如下:" << endl;Cpp cp;cp.header();cp.footer();cp.left();cp.content();
}int main()
{test();system("pause");return 0;
}
继承方式
继承的语法:class 子类 : 继承方式 父类
C++中的继承方式有:
public、private、protected三种
(它们直接影响到派生类的成员、及其对象对基类成员访问的规则)
(1)public(公有继承):
继承时保持基类中各成员属性不变,并且基类中private成员被隐藏。
派生类的成员只能访问基类中的public/protected成员,而不能访问private成员;
派生类的对象只能访问基类中的public成员。
(2)protected(保护性继承):
继承时基类中各成员属性均变为protected,并且基类中private成员被隐藏。
派生类的成员只能访问基类中的public/protected成员,而不能访问private成员;
派生类的对象不能访问基类中的任何的成员。
(3)private(私有继承):
继承时基类中各成员属性均变为private,并且基类中private成员被隐藏。
派生类的成员只能访问基类中的public/protected成员,而不能访问private成员;
派生类的对象不能访问基类中的任何的成员。
#include<iostream>
using namespace std;class dad
{
public:int m_A;
protected:int m_B;
private:int m_C;
};class son1 :public dad
{
public:void func(){m_A = 10;//父类中的公共权限成员到子类中 依然是公共权限m_B = 20;//父类中的保护权限成员到子类中 依然是保护权限//m_C = 30;//父类中的私有权限成员到子类中 访问不到}
};void test01()
{son1 s1;s1.m_A = 10;//s1.m_B = 20;//son1中m_B是保护权限 类外访问不到
}class son2 :protected dad
{
public:void func(){m_A = 10;//父类中的公共权限成员到子类中 变为保护权限m_B = 20;//父类中的保护权限成员到子类中 依然是保护权限//m_C = 30;//父类中的私有权限成员到子类中 访问不到}
};void test02()
{son2 s2;//s2.m_A = 10;//son2中m_A变为保护权限 类外访问不到//s2.m_B = 20;//son2中m_B是保护权限 不可访问
}class son3 :private dad
{
public:void func(){m_A = 10;//父类中的公共权限成员到子类中 变为私有权限m_B = 20;//父类中的保护权限成员到子类中 变为私有权限//m_C = 30;//父类中的私有权限成员到子类中 访问不到}
};void test03()
{son3 s3;//s3.m_A = 10;//son3中m_A变为私有权限 类外访问不到//s3.m_B = 20;//son3中m_B是私有权限 类外访问不到
}class grandson3 :public son3
{
public:void func(){//m_A = 10;//到son3中m_A变为私有,即使是儿子也访问不到//m_B = 20;//到son3中m_B变为私有,即使是儿子也访问不到}
};int main()
{test01();test02();test02();system("pause");return 0;
}
继承中的对象模型
#include<iostream>
using namespace std;class dad
{
public:int m_A;
protected:int m_B;
private:int m_C;
};class son :public dad
{
public:int m_D;
};void test01()
{//父类中所有非静态成员属性都会被子类继承下去//父类中私有成员属性是被编译器给隐蔽了,因此是访问不到,但是确实被继承下去了cout << "size of son=" << sizeof(son) << endl;//16
}int main()
{test01();system("pause");return 0;
}输出:
size of son=16
继承中的构造和析构顺序
子类继承父类后,当创建子类对象,也会调用父类的构造函数。
#include<iostream>
using namespace std;class dad
{
public:dad(){cout << "dad构造函数" << endl;}~dad() {cout << "dad析构函数" << endl;}
};class son :public dad
{
public:son() {cout << "son构造函数" << endl;}~son(){cout << "son析构函数" << endl;}
};void test01()
{dad d;
}void test02()
{cout << "继承中的构造和析构顺序如下:" << endl;//先构造父类,再构造子类,析构的顺序与构造顺序相反son s;
}int main()
{test01();test02();system("pause");return 0;
}输出:
dad构造函数
dad析构函数
继承中的构造和析构顺序如下:
dad构造函数
son构造函数
son析构函数
dad析构函数
总结:
继承中,先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反。
继承同名成员处理方式
访问子类同名成员,直接访问即可;
访问父类同名成员,需要加作用域。
#include<iostream>
using namespace std;class dad
{
public:dad(){m_A = 100;}void func(){cout << "dad的func()调用" << endl;}void func(int a){cout << "dad的func(int a)调用" << endl;}int m_A;
};class son :public dad
{
public:son(){m_A = 200;}void func(){cout << "son的func()调用" << endl;}int m_A;
};//同名成员属性处理
void test01()
{son s;cout << "son下m_A = " << s.m_A << endl;//如果通过子类对象访问到父类中同名成员,需要加作用域cout << "dad下m_A = " << s.dad::m_A << endl;
}//同名成员函数处理
void test02()
{son s;s.func();//直接调用,调用的是子类中的同名成员s.dad::func();//调用到父类中的同名成员函数//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数//如果想访问到父类中被隐藏的同名成员函数,需要加作用域s.dad::func(100);
}int main()
{test01();test02();system("pause");return 0;
}输出:
son下m_A = 200
dad下m_A = 100
son的func()调用
dad的func()调用
dad的func(int a)调用
总结:
1、子类对象可以直接访问子类中同名成员;
2、子类对象加作用域可以访问到父类同名成员;
3、当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数。
继承同名静态成员处理方式
静态成员特点:
1、所有变量共享同一份数据;
2、编译阶段分配内存;
3、类内声明,类外初始化。
静态成员和非静态成员出现同名,处理方式一致:
访问子类同名成员,直接访问即可;
访问父类同名成员,需要加作用域。
#include<iostream>
using namespace std;class dad
{
public:static void func(){cout << "dad的static void func()调用" << endl;}static void func(int a){cout << "dad的static void func(int a)调用" << endl;}static int m_A;
};
int son::m_A = 100;class son :public dad
{
public:static void func(){cout << "son的static void func()调用" << endl;}static int m_A;
};
int son::m_A = 200;//同名成员属性处理
void test01()
{//通过对象访问cout << "通过对象访问:" << endl;son s;cout << "son下m_A = " << s.m_A << endl;//如果通过子类对象访问到父类中同名成员,需要加作用域cout << "dad下m_A = " << s.dad::m_A << endl;//通过类名访问cout << "通过类名访问:" << endl;cout << "son下m_A = " << son::m_A << endl;//第一个::代表通过类名方式访问 第二个::代表访问父类作用域下cout << "dad下m_A = " << son::dad::m_A << endl;
}//同名成员函数处理
void test02()
{//通过对象访问cout << "通过对象访问:" << endl;son s;s.func();//直接调用,调用的是子类中的同名成员s.dad::func();//调用到父类中的同名成员函数//通过类名访问cout << "通过类名访问:" << endl;son::func();son::dad::func();//如果子类中出现和父类同名的静态成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数//如果想访问到父类中被隐藏的同名成员函数,需要加作用域son::dad::func(100);
}int main()
{test01();test02();system("pause");return 0;
}
总结:
同名静态成员处理方式和非静态处理方式一样,只不过有两种访问方式(通过对象和通过类名)。
多继承语法
c++允许一个类继承多个类
语法:class 子类 : 继承方式 父类1, 继承方式 父类2…
多继承可能会引发父类中有同名成员出现,需要加作用域区分
#include<iostream>
using namespace std;class dad1
{
public:dad1(){m_A = 100;}int m_A;
};class dad2
{
public:dad2(){m_A = 200;}int m_A;
};class son :public dad1, public dad2
{
public:son(){m_C = 300;m_D = 400;}int m_C;int m_D;
};void test01()
{son s;cout << "sizeof son = " << sizeof(s) << endl;//当父类在中出现同名成员,需要加作用域区分cout << "dad1::m_A = " << s.dad1::m_A << endl;cout << "dad2::m_A = " << s.dad2::m_A << endl;
}int main()
{test01();system("pause");return 0;
}
菱形继承
概念:
两个派生类继承同一个基类,又有某个类同时继承这两个派生类。
这种继承称为菱形继承,或者砖石继承。
菱形继承问题:
1、产生二义性;
2、继承两份数据,资源浪费。
利用虚继承(加关键字virtual)可以解决菱形继承问题。
#include<iostream>
using namespace std;class animal
{
public:int m_age;
};//利用虚继承 解决菱形继承的问题
//继承之前 加上关键字virtual变为虚继承
//animal类称为虚基类
class sheep :virtual public animal{};class tuo :virtual public animal{};class sheeptuo :public sheep, public tuo{};void test01()
{sheeptuo st;st.sheep::m_age = 18;st.tuo::m_age = 28;//当菱形继承,两个父类拥有相同数就,需要加上作用域区分cout << "st.sheep::m_age = " << st.sheep::m_age << endl;cout << "st.tuo::m_age = " << st.tuo::m_age << endl;cout << "st.m_age = " << st.m_age << endl;//这份数据我们知道,只有一份就可以,菱形继承导致数据有两份,造成资源浪费
}int main()
{test01();system("pause");return 0;
}
相关文章:
【c++】类和对象7—继承
文章目录关于继承继承与非继承的对比继承方式继承中的对象模型继承中的构造和析构顺序继承同名成员处理方式继承同名静态成员处理方式多继承语法菱形继承关于继承 我们发现,定义一些类时,下级别的成员处理拥有上一级的共性,还有自己的特性。 …...
vue实现预览、下载和打印后端返回的pdf文件流
需求:后端返回pdf文件流,前端能够预览、下载打印。 后端返回的文件流部分截图 需要实现的效果图 前面第1步只是为了展示后台返回数据流,完成功能的时候,不需要调用接口的,只需要利用调用接口的url。 实现步骤&am…...
【Android视频号④ 问题总结】
这节坑比较多~ 差点没把我给整死!!! 环境介绍 首先我调试都是root过的真机,但是生产环境都是没有Root的云机,属于自己改的Rom框架也不是XP或LSP 是技术人员利用Xposed源码改的框架 问题&解决 模块源码更改 这…...
推荐算法—widedeep原理知识总结代码实现
wide&deep原理知识总结代码实现1. Wide&Deep 模型的结构1.1 模型的记忆能力1.2 模型的泛化能力2. Wide&Deep 模型的应用场景3. Wide&Deep 模型的代码实现3.1 tensorflow实现3.2 pytorch实现今天,总结一个在业界有着巨大影响力的推荐模型,…...
PHP面向对象03:命名空间
PHP面向对象03:命名空间一、命名空间基础二、子空间三、命名空间访问1. 非限定名称2. 限定名称3. 完全限定名称四、全局空间五、命名空间应用六、命名空间引入一、命名空间基础 namespace,是指人为的将内存进行分隔,让不同内存区域的同名结构…...
Elasticsearch:使用 pipelines 路由文档到想要的 Elasticsearch 索引中去
路由文件 当应用程序需要向 Elasticsearch 添加文档时,它们首先要知道目标索引是什么。在很多的应用案例中,特别是针对时序数据,我们想把每个月的数据写入到一个特定的索引中。一方面便于管理索引,另外一方面在将来搜索的时候可以…...
前端开发常用的18个JavaScript框架和库
JavaScript 可以说是最流行的编程语言之一,也是Web 开发人员必须学习的 3 种语言之一,JavaScript 几乎可以做任何事情,更可以在包括物联网在内的多个平台和设备上运行。在WebGL库和SVG/Canvas元素的支持下,JavaScript变得惊人的强…...
理解、总结重点知识
一、常见的数据结构 1、数组结构 数组结构: 存储区间连续、内存占用严重、空间复杂度大 优点:随机读取和修改效率高,原因是数组是连续的(随机访问性强,查找速度快)缺点:插入和删除数据效率低&a…...
记一次从文件备份泄露到主机上线
前言 记录下某个测试项目中,通过一个文件备份泄露到主机上线的过程。 文件备份泄露 对于测试的第一项当然是弱口令,bp跑了一通词典,无果。目录又爆破了一通,发现一个web.rar可通,赶紧下载看看,如下图所示…...
8年测开经验面试28K公司后,吐血整理出1000道高频面试题和答案
1、python的数据类型有哪些 答:Python基本数据类型一般分为:数字、字符串、列表、元组、字典、集合这六种基本数据类型。 浮点型、复数类型、布尔型(布尔型就是只有两个值的整型)、这几种数字类型。列表、元组、字符串都是序列。 2、列表和元组的区别 答…...
Linux 基础知识之权限管理
目录一、权限的认识二、用户切换三、文件权限1.三类文件访问者2.文件权限类型3.文件访问权限4.文件权限值表示一、权限的认识 权限是对用户所能进行的操作的限制,如果不对用户作出限制,那么碰到恶意用户,就会损害其他用户的利益。 Linux是多用…...
百度LAC分词
对应数据的链接放这里了 import pandas as pd from util.logger import Log import os from util.data_dir import root_dir from LAC import LAC os_file_name os.path.split(os.path.realpath(__file__))[-1]# 加载LAC模型 lac LAC(mode"lac") # 载入自定义词典 …...
软件测试面试题 —— 整理与解析(1)
😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。 📡主页地址:🌎【Austin_zhai】🌏 🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能…...
深入浅出C++ ——红黑树模拟实现STL中的set与map
文章目录一、红黑树二、用泛型红黑树模拟实现set三、用泛型红黑树模拟实现map一、红黑树 红黑树作为set和map的底层容器,既要实现插入key又要实现插入pair,所以做了稍许的改动,使其成为一颗泛型结构的红黑树,通过不同的实例化参数…...
自动化测试框架设计
大数据时代,多数的web或app产品都会使用第三方或自己开发相应的数据系统,进行用户行为数据或其它信息数据的收集,在这个过程中,埋点是比较重要的一环。 埋点收集的数据一般有以下作用: 驱动决策:ABtest、漏…...
【虚拟仿真】Unity3D中实现鼠标的单击、双击、拖动的不同状态判断
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 这篇文章分享一下虚拟仿真项目中经常碰到鼠标事件控制代码。 …...
【2023】Prometheus-相关知识点(面试点)
目录1.Prometheus1.1.什么是Prometheus1.2.Prometheus的工作流程1.3.Prometheus的组件有哪些1.4.Prometheus有什么特点1.5.Metric的几种类型?分别是什么?1.6.Prometheus的优点和缺点1.7.Prometheus怎么采集数据1.8.Prometheus怎么获取采集对象1.9.Promet…...
英语二-电子邮件邀请短文写作
1. 邮件模板 Dear 邀请人, Hope you have a great day. I am writing this email to invite you to attend 主题. Please kindly find the following information for your reference: Time: 时间 Address: 地点 We hope that nothing will prevent you from coming, as…...
如何快速一次性通过pmp考试?
我们就从三个方向进行了解 1.PMP考试难不难? 2.PMP如何备考? 3.考试过程中需要注意什么? 一,PMP考试难不难? 首先关注的问题是,PMP考试难吗?我想全球55%的通过率和学会这边93.9%的通过率&a…...
1-Linux 保存kernel panic信息到flash
在系统运行过程中,如果内核发生了panic,那么开发人员需要通过内核报错日志来进行定位问题。但是很多时候出现问题的时候没有接调试串口,而报错日志是在内存里面的,重启后就丢失了。所以需要一种方法,可以在系统发生crash时&#x…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
