zoukankan      html  css  js  c++  java
  • 使用多态提高程序扩充性举例(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的,因此基类可以直接访问。因此执行狼的受伤函数时,狼减少对应的血量。

  • 相关阅读:
    MMT
    dappradar 分布式应用雷达
    dac去中心化自治公司
    如何立即手动执行BW周期性处理链
    BW之数据源 增量管理DELTA (比较详细的)
    abap问题:call transformation出来的xml字符串不能被proxy识别
    SHIFT 去掉前导0,SHIFT语法
    浅谈SAP实施过程中关键用户的作用
    什么是UAT测试?
    FI 基础财务知识
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764247.html
Copyright © 2011-2022 走看看