["Followup-To:" header set to comp.lang.c.]
Jeff Schwab said:
Kevin Smith wrote:
Can I provide the implementation of a pure virtual function by inheriting
from another class? eg.:
class A{
public:
virtual void f() = 0;
};
class B{
public:
void f(){};
};
class C: public A, public B{};
My compiler (VC++) tells me that C is an abstract class, even though there
is a public implementation of f() in C. Is this Standard?
Yes.
Yes, what? It is standard?
What you want is called a "mixin." Of course, the "easy" way is:
struct A { virtual void f() =0; };
struct B: virtual A { void f() { } };
Virtual base classes are a complicated way to solve this. And also,
you are editing one of the original classes. B::f is now virtual,
and overrides the pure virtual A::f.
The virtual inheritance of A ensures that the C object gets only one A. Since
the object has only one A, and since it contains a B which seals the pure
virtual A::f with B::f, the C object has no pure virtuals.
This is like duct-tape.
(In some 13 years of commercial C++ development, I've yet to find use for a
virtual base class, and I'm not sure you understand what they are for).
struct C: virtual A, B { };
See there is no reason for C now to inherit A directly, since it's
getting it from B. You can change this whole thing to:
struct A { virtual void f() = 0; };
struct B: public A { void f() { } };
struct C: public B { };
Look ma, no virtual inheritance.
If that's not an option for you, try this:
struct A { virtual void f() =0; };
struct B { void f() { } };
struct B_mixin: virtual A, private B { void f() { B::f(); } };
struct C: virtual A, B_mixin { };
Yuck. Five years in the Java slammer for you!
But I know a good language lawyer who may be able to get you three.
But at least this doesn't touch A and B. But note that instead
of this B_mixin implementing the override, C can just do it.
The above is a complicated way of doing this:
struct A { virtual void f() =0; };
struct B { void f() { } };
struct C: public A, public B { void f() { B::f() } };
No mixin, no virtual bases. Keep it simple and stupid.
Also note that C doesn't actually solve any problem in your
above solution. So what we can do is simply drop C,
and rename B_mixin to C:
struct A { virtual void f() =0; };
struct B { void f() { } };
// C was called B_mixin; original C gone
struct C: virtual A, private B { void f() { B::f(); } };
Drop the virtual from virtual A, and you get the same thing
again.