【C++进阶(八)】C++继承深度剖析

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

继承

  • 1. 前言
  • 2. 继承的基本概念
  • 3. 继承关系和访问限定符
  • 4. 继承中的作用域
  • 5. 父子类的对象赋值转换
  • 6. 子类中的默认成员函数
  • 7. 继承与友元,继承与静态变量
  • 8. 菱形继承和虚拟继承
  • 9. 总结以及拓展

1. 前言

接下来的几篇博客会进入C++
继承和多态的学习,在校招笔试
和面试中这一章节考察的很多!
请同学们耐心学习!

本章重点:

本篇文章着重讲解继承的概念和定义,
父类和子类的对象赋值转换,
继承中的作用域以及子类的默认成员函数
以及继承和友元,继承和静态成员的关系
最后讲解菱形继承和虚继承概念


2. 继承的基本概念

继承,其实就是一种代码的复用手段
子类继承父类就能用父类中的变量!

举一个例子:

在师生管理系统中,有学生和老师两个
角色,学生和老师的共同信息有:姓名
性别,年龄和身高等等,然而学生又有一些
专有的信息,比如学号和所属学院
老师也有专属信息如:工号和所教学科

这样就可以将师生的共同信息提取出来:

struct Person
{string name;string sex;int age;int height;
}

在实现student类和teacher类时
只需要继承上面的person类即可!

class Student : public Person
{
protected:int _stuid; // 学号
};
class Teacher : public Person
{
protected:int _jobid; // 工号
};

在这里插入图片描述

派生类也被称为子类
基类也被称为父类

父子类成员的使用:

Student st;
st._stuid=123456;
st.name="张三";
st.age=20;

子类对象中课直接调用父类变量!


3. 继承关系和访问限定符

继承方式和访问限定符一样有三种:
在这里插入图片描述

继承的方式不同,那么子类中继承
到的父类的变量的访问权限就不同
可以用下面的表格来表示它们的关系:

在这里插入图片描述
我简单的总结以下几点:

  1. 无继承体系中,protected和private没有区别
  2. 在继承体系中,父类的protected成员在子类
    中也是protected或保护成员
  3. 父类的private成员在子类是不可见的!
    (继承下来了但不能使用)
  4. 实际中使用继承时一般都用public继承
  5. 使用关键字class时默认的继承方式是private
    使用struct时默认的继承方式是public

4. 继承中的作用域

先说以下结论:

  1. 继承体系中基类和子类有独立的作用域
  2. 子类和父类中有同名成员时,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义(在子类成员函数中,可以使用基类::基类成员显示访问)
  3. 需要注意的是如果是成员函数的隐藏
    只需要函数名相同就构成隐藏
  4. 实际中在继承体系里面最好不要定义同名的成员
class Person
{
protected :int _num = 111;   // 身份证号
};class Student : public Person
{
protected:int _num = 999; // 学号
};

在main函数中定义student对象
后再打印_num默认为子类中的_num
若想打印父类中的_num,需要指定类域

Student st;
cout<<st._num;
cout<<st.Person::_num;

有同学可能会疑惑:函数名相同的话
不应该是构成函数重载吗?是的,在同一
作用域下,函数名相同确实构成函数重载
但是父子类是不同作用域,这里是构成隐藏!


5. 父子类的对象赋值转换

老样子,先说结论:

  • 子类对象可以赋值给基类的
    -/对象/基类的指针/基类的引用

  • 基类对象不能赋值给派生类对象

在这里插入图片描述

注意这里能够赋值不是隐式类型转换!


6. 子类中的默认成员函数

还记得类的六个默认成员函数吗?
就是不显示写系统会自动生成的:

在这里插入图片描述

子类的默认成员函数有哪些特殊的行为?
下面我直接给出结论:

  1. 子类的构造函数必须显示调用父类的构造
    去初始化父类的那部分成员(拷贝构造也是)
  2. 子类的operator=中必须调用父类的
    operator=完成父类成员赋值
  3. 子类的析构函数不用显示调用父类的析构
    编译器会自动去调用
  4. 子类初始化对象时,先初始化父类的成员变量
    再初始化子类的成员变量
  5. 子类析构清理时先调用子类的析构函数
    再调用父类的析构函数(与构造反过来)

可以使用以下代码区验证此结论:

class Person
{
public :Person(const char* name = "peter"): _name(name ){cout<<"Person()" <<endl;}Person(const Person& p): _name(p._name){cout<<"Person(const Person& p)" <<endl;}Person& operator=(const Person& p ){cout<<"Person operator=(const Person& p)"<< endl;if (this != &p)_name = p ._name;return *this ;}~Person(){cout<<"~Person()" <<endl;}
protected :string _name ; // 姓名
};
class Student : public Person
{
public :Student(const char* name, int num): Person(name ), _num(num ){cout<<"Student()" <<endl;}Student(const Student& s): Person(s), _num(s ._num){cout<<"Student(const Student& s)" <<endl ;}Student& operator = (const Student& s ){cout<<"Student& operator= (const Student& s)"<< endl;if (this != &s){Person::operator =(s);_num = s ._num;}return *this ;} ~Student(){cout<<"~Student()" <<endl;}
protected :int _num ; //学号
};
void Test ()
{Student s1 ("jack", 18);Student s2 (s1);Student s3 ("rose", 17);s1 = s3 ;
}

