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

#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;

就可以了

其他类似代码处理相同

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值