Re: Pure virtual, forced implementation, and base class methods
On 29.09.2011 00:02, Andy Champ wrote:
.. So what we want to do is expose a class that's got some methods in
that are pure virtual, so you have to override them - but they're
incompletely implemented in the base class. There's some useful stuff
in the base class implementation, just not enough. A diagnostic dump
function is an example.
I think it will be much more clear if you differentiate between
* implementation support, and
* the method to be implemented per subclass.
I suggest that you use different names for these.
The exposed class is the tip of a hierarchy. It is _not_ the one with
the implementation. This minimal example shows roughly what we have. C
is the exposed class; D is locally derived from it. In D we want to
call into a base class method; B forces us to implement that method.
Good understanding.
It
looks as though in the most derived method we have to know which of the
classes in the hierarchy has an implementation in order to call it.
Happily, no.
Just make sure that every class has an implementation. ;-)
Yet
if we leave out the declaration that forces us to implement a derived
method we can call through _without_ knowing which of the classes
implements it.
Is this just the way it is, an MS bug, or is there a better way?
It's because you have failed to provide an implementation of the pure
virtual. Then when you attempt to call that, the linker discovers that
hey, there's no implementation to call. Then it protests "no such".
struct A
{
virtual void m()
{
};
};
struct B: public A
{
// Uncomment this to get link failures
// virtual void m() = 0;
};
E.g. you can do
struct B: public A
{
virtual void m() = 0;
};
void B::m() { A::m(); }
struct C: public B
{
};
struct D: public C
{
virtual void m()
{
C::m();
// without the pure virtual declaration this calls A::m
// with the declaration it tries to call B::m
};
};
The comment is correct.
void main()
This is non-standard and with many compilers it will not compile.
Use standard
int main()
{
D().m();
}
***
The above is about how to rescue the current design.
Here's an in my opinion better way:
struct A
{
protected:
void defaultM()
{};
public:
};
struct B
: A
{
virtual void m() = 0;
};
struct C
: B
{
};
struct D
: C
{
virtual void m()
{
defaultM();
};
};
int main()
{
D().m();
}
Cheers & hth.,
- Alf