#include
class CollisionWithUnknownObject { public: CollisionWithUnknownObject() { std::cout << "unknown error" << std::endl; } //... };
class GameObject { public: virtual void collide(GameObject& otherObject) = 0; //... };
//The class SpaceShip Declaration class SpaceShip: public GameObject { public: virtual void collide(GameObject& otherObject); virtual void hitSpaceShip(GameObject& spaceShip); virtual void hitSpaceStation(GameObject& spaceStation); virtual void hitAsteroid(GameObject& asteroid); //... private: typedef void (SpaceShip::*HitFunctionPtr)(GameObject& what); static HitFunctionPtr lookup(GameObject& what); typedef map< string, HitFunctionPtr > HitMap; static HitMap* initializeCollisionMap(); };
//The class SpaceStation Declaration class SpaceStation: public GameObject { public: virtual void collide(GameObject& otherObject); virtual void hitSpaceShip(GameObject& otherObject); virtual void hitSpaceStation(GameObject& otherObject); virtual void hitAsteroid(GameObject& otherobject); //... private: typedef void (SpaceStation::*HitFunctionPtr)(GameObject& what); static HitFunctionPtr lookup(GameObject& what); typedef map< string, HitFunctionPtr > HitMap; static HitMap* initializeCollisionMap(); };
//The class Asteroid Declaration class Asteroid: public GameObject { public: virtual void collide(GameObject& otherObject); virtual void hitSpaceShip(GameObject& otherObject); virtual void hitSpaceStation(GameObject& otherObject); virtual void hitAsteroid(GameObject& otherobject); //...
private: typedef void (Asteroid::*HitFunctionPtr)(GameObject& what); static HitFunctionPtr lookup(GameObject& what); typedef map< string, HitFunctionPtr > HitMap; static HitMap* initializeCollisionMap(); };
//The class SpaceShip Definition void SpaceShip::collide(GameObject& otherObject) { HitFunctionPtr hfp = lookup(otherObject); //查找要调用的函数 if(hfp) { (this->*hfp)(otherObject); } else { throw CollisionWithUnknownObject(); } }
SpaceShip::HitFunctionPtr SpaceShip::lookup(GameObject& what) { //不好,会有付出拷贝赋值的代价 //static HitMap collisionMap = initializeCollisioniMap(); //用一个Smart Pointer static auto_ptr collisionMap(initializeCollisionMap()); HitMap::iterator mapEntry = collisionMap->find(typeid(what).name()); // 如果查找失败,mapEntry == collisionMap.end(); if(mapEntry == collisionMap->end()) return 0; // 如果找到了,mapEntry会指向一个完全的map入口, // 它是一个(string, HitFunctionPtr)对。我们只想要 // 它的第二部分,所以这是我们返回的 return (*mapEntry).second; }
SpaceShip::HitMap* SpaceShip::initializeCollisionMap() { HitMap *phm = new HitMap;
//这里书中直接就是(*phm["SpaceShip"] = &hitSpaceShip; //而我用的是Dev-C++编译器,结果我发现 // typeid(SpaceShip).name()并不仅仅是SpaceShip,而是128SpaceShip // 所以我做了如下修改 (*phm)[typeid(SpaceShip).name()] = &SpaceShip::hitSpaceShip; (*phm)[typeid(SpaceStation).name()] = &SpaceShip::hitSpaceStation; (*phm)[typeid(Asteroid).name()] = &SpaceShip::hitAsteroid; return phm; }
void SpaceShip::hitSpaceShip(GameObject& spaceShip) { SpaceShip& otherShip = dynamic_cast(spaceShip);
std::cout << "SpaceShip collide with SpaceShip" << std::endl; }
void SpaceShip::hitSpaceStation(GameObject& spaceStation) { SpaceStation& station = dynamic_cast(spaceStation);
std::cout << "SpaceShip collide with SpaceStation" << std::endl; }
void SpaceShip::hitAsteroid(GameObject& asteroid) { Asteroid& theAsteroid = dynamic_cast(asteroid);
std::cout << "SpaceShip collide with Asteroid" << std::endl; }
//The class SpaceStation Definition void SpaceStation::collide(GameObject& otherObject) { HitFunctionPtr hfp = lookup(otherObject); if(hfp) { (this->*hfp)(otherObject); } else { throw CollisionWithUnknownObject(); } }
SpaceStation::HitFunctionPtr SpaceStation::lookup(GameObject& what) { static auto_ptr collisionMap(initializeCollisionMap()); HitMap::iterator mapEntry = collisionMap->find(typeid(what).name());
if(mapEntry != collisionMap->end()) return (*mapEntry).second; }
SpaceStation::HitMap* SpaceStation::initializeCollisionMap() { HitMap * pfm = new HitMap; (*pfm)[typeid(SpaceShip).name()] = &SpaceStation::hitSpaceShip; (*pfm)[typeid(SpaceStation).name()] = &SpaceStation::hitSpaceStation; (*pfm)[typeid(Asteroid).name()] = &SpaceStation::hitAsteroid;
return pfm; }
void SpaceStation::hitSpaceShip(GameObject& otherObject) { SpaceShip& ship = dynamic_cast (otherObject); std::cout << "SpaceStation collide with SpaceShip" << std::endl; }
void SpaceStation::hitSpaceStation(GameObject& otherObject) { SpaceStation& otherSpaceStation = dynamic_cast (otherObject); std::cout << "SpaceStation collide with SpaceStation" << std::endl; }
void SpaceStation::hitAsteroid(GameObject& otherObject) { Asteroid& theAsteroid = dynamic_cast (otherObject); std::cout << "SpaceStation collide with Asteroid" << std::endl; }
//The class Asteroid Definition void Asteroid::collide(GameObject& otherObject) { HitFunctionPtr hfp = lookup(otherObject); if(hfp) { (this->*hfp)(otherObject); } else { throw CollisionWithUnknownObject(); } }
Asteroid::HitFunctionPtr Asteroid::lookup(GameObject& what) { static auto_ptr< HitMap > collisionMap(initializeCollisionMap()); HitMap::iterator mapEntry = collisionMap->find(typeid(what).name());
if(mapEntry != collisionMap->end()) return (*mapEntry).second; }
Asteroid::HitMap* Asteroid::initializeCollisionMap() { HitMap *pfm = new HitMap; (*pfm)[typeid(SpaceShip).name()] = &Asteroid::hitSpaceShip; (*pfm)[typeid(SpaceStation).name()] = &Asteroid::hitSpaceStation; (*pfm)[typeid(Asteroid).name()] = &Asteroid::hitAsteroid;
return pfm; }
void Asteroid::hitSpaceShip(GameObject& otherObject) { SpaceShip & ship = dynamic_cast (otherObject); std::cout << "Asteroid collide with SpaceShip" << std::endl; }
void Asteroid::hitSpaceStation(GameObject& otherObject) { SpaceStation & station = dynamic_cast (otherObject); std::cout << "Asteroid collide with SpaceStation" << std::endl; }
void Asteroid::hitAsteroid(GameObject& otherObject) { Asteroid & otherAsteroid = dynamic_cast (otherObject); std::cout << "Asteroid collide with Asteroid" << std::endl; }
int main() { GameObject *g = new SpaceShip; GameObject *h = new SpaceStation ; GameObject *a = new Asteroid; g->collide(*a); g->collide(*h); h->collide(*g); h->collide(*a); a->collide(*g); a->collide(*h);
system("pause");
}
该程序在winXP Professinal + Dev-C++上通过
我在vc.net上也进行了编译,可是总是在dynamic_cast 处出现错误,不知道为什么? 
|