c++ - Casting from abstract base class pointer to derived class -
i'm trying create state manager game, , have 4 classes:
gamestate:
// foward declaration avoid circular-referency class statemanager; class gamestate { public: virtual ~gamestate() { } virtual void update(statemanager* gamemanager) = 0; virtual void draw(statemanager* gamemanager) = 0; protected: gamestate() { } };
statemanager:
class statemanager { public: statemanager(); virtual ~statemanager(); void addstate(gamestate* gamestate); void update(statemanager* statemanager); void draw(statemanager* statemanager); protected: // store states in unique_ptr avoid memory leak std::vector<std::unique_ptr<gamestate> > states_; };
game:
class game : public statemanager { public: void compute() { // call methos of statemanager update(this); draw(this); } }
and mainmenu:
class mainmenu : public gamestate { public: // override pure virtual methos of gamestate void update(statemanager* statemanager) { // problem here. // need handle instance of game in class, // pointer 1 statemanager } void draw(statemanager* statemanager) {} }
when initialize game so: game.addstate(new mainmenu())
.
the way can access class game
in mainmenu
casting pointer?
// mainmenu class void update(statemanager* statemanager) { game* game = (game*) statemanager; game.input.getkey(any_key); //... }
is right? tells me i'm doing wrong.
the answer of immibis perfect addressing technical casting issue.
nevertheless there's weird in design. i'd provide alternative answer, addressing design issues.
first statemanager
not gamestate
. there no need have same signature update()
, draw()
. ever foresee have 1 of these statemanager
functions called statemanager
in argument ? game
, think makes no sense. i'd recommend refactor class (and adapt game
accordingly):
class statemanager { public: ... void update(); // know "this". void draw(); protected: ... };
next, seems statemanager
owns gamestate
(the protected vector using unique_ptr<>
,and casting question suggest it). design interesting well:
class gamestate { public: virtual ~gamestate() { } virtual void update() = 0; virtual void draw() = 0; protected: gamestate(statemanager* gamemanager) { } // gamestates created statemanager statemanager* gm; // manager can used gamestate functions need };
following logic, mainmenu
refactored as:
class mainmenu : public gamestate { public: mainmenu (game* g) : game(g), gamestate(g) {} void update() { // no longer needed: game* game = (game*) statemanager; game->input.getkey(any_key); // no more problems here: refer right object without overhead } void draw() {} protected: game *game; // owning game. };
the advantages of alternative design are:
- the code lighter, , less error prone, don't worry member function's argument.
statemanager
pointer usedstatemanager
abstraction.- concerete implementations of
gamestate
, rely ongame
, can use directly, should use game specific abstractions.
the main inconveniences are:
gamestate
must created 1 specifcstatemanager
.- the robustness of design comes @ cost of redundant pointer in
gamestate
implementations suchmainmenu
. if have millions of them, become memory issue.