文章目录

  • 继承简介
    • 定义
    • 访问限定符和继承方式
  • ⭐基类派生类赋值转换
  • 继承的作用域
  • 派生类的默认成员函数
  • 继承与友元
  • 继承与静态成员
  • ⭐复杂的菱形继承
    • 虚拟继承
  • 组合

继承简介

继承是面向对象程序设计代码复用的重要手段,使得程序员可以在保持原类的基础上扩展,新扩展的类叫派生类体现类的层级结构,之前的重载是函数复用,继承是类的复用

定义

#include <iostream>
#include <string>
using namespace std;
class person
{
public:void print(){cout << _name << " " << _sex << " " << _age << endl;;}
protected:string _name ="Jack";string _sex ="man";int _age=18;
};
class student : public person
{
protected:int _number;
};
int main()
{person p1;student s1;p1.print();s1.print();return 0;
}

可以看到,student是派生类,public是继承方式,person是基类
派生类拥有基类的所有成员

访问限定符和继承方式

在这里插入图片描述

在这里插入图片描述
总结
1,基类的private成员,无论什么继承,派生类都不可见,但是成员还是继承到了派生类中,但是语法限制了派生类访问
2,基类的private在派生类不可见,要想突破限制,就用protected,在类外不可访问,但在派生类可访问,访问限制符protected是为继承准备的
3,观察上面表格,可以发现两个不同限定符,取范围更小的,如protected和private 取private
4,class类默认继承方式private,struct类默认public一般都写出继承方式的
5,一般都是public继承,几乎很少private/protected

⭐基类派生类赋值转换

🚩 派生类对象可以赋值基类对象/基类引用/基类指针,这个过程叫切片,意为着把派生类那块基类所有的切给基类,
🚩基类对象不能赋值给派生类
在这里插入图片描述
如图,派生可以赋值给基类,只不过 _number消失了

int main()student s2;person p2 = s2;person* pp2 = &s2;person& ppp2 = s2;student* ss2 = (student*)pp2;//这种强转可以pp2 = &p2;//student* ss2 = (student*)pp2;//这种会越界访问return 0;

继承的作用域

class person
{
public:void print(){cout << "基类" << endl;}
};
class student : public person
{
public:void print(){cout << "派生类" << endl;}
};
int main()
{student s3;s3.print();s3.student::print();s3.person::print();return 0;
}

在这里插入图片描述
1,基类和派生类都有独立的作用域
🚩2,基类与派生类成员重名时,子类调用会直接跳过父类成员,这叫隐藏,也叫重定义,或者可用 类名::成员 访问
🚩3,在一个作用域的重名叫重载两个作用域重名叫隐藏
4,继承体系最好不要定义重名成员

派生类的默认成员函数

1,派生类对象初始化先调用基类构造函数,若基类无默认构造函数,则要在初始化列表显式调用,再调用自己的构造函数
2,构造,赋值,拷贝构造都是先调基类再调子类
3,析构先调子类再基类
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
class person
{
public:person(string name ="jack"):_name(name){cout << "person()" << endl;}person(const person& p1):_name(p1._name){cout << "person(& p1)" << endl;}person& operator=(const person& p1){cout << "operator(const person&p1)" << endl;if(this!=&p1){_name = p1._name;}return *this;}~person(){ }
protected:string _name;
};
class student : public person
{
public:student(const string name="peter", int number = 110):person(name),_number(number){cout << "student()" << endl;}student(const student& s):person(s),_number(s._number){cout << "student(student& s)" << endl;}student& operator=(const student& s){if (this != &s){person::operator= (s);_number = s._number;}cout << "operator=(const student &s)" << endl;return *this;}~student(){ }
protected:int _number;
};
int main()
{person p1("peter");student s1("jack", 11);student s2;s2 = s1;return 0;
}

在这里插入图片描述

继承与友元

友元不能继承,父类的朋友不是我的朋友
所以父类友元不能访问子类成员,除非子类也声明友元

#include <iostream>
#include <string>
using namespace std;
class student;//声明
class person {
public:friend void Display(const person& p, const student& s);
protected:string _name = "person";
};class student : public person {
public:friend void Display(const person& p, const student& s); // 子类也声明为友元student(int num = 0) : _number(num) {}
protected:int _number; 
};void Display(const person& p, const student& s) {cout << p._name << endl;cout << s._number << endl; //  现在可以访问(student 的友元)
}int main() {person p;student s(12345);Display(p, s);return 0;
}

继承与静态成员

🚩基类定义static静态成员,则整个继承体系只有一个这样的成员,无论多少派生多少子类,只有这一个静态成员

#include <iostream>
#include <string>
using namespace std;
class person
{
public:person() {++_count;}string _name;static int _count;
};
int person ::_count = 0;
class student:public person
{
public:student():person(){++_count;}
};
int main()
{student s;cout << person::_count<<endl;return 0;
}

2

⭐复杂的菱形继承

