C++进阶--继承

概念

继承,允许一个类(称为子类或派生类)从另一个类(称为父类或基类)继承属性和方法
继承的主要目的是实现代码的重用和构建类之间的层次关系。通过继承,子类可以获得父类的特性,包括数据成员和成员函数,而无需重新编写相同的代码。

定义

class Person
{
public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;}
protected:string _name = "peter";int _age = 18;
};class Student : public Person
{
protected:int _SId;
};class Teacher :public Person
{
protected:int _TId;
};int main()
{Student s;Teacher t;s.Print();t.Print();return 0;
}

格式

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

继承基类成员的访问方式变化

在这里插入图片描述

可以看出,基类的private成员在派生类无论以何种方式继承都是不可见的这里的不可见是虽然基类的成员仍然被继承到了,但在语法上限制了对private成员的访问,也就说如果要初始化派生类的继承成员,是没被办法初始化的
基类的protected成员以任何方式继承都是可以的,但是不同的继承方式展示出不同的权限;
使用关键字class默认继承方式是private,使用关键字struct默认继承方式是public,但还是写出继承方式比较好;
在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承。

基类和派生类的赋值转换

1.派生类对象可以赋值给基类的对象/基类的指针/基类的引用。由于子类可能会比父类多一些成员什么的,当派生类赋值给基类时,会切割基类没有的数据成员和成员函数,这种做法被称为“切片”;
2.基类对象不能赋值给派生类对象
3.基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用

class Person
{
protected:string _name="PersonName"; // 姓名string _sex; // 性别int _age=10; // 年龄
};
class Student : public Person
{
public:void Print(){cout<<"-name:" << _name << endl;cout<<"age:" << _age << endl;cout << "Personname:" << Person::_name << endl;}
protected:int _No; // 学号string _name="StudentName";
};
int main()
{Student s;//派生类赋值给基类Person p1=s;Person* p2 = &s;Person& p3 = s;//基类赋值给派生类//s = p1;//基类不能赋值给派生类Student* ps1 = (Student*)p2;//可以通过强制类型转换赋值给派生类return 0;
}

在这里插入图片描述
在这里插入图片描述

继承中的作用域

1.在继承体系中基类和派生类都有各自独立的作用域
2.在继承体系中最好不要定义同名的成员
3. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏
也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
4. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏
在这里插入图片描述

class A
{
public:void fun(){cout << "func()" << endl;}
};
class B : public A
{
public:void fun(int i){A::fun();cout << "func(int i)->" << i << endl;}
};

在这里插入图片描述

派生类的默认成员函数

1.派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认构造函数,那么可以在派生类中的构造函数初始化列表中进行显示调用;
2.派生类的拷贝构造必须调用基类的拷贝构造完成基类的拷贝初始化
3.派生类的赋值必须调用基类的operator=完成基类的复制
4.派生类的析构函数会在被调用完成后再调用基类的析构函数完成清理。这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。

