C++重点和练习-----多态

news2024/12/17 14:53:48

rpg.cpp:

#include <iostream>

using namespace std;


/*
    模拟一个游戏场景
    有一个英雄:初始所有属性为1
    atk,def,apd,hp

    游戏当中有以下3种武器
    长剑Sword: 装备该武器获得 +1atx,+1def
    短剑Blade: 装备该武器获得 +1atk,+1spd
    斧头Axe:   装备该武器获得 +1atk,+1hp

    要求英雄写一个函数:
    equipweapon 装备武器
    实现效果:装备不同武器英雄获得不同的属性加成
*/

class Hero;

class Weapon
{
    int atk;
public:
    Weapon():atk(1){}
    virtual ~Weapon(){}
    void set_atk(int atk)
    {
        this->atk = atk;
    }
    int get_atk()
    {
        return atk;
    }
    virtual void equip(Hero &h);
};

class Sword:public Weapon
{
    int def;
public:
    Sword():def(1){}
    void set_def(int def)
    {
        this->def = def;
    }
    int get_def()
    {
        return def;
    }
    void equip(Hero &h) override;
};

class Blade:public Weapon
{
    int spd;
public:
    Blade():spd(1){}
    void set_spd(int spd)
    {
        this->spd = spd;
    }
    int get_spd()
    {
        return spd;
    }
    void equip(Hero &h) override;
};

class Axe:public Weapon
{
    int hp;
public:
    Axe():hp(1){}
    void set_hp(int hp)
    {
        this->hp = hp;
    }
    int get_hp()
    {
        return hp;
    }
    void equip(Hero &h) override;
};

class Hero
{
    int atk;
    int def;
    int spd;
    int hp;
    Weapon * current_weapon;
public:
    Hero():atk(1),def(1),spd(1),hp(1),current_weapon(new Weapon){}
    ~Hero(){delete current_weapon;}
    void set_atk(int atk)
    {
        this->atk = atk;
    }
    int get_atk()
    {
        return atk;
    }
    void set_def(int def)
    {
        this->def = def;
    }
    int get_def()
    {
        return def;
    }
    void set_spd(int spd)
    {
        this->spd = spd;
    }
    int get_spd()
    {
        return spd;
    }
    void set_hp(int hp)
    {
        this->hp = hp;
    }
    int get_hp()
    {
        return hp;
    }
    void equip_weapon(Weapon *w);
    void show();
};

void Weapon::equip(Hero &h)
{
    int new_atk = h.get_atk() + this->get_atk();
    h.set_atk(new_atk);
}

void Sword::equip(Hero &h)
{
    Weapon::equip(h);
    int new_def = h.get_def() + def;
    h.set_def(new_def);
}

void Blade::equip(Hero &h)
{
    Weapon::equip(h);
    int new_spd = h.get_spd() + spd;
    h.set_spd(new_spd);

}

void Axe::equip(Hero &h)
{
    Weapon::equip(h);
    int new_hp = h.get_hp() + hp;
    h.set_hp(new_hp);
}

void Hero::equip_weapon(Weapon *w)
{
    delete current_weapon;
    current_weapon = w;
    w->equip(*this);

}

void Hero::show()
{
    cout << "******** 英雄属性 ********" << endl
         << "  " << "atk = " << atk << endl
         << "  " << "def = " << def << endl
         << "  " << "spd = " << spd << endl
         << "  " << "hp = \t" << hp << endl
         << "**************************" << endl;
}

int main()
{
    Hero h1,h2,h3;
    h1.equip_weapon(new Sword);
    h2.equip_weapon(new Blade);
    h3.equip_weapon(new Axe);
    h1.show();
    h2.show();
    h3.show();


    return 0;
}

通过虚函数解决菱形继承产生的二义性问题

    A       --------公共基类
  /   \
 B     C    --------中间子类
  \   /
    D       --------汇集子类
B类中会继承A类的成员,C类中也继承A类的成员,
D类中汇集成B和C中的所有成员 ------>导致A类中的内容,在D类中存在两份
有可能造成代码膨胀
#include <iostream>
using namespace std;
class A
{
public:
    int a;
    A():a(9){cout << "A构造" << endl;}
};
class B:public A
{
public:
    int b;
    B():b(0){cout << "B构造" << endl;}
};
class C:public A
{
    int c;
public:
    //因为继承顺序是先继承B,再继承A,所以B先构造结束,后A构造结束,最后C构造结束
    //和初始化列表中的调用顺序无关
    C():c(6),A(){cout << "C构造" << endl;}
    void show();
};
class D:public B,public C
{
    void show_a()
    {
        //cout << a << endl;   //因为中间基类中存在两种方式可以找到a
        cout << B::a << endl;  //存在于B类中的A类继承下来的a
        cout << C::a << endl;  //存在于C类中的A类继承下来的a
    }
};
int main()
{
    C c1;
    c1.show();
    return 0;
}

 虚继承(virtual)

#include <iostream>

using namespace std;


