Part 1.梳理思维导图

一.继承中的特殊成员函数

1.构造函数

父类的构造函数会被继承到子类中,在构造的顺序中,是先构造父类,再构造子类

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::无参构造函数" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有参构造函数" << endl;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::无参构造函数" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有参构造函数" << endl;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("张四",18,"张三",40,100);s1.show();return 0;
}

在创建子类时,会先调用父类的构造函数,再调用子类的构造函数

2.析构函数

父类的析构函数会被继承到子类中,在析构的顺序中,先析构子类,再析构父类

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::无参构造函数" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有参构造函数" << endl;}~Father(){delete age;age = nullptr;cout << "Father::析构函数" << endl;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::无参构造函数" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有参构造函数" << endl;}~Son(){delete sonage;sonage = nullptr;cout << "Son::析构函数" << endl;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("张四",18,"张三",40,100);s1.show();return 0;
}

在函数结束时,释放子类,会先调用子类的析构函数,再调用父类的析构函数

3.拷贝构造函数

父类的拷贝构造函数函数会被继承到子类中,如果有深拷贝的问题,子类父类完成各自的拷贝工作

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::无参构造函数" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有参构造函数" << endl;}~Father(){delete age;age = nullptr;cout << "Father::析构函数" << endl;}Father(const Father &other):name(other.name),age(new int(*(other.age))),weight(other.weight){cout << "Father::拷贝构造函数" << endl;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::无参构造函数" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有参构造函数" << endl;}~Son(){delete sonage;sonage = nullptr;cout << "Son::析构函数" << endl;}Son(const Son &other):Father(other),sonname(other.sonname),sonage(new int(*(other.sonage))){cout << "Son::拷贝构造函数" << endl;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("张四",18,"张三",40,100);s1.show();Son s2 = s1;s2.show();return 0;
}

在子类对象就行拷贝构造时,会调用子类的拷贝构造函数拷贝子类的内容,并调用父类的拷贝构造函数拷贝父类内容,最后构造另一个子类对象

4.拷贝赋值函数

父类的拷贝赋值函数函数会被继承到子类中,如果有深拷贝的问题,子类父类完成各自的拷贝工作

#include <iostream>using namespace std;class Father
{
public:string name;
protected:int *age;
private:int weight;
public:Father(){age = nullptr;cout << "Father::无参构造函数" << endl;}Father(string n,int a,int w):name(n),age(new int(a)),weight(w){cout << "Father::有参构造函数" << endl;}Father &operator=(const Father &other){if(this != &other){name = other.name;age = new int(*(other.age));weight = other.weight;}cout << "Father::拷贝赋值函数" << endl;return *this;}void show(){cout << name << " " << *age << " " << weight << endl;}
};class Son:public Father
{
private:string sonname;int *sonage;
public:Son(){sonage = nullptr;cout << "Son::无参构造函数" << endl;}Son(string sn,int sa,string fn,int a,int w):Father(fn,a,w),sonname(sn),sonage(new int(sa)){cout << "Son::有参构造函数" << endl;}Son &operator=(const Son &other){if(this != &other){sonname = other.sonname;sonage = new int(*(other.sonage));Father::operator = (other);}cout << "Son::拷贝赋值函数" << endl;return *this;}void show(){cout << sonname << " " << *sonage << " ";Father::show();}
};int main()
{Son s1("张四",18,"张三",40,100);s1.show();Son s3;s3 = s1;s3.show();return 0;
}

二.多继承

1.概念

一个子类继承了多个父类

2.格式

class 类名: 继承方式1 类名1,继承方式2 类名2,...,继承方式n 类名n
{子类的拓展;
};

3.例子

#include <iostream>using namespace std;class Sofa
{
private:string sit;
public:Sofa(){cout << "Sofa::无参构造函数" << endl;}Sofa(string sit):sit(sit){cout << "Sofa::有参构造函数" << endl;}~Sofa(){cout << "Sofa::析构函数" << endl;}void show(){Jiaju::show();cout << sit << endl;}
};class Bed
{
private:string sleep;
public:Bed(){cout << "Bed::无参构造函数" << endl;}Bed(string sleep):sleep(sleep){cout << "Bed::有参构造函数" << endl;}~Bed(){cout << "Bed::析构函数" << endl;}void show(){Jiaju::show();cout << sleep << endl;}
};class Bedsofa:public Sofa,public Bed
{
private:string color;
public:Bedsofa(){cout << "Bedsofa::无参构造函数" << endl;}Bedsofa(string sit,string sleep,string color,):Sofa(sit),Bed(sleep),color(color){cout << "Bedsofa::有参构造函数" << endl;}~Bedsofa(){cout << "Bedsofa::析构函数" << endl;}void show(){Bed::show();Sofa::show();cout << color << endl;}
};int main()
{Bedsofa b1("能坐","能躺","白色",100);b1.show();return 0;
}

