第六週 多態
1.虛函數和多態的基本概念
2.多態實例:魔法門之英雄無敵
3.更多多態程序實例
4.多態的實現原理
5.虛析構函數、純虛函數和抽象類
2.多態實例:魔法門之英雄無敵
遊戲中有很多種怪物,每種怪物都有一個類與之對應,每個怪物就是一個對象。假設現在有五種怪物,也就是現有五個類:CSoldier,CDragon,Cwolf,CPhonex,CAngel。怪物能夠互相攻擊,攻擊敵人和被攻擊時都有相應的動作,動作是通過對象的成員函數實現的。遊戲版本升級時,要增加新的怪物–雷鳥類CThunderBird。如何編程才能使升級時的代碼改動和增加量較小?
基本思路:
爲每個怪物類編寫 Attack、FightBack和 Hurted成員函數。
Attact函數表現攻擊動作,攻擊某個怪物,並調用被攻擊怪物的Hurted函數,以減少被攻擊怪物的生命值,同時也調用被攻擊怪物的 FightBack成員函數,遭受被攻擊怪物反擊。
Hurted函數減少自身生命值,並表現受傷動作。
FightBack成員函數表現反擊動作,並調用被反擊對象的Hurted成員函數,使被反擊對象受傷。
設置基類 CCreature,並且使CDragon, CWolf等其他類都從CCreature派生而來。
非多態的實現方法
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成員函數。對於其他類也如此。
缺點: 如果遊戲版本升級,增加了新的怪物雷鳥 CThunderBird,則程序改動較大。所有的類都需要增加兩個成員函數:
void Attack( CThunderBird * pThunderBird)和void FightBack( CThunderBird * pThunderBird) ,工作量極大。
多態的實現方法
//基類 CCreature:
class CCreature {
protected :
int m_nLifeValue, m_nPower;
public:
virtual void Attack( CCreature * pCreature) {}
virtual void Hurted( int nPower) { }
virtual void FightBack( CCreature * pCreature) { }
};
基類只有一個 Attack 成員函數;也只有一個 FightBack成員函數;所有CCreature 的派生類也是這樣。
// 以派生類 CDragon爲例
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,只需要編寫新類CThunderBird, 不需要在已有的類裏專
門爲新怪物增加void Attack( CThunderBird * pThunderBird) 和void FightBack( CThunderBird * pThunderBird) ,成員函數,已有的類可以原封不動。
原理
CDragon Dragon; CWolf Wolf; CGhost Ghost;
CThunderBird Bird;
Dragon.Attack( & Wolf); //(1)
Dragon.Attack( & Ghost); //(2)
Dragon.Attack( & Bird); //(3)
根據多態的規則,上面的(1),(2),(3)進入到CDragon::Attack函數後,能分別調用:
CWolf::Hurted
CGhost::Hurted
CBird::Hurted
void CDragon::Attack(CCreature * p)
{
p->Hurted(m_nPower); //多態
p->FightBack(this); //多態
}