7. 继承与友元,继承与静态变量

继承与友元的关系很简单一句话:

友元关系不能继承
也就是说基类友元不能访问子类私有和保护成员

继承和静态成员的关系也很简单:

基类中定义的静态成员被整个继承体系共享
整个继承体系里面只有一个这样的成员
无论派生出多少个子类
都只有一个static成员实例


8. 菱形继承和虚拟继承

在使用继承时会遇见以下情况:

类B继承了类A,类C也继承了类A
然而类D继承了类B和C

在这里插入图片描述

此时会有一个问题,类D的实例化对象中
有类B和类C,然而B类和C类都有A类
所以说D类对象中的A类成员就重复了!

class A
{int _a = 1;
};
class B :public A
{int _b = 2;
};
class C :public A
{int _c = 3;
};
class D :public B, A
{int _d = 4;
};

我们通过内存窗口观察一下:

在这里插入图片描述

D对象中有两个_a,一个在B类一个在C类
这就造成了数据冗余,于是可以使用虚拟继承
来解决这一问题:

虚拟继承:在继承前加上virtual关键字

class A
{int _a = 1;
};
class B :virtual public A
{int _b = 2;
};
class C :virtual public A
{int _c = 3;
};
class D :public B, A
{int _d = 4;
};

注意,只用腰部的类加上virtual即可!
virtual这一关键字在多态还有大用处!


9. 总结以及拓展

继承是多态的基础,而笔试面试的时候
继承和多态是考察的很多的,希望同学们
把基础打扎实.当然关于继承的内容其实不止
这些,这些只是最重要的内容,关于继承问题
我们将在下一章节:多态时再展开叙述

对于is-a和has-a的拓展阅读:

拓展阅读


🔎 下期预告:C++继多态 🔍

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

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

相关文章

酷开会员值得回味的经典老剧还记得吗?酷开系统家庭影院带你重温

那些年&#xff0c;大家的娱乐生活主要集中在那一台9寸的黑白电视机中&#xff1b;那些年&#xff0c;家家户户的孩子们晚上都会聚到电视机前欢声笑语&#xff1b;那些年&#xff0c;是诸多经典的电视剧陪伴了很多人的闲暇时光……那些年陪伴我们成长&#xff0c;在记忆中熠熠生…

下笔如有神:用VS Code写markdown

文章目录 Markdown All in One快捷键指令 输出PDFMarkdown Preview Enhancedmarkdown基本语法 Markdown All in One VS Coode中最推荐的Markdown插件是Markdown All in One&#xff0c;下文简称为mdAIO。千万别搜完markdown后下一个叫Markdown的插件&#xff0c;这个插件的名字…

新年学新语言Go之四

一、前言 任何编程语言都有类型系统&#xff0c;类型系统解决了数据的存取问题&#xff0c;它决定了使用这个类型需要开辟内存空间大小以及数据是如何存放的&#xff0c;也解决如何读出数据&#xff0c;因为在内存中相同二进制值不同类型的含义是不一样的&#xff0c;关于Go基…

Oracle的立场:官网更换首页与以色列站在一起

Oracle公司的官网&#xff0c;更换了首页内容&#xff0c;明确表明立场&#xff1a;Oracle与以色列站在一起。 声明指出&#xff1a; Oracle谴责针对以色列及其公民的恐怖袭击。Oracle将为其员工、以色列政府和国防机构提供一切必要的支持。 Magen David Adom是一家为以色列公民…

1024,毕业后工作的五个月

入职 一晃一下又到了1024&#xff0c;彼时已经成为打工人在写分享了&#xff0c;自己已经搬砖5个月了&#xff0c;总感觉4月份拍毕业照、去川渝毕业旅行看plmm还是在昨天&#xff0c;但五月下旬入职到现在已经5个月了。给大家简单的share一下工作和生活。 在5月初光速毁约ks入…

《数据结构、算法与应用C++语言描述》使用C++语言实现数组队列

《数据结构、算法与应用C语言描述》使用C语言实现数组队列 定义 队列的定义 队列&#xff08;queue&#xff09;是一个线性表&#xff0c;其插入和删除操作分别在表的不同端进行。插入元素的那一端称为队尾&#xff08;back或rear&#xff09;&#xff0c;删除元素的那一端称…

在 Python 3 中释放 LightGBM 的力量:您的机器学习大师之路

机器学习是 Python 占据主导地位的领域,它一直在给全球各行各业带来革命性的变化。要在这个不断变化的环境中脱颖而出,掌握正确的工具是关键。LightGBM 就是这样一个工具,它是一个强大且快速的梯度提升框架。在这份综合指南中,我们将通过实际示例和示例数据集从基础知识到高…

