【C++】学习笔记——继承_1

文章目录

  • 十一、模板进阶
    • 5. 模板的优缺点
  • 十二、继承
    • 1. 继承的概念及定义
    • 2. 基类和派生类对象赋值转换
    • 3. 继承中的作用域
    • 4. 派生类的默认成员函数
  • 未完待续


十一、模板进阶

5. 模板的优缺点

优点:

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生。
  2. 增强了代码的灵活性。

缺点:

  1. 模板会导致代码膨胀问题,也会导致编译时间变长。
  2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误。

其实总的来说,模板的利还是大于弊的,该用模板的时候还是要用模板。

十二、继承

1. 继承的概念及定义

继承 机制是面向对象程序设计 使代码可以复用 的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类(或叫做子类),被拓展的类叫基类(或叫做父类)。
比如说:我们想设计一个学生管理系统,涉及到的对象有学生和老师,分别封装成两个类,但是老师和学生都含有姓名、年龄、性别等等的信息,要是将这些变量都分别放到各个类里,就会有些冗余。而继承机制就是,设计一个类,这个类里有共有的成员变量或成员函数,派生出的子类继承这个父类,就能拥有父类的这些成员变量和成员函数,减少了冗余。
在这里插入图片描述

#include<iostream>
using namespace std;

// 父类,代表人
class Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	// 姓名
	string _name = "peter";
	// 年龄
	int _age = 18;
};

// 子类,代表学生,继承自 Person
class Student : public Person
{
protected:
	// 学号
	int _stuid;
};

// 子类,代表教师,继承自 Person
class Teacher : public Person
{
protected:
	// 工号
	int _jobid;
};

int main()
{
	Student s;
	Teacher t;
	s.Print();
	t.Print();
	return 0;
}

在这里插入图片描述

我们发现,学生类和教师类里既没有 Print() 函数,也没有 name,age 成员变量,但就是能够使用。这就是继承,从父类获得成员变量和成员函数

我们知道,类访问限定符有三种,public(共有)、protected(保护)、private(私有) 。同样的,继承方式也有三种:public(共有)、protected(保护)、private(私有) 。那么,这两者有什么关系?从父类继承过来的成员在子类中又是什么访问权限?
在这里插入图片描述
什么是共有?共有就是,类本身可以访问,类派生后的子类可以访问,类外也可以访问。什么是保护?保护就是,类本身可以访问,类派生后的子类可以访问,类外不能访问。什么是私有?私有就是,类本身可以访问,类派生后的子类不可以访问,类外不可以访问。

权限大小:public > protected > private

实际上面的表格我们进行一下总结会发现,父类的私有成员在子类都是不可见这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它父类。的其他成员在子类的访问方式是 成员在父类的访问限定符和继承方式的两者权限较小的

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

2. 基类和派生类对象赋值转换

由于子类是父类的拓展,所以,父类有的,子类都有,子类有的,父类不一定有。当子类赋值给父类时:子类将会把与父类相同的部分进行切割,然后赋值给父类
在这里插入图片描述
然而,父类并不能赋值给子类 。但是 父类的指针可以通过 强制类型转换 来赋值给子类

3. 继承中的作用域

在继承体系中父类和子类都有 独立的作用域 。父类和子类的作用域互不相干,因此,父类和子类允许出现同名变量或者同名函数。

#include<iostream>
using namespace std;

// 父类,代表人
class Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	// 姓名
	string _name = "peter";
	// 年龄
	int _age = 18;
	
	// 父类增加一个 _num
	int _num = 0;
};

// 子类,代表学生,继承自 Person
class Student : public Person
{
public:
	void func()
	{
		cout << _num << endl;
	}
protected:
	// 学号
	int _stuid;
	
	// 子类增加一个 _num
	int _num = 1;
};

// 子类,代表教师,继承自 Person
class Teacher : public Person
{
protected:
	// 工号
	int _jobid;
};

int main()
{
	Student s;
	s.func();
	return 0;
}

在这里插入图片描述
我们发现,此时子类访问的 _num 是子类本身的成员,因此我们可以知道,当父类和子类中出现同名成员时,会访问到子类成员 。这种情况叫做 隐藏 ,也叫做 重定义 。当然,可以通过作用域限定符来指定访问父类。需要注意的是,只要父类和子类的成员函数函数名相同,参数不同,依然构成 隐藏 ,只要同名就构成 隐藏 ,因为不在同一个域,所以不存在重载情况

4. 派生类的默认成员函数

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

  1. 对于子类的构造函数,我们需要将父类看作一个整体,看作一个独立的类。子类等价于父类 + 子类独有的成员 。而 父类就相当于自定义类型 ,所以子类的构造函数是需要调用父类的默认构造函数的,如果父类没有默认的构造函数,则子类需要在初始化列表显示定义父类的构造函数。