class Person
{
public:Person(string name = "hama"): _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(string 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; //学号
};int main()
{Student s1("傻风",12);//构造Student s2(s1);//拷贝构造Student s3("傻怕", 18);//赋值s1 = s3;return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

继承与友元

友元函数无法继承,也就是说,基类的友元不能访问子类私有和保护成员。

class Student;
class Person
{
public:
friend void Display(const Person& p, const Student& s);
protected:
string _name; // 姓名
};
class Student : public Person
{
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);
}

在这里插入图片描述
这个好理解,父亲的朋友怎么会是孩子的朋友呢?除非让父亲的朋友也跟孩子做朋友,当然这样就不叫继承了;
在这里插入图片描述
!](https://img-blog.csdnimg.cn/direct/15e5065f11a04d4bbd198f2eeb6c692d.png)

继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员,它是独立于基类和派生类之外作用域的;只是恰好在基类中当成员。静态成员伴随着整个运行阶段;

class Person
{
public:Person() { ++_count; }
protected:string _name; // 姓名
public:static int _count; // 统计人的个数。
};
int Person::_count = 0;//初始化class Student : public Person
{
protected:int _stuNum; // 学号
};
class Graduate : public Student
{
protected:string _seminarCourse; // 研究科目
};
int main()
{Student s1;Student s2;Student s3;Graduate s4;cout << " 人数 :" << Person::_count << endl;Student::_count = 0;cout << " 人数 :" << Person::_count << endl;
}

在这里插入图片描述

菱形继承

在上面最近代码中,一个子类只有一个父类时这种继承成为单继承;
多继承:一个子类有两个或以上的父类时称这个继承为多继承
菱形继承:如下
在这里插入图片描述
菱形继承的问题:

class A
{
public:int _a;
};
// class B : public A
class B :virtual  public A
{
public:int _b;
};
// class C : public A
class C :virtual  public A
{
public:int _c;
};
class D : public B, public C
{
public:int _d;
};

在上面代码中,类D同时继承了类C和类B,而类C和类B又都继承了类A,这就构成了菱形继承的情况了;
菱形继承的主要问题是二义性。由于类D继承了两个父类,并且这两个父类都有相同的成员a,编译器无法确定具体调用B类的a还是C类的a给D类继承,从而导致二义性问题;

int main()
{D d;//虽然菱形继承可以通过显示调用来解决二义性问题,当仍然存在数据冗余d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}

在这里插入图片描述
为了解决菱形继承的二义性,C++提供了虚拟继承的机制;就是在类B和类C继承类A时加上关键字virtual,可以告诉编译器在构建类D的对象时只保留一份A类的实例
在这里插入图片描述

在实际应用中,我们很少用到多继承,也就没有菱形继承的问题;

组合和继承

继承和组合是面向对象编程中两种常见的代码复用机制。
继承:继承是一种通过创建新类基于已有类的属性和方法来实现代码复用的机制,子类可以继承父类的所有公有和受保护的成员,并且可以在此基础上添加新的特性或修改现有的行为。通过继承可以实现类之间的“is-a”关系,即子类是父类的一种特殊类型。
组合:组合是通过将一个类的对象作为另一个类的成员来实现代码复用的机制。像我们前面的逆向迭代器,stack和queue都是用到了组合;通过组合,一个类可以拥有其他类的对象,并且可以通过调用这些对象的方法来实现自己的功能。组合主要用于表示“has-a”关系,即一个类包含另一个类的对象。

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

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

相关文章

嵌合抗体介绍-泰克生物

一&#xff0e;嵌合抗体简介 人-鼠嵌合抗体&#xff0c;即抗体的可变区来自鼠单克隆抗体&#xff0c;而恒定区则来自人的抗体。它是通过从杂交瘤细胞分离出功能性可变区基因&#xff0c;与人Ig恒定区基因连接,插入适当表达载体&#xff0c;转染宿主细胞表达产生。嵌合抗体既保留…

centOS+nodejs+mysql阿里云部署前后端个人网站

centOSnodejsmysql阿里云部署前后端个人网站 参考&#xff1a; 部署NodeExpressMySQL项目到阿里云轻量应用服务器 阿里云轻量应用服务器部署Node.jsReactMongoDB前后端分离项目 参考&#xff1a;在阿里云上部署nodejs服务 https 部署的原理就是你在本地测试的时候在地址栏&am…

给零基础朋友的编程课12 代码

给零基础朋友的编程课12 下 - 仿制品7 案例_哔哩哔哩_bilibili 源代码&#xff1a; // 色表 // 桃红 254,181,167 // 粉红 255,208,199void setup() {size(1000,750);background(254,181,167); }void draw() {// 绘制画框stroke(255,208,199);strokeWeight(28);noFill();rect…

Cmake编译Opencv3.3.1遇到有些文件无法下载的错误解决:

前言&#xff1a; 对于&#xff0c;opencv有些配置文件错误并未致命&#xff0c;所以&#xff0c;有错误也不影响后续的编译&#xff1a;但是&#xff0c;后引用如果要用&#xff0c;在回过头来还是要解决的。 问题表述&#xff1a; 比如&#xff0c;有些文件下载的错误&am…

Linux可视化管理

记得看目录哦&#xff01; 1. webmin2. webmin安装及配置2.1 把软件传到opt目录下的webmin目录2.2 解压rpm -ivh webmin-1.700-1.noarch.rpm2.3 重置webmin的root密码2.4 修改webmin的端口2.5 重启webmin2.6 放开6666端口的防火墙2.7 网址输入ip&#xff1a;端口号 3. webmin的…

自建DNS劫持服务器,纯内网劫持PS5,屏蔽更新,自动hen

背景&#xff1a;目前PS5首次折腾必须要连外网&#xff0c;还要改DNS&#xff0c;除非使用ESP8266/32&#xff0c; 本文的方法是完全不改DNS&#xff0c;不使用ESP8266,不连接外网的情况下自动折腾 能实现什么&#xff1a; 1.折腾全程不连接外网 2.完全自建hen服务器&#xff…

维护管理Harbor,docker容器的重启策略

维护管理Harbor 通过HarborWeb创建项目 在 Harbor 仓库中&#xff0c;任何镜像在被 push 到 regsitry 之前都必须有一个自己所属的项目。 单击“项目”&#xff0c;填写项目名称&#xff0c;项目级别若设置为"私有"&#xff0c;则不勾选。如果设置为公共仓库&#…

[C++]类和对象(上)

目录 一:面向过程与面向对象的区别 二:类的定义 三:类的访问限定符和封装 3.1访问限定符 3.2 封装 四:类的实例化 五:类对象模型 如何计算类的大小 类对象的存储方式 六:this指针 this指针的引出 this指针的特性 一:面向过程与面向对象的区别 面向过程 C语言是面…

[机器学习]TF-IDF算法

一.TF-IDF算法概述 什么是TF-IDF&#xff1f; 词频-逆文档频率&#xff08;Term Frequency-Inverse Document Frequency&#xff0c;TF-IDF&#xff09;是一种常用于文本处理的统计方法&#xff0c;可以评估一个单词在一份文档中的重要程度。简单来说就是可以用于文档关键词的提…

SQL注入:宽字节注入

SQL注入系列文章&#xff1a; 初识SQL注入-CSDN博客 SQL注入&#xff1a;联合查询的三个绕过技巧-CSDN博客 SQL注入&#xff1a;报错注入-CSDN博客 SQL注入&#xff1a;盲注-CSDN博客 SQL注入&#xff1a;二次注入-CSDN博客 ​SQL注入&#xff1a;order by注入-CSDN博客 …

wordcloud库和jieba库的使用

文章目录 wordcloud库的简单示范使用wordcloud库报错记录anaconda安装第三方jieba库jieba库的简单示范任务 1&#xff1a;三国演义中的常见词汇分布在“三国"这两个隶书字上&#xff0c;出现频率高的词字体大任务 2&#xff1a;三国演义中出现频率前十的人名。必须是以下这…

JZ15 二进制中1的个数(牛客)(C语言)

个人博客主页&#xff1a;https://blog.csdn.net/2301_79293429?typeblog 专栏&#xff1a;https://blog.csdn.net/2301_79293429/category_12545690.html 该题我为笨办法,与题解不同,如有疑问和见解,欢迎大家在评论区提出 题目链接: 二进制中1的个数_牛客题霸_牛客网 (now…

【日常总结】如何快速迁移Navicat中的全部连接设置到新安装的Navicat中?

一、场景 二、需求 三、解决方案 Stage 1&#xff1a;“文件”-->“导出连接”。 Stage 2&#xff1a;获取备份文件 connections.ncx Stage 3&#xff1a;导入connections.ncx 四、不足 一、场景 公司电脑换新&#xff0c;所有软件需要重装&#xff0c;包括navicat 1…

如何纯前端实现文件下载

业务场景 有一个下载文件的功能&#xff0c;不引入后端资源&#xff0c;纯前端应该如何实现&#xff1f; 解决方案 在vue2或者vue3项目中&#xff0c;可以把文件放在 public 文件夹下&#xff0c;然后使用a标签进行文件下载。 如&#xff1a;我要下载的文件是模版.xlsx 。首…

Django模型(五)

一、数据的条件查询 参考文档:QuerySet API 参考 | Django 文档 | Django 1.1、常用检索字段 字段检索,是在字段名后加 __ 双下划线,再加关键字,类似 SQL 语句中的 where 后面的部分, 如: 字段名__关键字 exact :判断是否等于value,一般不使用,而直接使用 =contai…

PL/SQL plsql Developer 14最新版注册码 (亲测可用)

plsql14 注册激活&#xff0c;亲测有效 product code: ke4tv8t5jtxz493kl8s2nn3t6xgngcmgf3 serial Number: 264452 password: xs374ca 激活成功

Qt6入门教程 14:QToolButton

目录 一.简介 二.常用接口 1.void setMenu(QMenu * menu) 2.void setPopupMode(ToolButtonPopupMode mode) 3.void setToolButtonStyle(Qt::ToolButtonStyle style) 4.void setArrowType(Qt::ArrowType type) 5.void setDefaultAction(QAction * action) 三.实战演练 1…

k8s从私有库harbor中拉取镜像

一、前言 Docker镜像是构建应用程序的基础。然而&#xff0c;许多组织和开发团队希望保留他们的Docker镜像在私有仓库中&#xff0c;并从中拉取镜像&#xff0c;而不是从公共Docker Hub中下载。这样做的原因有很多&#xff0c;包括&#xff1a; 1. 安全性&#xff1a;私有仓库可…

Java 字符串 07 练习-手机号屏蔽、身份证号信息查看,游戏骂人敏感词替换

注意点&#xff1a;只有返回值才是被截取的小串&#xff0c;所以需要有一个变量去承接它&#xff1b; 自己写的代码&#xff1a; import java.util.Scanner; public class practice {public static void main(String[] args) {Scanner input new Scanner(System.in);String …

Zookeeper分布式命名服务实战

目录 分布式命名服务 分布式API目录 分布式节点的命名 分布式的ID生成器 分布式的ID生成器方案&#xff1a; 基于Zookeeper实现分布式ID生成器 基于Zookeeper实现SnowFlakeID算法 分布式命名服务 命名服务是为系统中的资源提供标识能力。ZooKeeper的命名服务主要是利用Z…