系列十二、Redis的主从复制

一、概述 主从复制架构仅仅用来解决数据的冗余备份&#xff0c;从节点仅仅用来同步数据。 二、架构图 三、搭建主从复制 3.1、准备三台机器并修改配置 # 准备三台机器并修改配置 说明&#xff1a;由于是个人笔记本&#xff0c;开启3个虚拟机比较消耗内存&#xff0c;所以使用…

快如闪电的扩容:秒级启动,弹性伸缩让您无忧

文章目录 快速扩容&#xff1a;秒级启动&#xff0c;弹性伸缩服务器秒级启动服务秒级启动升级JDK的版本通过将应用程序打包成WAR文件并部署到已经启动的Tomcat服务器上来实现秒级启动使用Spring Cloud Function和云原生技术来构建无服务器应用程序&#xff0c;可以实现秒级启动…

《动手学深度学习 Pytorch版》 9.5 机器翻译与数据集

机器翻译&#xff08;machine translation&#xff09;指的是将序列从一种语言自动翻译成另一种语言&#xff0c;基于神经网络的方法通常被称为神经机器翻译&#xff08;neural machine translation&#xff09;。 import os import torch from d2l import torch as d2l9.5.1 …

云表|低代码开发崛起:重新定义企业级应用开发

低代码开发这个概念在近年来越来越受到人们的关注&#xff0c;市场对于低代码的需求也日益增长。据Gartner预测&#xff0c;到2025年&#xff0c;75&#xff05;的大型企业将使用至少四种低代码/无代码开发工具&#xff0c;用于IT应用开发和公民开发计划。 那么&#xff0c;为什…

黑豹程序员-架构师学习路线图-百科:MVC的演变终点SpringMVC

MVC发展史 在我们开发小型项目时&#xff0c;我们代码是混杂在一起的&#xff0c;术语称为紧耦合。 如最终写ASP、PHP。里面既包括服务器端代码&#xff0c;数据库操作的代码&#xff0c;又包括前端页面代码、HTML展现的代码、CSS美化的代码、JS交互的代码。可以看到早期编程就…

【C语言】#define宏与函数的优劣对比

本篇文章目录 1. 预处理指令#define宏2. #define定义标识符或宏&#xff0c;要不要最后加上分号&#xff1f;3.宏的参数替换后产生的运算符优先级问题3.1 问题产生3.2 不太完美的解决办法3.3 完美的解决办法 4.#define的替换规则5. 有副作用的宏参数6. 宏与函数的优劣对比6.1 宏…

向量数据库Transwarp Hippo1.1多个新特性升级,帮助用户实现降本增效

例如,当查询“A公司业务发展情况”时,通过向量检索可以检索出A公司“主要业务”、“经营模式”、“财务情况”、“市场地位”等信息,通过全文检索可以检索出知识库中和关键字“业务”、“发展”相关的结果作为补充,通过将两者检索的结果进行结合,可以使得大模型回答的结果…

分类预测 | Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入分类预测

分类预测 | Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入分类预测 目录 分类预测 | Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现WOA-GRU鲸鱼算法优化门控循环单元的数据多输入…

【Qt】常见控件

文章目录 按钮组QListWidget列表容器TreeWidget树控件TableWidget 表格控件其它控件介绍下拉框QLabel显示图片和动图 自定义控件封装 按钮组 QPushButton 常用按钮 QToolButton 工具按钮&#xff1a; 用于显示图片 如果想显示文字&#xff1a;修改风格&#xff1a;toolButto…

文档外发控制与安全:实现高效协作与数据安全的关键

随着企业数据量的不断增加&#xff0c;文档外发成为了一个不可避免的需求。然而&#xff0c;很多企业在文档外发过程中存在着很多问题&#xff0c;如数据泄露、信息误用等。因此&#xff0c;如何保证文档外发的安全性和高效性成为了企业亟待解决的问题。飞驰云联Ftrans的文件收…

Kafka Tool(Kafka 可视化工具)安装及使用教程

Kafka Tool&#xff08;Kafka 可视化工具&#xff09;安装及使用教程 Kafka Tool 工具下载 下载地址 http://www.kafkatool.com/download.html 下载界面 不同版本的Kafka对应不同版本的工具&#xff0c;个人使用的是2.11&#xff0c;所以下载的是最新的2.0.8版本&#xff…

C++初阶--C++入门(2)

C入门&#xff08;1&#xff09;链接入口 文章目录 内联函数auto关键字注意事项 基于范围的for循环(C11)nullptr 内联函数 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提…

Spring学习笔记(2)

Spring学习笔记&#xff08;2&#xff09; 一、Spring配置非定义Bean1.1 DruidDataSource1.2、Connection1.3、Date1.4、SqlSessionFactory 二、Bean实例化的基本流程2.1 BeanDefinition2.2 单例池和流程总结 三、Spring的bean工厂后处理器3.1 bean工厂后处理器入门3.2、注册Be…