4.小结

多继承可以使一个子类拥有多个父类的数据成员与成员函数,由于是多个父类,所以再构造子类对象时,会先构建父类;

在子类的构造函数中,注意调用父类的顺序,该顺序就是在子类头部声明调用父类的顺序

三.菱形继承

1.概念

一个公共基类生出多个中间子类,这些中间子类生出一个汇聚子类,这就是菱形继承

(一个父类生出多个子类,这些子类合出一个孙类)

2.例子

#include <iostream>using namespace std;
class Jiaju
{
private:int weight;
public:Jiaju(){cout << "Jiaju::无参构造函数" << endl;}Jiaju(int weight):weight(weight){cout << "Jiaju::有参构造函数" << endl;}~Jiaju(){cout << "Jiaju::析构函数" << endl;}void show(){cout << weight << endl;}
};class Sofa:public Jiaju
{
private:string sit;
public:Sofa(){cout << "Sofa::无参构造函数" << endl;}Sofa(string sit,int weight):Jiaju(weight),sit(sit){cout << "Sofa::有参构造函数" << endl;}~Sofa(){cout << "Sofa::析构函数" << endl;}void show(){Jiaju::show();cout << sit << endl;}
};class Bed:public Jiaju
{
private:string sleep;
public:Bed(){cout << "Bed::无参构造函数" << endl;}Bed(string sleep,int weight):Jiaju(weight),sleep(sleep){cout << "Bed::有参构造函数" << endl;}~Bed(){cout << "Bed::析构函数" << endl;}void show(){Jiaju::show();cout << sleep << endl;}
};class Bedsofa:public Sofa,public Bed
{
private:string color;
public:Bedsofa(){cout << "Bedsofa::无参构造函数" << endl;}Bedsofa(string sit,string sleep,string color,int weight):Sofa(sit,weight),Bed(sleep,weight),color(color){cout << "Bedsofa::有参构造函数" << endl;}~Bedsofa(){cout << "Bedsofa::析构函数" << endl;}void show(){Bed::show();Sofa::show();cout << color << endl;}
};int main()
{Bedsofa b1("能坐","能躺","白色",100);b1.show();return 0;
}

在该函数中,公共基类(jiaju)生出两个中间子类(bed和sofa),最后俩中间子类生出一个汇聚子类(bedsofa),汇聚子类用到了多继承,继承两个父类及两个中间子类,俩中间子类的共同父类及公共基类

3.菱形继承的弊端及分析

        A.弊端

1.汇聚子类会得到多分由中间子类继承下来的公共基类,这样会浪费空间

2.汇聚子类对象创建时,会多次调用公共基类的构造函数和析构函数

        B.原因

1.因为子类创建时都会调用父类,在汇聚子类创建时,会调用自己的父类及中间子类,bedsofa创建类对象按顺序会调用sofa和bed的构造函数,但是sofa和bed会先调用自己父类及公共基类的构造函数,按调用顺序是:jiaju - sofa - jiaju - bed - bedsofa,所以在构造和析构时,jiaju的构造函数和析构函数都会被多次调用。如果函数中有指针类型成员,在析构时会多次delete空间,会出现错误

2.按上述所讲,子类会继承父类所有数据成员和成员函数,有两个中间子类,汇聚子类就会继承到两次公共基类

四.虚继承

1.作用

解决菱形继承的错误,让多个中间子类只继承一次公共基类

2.格式

在中间子类继承前面加上virtual

class 类名:virtual 继承方式 类名  // 中间子类
{中间子类分拓展;
};

3.注意事项

1.由于中间子类中的公共基类太多,编译器不清楚应该保存公共基类哪些成员函数,所以会直接保存公共基类的无参构造函数,所以如果需要公共基类的有参构造函数,需要在汇集子类里手动调用

2.所有虚继承的中间子类会返回一个公共基类,如果有中间子类没有虚继承,那个中间子类会返回公共基类,所以需要把所有中间子类都虚继承

4.示例

