• 使用多态提高程序扩充性举例(1)——游戏


    1、游戏简介

    假如一款打怪类的游戏,游戏中有多个不同的怪物:龙、天使、凤凰、士兵等。怪物能够互相攻击,攻击敌人和被攻击时都有相应的动作。动作是通过对象的成员函数实现的。假如现在游戏需要升级:要增加新的怪物–雷鸟。

    2、编程的基本思路

    • 为每个怪物类编写 Attack、FightBack和 Hurted成员函数。
    • Attact函数表现攻击动作,攻击某个怪物,并调用被攻击怪物的Hurted函数,以减少被攻击怪物的生命值,同时也调用被攻击怪物的FightBack成员函数,遭受被攻击怪物反击。
    • Hurted函数减少自身生命值,并表现受伤动作。
    • FightBack成员函数表现反击动作,并调用被反击对象的Hurted成员函数,使被反击对象受伤。

    3、基本代码

    设置基类 CCreature,并且使CDragon, CWolf等其他类都从CCreature派生而来。
    在这里插入图片描述

    4、采用非多态的思想实现需求

    class class CCreature {
    protected:
    	int nPower ; //代表攻击力
    	int nLifeValue ; //代表生命值
    };
    
    //龙的代码
    class CDragon:public CCreature {
    public:
    	void Attack(CWolf * pWolf) {//攻击狼
    		//...表现攻击动作的代码
    		pWolf->Hurted( nPower);
    		pWolf->FightBack( this);
    	}
    	void Attack( CGhost * pGhost) {//攻击鬼
    		//...表现攻击动作的代码
    		pGhost->Hurted( nPower);
    		pGohst->FightBack( this);
    	}
    	void Hurted ( int nPower) {//自己受伤受伤
    		//....表现受伤动作的代码
    		nLifeValue -= nPower;//生命值变低
    	}
    	void FightBack( CWolf * pWolf) {//反击狼
    		//....表现反击动作的代码
    		pWolf ->Hurted( nPower / 2);
    	}
    	void FightBack( CGhost * pGhost) {// 反击鬼
    		//....表现反击动作的代码
    		pGhost->Hurted( nPower / 2 );
    	}
    	//攻击其他怪物
    	//反击其他怪物
    }
    // 其他怪物类同样也需要写类似的代码
    

    有n种怪物,CDragon 类中就会有n个 Attack 成员函数,以及 n个FightBack成员函数。对于其他类也如此。

    当游戏升级时,按照这种编程思想,需要修改每一个类(增加两个成员函数:攻击和反击)。这样程序改动非常大。

    5、采用多态思想实现需求

    class CCreature {
    protected :
    	int m_nLifeValue, m_nPower;
    public:
    	virtual void Attack( CCreature * pCreature) {}
    	virtual void Hurted( int nPower) { }
    	virtual void FightBack( CCreature * pCreature) { }
    };
    
    class CDragon : public CCreature {
    public:
    	virtual void Attack( CCreature * pCreature);
    	virtual void Hurted( int nPower);
    	virtual void FightBack( CCreature * pCreature);
    };
    
    void CDragon::Attack(CCreature * p)//接收一个基类指针
    {
    	//...表现攻击动作的代码
    	p->Hurted(m_nPower); //多态
    	p->FightBack(this); //多态
    }
    void CDragon::Hurted( int nPower)
    {
    	//...表现受伤动作的代码
    	m_nLifeValue -= nPower;
    }
    void CDragon::FightBack(CCreature * p)//接收一个基类指针
    {
    	//...表现反击动作的代码
    	p->Hurted(m_nPower/2); //多态
    }
    
    //其他怪物也写类似与龙的代码
    

    使用多态思想实现的好处:只需要编写新类CThunderBird, 不需要在已有的类里专门为新怪物增加成员函数:

    void Attack( CThunderBird * pThunderBird) ;
    void FightBack( CThunderBird * pThunderBird) ;
    

    已有的类可以原封不动,程序改动非常小。

    6、使用多态实现该需求的原理

    int main(){
    	CDragon Dragon; 
    	CWolf Wolf; 
    	CGhost Ghost;
    	CThunderBird Bird;//创建一个 龙、狼、鬼、雷鸟
    	Dragon.Attack( & Wolf);//(1)龙攻击狼
    	Dragon.Attack( & Ghost);//(2)龙攻击鬼
    	Dragon.Attack( & Bird);//(3)龙攻击雷鸟
    }
    

    以龙攻击狼为例:

    Dragon.Attack( & Wolf);
    

    龙的攻击函数的形参是一个指向基类的指针,而这个指针现在指向一只狼Wolf,当进入龙对象的攻击函数时,首先执行:

    p->Hurted(m_nPower); //多态
    

    即,执行受伤函数时,由于p是基类指针,而Hurted是虚函数,因此这条语句使用了多态。由于这里p实际是指向狼对象Wolf的,因此这条语句执行狼 Wolf对象的Hurted函数。这里传递的参数便是这条龙的攻击力,这个参数是protected的,因此基类可以直接访问。因此执行狼的受伤函数时,狼减少对应的血量。

  • 相关阅读:
    Python数据分析与机器学习-Matplot_2
    Python数据分析与机器学习-Matplot_1
    1008. 数组元素循环右移问题 (20)
    Latex小技巧
    执行PowerShell脚本的时候出现"在此系 统上禁止运行脚本"错误
    Linux使用MentoHust联网线上校园网, 回到普通有线网络却连不上?
    Re:uxul
    Linux下nautilus的右键快捷菜单项设置
    从入门到入狱——搭讪技巧
    Latex命令
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764247.html
Copyright © 2020-2023  润新知