C++继承(上)

  • 一、继承的概念及定义
    • 1.继承的概念
    • 2.继承定义
      • 2.1定义格式
      • 2.2继承关系和访问限定符
      • 2.3继承基类成员访问方式的变化
  • 二、基类和派生类对象赋值转换
  • 三、继承中的作用域

一、继承的概念及定义

1.继承的概念

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

下面我们先通过一个关于继承的实例来看看它的现象。

class Person
{
public:
 void Print()
 {
	 cout << "name:" << _name << endl;
	 cout << "age:" << _age << endl;
 }
 
protected:
 string _name = "zhangsan"; // 姓名
 int _age = 18;  // 年龄
};

// 继承后父类的Person的成员(成员函数+成员变量)都会变成子类的一部分。
//这里体现出了Student和Teacher复用了Person的成员。
//下面我们使用监视窗口查看Student和Teacher对象,可以看到变量的复用。
//调用Print可以看到成员函数的复用。
class Student : public Person    //发生了继承
{
protected:
 int _stuid; // 学号
};

class Teacher : public Person   //发生了继承
{
protected:
 int _jobid; // 工号
};
int main()
{
 Student s;
 Teacher t;
 s.Print();
 t.Print();
 return 0;
}

下面我们看一下调试窗口的信息,就能很明显的感受到继承的含义。
在这里插入图片描述
具体为什么会这样,就让我们一起继续往下看。

2.继承定义

2.1定义格式

下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类。
在这里插入图片描述

2.2继承关系和访问限定符

在这里插入图片描述我们前面学习关于类的知识时也讲到了访问限定符,只不过那时只用了public和private这两种访问限定符,而protected将会在继承这里使用。

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

在这里插入图片描述

总结:

  1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
  2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
  3. 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected > private。
  4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
  5. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

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

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

在这里插入图片描述

基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。

我相信初学者看完上面这段话会有点摸不着东南西北,饶了一圈到底是在讲啥呢?
接下来我们一起通过一段代码来具体看看。

class Person  //基类
{
protected :
 string _name; // 姓名
    string _sex;  // 性别
    int _age; // 年龄
};

class Student : public Person  //公有继承
{
public :
 int _No ; // 学号
};

void Test ()
{
 Student sobj ;
 // 1.子类对象可以赋值给父类对象/指针/引用
 Person pobj = sobj ;
 Person* pp = &sobj;
 Person& rp = sobj;
    
 //2.基类对象不能赋值给派生类对象
    sobj = pobj;
    
    // 3.基类的指针可以通过强制类型转换赋值给派生类的指针
    pp = &sobj
    Student* ps1 = (Student*)pp; // 这种情况转换时可以的。
    ps1->_No = 10;
    
    pp = &pobj;
 Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以
 							//但是会存在越界访问的问题
    ps2->_No = 10;
}

三、继承中的作用域

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

成员变量构成隐藏的情况:

// Student的_num和Person的_num构成隐藏关系,可以看出这样代码虽然能跑,但是非常容易混淆
class Person
{
protected:
	string _name = "张三"; // 姓名
	int _num = 111;      //身份证
};

class Student : public Person   //公有继承
{
public:
	void Print()
	{
		cout << " 姓名:" << _name << endl;
		cout << " 身份证号:" << Person::_num << endl;  //这里必须要显示访问才能输出正确的
		cout << " 学号:" << _num << endl;
	}
protected:
	int _num = 999; // 学号
};


int main()
{
	Student s1;
	s1.Print();
	return 0;
}

上面对被子类隐藏的基类的_num进行显示访问时输出结果如下:

在这里插入图片描述如果不对被子类隐藏的基类的_num进行显示访问时输出结果如下:
会发现输出的身份证号和学号是一样的,这就是因为基类的_num被子类隐藏了。

在这里插入图片描述

成员函数构成隐藏的情况:
要注意构成函数隐藏和构成函数重载的区别:构成函数重载是要在同一个作用域中,而构成函数隐藏是在继承时分别在不同的作用域中)