#include <iostream>using namespace std;
class Jiaju
{
private:int weight;
public:Jiaju(){cout << "Jiaju::无参构造函数" << endl;}Jiaju(int weight):weight(weight){cout << "Jiaju::有参构造函数" << endl;}~Jiaju(){cout << "Jiaju::析构函数" << endl;}void show(){cout << weight << endl;}
};class Sofa:virtual public Jiaju//虚继承
{
private:string sit;
public:Sofa(){cout << "Sofa::无参构造函数" << endl;}Sofa(string sit,int weight):Jiaju(weight),sit(sit){cout << "Sofa::有参构造函数" << endl;}~Sofa(){cout << "Sofa::析构函数" << endl;}void show(){Jiaju::show();cout << sit << endl;}
};class Bed:virtual public Jiaju//虚继承
{
private:string sleep;
public:Bed(){cout << "Bed::无参构造函数" << endl;}Bed(string sleep,int weight):Jiaju(weight),sleep(sleep){cout << "Bed::有参构造函数" << endl;}~Bed(){cout << "Bed::析构函数" << endl;}void show(){Jiaju::show();cout << sleep << endl;}
};class Bedsofa:public Sofa,public Bed
{
private:string color;
public:Bedsofa(){cout << "Bedsofa::无参构造函数" << endl;}Bedsofa(string sit,string sleep,string color,int weight):Jiaju(weight),Sofa(sit,weight),Bed(sleep,weight),color(color)//汇聚子类手动调用公共基类{cout << "Bedsofa::有参构造函数" << endl;}~Bedsofa(){cout << "Bedsofa::析构函数" << endl;}void show(){Bed::show();Sofa::show();cout << color << endl;}
};int main()
{Bedsofa b1("能坐","能躺","白色",100);b1.show();return 0;
}

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

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

相关文章

PDF教程|如何把想要的网页保存下来?

前段时间有个小伙伴咨询了小白&#xff1a;领导想要某个网页的整个页面&#xff0c;有没有比较好的方法把它保存下来&#xff1f; 在他找到小白之前&#xff0c;这种事情他已经接到好几次了&#xff0c;每次都是怎么解决的呢&#xff1f;其实很简单&#xff0c;就是打开Word&a…

【bash】命令查看当前目录下文件个数

要用 ls 查看当前目录下的文件个数&#xff0c;可以结合 wc -l 来统计行数&#xff1a; ls -1 | wc -l说明&#xff1a; ls -1&#xff1a;以一行一个文件的方式列出。wc -l&#xff1a;统计行数&#xff0c;也就是文件/目录的数量。 ⚠️ 需要注意&#xff1a; 这个方法会把文…

「日拱一码」081 机器学习——梯度增强特征选择GBFS

目录 什么是梯度增强特征选择&#xff08;GBFS&#xff09; 为什么 GBM 适合做特征选择 GBFS 的一般步骤 代码示例 什么是梯度增强特征选择&#xff08;GBFS&#xff09; GBFS 并非一个像 Lasso 或随机森林那样有严格标准定义的独立算法&#xff0c;而是一种基于梯度提升机…

解构汇编, 万物起源

汇编的诞生汇编全景图核心主干: CPU架构主要分支: 语法和工具共同的地貌: 核心概念延伸: 跨平台 & 跨架构跨平台跨架构总结以 GAS vs. NASM 为例NASM 不支持跨架构 ≠ 无法在ARM架构上的系统安装汇编的诞生 机器语言的困境 早期的程序员直接使用机器语言进行编程机器语言由…

广州旅游网站系统 - 纯静态旅游展示平台

&#x1f31f; 广州旅游网站系统 - 纯静态旅游展示平台观世界才有世界观 - 一个集景区展示、旅游攻略、文化传播于一体的精美旅游网站&#x1f4cb; 项目概述 这是一个专注于广州旅游文化的纯静态网站系统&#xff0c;采用现代化的前端技术栈&#xff0c;为游客提供全方位的广州…

Qt UDP通信学习

Qt UDP通信学习 一、项目概述 本项目基于Qt框架实现了UDP通信功能&#xff0c;支持单播与广播消息收发&#xff0c;展示了UDP套接字的基本用法&#xff0c;适合初学者学习Qt网络模块的实际应用。 二、项目结构 55.pro&#xff1a;Qt工程文件&#xff0c;配置模块与源码文件main…

古德哈特定律(Goodhart‘s Law)

古德哈特定律&#xff08;Goodhart’s Law&#xff09;表述为“当一个指标变成了目标&#xff0c;它将不再是个好指标”。 该定律由英国经济学家查尔斯古德哈特&#xff08;Charles Goodhart&#xff09;在1975年提出&#xff0c;最初用于批判撒切尔夫人政府的货币主义政策&…

在 ASP.NET Core 8 Web API 中实现基于角色的授权 安全且可扩展 API 的最佳实践

