Reputation: 301
I would like to extend an abstract base class with a virtual function and keep the function name as virtual, but running code before and after the "possibly" overridden child function.
Here is an example:
I have a base class (interface) for things that can be drawn:
class IDraw {
public:
virtual void do_draw(Screen *scr) = 0;
};
I want to keep this interface in subclasses and be able to override it, for example I have a class for a Game, which cleans the screen, draw stuff and than flip the display buffer:
class Game : public IDraw {
public:
// Keep the interface
// This can be overridden by sub classes
virtual void do_draw(Screen *scr) = 0; // (1)
private:
// But override the base class so if s.b. calls
// do_draw from a IDraw pointer it executes this!
void IDraw::do_draw(Screen *scr) override; // (2)
};
// Implementation of (2)
void Game::IDraw::do_draw(Screen *scr) {
// Do stuff before like clear the screen
scr->clear();
// Call the method supplied by childs
this->do_draw(scr); // (1)
// Present the drawing
scr->present();
}
Since I have code before and after the function supplied by the child I cannot simply override keeping it virtual because the child must decide if calling Game::do_draw() // (2) before or after.
I know I can simply call the function (2) with a different name, but since I need many class doing this kind of stuff it will end with plenty of names for the same concept.
Is there any way to do this sort of thing in C++11?
Upvotes: 2
Views: 1733
Reputation: 8018
I want to keep this interface in subclasses and be able to override it,
That will be already the case automatically, because you inherited it at the public
access level.
for example I have a class for a Game, which cleans the screen, draw stuff and than flip the display buffer ...
... Is there any way to do this sort of thing in C++11?
Completely independent of any c++11 particularities, just write an implementation for the abstract function declaration, and add an additional layer of indirection (aka the Template Method Pattern):
class Game : public IDraw {
public:
// Keep the interface
// This can be overridden by sub classes
void do_draw(Screen *scr) override {
OnPreDraw(scr);
OnDraw(scr);
OnPostDraw(scr);
}
protected:
virtual void OnPreDraw(Screen *scr) {
// Default implementation
scr->clear();
}
virtual void OnDraw(Screen *scr) = 0; // << Class is still abstract
virtual void OnPostDraw(Screen *scr) {
// Default implementation
scr->present();
}
};
This would allow to inject any implementation of Game
at that finer grained sequence of operations, but keep default behavior from the base class implementation.
Also the base class is still abstract and effectively forces any derived class to implement OnDraw()
, which is effectively the same as do_draw()
.
but since I need many class doing this kind of stuff it will end with plenty of names for the same concept.
No. As far your concept just involves the operations
OnPreDraw(scr);
OnDraw(scr);
OnPostDraw(scr);
in that sequence, that won't change for the whole class inheritance hierarchy anymore in future.
To an extend:
You can also do that with Mixin pattern classes1
template<typename Derived>
class AbstractIDrawImpl : public IDraw {
void do_draw(Screen *scr) override {
static_cast<Derived*>(this)->OnPreDraw(scr);
static_cast<Derived*>(this)->OnDraw(scr);
static_cast<Derived*>(this)->OnPostDraw(scr);
}
// Expects public implementations
void OnPreDraw(Screen *scr) {
// Default implementation
scr->clear();
}
// Just no default implementation for
// void OnDraw(Screen *scr) << Class is still abstract
void OnPostDraw(Screen *scr) {
// Default implementation
scr->present();
}
};
The above mixin example can be bound to any implementation of IDraw
that provides public
functions for OnPreDraw()
, OnDraw()
and OnPostDraw()
:
class MyGame : public AbstractIDrawImpl<MyGame> {
public:
// IDraw interface implementation
void OnPreDraw(Screen *scr) {
// Call base class implementation
AbstractIDrawImpl<MyGame>::OnPreDraw(scr);
// E.g fill my background here
}
void OnDraw(Screen *scr) {
// For each game entity call
// IDraw::do_draw(scr);
for(auto drawableEntity : drawableEntities_) {
drawableEntity->do_draw(scr);
}
}
// Skip implementation of OnPostDraw()
private:
std::vector<std::shared_ptr<IDraw>> drawableEntities_;
};
1)
That pattern is well described with Alexei Andrescou's Policy based design paradigm and heavily used with Microsoft's ATL.
Upvotes: 3