1.暴力法
基本想法是:Using Virtual Functions and RTTI
下面的代码摘自《More Effective C++》
class GameObject {
public:
virtual void collide(GameObject& otherObject) = 0;
...
};
class SpaceShip: public GameObject {
public:
virtual void collide(GameObject& otherObject);
...
};
void SpaceShip::collide(GameObject& otherObject)
{
const type_info& objectType = typeid(otherObject);
if (objectType == typeid(SpaceShip)) {//类型完全一样的对象的typeid才一样,父类和子类的typeid不一样
paceShip& ss = static_cast<SpaceShip&>(otherObject);
process a SpaceShip-SpaceShip collision;
}
else if (objectType == typeid(SpaceStation)) {
SpaceStation& ss =
static_cast<SpaceStation&>(otherObject);
process a SpaceShip-SpaceStation collision;
}
else if (objectType == typeid(Asteroid)) {
Asteroid& a = static_cast<Asteroid&>(otherObject);
process a SpaceShip-Asteroid collision;
}
else {
throw CollisionWithUnknownObject(otherObject);
}
}
对GameObject的每个子类,都撰写类似的代码。这种做法比较直观,但是比较死板。如果要增加一个新的GameObject的子类,则需要修改所有GameObject的已有子类的collide函数。而且所有GameObject的子类都知晓GameObject的所有其他子类。
2.只使用虚函数
下面的代码摘自《More Effective C++》
class SpaceShip; // forward declarations class SpaceStation; class Asteroid; 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); ... };
void SpaceShip::collide(GameObject& otherObject) { otherObject.collide(*this);//关键的一个调用,由于*this的类型此时已知,otherObject.collide(*this)就会调用到正确版本的重载函数 }void SpaceShip::collide(SpaceShip& otherObject) { process a SpaceShip-SpaceShip collision; } void SpaceShip::collide(SpaceStation& otherObject) { process a SpaceShip-SpaceStation collision; } void SpaceShip::collide(Asteroid& otherObject) { process a SpaceShip-Asteroid collision; } 这种方法比暴力法巧妙,但是扩展性仍然不好,增加新的子类的时候需要修改GameObject的接口,增加相应的成员函数,所有已经存在的子类也需要修改。3.利用类似map的东西制造函数影射表
相比1,2来说,可扩展性要好点。