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

More Effective C++之31

2006-07-24 21:01 344 查看
条款31:让函数根据一个以上的对象型别来决定如何虚化
如果函数有两个自变量,而这两个自变量都是继承类,我们如果根据排列组合的办法来实现继承类。RTTI或者只使用虚函数?似乎都不是好办法。Meyers给出的解决方案是自行仿真虚函数表格(Virtual Function Tables)

考虑如下代码:
[align=left]#include <string>[/align]
[align=left]#include <algorithm>[/align]
[align=left]#include <iostream>[/align]
[align=left]#include <map>[/align]
[align=left]#include <typeinfo>[/align]
[align=left]usingnamespacestd;[/align]
[align=left]classGameObject[/align]
[align=left]{[/align]
[align=left]public:[/align]
[align=left] GameObject(){}[/align]
[align=left] virtual ~GameObject(){}[/align]
[align=left]protected:[/align]
[align=left]private:[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]classSpaceShip:publicGameObject[/align]
[align=left]{[/align]
[align=left]public:[/align]
[align=left] SpaceShip(){};[/align]
[align=left] virtual ~SpaceShip(){}[/align]
[align=left]protected:[/align]
[align=left]private:[/align]
[align=left] inti;[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]classStation:publicGameObject[/align]
[align=left]{[/align]
[align=left]public:[/align]
[align=left] Station(){}[/align]
[align=left] virtual ~Station(){}[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]classAsteriod:publicGameObject[/align]
[align=left]{[/align]
[align=left]public:[/align]
[align=left] Asteriod(){}[/align]
[align=left] virtual ~Asteriod(){}[/align]
[align=left]};[/align]
[align=left]voidshipAsteriod(GameObject& spaceShip,GameObject& asteriod)[/align]
[align=left]{[/align]
[align=left] printf("shipAsteriod/n");[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]voidshipStation(GameObject& spaceShip,GameObject& station)[/align]
[align=left]{[/align]
[align=left] printf("shipStation/n");[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]voidasteriodStation(GameObject& asteriod,GameObject& station)[/align]
[align=left]{[/align]
[align=left] printf("asteriodStation/n");[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]voidasteriodShip(GameObject& asteriod,GameObject& spaceShip)[/align]
[align=left]{[/align]
[align=left] shipAsteriod(spaceShip,asteriod);[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]voidstationShip(GameObject& station,GameObject& spaceShip)[/align]
[align=left]{[/align]
[align=left] shipStation(station,spaceShip);[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]voidstationAsteriod(GameObject& station,GameObject& asteriod)[/align]
[align=left]{[/align]
[align=left] asteriodStation(asteriod,station);[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]typedefvoid (*HitFunctionPtr)(GameObject&,GameObject&);[/align]
[align=left]typedefmap<pair<string,string> ,HitFunctionPtr> HitMap;[/align]
[align=left]HitMap* initializeCollisionMap();[/align]
[align=left]HitFunctionPtrlookup(conststring& class1,conststring& class2);[/align]
[align=left] [/align]
[align=left]pair<string,string> makeStringPair(constchar* s1,constchar* s2);[/align]
[align=left] [/align]
[align=left]voidprocessCollision(GameObject& obj1,GameObject& obj2)[/align]
[align=left]{[/align]
[align=left] HitFunctionPtrphf = lookup(typeid(obj1).name(),typeid(obj2).name());[/align]
[align=left] if (phf) [/align]
[align=left] {[/align]
[align=left] phf(obj1,obj2);[/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] throwexception();[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]pair<string,string> makeStringPair(constchar* s1,constchar* s2)[/align]
[align=left]{[/align]
[align=left] returnpair<string,string>(s1,s2);[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]HitMap* initializeCollisionMap()[/align]
[align=left]{[/align]
[align=left] HitMap *phm = newHitMap;[/align]
(*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;
[align=left] returnphm;[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]HitFunctionPtrlookup(conststring& class1,conststring& class2)[/align]
[align=left]{[/align]
[align=left] staticauto_ptr<HitMap> collisionMap(initializeCollisionMap());[/align]
[align=left] HitMap::iteratoriter = collisionMap->find(makeStringPair(class1.c_str(),class2.c_str()));[/align]
[align=left] if (iter == collisionMap->end()) [/align]
[align=left] return 0;[/align]
[align=left] returniter->second;[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]intmain(intargc, char* argv[])[/align]
[align=left]{[/align]
[align=left] SpaceShipship;[/align]
[align=left] Asteriodast;[/align]
[align=left] Stations;[/align]
[align=left] processCollision(ship,ast);[/align]
[align=left] processCollision(ast,ship);[/align]
[align=left] processCollision(s,ship);[/align]
[align=left] processCollision(ship,s);[/align]
[align=left] processCollision(ast,s);[/align]
[align=left] processCollision(s,ast);[/align]
[align=left] return 0;[/align]
[align=left]}[/align]

这是一个用RTTI来实现的Virtual Function Table的仿真,那么在这个Function Table中,只需要加入合适的函数指针到map中去就可以了。千万注意的是,如果想支持RTTI,并须有虚函数存在才可以,否则……。我开始就犯了这个错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: