Let's assume I have a hierarchy of several classes each derived from each other using virtual functions. The base class acts as an interface and defines functions, which may not be required by all of the derived classes. Now I wonder what the best practice is for such intermediate functions. Should those still be implemented and simple chain down to the base class, or should they be skipped? The problem I have is, that implementing such a function, when it isn't needed, simply adds noise to the code. On the other hand, when using a higher class, in C++ you can not simply call a superclass method (like in Java), so you need to know in which base class the method is really implemented. And to my mind, this would violate encapsulation, because I would need to know some implementation details of the base class.
To illustrate what I mean here is an artifical exmaple:
class MyInterface
{
virtual void foo(bool) = 0;
virtual void foo1(int) = 0;
};
class Base : public MyInterface
{
void foo(bool param) override
{
// do some stuff here.
}
void foo1(int param) override
{
// do some stuff here.
}
};
class A : Base
{
void foo(bool param) override
{
// do some stuff here.
Base::foo(param);
}
// class doesn't need foo1() here so it is not implemented.
};
class B : A
{
void foo(bool param) override
{
// do some stuff here.
A::foo(param);
}
void foo1(int param) override
{
// This class needs foo1() but as A doesn't have it implemented
// I have to knwo this and skip A going directly to Base
Base::foo1(1);
}
};
Here the class B
needs to know that A doesn't implement foo1
and has to skip it. Of course this can be seen in the header, but if I want to later change class A
it shouldn't be neccessary to touch all the other classes that are derived from it (encapsulation and isolation principle) So even worse, if I implement now foo1()
in A
later, B
would still skip it and never realise that the functionality has changed.
So from an object model point of view I would assume that such empty functions should still be designed into a class?
using Base::foo1;
in class A, after whichA::foo1(1);
will work.