单继承:一个子类只有一个父类
在这里插入图片描述
多继承:一个子类有两个及以上的父类
在这里插入图片描述
菱形继承:多继承的一种
在这里插入图片描述
下图,可看出菱形继承数据冗余二义性问题,有两份person值
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
class person
{
public:string _name;
};
class student :public person
{
public:string _num;
};
class teacher :public person
{
public:string _id;
};
class assistant :public student, public teacher
{
public:string _majorcourse;
};
int main()
{assistant a;//a._name = "peter";//❌不明确a.student::_name = "peter";//可以指明访问,a.teacher::_name = "jack";return 0;
}

指明访问解决了二义性,但数据冗余还是没解决,

虚拟继承

虚拟继承解决了二义性和数据冗余问题,

class person
{
public:string _name;
};
class student :virtual public person
{
public:string _num;
};
class teacher :virtual public person
{
public:string _id;
};
class assistant :virtual public student, virtual public teacher
{
public:string _majorcourse;
};

原理:
在这里插入图片描述
只存一个person,student和teacher中的person 存到assistant的地址偏移量,用时再跳过去找

注意
菱形虚拟继承底层复杂,一般不设计多继承,更不能设计菱形继承

组合

继承是 is-a关系
组合是 has-a关系

  • 继承复用 基类对子类公布了成员细节,俗称白箱复用,一定程度上破坏了封装,且基类 改动对子类影响较大,子类和基类关联性强耦合度高
  • 组合复用 被组合对象要求有良好接口,基类成员细节不可见,俗称黑箱复用不破坏封装关联性低耦合度低

实战中能用组合就用组合,耦合度低,代码便于维护,不过有些情况就适合继承多态也需要继承实现,可以用继承和组合就用组合

class car
{
protected:string _colour;string _num;
};class Benz :public car
{
public:void Drive(){cout << "奢华" << endl;}
};

继承关系

class tire
{
public:string _brand;int _size;
};
class car {string _colour;string _num;//车牌tire _t;//轮胎
};

组合关系

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

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

相关文章

.Net下载共享文件夹中的文件

由于IIS站点权限等问题&#xff0c;总是没找到处理办法&#xff0c;所以改用外挂的winform的方式来下载共享文件&#xff08;也可以改为使用windows服务的方式&#xff09;。 前提需要先在资源管理器中登录到共享文件夹&#xff0c;确保系统能访问。 服务端代码 (.NET后端) usi…

目标检测数据集 - 眼睛瞳孔检测数据集下载「包含COCO、YOLO两种格式」

数据集介绍&#xff1a;眼睛瞳孔检测数据集&#xff0c;真实采集高质量人脸眼部图片数据&#xff0c;适用于人脸定位、人脸疾病如白内障等疾病的视觉检测。数据标注标签包括 eyepupil 瞳孔一 个缺陷类别&#xff1b;适用实际项目应用&#xff1a;眼睛瞳孔检测项目&#xff0c;以…

Keil MDK-ARM V5.42a 完整安装教程

文章目录一、安装前期准备二、Keil MDK-ARM 主程序安装三、器件支持包&#xff08;Pack&#xff09;安装四、许可证激活五、安装验证Keil MDK&#xff08;Microcontroller Development Kit&#xff09;是针对 Arm Cortex-M 系列微控制器的专业开发环境&#xff0c;集成了 μVis…

WPF中引用其他元素各种方法

在WPF中&#xff0c;引用其他元素的方式有多种&#xff0c;每种方式适用于不同场景&#xff0c;各有优缺点。除了x:Reference&#xff0c;常用的还有以下几种&#xff1a; 一、ElementName 绑定&#xff08;最常用的XAML绑定方式&#xff09; 通过元素的x:Name属性引用同一作用…

Python生成统计学公式

一元线性回归模型 2.1回归分析概述/25 一、回归分析基本概念/25 二、总体回归函数/27 三、随机误差项/29 四、样本回归函数/30 2.2 一元线性回归模型的参数估计/32 一、参数估计的普通最小二乘法/32 二、拟合优度/35 2.3基本假设与普通最小二乘估计量的统计性质/36 一、一元线性…

网络工程师--华为命令专题

一、交换机 交换机分类&#xff1a;1.根据交换方式划分&#xff1a;&#xff08;1&#xff09;存储转发式交换&#xff08;Store and Forward&#xff09;&#xff08;2&#xff09;直通式交换&#xff08;Cut-through&#xff09;&#xff08;3&#xff09;碎片过滤式交换&…

判断可编辑div的光标是否在最前面

要判断一个可编辑div(contenteditable)中的光标是否位于最前面&#xff0c;可以使用以下几种方法&#xff1a; 方法一&#xff1a;使用Selection和Range API function isCaretAtStart(div) {const selection window.getSelection();if (selection.rangeCount 0) return false…

【unity实战】使用Unity程序化生成3D随机地牢(附项目源码)

最终效果 文章目录最终效果前言1、理解程序生成的核心概念2、种子值的核心作用3、程序生成的实际应用4、主流程序生成技术概览5、选择合适的技术实战1、素材2、生成一面墙变换矩阵数据3、渲染墙壁4、加点随机不同的墙壁效果5、绘制四面墙壁4、在四个角落生成支柱5、生成地板6、…

