*****水上飞机:继承,虚函数,虚继承

一题目

请设计以下航行器、飞机、船、水上飞机等 4 个类。

  • CRAFT 为航行器类,是公共基类,提供航行器的基本特性。包括:

    一个保护数据成员:speed(速度)。

    三个公有成员函数:构造函数(初始化速度)、析构函数和 Show 函数(显示速度)。

  • PLANE 为飞机类,以公有方式继承 CRAFT 类,在航行器类的基础上增加飞机的特性。包括:

    一个保护数据成员:width(翼展)。

    三个公有成员函数:构造函数(初始化速度和翼展)、析构函数和 Show 函数(显示速度和翼展)。

  • SHIP 为船类,以公有方式继承 CRAFT 类,在航行器类的基础上增加船的特性。包括:

    一个保护数据成员:depth(吃水深度)。

    三个公有成员函数:构造函数(初始化速度和吃水深度)、析构函数和 Show 函数(显示速度和吃水深度)。

  • SEAPLANE 为水上飞机类,同时以公有方式继承 PLANE 类和 SHIP 类,兼具飞机和船的特性。包括:

    三个公有成员函数:构造函数(初始化速度、翼展、吃水深度)、析构函数和 Show 函数(显示速度、翼展和吃水深度)。

  • 测试用例
  • 样例一
  •  CRAFT *p; p = new CRAFT(87.2); p->Show(); delete p; 
    创建航行器(速度: 87.2)
    航行(速度: 87.2)
    销毁航行器(速度: 87.2)
    
  • 样例二
  •  CRAFT *p; p = new PLANE(613.5, 45.3); p->Show(); delete p; 
    创建航行器(速度: 613.5)
    创建飞机(翼展: 45.3)
    航行(速度: 613.5, 翼展: 45.3)
    销毁飞机(翼展: 45.3)
    销毁航行器(速度: 613.5)
    
  • 样例三
  •  CRAFT *p; p = new SHIP(45.8, 8.3); p->Show(); delete p; 
    创建航行器(速度: 45.8)
    创建船(吃水: 8.3)
    航行(速度: 45.8, 吃水: 8.3)
    销毁船(吃水: 8.3)
    销毁航行器(速度: 45.8)
    
  • 样例四
  •  CRAFT *p; p = new SEAPLANE(415.2, 36.5, 2.1); p->Show(); delete p;
创建航行器(速度: 415.2)
创建飞机(翼展: 36.5)
创建船(吃水: 2.1)
创建水上飞机
航行(速度: 415.2, 翼展: 36.5, 吃水: 2.1)
销毁水上飞机
销毁船(吃水: 2.1)
销毁飞机(翼展: 36.5)
销毁航行器(速度: 415.2)

二.代码部分

#include <iostream>
using namespace std;
class CRAFT
{
protected:double speed;
public:CRAFT(double s){speed = s;cout << "创建航行器(速度: " << speed << ")" << endl;}virtual void Show(){cout << "航行(速度: " << speed << ")" << endl;}virtual ~CRAFT(){cout << "销毁航行器(速度: " << speed << ")" << endl;}
};
class PLANE :virtual public CRAFT
{
protected:double width;
public:PLANE(double s, double w) :CRAFT(s), width(w)//调用CRAFT的构造函数,传递speed{cout << "创建飞机(翼展: " << width << ")" << endl;}void Show()override{cout << "航行(速度: " << speed << ", 翼展: " << width << ")" << endl;}~PLANE()override{cout << "销毁飞机(翼展: " << width << ")" << endl;}
};
class SHIP :virtual public CRAFT
{
protected:double depth;
public:SHIP(double s, double d) :CRAFT(s), depth(d)//调用CRAFT的构造函数,传递speed{cout << "创建船(吃水: " << depth << ")" << endl;}void Show()override{cout << "航行(速度: " << speed << ", 吃水: " << depth << ")" << endl;}~SHIP()override{cout << "销毁船(吃水: " << depth << ")" << endl;}
};
class SEAPLANE : virtual public PLANE, virtual public SHIP
{
public:SEAPLANE(double s, double w, double d) :CRAFT(s), PLANE(s, w), SHIP(s, d)//调用CRAFT的构造函数,传递speed,调用 PLANE 的构造函数,传递 speed 和 width参数,调用 SHIP 的构造函数,传递 speed 和 depth参数{cout << "创建水上飞机" << endl;}void Show()override{cout << "航行(速度: " << speed << ", 翼展: " << width << ", 吃水: " << depth << ")" << endl;}~SEAPLANE()override{cout << "销毁水上飞机" << endl;}
};int main()
{double s, w, d;CRAFT* p;//CRAFT类型的指针cin >> s >> w >> d;p = new SEAPLANE(s, w, d);//实际指向SEAPLANE类的对象(未命名)p->Show();//调用SEAPLAENE的show函数delete p;return 0;
}

