c++的学习之路:20、继承(1)

摘要

本章主要是讲以一下继承的一些概念以及使用方法等等。

目录

摘要

一、继承的概念及定义

1、继承的概念

2、继承定义

1.2.1、定义格式

1.2.2、继承关系和访问限定符

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

3、总结

二、基类和派生类对象赋值转换

三、继承中的作用域

四、派生类的默认成员函数

五、继承与友元

六、继承与静态成员

七、代码

 八、思维导图


一、继承的概念及定义

1、继承的概念

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保
持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象
程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继
承是类设计层次的复用。

这个继承形容的十分形象,就像子承父业继承家产,哈哈这个就是继承,但是呢在之前说类的时候就说了有三个类型,public、private、protected这三个类型,但是protected我却没咋用过,这里就使用,下面将会一一介绍。

2、继承定义

1.2.1、定义格式

如下方代码就是一个继承的定义,如图二就是测试结果,图一就是继承定义格式,这里public也可以不写,但是默认是私密形式,但是不也可以用struct就是共有的这里和类的定义有点相像。

class Person
{
protected:
    string _name = "张三";
    int _age = 18; 
};

class Student :public Person
{
protected:
    int _stuid;
};

1.2.2、继承关系和访问限定符

如下方两个导图就是所有的继承关系和访问限定符

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

下面表就是继承的基类成员访问方式的变化,就是根据这个表去写的权限。

类成员/继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected
成员
派生类的private
成员
基类的protected
成员
派生类的protected
成员
派生类的protected
成员
派生类的private
成员
基类的private成
在派生类中不可见在派生类中不可见在派生类中不可

3、总结

1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。

2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。

3. 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public  > protected> private。

4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。

5. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

二、基类和派生类对象赋值转换

派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片
或者切割。寓意把派生类中父类那部分切来赋值过去。基类对象不能赋值给派生类对象。

基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类
的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(Run-Time Type Information)的dynamic_cast 来进行识别后进行安全转换。

如下图所示这种切割方式,就是上述所说的切片。

三、继承中的作用域

1. 在继承体系中基类和派生类都有独立的作用域。

2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)

3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。

4. 注意在实际中在继承体系里面最好不要定义同名的成员

如下方代码想要访问B里面的fun就会访问不到,所以这里就可以看到下方代码中main的方式就可以访问了,结果如图。

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;
    }
};

int main()
{
    /*Student s;*/
    B b;
    b.fun(10);
}

四、派生类的默认成员函数

6个默认成员函数,“默认”的意思就是指我们不写,编译器会变我们自动生成一个,那么在派生类
中,这几个成员函数是如何生成的呢?

1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。

2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。

3. 派生类的operator=必须要调用基类的operator=完成基类的复制。

4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。

5. 派生类对象初始化先调用基类构造再调派生类构造。

6. 派生类对象析构清理先调用派生类析构再调基类的析构。

7. 因为后续一些场景析构函数需要构成重写,重写的条件之一是函数名相同(这个我们后面会讲解)。那么编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数不加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系。

下面的导图就是六个默认成员函数。

五、继承与友元

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员,这中的解决方式也简单就是在子类在进行声明一下是友元就可以了,如下方代码所示,就是接着声明,要不就会使用不了。

class Person
{
public:
    friend void test(const Person& p, const Student& s);
protected:
    string _name; // 姓名
};
class Student : public Person
{
public:
    friend void test(const Person& p, const Student& s);
protected:
    int _stuNum; // 学号
};

六、继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个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 s;*/
    /*B b;
    b.fun(10);*/
    Student s1;
    Student s2;
    Student s3;
    Graduate s4;
    cout << " 人数 :" << Person::_count << endl;
    
}

