您的位置:首页 > 编程语言 > C语言/C++

more effective c++学习笔记 ---- 条款31

2004-09-07 19:55 645 查看
#include
#include
#include
#include
#include
#include
using namespace std;
//
//class SpaceStation;
//class Asteroid;
//class SpaceShip;

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上也通过。

只是Dev-C++要求代码中的

(*pfm)[typeid(SpaceShip).name()] = &Asteroid::hitSpaceShip;

而vc中只要

(*pfm)[typeid(SpaceShip).name()] = &hitSpaceShip;

就可以了

其他类似代码处理相同
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: