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

一题目

请设计以下航行器、飞机、船、水上飞机等 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();//输出1
	p->fun();//输出2
	p = &b;//我们将指针 p 的指向从 a 对象更改为 b 对象。注意,此时 p 仍然是一个指向 A 的指针,但它现在指向了 B 类的对象 b。
	p->foo();//取决于指针类型,定义为A类指针,故输出1
	p->fun();//取决于对象类型,指向了B的b对象,输出4(虚函数调用B类的fun)
	return 0;
}
总结     
  • 非虚函数(如 foo())在运行时不会被动态绑定。它们总是根据指针或引用的静态类型(即声明时的类型)来调用。
  • 虚函数(如 fun())在运行时会被动态绑定。它们会根据指针或引用实际指向的对象的类型来调用。
  • 仅在虚函数的顶层基类加上virtual关键字,子类不加,而改用override关键字

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

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

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

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

3.虚继承

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

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

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

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

相关文章

ASP.NET学生成绩管理系统

摘要 本系统依据开发要求主要应用于教育系统&#xff0c;完成对日常的教育工作中学生成绩档案的数字化管理。开发本系统可使学院教职员工减轻工作压力&#xff0c;比较系统地对教务、教学上的各项服务和信息进行管理&#xff0c;同时&#xff0c;可以减少劳动力的使用&#xf…

操作系统实战(三)(linux+C语言实现)

实验目的 加深对进程调度概念的理解&#xff0c;体验进程调度机制的功能&#xff0c;了解Linux系统中进程调度策略的使用方法。 练习进程调度算法的编程和调试技术。 实验说明 1.在linux系统中调度策略分为3种 SCHED_OTHER&#xff1a;默认的分时调度策略&#xff0c;值为0…

通俗的理解网关的概念的用途(四):什么是网关设备?(网络层面)

任何一台Windows XP操作系统之后的个人电脑、Linux操作系统电脑都可以简单的设置&#xff0c;就可以成为一台具备“网关”性质的设备&#xff0c;因为它们都直接内置了其中的实现程序。MacOS有没有就不知道&#xff0c;因为没用过。 简单的理解&#xff0c;就是运行了具备第二…

使用nmcli命令在Linux系统上配置各种网络(有线、无线、vlan、vxlan、路由、网桥等)

前言&#xff1a;原文在我的博客网站中&#xff0c;持续更新数通、系统方面的知识&#xff0c;欢迎来访&#xff01; 使用nmcli命令在Linux系统上配置各种网络&#xff08;有线、无线、vlan、vxlan、路由、网桥等&#xff09;https://myweb.myskillstree.cn/123.html 你是否会…

使用GitLab自带的CI/CD功能在远程服务器部署项目(三)

前置内容&#xff1a; 通过Docker Compose部署GitLab和GitLab Runner&#xff08;一&#xff09; 使用GitLab自带的CI/CD功能在本地部署项目&#xff08;二&#xff09; 目录 一、在GitLab服务器上生成私钥与公钥 二、将公钥拷贝到应用服务器上 三、将私钥给到Docker Exec…

Windows系统下通过nginx配置多项目

文章目录 前言大概思路实际操作记录&#xff1a;查看nginx 错误日志问下AI注意点&#xff1a; 当访问域名根路径时&#xff0c;重定向到/pc总结 前言 在windows电脑启动一个nginx 测试配置多前端项目&#xff0c;一个pc端&#xff08;vue3tsvite &#xff0c;history路由&…

Vue3专栏项目 -- 二、自定义From组件(下)

需求分析&#xff1a; 现在我们还需要一个整体的表单在单击某个按钮的时候可以循环的验证每个input的值&#xff0c;最后我们还需要有一个事件可以得到最后验证的结果&#xff0c;从而进行下一步的操作 如下&#xff0c;我们应该有一个form表单包裹着全部的input表单&#xf…

【C语言】整数和浮点数在内存中的存储