七、代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
#include <string>
using namespace std;//class Person
//{
//protected:
//	string _name = "张三";
//	int _age = 18; 
//};
//
//class Student :public Person
//{
//protected:
//	int _stuid;
//};
//
//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;
//	}
//};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; 
};//class Person
//{
//public:
//	friend void test(const Person& p, const Student& s);
//protected:
//	string _name; // 姓名
//};
//class Student : public Person
//{
//public:
//	friend void test(const Person& p, const Student& s);
//protected:
//	int _stuNum; // 学号
//};int main()
{/*Student s;*//*B b;b.fun(10);*/Student s1;Student s2;Student s3;Graduate s4;cout << " 人数 :" << Person::_count << endl;}

 八、思维导图

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

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

相关文章

【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt信号和槽的其他说明及Lambda表达式 文章编号&#xff1a;Qt 学习笔记…

JVS-智能BI数据分析:数仓+流程化加工的独特优势

在JVS-BI中采用了数仓流程化加工的方式进行数据分析&#xff0c;主要涉及到数据的离线抽取&#xff0c;流程化加工&#xff0c;生成标准的数据分析结果。 下面我们先看下什么是数仓&#xff1a; 数仓&#xff08;Data Warehouse&#xff09;是一个用于集中存储和管理企业中各种…

iOS 开发中上传 IPA 文件的方法(无需 Mac 电脑)

引言 在 iOS 开发中&#xff0c;将 IPA 文件上传到苹果开发者中心是一个重要的步骤。通常情况下&#xff0c;我们需要使用 Mac 电脑上的 Xcode 或 Application Loader 工具来完成这个任务。然而&#xff0c;如果你没有 Mac 电脑&#xff0c;也没有关系&#xff0c;本文将介绍一…

2024 抖音欢笑中国年(三):编辑器技巧与实践

前言 本次春节活动中&#xff0c;我们大部分场景使用内部的 SAR Creator互动方案来实现。 SAR Creator 是一款基于 TypeScript 的高性能、轻量化的互动解决方案&#xff0c;目前支持了Web和字节内部跨端框架平台&#xff0c;服务于字节内部的各种互动业务&#xff0c;包括但不限…

RabbitMQ的自动应答和手动应答,解决重试死循环

RabbitMQ的自动应答和手动应答&#xff0c;解决重试死循环 1.应答模式 RabbitMQ 中的消息应答模式主要包括两种&#xff1a;自动应答&#xff08;Automatic Acknowledgement&#xff09;和手动应答&#xff08;Manual Acknowledgement&#xff09;。 1、自动应答&#xff1a;…

保研线性代数复习4

一.范数&#xff08;Norms&#xff09; 1.什么是范数&#xff1f; 范数是一个向量空间V的函数&#xff0c;每一个属于向量空间V的向量x都匹配了一个实数&#xff08;它的长度&#xff09;&#xff1a; 2.范数的性质&#xff1f; 齐次性&#xff1a; 正定性&#xff1a; 三…

网络安全之权限维持那点事

权限维持 一旦黑客成功地入侵了目标系统&#xff0c;他们通常会尝试保持对系统的持久访问权&#xff0c;以便继续执行恶意活动&#xff0c;如窃取敏感数据、植入恶意软件、破坏系统功能等。 权限维持的过程可能包括以下几个方面&#xff1a; 后门植入&#xff1a;黑客可能会在…

easyExcel - 动态复杂表头的编写

目录 前言一、情景介绍二、问题分析三、代码实现方式一&#xff1a;head 设置方式二&#xff1a;模板导出方式三&#xff1a;自定义工具类 前言 Java-easyExcel入门教程&#xff1a;https://blog.csdn.net/xhmico/article/details/134714025 之前有介绍过如何使用 easyExcel&…

CSS-浮动文字环绕布局、隐藏属性display、overflow、三角形制作、鼠标样式

文字环绕布局 CSS文字环绕布局是指在网页中让文字环绕在图片或其他元素周围的布局方式。这通常通过CSS中的float属性来实现。你可以将图片设置为float: left;或float: right;&#xff0c;然后在文本元素中使用clear属性来清除浮动&#xff0c;以确保文字不会覆盖图片。另外&am…

Jmeter02-2:参数化组件其他方式

