More Effective C++之31

条款31:让函数根据一个以上的对象型别来决定如何虚化

       如果函数有两个自变量,而这两个自变量都是继承类,我们如果根据排列组合的办法来实现继承类。RTTI或者只使用虚函数?似乎都不是好办法。Meyers给出的解决方案是自行仿真虚函数表格(Virtual Function Tables)

考虑如下代码:
#include < string >
#include <algorithm>
#include < iostream >
#include < map >
#include <typeinfo>
using namespace std ;
class GameObject
{
public :
       GameObject (){}
       virtual ~ GameObject (){}
protected :
private :
};
 
class SpaceShip : public GameObject
{
public :
       SpaceShip (){};
       virtual ~ SpaceShip (){}
protected :
private :
       int i ;
};
 
class Station : public GameObject
{
public :
       Station (){}
       virtual ~ Station (){}
};
 
class Asteriod : public GameObject
{
public :
       Asteriod (){}
       virtual ~ Asteriod (){}
};
void shipAsteriod ( GameObject & spaceShip , GameObject & asteriod )
{
       printf ( "shipAsteriod/n" );
}
 
void shipStation ( GameObject & spaceShip , GameObject & station )
{
       printf ( "shipStation/n" );
}
 
void asteriodStation ( GameObject & asteriod , GameObject & station )
{
       printf ( "asteriodStation/n" );
}
 
void asteriodShip ( GameObject & asteriod , GameObject & spaceShip )
{
       shipAsteriod ( spaceShip , asteriod );
}
 
void stationShip ( GameObject & station , GameObject & spaceShip )
{
       shipStation ( station , spaceShip );
}
 
void stationAsteriod ( GameObject & station , GameObject & asteriod )
{
       asteriodStation ( asteriod , station );
}
 
typedef void (* HitFunctionPtr )( GameObject &, GameObject &);
typedef map < pair < string , string > , HitFunctionPtr > HitMap ;
HitMap * initializeCollisionMap ();
HitFunctionPtr lookup ( const string & class1 , const string & class2 );
 
pair < string , string > makeStringPair ( const char * s1 , const char * s2 );
 
void processCollision ( GameObject & obj1 , GameObject & obj2 )
{
       HitFunctionPtr phf = lookup ( typeid ( obj1 ). name (), typeid ( obj2 ). name ());
       if ( phf )
       {
              phf ( obj1 , obj2 );
       }
       else
              throw exception ();
}
 
 
pair < string , string > makeStringPair ( const char * s1 , const char * s2 )
{
       return pair < string , string >( s1 , s2 );
}
 
HitMap * initializeCollisionMap ()
{
       HitMap * phm = new HitMap ;

       (*phm)[makeStringPair(typeid(SpaceShip).name(),typeid(Asteriod).name())] = &shipAsteriod;

       (*phm)[makeStringPair(typeid(SpaceShip).name(),typeid(Station).name())] = &shipStation;

       (*phm)[makeStringPair(typeid(Station).name(),typeid(Asteriod).name())] = &stationAsteriod;

       (*phm)[makeStringPair(typeid(Station).name(),typeid(SpaceShip).name())] = &stationShip;

       (*phm)[makeStringPair(typeid(Asteriod).name(),typeid(SpaceShip).name())] = &asteriodShip;

       (*phm)[makeStringPair(typeid(Asteriod).name(),typeid(Station).name())] = &asteriodStation;

       return phm ;
}
 
 
HitFunctionPtr lookup ( const string & class1 , const string & class2 )
{
       static auto_ptr < HitMap > collisionMap ( initializeCollisionMap ());
       HitMap :: iterator iter = collisionMap -> find ( makeStringPair ( class1 . c_str (), class2 . c_str ()));
       if ( iter == collisionMap -> end ())
              return 0;
       return iter -> second ;
}
 
int main ( int argc , char * argv [])
{
       SpaceShip ship ;
       Asteriod ast ;
       Station s ;
       processCollision ( ship , ast );
       processCollision ( ast , ship );
       processCollision ( s , ship );
       processCollision ( ship , s );
       processCollision ( ast , s );
       processCollision ( s , ast );
       return 0;
}
 

这是一个用RTTI来实现的Virtual Function Table的仿真,那么在这个Function Table中,只需要加入合适的函数指针到map中去就可以了。千万注意的是,如果想支持RTTI,并须有虚函数存在才可以,否则……。我开始就犯了这个错误。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值