class Person
{
    int age;                //4字节
    string name;            //32字节 +4对齐 36
public:
    Person(){}
    Person(int age,string name):age(age),name(name){}
    virtual void show();    //虚指针 8字节
};                          //48

class Stu:public Person     // 继承Person 48
{
    double score;           //56
public:
    Stu(){}
    Stu(int age,string name,double score):Person(age,name),score(score){}
    void show();            //对虚指针指向的虚函数表中的show进行重写
};                          //56

void Person::show()
{
    cout << "Person 中的show函数 " << endl;
    cout << "age = " << age << endl;
    cout << "name = " << name << endl;
}

void Stu::show()
{
    cout << "Stu 中的show函数 " << endl;
    cout << "score = " << score << endl;
}

int main()
{
    cout << sizeof (Person) << endl;
    cout << sizeof (Stu) << endl;
    Stu s1(18,"张三",99);
    Person &rp = s1;
    rp.show();
    rp.Person::show();
    return 0;
}

在菱形继承中,由于汇集子类中会保存两份公共基类的内容造成二义性问题,所以通常两个中间子类会虚继承公共基类 ------>在汇集子类中就只存在一份公共基类的内容

#include <iostream>
using namespace std;
class A
{
public:
    int a;
    A():a(9){cout << "A构造" << endl;}
};
//中间子类虚继承公共基类A
class B:virtual public A
{
public:
    int b;
    B():b(0),A(){cout << "B构造" << endl;}
};
class C:virtual public A
{
    int c;
public:
    //因为继承顺序是先继承B,再继承A,所以B先构造结束,后A构造结束,最后C构造结束
    //和初始化列表中的调用顺序无关
    C():c(6),A(){cout << "C构造" << endl;}
    void show();
};
class D:public B,public C
{
    //汇集子类的构造函数中对于公共基类的构造,需要直接调用公共基类的构造函数即可
    D():B(),C(),A(){}
    void show_a()
    {
        //不加virtual,有两份A中的a
        cout << a << endl;   //由于我们使用了虚继承,所以D类中只有一份从公共基类中继承下来的a
        cout << B::A::a << endl;
        cout << C::A::a << endl;
    }
};
int main()
{
    C c1;
    c1.show();
    return 0;
}

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

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

相关文章

细说STM32F407单片机SPI基础知识

目录 一、 SPI接口和通信协议 1、 SPI硬件接口 &#xff08;1&#xff09;MOSI(Master Output Slave Input) &#xff08;2&#xff09;MISO(Master Input Slave Output) &#xff08;3&#xff09;SCK 2、SPI传输协议 &#xff08;1&#xff09;CPHA0时的数据传输时序 …

种草电商系统APP功能需求开发案例

种草电商系统‌是一种结合了社区互动和电商交易的平台&#xff0c;能看到其他小伙伴分享的各种真实购物心得、超美商品图片和超实用视频&#xff0c;让我们去发现好物。可以随心关注感兴趣的人&#xff0c;跟他们畅聊购物体验&#xff0c;点赞、评论、转发那些心动的分享。其主…

EnumMap:让Java Map更高效的技巧

前言 摘要 内容 什么是EnumMap 如何使用EnumMap EnumMap的实现原理 EnumMap的例子 测试用例 小结 前言 在Java中&#xff0c;枚举类型是一种非常有用的数据类型&#xff0c;它可以用于定义一组固定的常量。枚举类型在很多场景中都有广泛的应用&#xff0c;例如状态码、…

测试工程师八股文05|功能测试、业务测试

一、基础概念 1、软件测试分类 1️⃣按照软件产生的阶段划分 单元测试&#xff1a;针对程序源代码进行测试【开发自测】集成测试&#xff1a;针对模块之间功能交互进行测试系统测试&#xff1a;对整个系统&#xff08;功能、非功能&#xff09;进行全面测试验收测试&#xff…

中国计算机学会计算机视觉专委会携手合合信息举办企业交流活动,为AI安全治理打开“新思路”

近期&#xff0c;《咬文嚼字》杂志发布了2024年度十大流行语&#xff0c;“智能向善”位列其中&#xff0c;过去一年时间里&#xff0c;深度伪造、AI诈骗等话题屡次登上热搜&#xff0c;AI技术“野蛮生长”引发公众担忧。今年9月&#xff0c;全国网络安全标准化技术委员会发布了…

《计算机视觉:瓶颈之辩与未来之路》

一、计算机视觉的崛起 计算机视觉是使用计算机模仿人类视觉系统的科学&#xff0c;让计算机拥有类似人类提取、处理、理解和分析图像以及图像序列的能力。它是一个多学科交叉的领域&#xff0c;与机器视觉、图像处理、人工智能、机器学习等领域密切相关。 计算机视觉行业可分为…

Airborne使用教程

1.安装环境 前提条件&#xff1a;系统已安装Ruby 打开终端输入如下命令 gem install airborne 或者在Gemfile添加 gem airborne 然后运行bundle install 2.编写脚本 在项目中新建api_tests_spec.rb文件 以GET接口"https://www.thunderclient.com/welcome"为…