Person(const char* name = "peter")
 	: _name(name)
{
	//
}
 
Student(const char* name, int num)
	: Person(name)  // 匿名对象,显示调用父类的构造函数
	, _num(num)
{
	//
}
  1. 拷贝构造函数与构造函数一样。内置类型进行值拷贝,自定义类型调用它的拷贝构造函数。
Person(const Person& p)
	: _name(p._name)
{
	//
}

Student(const Student& s)
 	: Person(s)   // 切片,子类可以赋值给父类
 	, _num(s ._num)
{
	//
}
  1. 赋值重载同理,不过需要注意同名函数产生的隐藏。
Person& operator=(const Person& p)
{
	if (this != &p)
	_name = p ._name;
       
	return *this ;
}

Student& operator = (const Student& s )
{
	if (this != &s)
	{
		// 限定作用域,避免发生隐藏
		Person::operator =(s);
		_num = s ._num;
	}
	
	return *this ;
}
  1. 对于析构函数,构造函数要满足先构造父类后构造子类,析构函数需要满足先析构子类后析构父类,子类的析构函数会在被调用完成后 自动调用父类的析构函数 清理父类成员。
~Person()
{
	//
}

~Student()
{
	//
} //子类析构完成后会自动调用父类的析构函数

未完待续

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

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

相关文章

网络安全快速入门(十二) linux的目录结构

我们前面已经了解了基础命令&#xff0c;今天我们来讲讲linux中的目录结构&#xff0c;我们在了解linux的目录结构之前&#xff0c;我们先与Windows做一个对比 12.1linux和windows的目录结构对比 在之前认识liunx的章节中&#xff0c;我们已经简单说明了linux和window的目录结构…

一文入门DNS

概述 DNS是一个缩写&#xff0c;可以代表Domain Name System&#xff0c;域名系统&#xff0c;是互联网的一项基础服务。也可以代表Domain Name Server&#xff0c;域名服务器&#xff0c;是进行域名和与之相对应的IP地址相互转换的服务器。DNS协议则是用来将域名转换为IP地址…

blender cell fracture制作破碎效果,将一个模型破碎成多个模型

效果&#xff1a; 1.打开编辑-》偏好设置。搜索cell&#xff0c;勾选上如下图所示的&#xff0c;然后点击左下角菜单里的保存设置。 2.选中需要破碎的物体&#xff0c;按快捷键f3&#xff08;快速搜索插件&#xff09;&#xff0c;搜索cell fracture。 3.调整自己需要的参数配置…

机器学习之sklearn基础教程:新手入门指南

引言 在机器学习领域&#xff0c;sklearn&#xff08;Scikit-learn&#xff09;是一个广受欢迎的开源库&#xff0c;它为各种常见的机器学习算法提供了高效的实现。对于初学者来说&#xff0c;sklearn 提供了一个简单且易于上手的工具&#xff0c;可以用来实现分类、回归、聚类…

git使用及github

文章目录 操作命令基本组成框架在开发中git分支的重要性 github的使用将本地仓库关联到远程仓库将远程仓库关联到本地和拉取指定分支、切换远程分支提交本地仓库到远程仓库修改分支名称 保存当前工作切换分支将别的分支修改转移到自己的分支远程删除分支后本地git branch -a依然…

MongoDB事务的理解和思考

3.2版本开始引入Read Concern&#xff0c;解决了脏读&#xff0c;支持Read Commit 3.6版本引入Session&#xff0c;支持多个请求共享上下文&#xff0c;为后续的事务支持做准备 4.0支持多行事务&#xff0c;但4.0的事务只是个过渡的版本 4.2开始支持多文档事务 1. Mongo的架…

具备教学意义的实操(用栈实现队列)

具备教学意义的实操&#xff08;用队列实现栈&#xff09;-CSDN博客https://blog.csdn.net/Jason_from_China/article/details/138729955 具备教学意义的实操&#xff08;用栈实现队列&#xff09; 题目 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; ​ 逻辑​​…

一、VIsual Studio下的Qt环境配置(Visual Studio 2022 + Qt 5.12.10)

一、下载编译器Visual Studio2022和Qt 5.12.10 Visual Studio 2022 社区版就够学习使用了 Qt5.12.10 安装教程网上搜&#xff0c;一大堆 也很简单&#xff0c;配置直接选默认&#xff0c;路径留意一下即可 二、配置环境 Ⅰ&#xff0c;配置Qt环境变量 系统变量下的Path&a…

C++的数据结构(五):树和存储结构及示例

