c++ - An alternative to PIMPL Idiom when you'd like the interface to have all the memory -
the purpose of pimpl idiom hide implementation, including methods, structures, , sizes of structures. 1 downside uses heap.
however, if didn't want hide size requirements of anything. wanted hide methods, formatting of structure , variable names. 1 way allocate array of bytes of perfect size, have implementation cast whatever structure , use that. manually find size of bytes allocate object? , casts time? not practical.
is there idiom or general way of handling case advantageous pimpl or opaque pointers.
a rather different approach rethink nature of objects represent. in traditional oop it's customary think of objects self-contained entities have own data , methods. of methods private class because they're required class's own housekeeping, , these kind of thing move 'impl' of pimpl class.
in recent project i've been favouring domain-driven design approach 1 of desirables separate data logic things it. data classes become little more structs, , complex logic hidden in pimpl can go in service object has no state of own.
consider (rather contrived) example of game loop:
class enemysoldier : public gameobject { public: // implement basic gameobject interface void updatestate(); void draw(surface&); private: std::unique_ptr<enemysoldierimp> m_pimpl; };
class enemysolderimpl { public: // 100 methods of complex ai logic // don't want exposed clients private: statedata m_statedata; };
void rungame() { (auto gameobject : allgameobjects) { gameobject->updatestate(); } }
this restructured instead of gameobjects
managing data and program logic, separate these 2 things out:
class enemysoldierdata { public: // getters may allowed, other data // modifiable service class. no program logic in class private: friend class enemysoldieraiservice; statedata m_statedata; };
class enemysoldieraiservice { public: enemysoldieraiservice() {} void updatestate(game& game) { (auto& enemysoldierdata : game.getallenemysoldierdata()) { updatestateforsoldier(game, enemysoldierdata); } } // 100 methods of ai logic here // no state variables };
we don't have need pimpls or hacky tricks memory allocation. can use game programming technique of getting better cache performance , reduced memory fragmentation storing global state in several flat vectors rather needing array of pointers-to-base-classes, eg:
class game { public: std::vector<enemysoldierdata> m_soldierdata; std::vector<missiledata> m_missiledata; ... }
i find general approach simplifies lot of program code:
- there's less need pimpls
- the program logic in 1 place
- it's easier retain backwards compatibility or drop in alternate implementations choosing between v1 , v2 version of service class @ runtime
- much less heap allocation
Comments
Post a Comment