#include <iostream>
/*
>如果宇宙飛船以低速與太空站碰撞,宇宙飛船會泊進太空站(程序沒有涉及)
否則宇宙飛船和太空站受到的損害與其速度成正比
>如果宇宙飛船與宇宙飛船碰撞,或是太空站與太空站碰撞,都會受損,受到的損害與其速度成正比
>如果小號的小行星與宇宙飛船或太空站相撞,小行星會損毀。如果碰到的是大號小行星,
那宇宙飛船或太空站損毀
>如果小行星撞擊另一顆小行星,兩者都碎裂成更小的小行星,且想四面八方散去
*/
class GameObject{ ... };
class SpaceShip : public GameObject{... };
class SpaceStation : public GameObject{... };
class Asteroid : public GameObject{... };
void checkForCollision(GameObject&, GameObject&)
{
if(theyJustCollision(lhs, rhs))
processCollision(lhs, rhs)
else
...
}//
//virtual fcn + RTTI
// if_then_else way
class GameObject{
virtual void collide(GameObject& otherObject) = 0;
};
class SpaceShip : public GameObject{... };
class SpaceStation : public GameObject{... };
class Asteroid : public GameObject{... };
class CollisionWithUnKnowObject{//except class
public:
CollisionWithUnKnowObject(GameObject& whatWeHit);//why?
}
void SpaceShip::collide(GameObject& otherObject)
{
const type_info& objectType = typeid(otherObject);//lookup typeid & type_info
if(objectType == typeid(SpaceShip))
SpaceShip& ss = static_cast<SpaceShip&>(otherObject);
process a SpaceShip-SpaceShip collision;
else if (objectType == typeid(SpaceStation))//--copy
SpaceShip& ss = static_cast<SpaceStation&>(otherObject);
process a SpaceShip-SpaceStation collision;
else if (objectType == typeid(Asteroid))
SpaceShip& ss = static_cast<Asteroid&>(otherObject);
process a SpaceShip-Asteroid collision;//copy end
else
throw CollisionWithUnKnowObject(otherObject);
};
/*
*/
/////////////////////////////////////
//overload只用虛函數,有圖1
class GameObject{
public:
virtual void collide(GameObject& otherObject) = 0;
virtual void collide(SpaceShip& otherObject) = 0;
virtual void collide(SpaceStation& otherObject) = 0;
virtual void collide(Asteroid& otherObject) = 0;
};
class SpaceShip : public GameObject{
public:
virtual void collide(GameObject& otherObject) ;
virtual void collide(SpaceShip& otherObject) ;
virtual void collide(SpaceStation& otherObject) ;
virtual void collide(Asteroid& otherObject) ;
};
//impoint point:
virtual void collide(GameObject& otherObject)
{
otherObject.collide(*this);
}
//
class SpaceStation : public GameObject{... };
class Asteroid : public GameObject{... };
//////////////////////////////////////
// virtual FCN Tables way
class GameObject{
public:
virtual void collide(GameObject& otherObject) ;
virtual void hitSpaceShip(SpaceShip& otherObject) ;
virtual void hitSpaceStation(SpaceStation& otherObject) ;
virtual void hitAsteroid(Asteroid& otherObject) ;
};
class SpaceShip : public GameObject{
private://!!
typedef void (SpaceShip::*HitFCNPtr)(GameObject&);//!!
static HitFCNPtr lookup(const GameObject& whatWeHit);
};
void SpaceShip::collide(GameObject& otherObject)
{
HitFCNPtr hfp = lookup(otherObject);
if(hfp)
{ this->*hfp}(otherObject);
else
throw CollisionWithUnKnowObject(otherObject);
}
class SpaceShip : public GameObject{
private:
typedef void (SpaceShip::*HitFCNPtr)(GameObject&);
typedef map<string, HitFCNPtr> HitMap;
};
void SpaceShip::lookup()
{
static HitMap collisionMap;//static in fcn !!
//init
collisionMap["SpaceShip"] = &hitSpaceShip;
collisionMap["SpaceStation"] = &hitSpaceStation;
collisionMap["Asteroid"] = &hitAsteroid;//error
HitMap::iterator mapEntry =
collisionMap.find(typeid(wharWeWait).name())//typeid::name
if(mapEntry == collision.end())
return 0;
return (*mapEntry).second;
}
//make init be smart ptr
//雖然只是爲了調用時初始化,但好像簡便了許多
class SpaceShip : public GameObject{
private://!!
static HitMap * initCollisionMap();
};
SpaceShip::HitFCNPtr
SpaceShip::lookup(const GameObject& otherObject)
{
static auto_ptr<HitMap>
collisionMap(initCollisionMap() );
}
SpaceShip::HitMap * SpaceShip::initCollisionMap()
{
HitMap* phm = new HitMap;
(*phm)["SpaceShip"] = &hitSpaceShip;
(*phm)["SpaceStation"] = &hitSpaceStation;
(*phm)["Asteroid"] = &hitAsteroid;
return phm;
}
//但上面的會出錯,因爲map的元素:函數指針的類型不一樣
//因參數類型不一樣。也不符合聲明
SpaceShip::HitMap * SpaceShip::initCollisionMap()
{
HitMap * phm = new HitMap;
(*phm)["SpaceShip"] =
reinterpret_cast<HitFCNPtr>(&hitSpaceShip);
(*phm)["SpaceStation"] =
reinterpret_cast<HitFCNPtr>(&hitSpaceStation);
(*phm)["Asteroid"] =
reinterpret_cast<HitFCNPtr>(&hitAsteroid);
return phm;
}
//圖2
//所謂reinterpret_cast 能不用就不用,解決辦法是
class SpaceShip : public GameObject{
public:
virtual void collide(GameObject& otherObject) ;
virtual void hitSpaceShip(GameObject& otherObject) ;
virtual void hitSpaceStation(GameObject& otherObject) ;
virtual void hitAsteroid(GameObject& otherObject) ;
/*參數類型一致了*/
};
/*夾帶真是性,我覺得我這一步有些多餘,但爲了消除使用者困惑*/
void SpaceShip::hitSpaceShip(GameObject& spaceShip)
{
SpaceShip& otherShip
= dynamic_cast<SpaceShip&>(spaceShip);
process a SpaceShip-SpaceShip collision;
}
void SpaceShip::hitSpaceStation(GameObject& spaceStation){...}
void SpaceShip::hitAsteroid(GameObject& asteroid){...}
//use non_member fcn to process a collision fcn
#include "SpaceShip.h"
#include "spaceStation"
#include "Asteroid"
namespace{
void shipAsteroid(GameObject& spaceShip,GameObject &asteroid);
void shipStation(GameObject& spaceShip,GameObject &spaceStation);
void StationAsteroid(GameObject& spaceStation,GameObject &asteroid);
void Asteroidship(GameObject& asteroid,GameObject &spaceShip)
{
shipAsteroid(asteroid,spaceShip);//就是如果參數相反,就調用上面的函數
}
//...都一樣
};
item31讓函數根據一個以上的對象類型來決定如何虛化
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.