输出:

创建航行器(速度: 583.6)
创建飞机(翼展: 48.2)
创建船(吃水: 3.8)
创建水上飞机
航行(速度: 583.6, 翼展: 48.2, 吃水: 3.8)
销毁水上飞机
销毁船(吃水: 3.8)
销毁飞机(翼展: 48.2)
销毁航行器(速度: 583.6)

三总结

1.继承

方式

class 派生类:继承方式 基类

继承后的访问权限

 记忆方式:假设

public>protected>private

取基类属性和继承方式中较小的作为在派生类的访问属性

1.基类的pirvate在派生类中无法访问

2.基类的protected继承后可以在派生类中访问类外不行

2.虚函数

虚函数允许在派生类中重写基类的函数,从而实现运行的多态性

核心目的是通过基类访问派生类定义的函数,以便在通过基类指针引用或调用的时候可以执行派生类中的版本

#include<iostream>
using namespace std;
class A//基类
{
public:void foo(){cout << "1" << endl;}virtual void fun()//声明为虚函数virtual关键字{cout << "2" << endl;}
};
class B :public A//派生类
{
public:void foo()//隐藏:派生类的函数屏蔽了与其同名的基类函数{cout << "3" << endl;}void fun()//多态覆盖{cout << "4" << endl;}
};
int main()
{A a;B b;A* p = &a;//这里定义了一个指向 A 类的指针 p,并将其初始化为指向 a 对象的地址。p->foo();//输出1p->fun();//输出2p = &b;//我们将指针 p 的指向从 a 对象更改为 b 对象。注意,此时 p 仍然是一个指向 A 的指针,但它现在指向了 B 类的对象 b。p->foo();//取决于指针类型,定义为A类指针,故输出1p->fun();//取决于对象类型,指向了B的b对象,输出4(虚函数调用B类的fun)return 0;
}
总结     
  • 非虚函数(如 foo())在运行时不会被动态绑定。它们总是根据指针或引用的静态类型(即声明时的类型)来调用。
  • 虚函数(如 fun())在运行时会被动态绑定。它们会根据指针或引用实际指向的对象的类型来调用。
  • 仅在虚函数的顶层基类加上virtual关键字,子类不加,而改用override关键字

有了这方面的只是支持,我们现在来理解题目的输出部分:

1.构造函数不会被多态性影响。无论是通过基类指针还是派生类对象本身,构造函数总是会被调用,并且会调用基类的构造函数。

2.成员函数,当他们是虚函数时,他们被通过基类指针或调用引用时会表现出多态性,即会调用与指针或调用引用实际指向的对象类型相对应的函数版本。

3.析构函数,与构造函数类似,但与虚函数关系密切。如果基类的析构函数时虚函数时,则会表现出多态性,通过基类指针删除派生类对象时,会先调用派生类的析构函数,在调用基类的。如果基类的析构函数不是虚函数,那么只会调用基类的析构函数,这可能会导致派生类部分没有被正确清理,造成资源泄漏或其他问题。

3.虚继承