0、Jmeter组件&#xff1a;参数化概述 0.1 是什么&#xff1f; 参数化是动态的获取并设置数据 0.2 为什么&#xff1f; 比如执行批量操作时&#xff0c;批量插入或批量删除&#xff0c;之前数据都是手写的&#xff0c;每执行完都要修改一次&#xff0c;效率太低 而参数化就是…

基于javassmJSP的教学质量评价系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

maxpool long数据类型报错

报错&#xff1a; RuntimeError: “max_pool2d” not implemented for ‘Long’ 源码&#xff1a; import torch from torch import nn from torch.nn import MaxPool2dinput torch.tensor([[1, 2, 0, 3, 1],[0, 1, 2, 3, 1],[1, 2, 1, 0, 0],[5, 2, 3, 1, 1],[2, 1, 0, 1, 1…

重温OKHTTP源码

本文基于OkHttp4.12.0源码分析 官方地址 概括 本篇主要是对okhttp开源库的一个详细解析&#xff0c;包含详细的请求流程分析、各大拦截器的解读等。 使用方法 同步请求&#xff1a;创建一个OKHttpClient对象&#xff0c;一个Request对象&#xff0c;然后利用它们创建一个Ca…

文献速递:深度学习胰腺癌诊断--基于螺旋变换的胰腺癌分割模型驱动深度学习方法

Title 题目 Model-Driven Deep Learning Method forPancreatic Cancer Segmentation Basedon Spiral-Transformation 基于螺旋变换的胰腺癌分割模型驱动深度学习方法 01 文献速递介绍 胰腺癌是最致命的恶性肿瘤之一&#xff0c;其特点是诊断延迟、治疗困难和高死亡率。患者…

采用Flink CDC操作SQL Server数据库获取增量变更数据

采用Flink CDC操作SQL Server数据库获取增量变更数据 Flink CDC 1.12版本引入了对SQL Server的支持&#xff0c;包括SqlServerCatalog和SqlServerTable。在SqlServerCatalog中&#xff0c;你可以根据表名获取对应的字段和字段类型。 SQL Server 2008 开始支持变更数据捕获 (C…

【C语言】简单介绍进制和操作符

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 本文简要介绍进制和操作符&#xff0c;愿能为您提供帮助&#xff01;文章…

论文解读:吴恩达来信AI Agent技巧—利用自我反馈的迭代细化技术

《自我完善&#xff1a;利用自我反馈的迭代细化技术》 https://arxiv.org/pdf/2303.17651.pdf 摘要 Large language models (LLMs) 经常无法在一次尝试中生成最佳输出。受人类在修改书面文本时所表现出的迭代精炼过程的启发&#xff0c; 我们提出了 SELF-REFINE&#xff0c…

R语言绘图 | 散点小提琴图

原文链接&#xff1a;R语言绘图 | 散点小提琴图 本期教程 写在前面 本期的图形来自发表在Nature期刊中的文章&#xff0c;这样的基础图形在日常分析中使用频率较高。 获得本期教程数据及代码&#xff0c;后台回复关键词&#xff1a;20240405 绘图 设置路径 setwd("You…

CSDN 广告太多,停更通知,转移到博客园

文章目录 前言新博客地址 前言 CSDN的广告实在是太多了&#xff0c;我是真的有点忍不了。直接把广告插在我的文章中间。而且我已经懒得找工作了&#xff0c;我当初写CSDN的目的就是为了找工作&#xff0c;有个博客排名。当时经济环境实在是太差了。我也没必要纠结这个2000粉丝…

因为使用ArrayList.removeAll(List list)导致的机器重启

背景 先说一下背景&#xff0c;博主所在的业务组有一个核心系统&#xff0c;需要同步两个不同数据源给过来的数据到redis中&#xff0c;但是每次同步之前需要过滤掉一部分数据&#xff0c;只存储剩下的数据。每次同步的数据与需要过滤掉的数据量级大概在0-100w的数据不等。 由…