您的位置:首页 > 其它

item31让函数根据一个以上的对象类型来决定如何虚化

2016-05-22 15:49 351 查看
#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);//就是如果参数相反,就调用上面的函数
}
//...都一样

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