在C++中,虚继承是用于解决多重继承中公共基类(或称为“菱形继承”或“钻石问题”)的重复子对象问题的一种机制。当一个类(SEAPLANE)从多个类(SHIP,PLANE)继承,而这些类又都从一个公共基类(CRAFT)继承时,如果没有使用虚继承,那么该公共基类在派生类中将会有多个实例(或称为子对象),这通常不是我们想要的结果。

为了解决这个问题,C++引入了虚继承的概念。当某个基类被声明为虚继承时,它的所有派生类(无论是直接派生还是间接派生)都会共享这个基类的单一实例,而不是每个派生类都有自己的一个实例。

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

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

相关文章

AOSP开发

Android 开发者 | Android Developers (google.cn) android开源代码&#xff1a; Android 开源项目 | Android Open Source Project (google.cn)

FreeRTOS任务调度器

目录 1、什么是任务调度器 2、FreeRTOS中的任务调度器 2.1 抢占式调度 2.2 时间片调度 2.3 协作式调度 3、任务调度案例分析 3.1 实验需求 3.2 CubeMX配置 3.3 代码实现 3.3.1 uart.c 重定向printf 3.3.2 打开freertos.c并添加代码 3.3.4 代码现象 1、什么是任务调度…

Spring:spring-boot-starter-parent与spring-boot-dependencies的区别

参考&#xff1a;spring-boot-starter-parent与spring-boot-dependencies的区别

[uniapp] 配置ts类型声明

我想引进图片,但是报错 声明一下就行 TypeScript 支持 | uni-app官网 创建tsconfig.json文件,复制官网的配置 然后在随便一个目录下写一个随便名字的.d.ts文件 例如这样 保存就行 因为ts是默认扫描全部的,所以要按照官网的写法 把不必要的排除掉就行,免得浪费性能

JS-导入导出

export和export default是ES6中导出模块中变量的语法 导入导出变量 //导出方法&#xff08;js文件中&#xff09; export const 变量名值//导入方法 对应导入的变量&#xff0c;一定要加花括号 import {变量名} from js文件路径 导入导出函数 //导出方法&#xff08;js文件中…

RST文档技巧汇总

RST文件技巧汇总 前言转换工具简洁语法注释空行标题与章节样式链接图片列表表格代码块文档内引用引用rst 前言 RST全称ReStructuredText&#xff0c;是一种使用简单标记语法编写文档的文本文件格式。RST文档是轻量级标记语言的一种&#xff0c;被设计为容易阅读和编写的纯文本…

TikTok自动评论、回复的脚本怎么制作?

在当今数字化的时代&#xff0c;社交媒体平台如TikTok已经成为人们日常生活的一部分&#xff0c;为了更有效地在TikTok上进行营销或互动&#xff0c;许多用户和企业开始寻找自动化工具&#xff0c;如自动评论和回复的脚本&#xff0c;以节省时间并提高效率。 本文将科普如何制…

[数据结构]——非递归排序总结——笔试爱考

具体代码实现在gitee&#xff1a;登录 - Gitee.com 目录 具体代码实现在gitee&#xff1a;登录 - Gitee.com 1.非递归实现的快速排序算法。 第一步 首先要创建一个栈 第二步紧接着进行入栈&#xff0c;出栈&#xff0c;弹出栈顶元素&#xff0c;获取栈顶元素&#xff0c;判…

Windows下安装Node.js、npm和electronic,并运行一个Hello, World!脚本程序

20240510 By wdhuag 目录 简介&#xff1a; 参考&#xff1a; 安装Node.js 安装npm 配置npm&#xff1a; 修改包存放目录和缓存目录 切换镜像源 使用 nrm 切换镜像源 安装Electron 运行一个Hello, World!脚本程序 安装Yarn JavaScript 指南 简介&#xff1a; Nod…

英文论文审稿

英文论文审稿1 英文论文审稿4英文论文审稿5审稿意见: Identification and early warning method of key disaster-causing factors of AE signals for rockburst based on principal component analysis method 作者从城市地质环境的量化评价出发,创造性地提出城市地质环境健…

MT8370_联发科MTK8370(Genio 510)芯片性能规格参数

