Safely Override C++ Virtual Functions

Safely override C++ virtual functions

Since g++ 4.7 it does understand the new C++11 override keyword:

class child : public parent {
public:
// force handle_event to override a existing function in parent
// error out if the function with the correct signature does not exist
void handle_event(int something) override;
};

Is there any point in using `override` when overriding a pure virtual function?

However, in the case of a pure virtual function, the compiler would throw an error if we used an incorrect signature in the Derived class

No, this compiles:

class Base {
virtual void my_function() = 0;
};

class Derived : Base {
void my_function(int);
// ^^^ mistake!
};

While this does not:

class Base {
virtual void my_function() = 0;
};

class Derived : Base {
void my_function(int) override;
};

error: void Derived::my_function(int) marked override, but does not override


The error you're talking about only occurs when instantiating Derived - override allows you to catch the mistake earlier and makes the definition of Derived clearer/more readable.

Can you override a pure virtual function within the same class?

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.

Overriding C++ pure virtual functions

Is the keyword "override" always necessary? If not, what are the best practices?

It is never "necessary". Overriding works with or without this keyword. It is only here to help you prevent issues like typos etc.

struct A
{
virtual int foo();
};

struct B: public A
{
int fooo(); //whoops, not overriding, no compiler error
};

struct C: public A
{
int fooo() override; //compiler error, compiler noticed my typo
};

So, the best practice is to always use override keyword when you want to override a virtual function.


The main question: I know the code above works for me. But I have the problem, that I basically have to "copy" the function signature of the pure virtual function out of the base class into my derived class. What happens, if I don't know what pure virtual functions the base class has?

You cannot not know that. To derive from class, compiler requires full definition of that class, which typically means you have #included it (and you have access to that definition).


My implementation above implies that I have to know all the pure virtual functions available in the base class. I tried accessing the pure virtual function by the Mode:: scope and LocalMode:: scope but in Visual Studio I simply got some error messages (I deem those error messages to be rather irrelevant to this question).

Are you looking for reflection mechanism? It's not present in C++, so you cannot e.g. get a list of function for given class. If you want to call pure virtual function from another function, that cannot work because, well, they are pure virtual.


Some plug-ins/Intellisense?

That is explicitly off-topic for StackOverflow, but there are many IDEs for C++, you shouldn't have any trouble finding them.

How to override a pure virtual function using a subclass reference in the overriden function

You cannot change the function signature that way – read about co- and contravariance for details and why C++ disallows both for function parameters (covariant return types are allowed).

On the other hand, if the other object is referred to via reference to base, the overriding (actually: overloading!) function would not be called at all:

Derived d1;
Derived d2;
Base& b2 = d2;

d1.isEqual(b2); // how do you imagine the derived version to get called now???

Key to a solution is a dynamic_cast:

struct Base
{
virtual ~Base() { }
virtual bool operator==(Base const& other) = 0;
};

struct Derived : Base
{
bool operator==(Base const& other) override
{
auto o = dynamic_cast<Derived const*>(&other);
return o && o->str == this->str;
}
};

Note that I renamed the function to operator==; this is far more natural in C++. With that, you can compare in the example above with:

bool isEqual = d1 == b2;

Edit:

The teacher told us that we must not overload operator

Well, then just revert the renaming... Actually, operators are just as ordinary functions as any other one else, solely that calling syntax differs (actually: an alternative variant exists, you could always call as d1.operator ==(d2), too).

C++ virtual keyword for functions in derived classes. Is it necessary?

They are exactly the same. There is no difference between them other than that the first approach requires more typing and is potentially clearer.



Related Topics



Leave a reply



Submit