Topic: Proposal: Extending Final Overriders


Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Mon, 22 Apr 2002 19:32:08 GMT
Raw View
On Thu, 18 Apr 2002 21:05:29 GMT, Hyman Rosen <hyrosen@mail.com>
wrote:

>There is currently one trick with respect to inheritance that
>Java can do and C++ can't. In Java, the following works -
>
>interface a { void f(); }
>class b { void f() { } }
>class c implements a extends b { } // c.f() invokes b.f()
>
>In C++, the following does not:
>
>struct a { virtual void f() = 0; };
>struct b { void f() { } };
>struct c : a, b { }; // c::f() is ambiguous
>
>Neither does this:
>
>struct a { virtual void f() = 0; };
>struct b { virtual void f() { } };
>struct c : a, b { }; // c is ill-formed

No, C is abstract. The final overrider of a::f is a::f itself, which
is pure.

>
>Neither does this:
>
>struct a { virtual void f() = 0; };
>struct b { void f() { } };
>struct c : a, b { using b::f; }; // c::f() is ill-formed

No, C is again abstract. This time the final part of 10.3p2 comes into
play, which states using-declarations are ignored for the purpose of
determining final overriders.

All this is absolutely intentional: search the comp.lang.c++.moderated
archive for a thread entitled "multiple inheritance and abstract
methods". BTW the paper at
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/1997/N1048.pdf gives
the very same example you provide here :)


Genny.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: Tue, 23 Apr 2002 08:26:36 GMT
Raw View
Gennaro Prota wrote:
> No, C is abstract. The final overrider of a::f is a::f itself

Yes, I reread 10.3/2 more closely, and I do see that.
This doesn't affect my suggestion, however, which is
precisely to make certain classes which are now abstract
not be so.

> All this is absolutely intentional: search the comp.lang.c++.moderated
> archive for a thread entitled "multiple inheritance and abstract
> methods".

I read the thread, and the only downside anyone mentioned was that
the results could be surprising or accidental. The problem is that
a potentially useful technique is forbidden on those grounds.
That's not generally in the spirit of C++. And the only alternative
is laboriously coding forwarding functions.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Hyman Rosen <hyrosen@mail.com>
Date: Thu, 18 Apr 2002 21:05:29 GMT
Raw View
There is currently one trick with respect to inheritance that
Java can do and C++ can't. In Java, the following works -

interface a { void f(); }
class b { void f() { } }
class c implements a extends b { } // c.f() invokes b.f()

In C++, the following does not:

struct a { virtual void f() = 0; };
struct b { void f() { } };
struct c : a, b { }; // c::f() is ambiguous

Neither does this:

struct a { virtual void f() = 0; };
struct b { virtual void f() { } };
struct c : a, b { }; // c is ill-formed

Neither does this:

struct a { virtual void f() = 0; };
struct b { void f() { } };
struct c : a, b { using b::f; }; // c::f() is ill-formed

The only solution is this:

struct a { virtual void f() = 0; };
struct b { void f() { } };
struct c : a, b { void f() { b::f(); } };

My proposal is to change 10.3/2 as follows:

    If a member function f is declared in a class Base
    and in a class Derived, derived directly or indirectly
    from Base, a member function f with the same name and
    same parameter list as Base::f is declared, then it
    overrides Base::f. For convenience, we say that any
    member function overrides itself. A member function
    which overrides a virtual member function is also
    virtual (whether or not it is so declared). A final
    overrider is a member function which has no overriders
    but itself. Then in any well-formed class, for each
    virtual function declared in that class or any of its
    direct or indirect base classes, either all final
    overriders with the same name and argument list as the
    function are pure (10.4), or there is a single non-pure
    final overrider which becomes virtual and the unique
    final overrider of that function. The rules for member
    lookup (10.2) are used to determine the final overriders
    for a virtual function in the scope of a derived class
    but ignoring names introduced by using-declarations.

10.4/2 needs a slight change as well:

    A class is abstract if it contains or inherits at least
    one pure virtual function for which all final overriders
    are pure virtual.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]