多账号管理方案:解析一款免Root的App分身工具

之前有小伙伴问阿灿有没有可以软件分身的免费软件&#xff0c;后来阿灿找到了一款可以无限分身的app感觉很实用&#xff0c;只有10M大小 02软件介绍说白了它能给各种app和游戏做分身&#xff0c;包括V信、qQ、某音、某付宝这些&#xff0c;而且支持最新的安卓15系统。每个分身…

(附源码)基于PHP和Vue的网上购物平台

内容摘要 内容摘要: 随着互联网技术的迅猛发展&#xff0c;网上购物已成为人们日常生活的重要组成部分。本文围绕PHPVue技术栈构建的网上购物平台展开研究&#xff0c;深入探讨了该平台的架构设计与实现细节。平台前端采用Vue框架&#xff0c;利用其组件化开发和数据驱动的特性…

51单片机

中断系统1.什么是中断当CPU正在处理某件事的时候外界发生了紧急事件请求&#xff0c;要求CPU暂停当前的工作&#xff0c;转而去处理这个紧急事件&#xff0c;处理完以后&#xff0c;再回到原来被中断的地方&#xff0c;继续原来的工作&#xff0c;这样的过程称为中断2.为什么要…

前端开发:HTML(5)—— 表单

下面我们来学习表单。 目录 什么是Web表单&#xff1f; 表单标签 1.form标签 2.输入框 文本框和密码框 单选框和复选框 1.单选框 2.复选框 3.按钮 &#xff08;1&#xff09;普通按钮 &#xff08;2&#xff09;提交按钮 &#xff08;3&#xff09;重置按钮 &#…

【YOLOv8改进 - C2f融合】C2f融合SFS-Conv(空间 - 频率选择卷积)提升特征多样性,同时减少参数和计算量

YOLOv8目标检测创新改进与实战案例专栏 专栏目录: YOLOv8有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例 专栏链接: YOLOv8基础解析+创新改进+实战案例 文章目录 YOLOv8目标检测创新改进与实战案例专栏 介绍 摘要 文…

如何将照片从POCO手机传输到Mac电脑

将照片从POCO手机传输到Mac电脑可能会有些困难&#xff0c;因为与iPhone不同&#xff0c;POCO设备没有原生的macOS支持。这常常让用户寻找简单、有效的方法来移动图片&#xff0c;同时避免丢失质量&#xff0c;节省时间&#xff0c;并避免复杂的软件设置。如果你想知道如何将照…

最新教程 | CentOS 7 内网环境 Nginx + ECharts 页面离线部署手册(RPM 安装方式)

&#x1f4c1; 一、准备阶段&#xff08;在联网电脑上完成&#xff09; 1.1 下载 Nginx 官方 RPM 安装包 在联网电脑浏览器中访问 Nginx 官方稳定版本仓库&#xff1a; &#x1f517; 地址&#xff1a;http://nginx.org/packages/centos/7/x86_64/ ☁️云盘&#xff1a;htt…

Redis 常用数据类型 (下)

文章目录前言一 Hash 哈希1. Hash 相关命令hset 和 hgethexistshdelhkeyshvalshgetallhmgethlenhsetnxhincrbyincrbyfloat2. Hash 命令小结3. Hash 内部编码Hash 在缓存中的应用场景介绍缓存方式对比二、List 列表1. LIST总体介绍2. List 普通命令lpushlpushxrpushrpushxlrange…

Java Lambda表达式:简洁高效的函数式编程

1 lambda表达式Lambda 表达式本质是一个匿名函数&#xff0c;用于把函数作为参数&#xff0c;传入方法中&#xff0c;实现函数式编程风格。使用Lambda 表达式可以使代码变的更加简洁紧凑。语法格式&#xff1a;(parameters)-> expression 或 (parameters)->{ statements…

python中的集合

目录 初识集合 集合的含义 集合的作用 集合的使用场景 集合的定义 集合的常用操作 元素的增加 函数add() 元素的删除 函数remove() 函数clear() 函数pop() 集合的遍历 for循环 while循环 初识集合 集合的含义 在pyrhon中&#xff0c;集合是一种内置的数据结构…

如何将普通HTTP API接口改造为MCP服务器

在现代微服务架构中&#xff0c;MCP&#xff08;Mesh Configuration Protocol&#xff09; 作为高效配置分发协议&#xff0c;正逐渐替代传统HTTP API。本文将手把手教你如何将普通HTTP API升级为高性能MCP服务器。 为什么需要MCP&#xff1f; 传统HTTP API在配置分发场景存在…

数据结构第8问:什么是树?

树 【本节仅描述树的定义、术语以及相关性质】 定义 树是由若干个结点组成的有限集合。具有如下特征&#xff1a; 有且仅有一个根结点&#xff1b;除根结点外&#xff0c;每个其它结点有且仅有一个直接的父结点&#xff1b;除根结点外&#xff0c;每个结点可以有零个或者多个子…