This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: C++ question: MI vs. pure virtuals
- To: chip at valinux dot com
- Subject: Re: C++ question: MI vs. pure virtuals
- From: "Martin v. Loewis" <martin at loewis dot home dot cs dot tu-berlin dot de>
- Date: Sat, 1 Jan 2000 15:41:48 +0100
- CC: llewelly at 198 dot dsl dot xmission dot com, gcc-bugs at gcc dot gnu dot org
- References: <19991231180843.C13730@perlsupport.com> <Pine.LNX.4.10.9912311911360.28190-100000@198.dsl.xmission.com> <19991231192320.D13730@perlsupport.com>
> In a related question, a slight variation that I tried with gcc 2.96 is:
>
> struct A {virtual void f()=0;};
> struct B {void f() {}};
> struct C : public A, public B { using B::f; };
>
> That didn't work either (the compiler still considered C abstract).
> To your understanding, is the compiler still correct in this case?
> (I expect that it is, but it doesn't hurt to ask.)
It is ill-formed, according to 10.3, [class.virtual]/2:
# If a virtual member function vf is declared in a class Base and in a
# class Derived, derived directly or indirectly from Base, a member
# function vf with the same name and same parameter list as Base::vf
# is declared, then Derived::vf is also virtual (whether or not it is
# so declared) and it overrides Base::vf. For convenience we say that
# any virtual function overrides itself. Then in any wellformed
# class, for each virtual function declared in that class or any of
# its direct or indirect base classes there is a unique final
# overrider that overrides that function and every other overrider of
# that function. The rules for member lookup (10.2) are used to
# determine the final overrider for a virtual function in the scope of
# a derived class but ignoring names introduced by usingdeclarations.
So overriding requires 'real' definitions; using-declarations are not
enough.
What you want to do is known as "mix-in" classes. In C++, you can do
this with interfaces (class A, only pure virtual functions), which are
used as virtual bases:
struct A {virtual void f()=0;};
struct B: virtual A {void f() {}};
struct C : public virtual A, public B { };
The implementation always needs to inherit the interface. That allows
the C++ compiler to perform late binding using virtual function
tables.
Regards,
Martin