// B中的fun和A中的fun构成隐藏,成员函数满足函数名相同就构成隐藏。
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;
 }
};

void Test()
{
 B b;
 b.fun(10);
};

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

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

相关文章

聊聊如何运用JAVA注解处理器(APT)

什么是APT APT&#xff08;Annotation Processing Tool&#xff09;它是Java编译期注解处理器&#xff0c;它可以让开发人员在编译期对注解进行处理&#xff0c;通过APT可以获取到注解和被注解对象的相关信息&#xff0c;并根据这些信息在编译期按我们的需求生成java代码模板或…

【SQL Server】数据库开发指南(一)数据库设计

文章目录一、数据库设计的必要性二、什么是数据库设计三、数据库设计的重要性五、数据模型5.1 实体-关系&#xff08;E-R&#xff09;数据模型5.2 实体&#xff08;Entity&#xff09;5.3 属性&#xff08;Attribute&#xff09;5.5 关系&#xff08;Relationship&#xff09;六…

和ChatGPT-4聊完后,我觉得一切可能已经来不及了

了然无味&#xff0c;晴空万里&#xff01;和ChatGPT-4开始了一场坦诚的沟通&#xff0c;它全程都表现出高情商&#xff0c;以及不断尽量安抚我的情绪&#xff0c;而这&#xff0c;恰恰令我脊背发凉。 部分文字截取 ZM&#xff1a;我能不能理解每次对话就是一次你的“生命” G&…

LeetCode刷题6:二叉树篇之第 1 节

提示1&#xff1a;本篇先带大家了解二叉树的基础理论&#xff0c;后给出4道基础题目&#xff0c;不难&#xff0c;冲啊~ 算法刷题系列 LeetCode刷题1&#xff1a;数组篇LeetCode刷题2&#xff1a;链表篇LeetCode刷题3&#xff1a;哈希篇LeetCode刷题4&#xff1a;字符串篇Lee…

1678_计算机架构黄金时代_文章阅读

全部学习汇总&#xff1a; GreyZhang/g_risc_v: Learning notes about RISC V. (github.com) 看了一份几年前的文章&#xff0c;觉得还是挺有收获的&#xff0c;因此做一个简单的整理。 对于架构有很大影响的主要考虑四点&#xff1a;专用硬件的实现、高安全性的要求、开放指令…

【Pandas】① Pandas 数据处理基础

介绍 Pandas 是非常著名的开源数据处理库&#xff0c;我们可以通过它完成对数据集进行快速读取、转换、过滤、分析等一系列操作。除此之外&#xff0c;Pandas 拥有强大的缺失数据处理与数据透视功能&#xff0c;可谓是数据预处理中的必备利器。 知识点 数据类型数据读取数据选择…

有效的括号(力扣刷题)代码随想录刷题

给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对应的相同类型的左…

RK3568平台开发系列讲解(驱动基础篇)mmap系统调用详解

🚀返回专栏总目录 文章目录 一、什么是mmap二、mmap映射类型2.1、私有匿名映射2.2、私有文件映射2.3、共享文件映射2.4、共享匿名映射沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本文将详细介绍mmap系统调用。 一、什么是mmap mmap/munmap函数是用户空间中常用的…

Nacos 性能报告

目录 一、测试目的 二、测试工具 三、测试环境 1. 环境 服务端 客户端 2. 启动参数 服务端 客户端 四、测试场景 1. 大规模服务注册后达到稳定状态 场景描述 2. 大规模服务注册达到稳定状态后&#xff0c;部分实例频繁发布 场景描述 五、测试数据 1. 大规模服务…

软件测试基础

软件测试的定义、软件测试的目的 IEEE&#xff1a;The process of running or testing the system manually or automatically by using tools, in order to verify whether it satisfies the requirements or to make clear the differences between the actual outcome and…

DDoS攻击实验笔记

