今天在研究AirSim的代码过程中,发现了以下有趣的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
class UpdatableObject { public: virtual void reset() = 0; virtual void update(real_T dt) = 0; virtual ~UpdatableObject() = default; virtual void reportState(StateReporter& reporter) { //default implementation doesn't do anything } virtual UpdatableObject* getPhysicsBody() { return nullptr; } }; template<typename TUpdatableObjectPtr> class UpdatableContainer : public UpdatableObject { public: //limited container interface typedef vector<TUpdatableObjectPtr> MembersContainer; typedef typename MembersContainer::iterator iterator; typedef typename MembersContainer::const_iterator const_iterator; typedef typename MembersContainer::value_type value_type; iterator begin() { return members_.begin(); } iterator end() { return members_.end(); } const_iterator begin() const { return members_.begin(); } const_iterator end() const { return members_.end(); } uint size() const { return static_cast<uint>(members_.size()); } const TUpdatableObjectPtr& at(uint index) const { members_.at(index); } TUpdatableObjectPtr& at(uint index) { return members_.at(index); } //allow to override membership modifications virtual void clear() { members_.clear(); } virtual void insert(TUpdatableObjectPtr member) { members_.push_back(member); } virtual void erase_remove(TUpdatableObjectPtr obj) { members_.erase(std::remove(members_.begin(), members_.end(), obj), members_.end()); } public: //*** Start: UpdatableState implementation ***// virtual void reset() override { for (TUpdatableObjectPtr& member : members_) member->reset(); } virtual void update(real_T dt) override { for (TUpdatableObjectPtr& member : members_) member->update(dt); } virtual void reportState(StateReporter& reporter) override { for (TUpdatableObjectPtr& member : members_) member->reportState(reporter); } //*** End: UpdatableState implementation ***// virtual ~UpdatableContainer() = default; private: MembersContainer members_; }; |
UpdatableObject描述了一个可以被Update,Reset的对象。而在实际的代码中,有许多相关的代码都是可以Update的,不过又不便于通过继承特性来维持一个统一的接口,对于这种情况,一种方法可以把update方法用Bind绑定成为一个Func<>对象然后统一处理,或者也可以像下面一样用一个模板类来做类似的事情。
UpdatableContainer可以将拥有Update,Reset,ReportState方法的TUpdatableObjectPtr对象指针,包装到自己里面,同时对外是一个明确的,与内在对象类型无关的UpdatableObject,供其他模块批量调用。因为是作为模板参数传过去的,在模板匹配过程中(编译时)会检查是否满足条件,也就不必用继承的方式来约束了(编译器:???)(intellisence:???)。
顺便一说,这里似乎也是支持update为Func<>变量的情况,这也算是模板的好处之一吧。