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

原文地址:https://www.cnblogs.com/lasnitch/p/12764247.html