大家可能在学习的时候会经常疑惑数据在内存中是怎样存储的&#xff0c;今天用一篇博客给你讲清楚&#xff01;&#xff01;&#xff01;从此不再疑惑&#xff01;&#xff01;&#xff01; 文章目录 1. 整数在内存中的存储2. 大小端字节序和字节序判断2.1 什么是大小端2.2 为什…

[VulnHub靶机渗透] Hackademic: RTB1

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

day2_greedyIntervalsLRU/LFU

二、贪心算法之区间调度问题 0.计算一个区间集合中无重复的区间的最大数量(模板) public int intervalSchedule(int[][] intvs) {if (intvs.length 0) return 0;// 按 end 升序排序Arrays.sort(intvs, (a, b) -> Integer.compare(a[1], b[1]));// 至少有一个区间不相交in…

Baidu Comate 编程插件:提升开发效率的利器

文章目录 引言简介目的 Baidu Comate插件概述定义与功能市场现状竞品分析 安装与配置VsCode 安装&#xff1a;注意事项 版本选择 核心特性详解功能介绍代码生成实时续写错误纠正 使用体验体验地址 引言 简介 基于文心大模型&#xff0c;结合百度积累多年的编程现场大数据和外…

专业做护眼灯的有哪些品牌?几款专业儿童卧室灯品牌分享

在当今时代&#xff0c;我们观察到一个不容忽视的现象&#xff1a;孩子们的视力问题日益增多&#xff0c;这无疑向众多家长发出了警示。它提醒着我们&#xff0c;除了追求学术成就之外&#xff0c;孩子们的视觉健康同样重要&#xff0c;不容忽视。因此&#xff0c;选择一款适合…

leetcode刷题:对称二叉树

题目&#xff1a; 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示&#xf…

以导航产品为核心,东软想为车企扫除出海障碍

得益于新能源汽车领域多年的布局&#xff0c;以及在汽车智能化方面的先发优势&#xff0c;近年来&#xff0c;中国汽车品牌在质与量上都得到了极大提升&#xff0c;并带来强大的竞争力。 据海关总署公布的数据&#xff0c;过去三年&#xff0c;中国汽车出口规模连续突破式发展…

LeetCode算法题:7. 整数反转

给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示例 1&#xff1a; 输…

会赚钱的人都在做这件事:你了解吗?

在我们日常生活的点滴中&#xff0c;以及在各种场合的交互中&#xff0c;利他思维始终扮演着不可或缺的角色。当我们追求合作与共赢时&#xff0c;单方面的自我立场显然是不够的&#xff0c;真正的关键在于换位思考&#xff0c;寻找并满足对方的需求。 互利互赢的核心理念正是利…

【挑战30天首通《谷粒商城》】-【第一天】【10 番外篇】 解决docker 仓库无法访问 + MobaXterm连接VirtualBox虚拟机

文章目录 课程介绍 1、解决docker 仓库无法访问 2、 MobaXterm连接VirtualBox虚拟机 Stage 1&#xff1a;下载MobaXterm选择适合你的版本 Stage 2&#xff1a;vagrant ssh 连接&#xff0c;开启ssh访问 Stage 2-1&#xff1a;su获取root账号权限,输入密码&#xff08;默认vagra…

纯血鸿蒙APP实战开发——阅读翻页方式案例

介绍 本示例展示手机阅读时左右翻页&#xff0c;上下翻页&#xff0c;覆盖翻页的功能。 效果图预览 使用说明 进入模块即是左右翻页模式。点击屏幕中间区域弹出上下菜单。点击设置按钮&#xff0c;弹出翻页方式切换按钮&#xff0c;点击可切换翻页方式。左右翻页方式可点击翻…

【软件测试】3.开发模型

目录 1.常见的开发模型 1.1瀑布模型 1.2螺旋模型 1.3增量模型和迭代模型 1.4敏捷模型 1.4.1特点&#xff1a; 1.5Scrum模型&#xff08;三个角色和五个重要会议&#xff09; 1.5.1三个角色&#xff1a; 1.5.2Scrum工作流程&#xff08;五个会议&#xff09; 1.6测试模…