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);//就是如果参数相反,就调用上面的函数 } //...都一样 };
相关文章推荐
- java静态内部类(重点
- 入驻第一天
- 慕课R语言之数据可视化学习笔记——3.3基本绘图系统实战
- JavaScript的函数作用域
- Wooyun最新确认漏洞爬虫V0.02
- Linux操作系统基础解析之(四)——Linux基本命令剖析(2)
- HDU1518:Square(DFS)
- 一步步学spark之一scala函数1.3
- Intent MIME 打开各种类型的文件
- Linux下find命令详解
- python 中的split()函数和os.path.split()函数
- vs2010 mfc c++ struct
- 按钮控件编程实例
- 人工智能之机器学习常见算法
- 工厂方法模式
- sax 解析 xml
- 谈一谈.net析构函数对垃圾回收的影响
- 16色工具栏
- 多项式求和
- Git在另一个电脑上创建仓库并向远程仓库提交代码