在计算机科学中&#xff0c;树是一种抽象数据类型&#xff08;ADT&#xff09;或是实现这种抽象数据类型的数据结构&#xff0c;用来模拟具有树状结构性质的数据集合。这种数据结构以一系列连接的节点来形成树形结构。在C中&#xff0c;树的概念和存储结构是实现各种复杂算法和…

Golang | Leetcode Golang题解之第87题扰乱字符串

题目&#xff1a; 题解&#xff1a; func isScramble(s1, s2 string) bool {n : len(s1)dp : make([][][]int8, n)for i : range dp {dp[i] make([][]int8, n)for j : range dp[i] {dp[i][j] make([]int8, n1)for k : range dp[i][j] {dp[i][j][k] -1}}}// 第一个字符串从 …

61、内蒙古工业大学、内蒙科学技术研究院:CBAM-CNN用于SSVEP - BCI的分类方法[脑机二区还是好发的]

前言&#xff1a; 之前写过一篇对CBAM模型改进的博客&#xff0c;在CBAM中引入了ECANet结构&#xff0c;对CBAM中的CAM、SAM模块逐一改进&#xff0c;并提出ECA-CBAM单链双链结构&#xff0c;我的这个小的想法已经被一些同学实现了&#xff0c;并进行了有效的验证&#xff0c;…

算法-卡尔曼滤波之为什么要使用卡尔曼滤波器

假设使用雷达来预测飞行器的位置&#xff1b; 预先的假设条件条件: 1.激光雷达的激光束每5s发射一次&#xff1b; 2.通过接受的激光束&#xff0c;雷达估计目标当前时刻的位置和速度&#xff1b; 3.同时雷达要预测下一时刻的位置和速度 根据速度&#xff0c;加速度和位移的…

ROS2 - 创建项目 (Ubuntu22.04)

本文简述&#xff1a;在 Ubuntu22.04 系统中使用 VS CODE 来搭建一个ROS2开发项目。 1. 创建工作空间 本文使用 Ubuntu 22.04&#xff0c; 已安装配置完成 VS Code&#xff0c;C 环境&#xff08;g/gdb&#xff09; 1.1 创建目录 选择文件夹作为工作空间&#xff0c;并在这…

Django开发实战之定制管理后台界面及知识梳理(下)

接上一篇&#xff1a;Django开发实战之定制管理后台界面及知识梳理&#xff08;中&#xff09; 1、前台设置 1、隐藏路由 当你输入一个错误地址时&#xff0c;可以看到这样的报错&#xff1a; 从这样的报错中&#xff0c;我们可以看到&#xff0c;这个报错页面暴漏了路由&a…

数据结构-题目

1.已知一颗完全二叉树的第6曾&#xff08;设根为第1层&#xff09;&#xff0c;有8个结点&#xff0c;则完全二叉树的结点个数&#xff0c;最少和最多分别是多少&#xff1f; 因此最少为39&#xff0c;最多为111 2.假设一棵三叉树的结点数为50&#xff0c;则它的最小高度为&…

【数据结构与算法 刷题系列】合并两个有序链表

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;数据结构与算法刷题系列&#xff08;C语言&#xff09; 目录 一、问题描述 二、解题思路详解 合并两个有序链表的思路 解题的步…

[PythonWeb:Django框架]:前后端请求调用;

文章目录 接着上篇项目app包下面创建static包&#xff0c;引入jquery&#xff0c;bootstrap 相关js文件views.py编写apicompute文件夹下面的urls.py路由模块引入views.py刚刚定义的函数html发送ajax请求 接着上篇 https://blog.csdn.net/Abraxs/article/details/138739727?sp…

【pouchdb-可视化工具 】

最近使用pouchdb&#xff0c;想找个其对应的可视化工具&#xff0c;可以对数据库进行操作。 找了好久才找到&#xff0c;网上有说先同步到couchdb&#xff0c;再用couchdb的可视化工具查看&#xff0c;其实没有那么麻烦&#xff0c;pouchdb的可视化工具其实藏在另外的pouchdb-…

让创意在幻觉中肆虐: 认识Illusion Diffusion AI

人工智能新境界 在不断发展的人工智能领域,一款非凡的新工具应运而生,它能将普通照片转化为绚丽的艺术品。敬请关注Illusion Diffusion,这是一个将现实与想象力完美融合的AI驱动平台,可创造出迷人的视错觉和超现实意境。 AI算法的魔力所在 Illusion Diffusion 的核心是借助先进…

react Effect副作用 - 避免滥用Effect

react Effect副作用 - 避免滥用Effect react Effect副作用基础概率什么是纯函数? 什么是副作用函数?纯函数副作用函数 什么时候使用Effect如何使用Effect 避免滥用Effect根据 props 或 state 来更新 state当 props 变化时重置所有 state将数据传递给父组件获取异步数据 react…