Hadoop其一,介绍本地模式,伪分布模式和全分布搭建

目录 一、Hadoop介绍 二、HDFS的本地模式 三、伪分布模式 四、Hdfs中的shell命令 五、全分布搭建 六、使用Java代码操作HDFS 1、环境准备 2、单元测试&#xff08;Junit&#xff09;​编辑 一、Hadoop介绍 Hadoop 分为三部分 &#xff1a; Common、HDFS 、Yarn、MapRe…

【Tomcat】第五站:Servlet容器

Tomcat启动后&#xff0c;获取到项目当中所有的servlet的WebServlet中的配置信息。将配置信息和类对象都写入一个map集合当中。 map就是一个key-value类型的集合。 在MyTomcat中我们获取到了类对象和注解值。 Tomcat与请求连通 1. ServletConfigMapping 1. 创建一个config包…

猫眼浏览器v4.12.1重磅升级,极速、安全、保护全方位提升

猫眼浏览器&#xff08;Catsxp&#xff09;是一款经过深度优化的网页浏览器&#xff0c;凭借其创新性的设计理念和卓越的性能表现&#xff0c;正在重新定义现代浏览器的标准。这款基于Chrome内核精心打造的浏览器不仅为用户带来了全方位的网络体验提升&#xff0c;更在保护用户…

Axure原型设计技巧与经验分享

AxureRP作为一款强大的原型设计工具&#xff0c;凭借其丰富的交互设计能力和高保真度的模拟效果&#xff0c;赢得了众多UI/UX设计师、产品经理及开发人员的青睐。本文将分享一些Axure原型设计的实用技巧与设计经验&#xff0c;帮助读者提升工作效率&#xff0c;打造更加流畅、用…

梳理你的思路(从OOP到架构设计)_UML应用:业务内涵的分析抽象表达02

目录 1、举例(二) &#xff1a;西方童话 童话『青蛙王子』 的故事 故事中的概念 2、举例(三) &#xff1a;点餐服务 『 餐馆点餐服务』 的分析步骤&#xff1a; 1、举例(二) &#xff1a;西方童话 童话『青蛙王子』 的故事 从前有一位美丽的公主&#xff0c;喜欢玩金球。…

DevExpress WPF中文教程:Grid - 如何移动和调整列大小?(一)

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

OpenIPC开源FPV之Adaptive-Link天空端代码解析

OpenIPC开源FPV之Adaptive-Link天空端代码解析 1. 源由2. 框架代码3. 报文处理3.1 special报文3.2 普通报文 4. 工作流程4.1 Profile 竞选4.2 Profile 研判4.3 Profile 应用 5. 总结6. 参考资料7. 补充资料7.1 RSSI 和 SNR 的物理含义7.2 信号质量加权的理论依据7.3 实际应用中…

23.DDD与微服务

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 DDD与微服务的关系1. DDD可以用微服务实现&#xff0c;也可以不用微服务实现2. DDD是微服务拆分的必须参考项之一3. 微服务架构…

最新全开源IM即时通讯系统源码(PC+WEB+IOS+Android)部署指南

全开源IM&#xff08;即时通讯&#xff09;系统源码部署是一个复杂但系统的过程&#xff0c;涉及多个组件和步骤。以下是一个详细的部署指南&#xff0c;旨在帮助开发者或系统管理员成功部署一个全开源的IM系统&#xff0c;如OpenIM。      IM即时通讯系统源码准备工作   …

PVE系统下——OpenWRT一键扩容脚本(x86下EXT4SquashFS)

扩容了x86上的 OpenWrt 根分区和文件系统。 1.PVE 上增加硬盘大小 2.执行脚本 安装依赖 opkg update opkg install parted losetup resize2fs下载脚本并一键执行 wget -U "" -O expand-root.sh "https://openwrt.org/_export/code/docs/guide-user/advanced…

Midjourney教程之生成同一角色的不同姿势和服装

今天给大家介绍的是在 Midjourney 中如何创建同一个角色的不同姿势。这个功能是大家期待已久的&#xff0c;现在它已经正式可用了。 这个功能能够创建与原始图像相似的角色。"Character Reference" 功能类似于 "Style Reference"&#xff0c;但侧重于角色…

gitlab仓库API操作

几年没接触gitlab了&#xff0c;新版本装完以后代码提交到默认的main分支&#xff0c;master不再是主分支 项目有几十个仓库&#xff0c;研发提交代码后仓库地址和之前的发生了变化 先修改Group的默认分支&#xff0c;不会影响已存在的项目 修改gitlab全局的默认分支 这就引…

aws(学习笔记第十七课) SQS Amazon Simple Queue Service服务

aws(学习笔记第十七课) SQS Amazon Simple Queue Service服务 学习内容&#xff1a; 使用SQS Amazon Simple Queue Service服务整体代码&#xff08;nodejs的通常工程&#xff09;代码动作 1. 使用SQS Amazon Simple Queue Service服务 利用应用程序来学习SQS 创建S3$ aws s…