掌握基于角色的授权&#xff1a;使用专家策略保护您的 ASP.NET Core 8 Web API。在 ASP.NET Core 8 Web API 中实现基于角色的授权&#xff1a;安全且可扩展 API 的最佳实践介绍授权是任何 Web 应用程序的关键组件。在开发 API 时&#xff0c;使用基于角色的授权保护端点可确保…

AutoHotkey识别图片

一、下载ImagePut插件 下载地址&#xff1a;GitHub - iseahound/ImagePut: A core library for images in AutoHotkey. Supports AutoHotkey v1 and v2. 二、将插件和要搜索的图片导入项目 #Include ./plugin/ImagePut.ahk ; 截取当前屏幕 pic : ImagePutBuffer(0) point : p…

CamX-Camera常用编译命令和adb指南

g_camxsettings vendor/qcom/proprietary/camx/src/settings/g_camxsettings.xml 控制相机debug的信息都在该文件里面 0、相关代码 framwork层 frameworks/av/camera/ frameworks/av/services/camera frameworks/av/services/camera frameworks/hardware/interfaces/camerase…

LabVIEW 实现颜色平滑渐变控制

LabVIEW 中实现 LED 颜色从蓝到红的平滑渐变显示在 LabVIEW 开发中&#xff0c;若需让 LED&#xff08;或类 LED 显示控件&#xff09;实现从蓝色到红色的平滑色彩渐变&#xff08;模拟温度等参数从低到高的视觉反馈&#xff09;&#xff0c;可通过自定义颜色查找表 数值缩放映…

阴阳学:从入门到精通

第一篇&#xff1a;入门篇——阴阳基础理论1.1 阴阳的起源与哲学意义阴阳概念的历史渊源《易经》中的阴阳思想阴阳与宇宙、自然、人生的关系阴阳对思想、行为、社会的影响1.2 阴阳的基本属性与符号阴阳的特征、象征与对立统一阴阳在自然界的表现&#xff08;昼夜、冷热、动静等…

Java工业通信实战(三):Modbus RTU串口通信实现

想象一下&#xff0c;你要和一台工业设备"对话"&#xff0c;比如询问温度传感器"现在多少度&#xff1f;“或者告诉电机"转快一点”。 Modbus RTU就是这种"对话"的标准语言&#xff0c;就像人与人之间说普通话一样。 它采用主从结构&#xff0c;…

CentOS安装或升级protoc

卸载旧版本 sudo yum remove protobuf protobuf-c protobuf-compiler -y sudo rm -f /usr/bin/protoc sudo rm -rf /usr/include/google/protobuf 下载 wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.0/protoc-3.15.0-linux-x86_64.zip unz…

人工智能在医学图像中的应用:从机器学习到深度学习

目的&#xff1a;人工智能&#xff08;AI&#xff09;模型在生物医学研究和医疗服务中扮演着越来越重要的角色。本综述聚焦于在现实世界背景下&#xff0c;开发AI应用作为临床决策支持系统时需要澄清的挑战性问题。方法&#xff1a;进行了一项叙述性综述&#xff0c;包含对1989…

基于Echarts+HTML5可视化数据大屏展示-智慧小区大数据分析

效果展示&#xff1a;代码结构&#xff1a;主要代码实现 index.html布局 <!doctype html> <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8"><title>智慧农业大数据展示</title><link rel"s…

【LeetCode热题100道笔记】验证二叉搜索树

题目描述 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 严格小于 当前节点的数。 节点的右子树只包含 严格大于 当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。 示例 1&…

Apache Tomcat 教程:从入门到精通(含目录结构与版本详解)

​​​​​​1. 背景​​ Apache Tomcat 是一个开源的 ​​Java Servlet 容器​​&#xff0c;由 ​​Apache 软件基金会&#xff08;ASF&#xff09;​​ 开发和维护&#xff0c;最初由 ​​Sun Microsystems​​ 的软件架构师 ​​James Duncan Davidson​​ 设计&#xff0…

设计模式从入门到精通之(六)策略模式

策略模式&#xff1a;让算法灵活切换的秘密武器在日常开发中&#xff0c;算法的选择常常是程序设计的核心&#xff0c;比如支付方式的选择、排序逻辑的切换、促销活动的动态调整等。当需求变化时&#xff0c;我们需要在多个算法之间切换&#xff0c;但又不希望修改已有代码。如…

安装MATLAB205软件记录

安装MATLAB2025 一台电脑可以安装多个版本的MATLAB; 下载资源 微信公众平台-MATLAB R2025a v25.1下载及安装教程 安装步骤 解压, 压缩文件大小为13.8GB 装载 选中setup.exe右键单击以管理员身份运行 我有文件安装密钥 接受许可条款 复制粘贴密钥 63733-59078-50866-02827-…