MT8370芯片是一款利用超高效的6nm制程工艺打造的边缘AI平台&#xff0c;具有强大的性能和功能。这款芯片集成了六核CPU(2x2.2 GHz Arm Cortex-A78 & 4x2.0 GHz Arm Cortex-A55)、Arm Mali-G57 MC2 GPU、集成的APU(AI处理器)和DSP&#xff0c;以及一个HEVC编码加速引擎&…

数据库查询--条件查询

目录 1.关系运算条件的查询 2.逻辑运算符条件的查询 3.带关键字IN的查询 4.带BETWEEN AND关键字的查询 5.空值查询 6.带LIKE关键字的模糊查询 1.关系运算条件的查询 在SELECT语句中&#xff0c;最常见的是使用WHERE字句指定关系运算条件对数据进行过滤。 语法格式&#x…

【二叉树算法题记录】二叉树的所有路径,路径总和——回溯

目录 257. 二叉树的所有路径题目描述题目分析cpp代码 112. 路径总和题目描述题目分析cpp代码 257. 二叉树的所有路径 题目描述 给你一个二叉树的根节点root &#xff0c;按任意顺序&#xff0c;返回所有从根节点到叶子节点的路径。 题目分析 其实从根节点往下走&#xff0c…

设计模式——迭代器模式(Iterator)

迭代器模式&#xff08;Iterator Pattern&#xff09;是一种行为设计模式&#xff0c;它使得我们能够顺序地访问一个聚合对象中的各个元素&#xff0c;而又不需要暴露该对象的内部表示。迭代器模式为遍历不同的聚合结构提供了一个统一的接口&#xff0c;使得客户端代码可以独立…

【回溯算法】【Python实现】图的m着色问题

文章目录 [toc]问题描述图的 m m m可着色判定问题图的 m m m可着色优化问题四色猜想 回溯法时间复杂性Python实现 问题描述 图的 m m m可着色判定问题 给定无向连通图 G G G和 m m m种不同的颜色&#xff0c;用这些颜色为图 G G G的各顶点着色&#xff0c;每个顶点着一种颜色…

自然资源-地质勘查工作的流程梳理

自然资源-地质勘查工作的流程梳理 地质勘查从广义上可理解为地质工作&#xff0c;地质队员就好像是国家宝藏的“寻宝人”&#xff0c;通过地质勘查&#xff0c;为国家找矿&#xff0c;以保障国家能源资源安全和服务国计民生&#xff0c;发挥着地质工作在国民经济建设中的基础性…

Qt——信号 和 槽

目录 概述 信号和槽的使用 自定义信号和槽 带参数的信号和槽 概述 在Linux系统中&#xff0c;我们也介绍了信号的产生、信号的检测以及信号的处理机制&#xff0c;它就是系统内部的通知机制&#xff0c;也可以是一种进程间通信的方式。在系统中有很多信号&#xff0c;我们可…

kubernate 基本概念

一 K8S 是什么&#xff1f; K8S 全称&#xff1a;Kubernetes 1 kubernate基本概念 作用&#xff1a; 用于自动部署、扩展和管理“容器化&#xff08;containerized&#xff09;应用程序”的开源系统。 可以理解成 K8S 是负责自动化运维管理多个容器化程序&#xff08;比如…

C语言—深入理解指针(3)

1.字符指针变量 一般使用&#xff1a; 另一种使用方法&#xff1a; “hello world”是一个常量字符串&#xff0c;不能被修改。 上述代码是将字符串中的首字符‘h’赋值给指针pstr&#xff0c;用%s打印字符串的时候&#xff0c;只需要提供首字符的地址就行。&#xff08;如果…

Golang | Leetcode Golang题解之第73题矩阵置零

题目&#xff1a; 题解&#xff1a; func setZeroes(matrix [][]int) {n, m : len(matrix), len(matrix[0])col0 : falsefor _, r : range matrix {if r[0] 0 {col0 true}for j : 1; j < m; j {if r[j] 0 {r[0] 0matrix[0][j] 0}}}for i : n - 1; i > 0; i-- {for …