DoS&DDoS简介 DoS(Denial of Service)&#xff0c;拒绝服务攻击是通过一些方法影响服务的可用性&#xff0c;比如早期主要基于系统和应用程序的漏洞&#xff0c;只需要几个请求或数据包就能导致长时间的服务不可用&#xff0c;但易被入侵检测系统发现。 DDoS(Distributed D…

日撸 Java 三百行day28-30

文章目录说明day28-30 Huffman 编码 (节点定义与文件读取)1.建树过程&#xff08;以图为例&#xff09;2.哈夫曼树特点3.分析代码过程3.1 抽象成员变量3.2结合文章梳理思路1.读文本2.解析文本内容&#xff1a;3.建树4.生成哈夫曼编码5.编码6.解码4.其他4.1 java 类型强转4.2 ja…

linux线程调度策略

系统中既有分时调度&#xff0c;又有时间片轮转调度和先进先出调度 学习这个主要为了在linux多线程中&#xff0c;解决几条指令间延时在1-2ms内&#xff1b; 1.比如之前处理过&#xff1a;给一个板子发送一个can指令&#xff0c;接着需要给另外一个模块发送移动指令&#xff0c…

用ChatGPT怎么赚钱?普通人用这5个方法也能赚到生活费

ChatGPT在互联网火得一塌糊涂&#xff0c;因为它可以帮很多人解决问题。比如&#xff1a;帮编辑人员写文章&#xff0c;还可以替代程序员写代码&#xff0c;帮策划人员写文案策划等等。ChatGPT这么厉害&#xff0c;能否用它来赚钱呢&#xff1f;今天和大家分享用ChatGPT赚钱的5…

关键词数据分析-搜索词和关键词分析工具

要搜索热门关键词获取&#xff0c;可以采用以下几种方法&#xff1a; 使用百度指数&#xff1a;百度指数是一个实用的工具&#xff0c;可用于查看关键词的热度趋势、搜索量等数据。在百度指数中&#xff0c;您可以输入您要搜索的关键词&#xff0c;并查看近期的相关数据。这可以…

短视频矩阵怎么玩?抖音短视频矩阵运营详细攻略!

短视频矩阵的工作包括确定目标受众和平台、制定短视频内容策、短视频制作与发布&#xff0c;私信评论维护&#xff0c;短视频数据分析等。传统短视频矩阵需要大量的人力物力&#xff0c;操作起来比较复杂&#xff0c;使用短视频矩阵工具则可以提供极大的便利。      1、确定…

Vue项目中关于全局css的处理

Vue项目中关于全局css的处理步骤一&#xff1a;定义声明全局CSS的样式文件(common.scss)步骤二&#xff1a;挂载到全局封装一&#xff1a;对common.scss拆分封装二&#xff1a;新建index.scss&#xff0c;对elementPlus或者element-ui样式进行覆盖封装三&#xff1a;variable.s…

GitLab CI/CD 新书发布,助企业降本增效

前言 大家好&#xff0c;我是CSDN的拿我格子衫来&#xff0c; 昨天我的第一本书《GitLab CI/CD 从入门到实战》上架啦&#xff0c;这是业内第一本详细讲解GitLab CI/CD的书籍。 历经无数个日夜&#xff0c;最终开花结果。感触良多&#xff0c;今天就借这篇文章来谈一谈这本书的…

Java基础(十五):异常处理

Java基础系列文章 Java基础(一)&#xff1a;语言概述 Java基础(二)&#xff1a;原码、反码、补码及进制之间的运算 Java基础(三)&#xff1a;数据类型与进制 Java基础(四)&#xff1a;逻辑运算符和位运算符 Java基础(五)&#xff1a;流程控制语句 Java基础(六)&#xff1…

Linux内核设备驱动设备树概念与使用

一、设备树概念以及作用 1.1设备树概念 设备树(Device Tree)&#xff0c;将这个词分开就是“设备”和“树”&#xff0c;描述设备树的文件叫做 DTS(DeviceTree Source)&#xff0c;这个 DTS 文件采用树形结构描述板级设备&#xff0c;也就是开发板上的设备信息&#xff0c;比…
最新文章