Topic: Overriding Virtual Fn Return Types


Author: fenster@age.cs.columbia.edu (Sam Fenster)
Date: 07 Mar 1995 00:02:42 GMT
Raw View
tob@world.std.com (Tom O Breton) writes:
> tmurphy@panix.com (Timothy Murphy) writes:
> > I propose that this return type overriding be extended to include "const".
> > That is:
> >    A a;
> >    class E : { virtual const A *g() =0;};
> >    class F : public E { A *g() { return &a;}};
>
> I notice that in your example the override widens the type to a
> non-const. If it had narrowed it from non-const to const, it could not
> guarantee the const was honored.

This proposal is subsumed by a suggestion that's been here before:
- Observation:  An `A' is always substitutable where a `const A' is expected.
- So `const A' should be considered a superclass of `A'.

Thus, covariant return would naturally allow `virtual const A *f()' to be
overridden by `A *f()'.

In addition, a class `B' could inherit from `const A' rather than from `A'.  B
would only inherit A's const methods and const access to its A members.  Then
there would be an implicit conversion from `B&' to `const A&' but not to `A&'.
This is quite useful if B restricts A's allowable states (say, from Matrix to
SquareMatrix, or from Ellipse to Circle).  B is thus welcome anywhere a `const
A&' is welcome, but not where an `A&' is required.




Author: Duncan@rcp.co.uk (Duncan Booth)
Date: Tue, 07 Mar 1995 09:17:41 +0000
Raw View
In article <JASON.95Mar6161827@phydeaux.cygnus.com>,
jason@cygnus.com (Jason Merrill) wrote:
> >>>>> Timothy Murphy <tmurphy@panix.com> writes:
>
> > Include "const" in virtual function return type overriding.
>
> This is already the case.
>
>     10.3  Virtual functions                              [class.virtual]
>
> 4   A program is ill-formed if the return type of any  overriding  func-
>     tion  differs from the return type of the overridden function unless
>     the return type of the latter is pointer or reference (possibly  cv-
>     qualified)  to  a  class  B,  and  the  return type of the former is
>     pointer or reference (respectively) to a class D such that B  is  an
>     unambiguous  direct  or  indirect base class of D, accessible in the
>     class of the overriding function, and the  cv-qualification  in  the
>     return  type of the overriding function is less than or equal to the
>     cv-qualification in the return type of the overridden function.
>
> Jason

I may be having problems working out exactly what this means, but I
don't think it allows the example given by Mr. Murphy. In his
example, the derived class member function has a cv-qualification
less than or equal to the cv-qualification in the return type of the
overridden function, BUT the return type is not a pointer to a class
D such that B is an base class of D.

In other words, the paragraph above seems to say that you can
override returning a less const pointer to a class derived from the
original return value, but it doesn't allow you to return a less
const pointer to the original class.

--
Duncan Booth                                             duncan@rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?




Author: tmurphy@panix.com (Timothy Murphy)
Date: 6 Mar 1995 13:04:05 -0500
Raw View
Include "const" in virtual function return type overriding.

Timothy S. Murphy   5 March 1995.


  A few observations and proposals regarding the C++ language standard.
The last draft specification (DS) I looked at was dated 20 September 1994;
I also refer to the ARM.

   Please rip this apart, both with your editor and your words; I am
very interested in feedback, particularly from members of the standards
committee.


   [ARM 10.2] now permits a virtual function in a derived class to
return a pointer (or reference) to an object of a class derived from
the class referred to by the virtual function in the base class.
That is:

   class A : {...};
   class B : ... public A ... {...};
   B b;
   class C : { virtual A *f() =0;};
   class D : public C { B *f() { return &b;} };
   D d;
   C *cp = &d;
   A *ap = cp->f();

   leaves ap pointing at the A part of b.  I propose that this return
type overriding be extended to include "const".  That is:

   A a;
   class E : { virtual const A *g() =0;};
   class F : public E { A *g() { return &a;}};
   F foo;
   E *ep = &foo;
   const A *cap = ep->g();

   leaves cap pointing at a.  This is completely reasonable, trivial
to implement, and is of utility in the devolopment of container classes.


   By the way, the implementation of the already required return type
override is nontrivial in the "A,B" case above if the derivation of
B from A involves multiple or virtual inheritance.  Invoking f() on
a D through a C* of course returns an A*; the production of this A*
from the B* returned by D::f() requires address arithmetic and an
implicit augmentation of the vtable for class D.  Indeed, at the point
that the declaration of D is seen, the vtable entry for f() must split in
two, the first (returning an A*) is called via references to a C,
the second (returning a B*) is called via references to a D.  These
functions are _different_ and this "forking" may continue as we
proceed down the heterarchy.  The one compiler I have used that
ostensibly supports this feature (HP C++ 3.50) muffs this case completely:
It never changes the bits of the return value and, in the case above,
produces a bogus value of ap.  This is a somewhat subtle point of which
the development community should be made more aware.


-- Timothy S. Murphy: A serious user and admirer of C++.
   tmurphy@panix.com





Author: tob@world.std.com (Tom O Breton)
Date: Mon, 6 Mar 1995 22:10:08 GMT
Raw View
tmurphy@panix.com (Timothy Murphy) writes:
>    leaves ap pointing at the A part of b.  I propose that this return
> type overriding be extended to include "const".  That is:
>
>    A a;
>    class E : { virtual const A *g() =0;};
>    class F : public E { A *g() { return &a;}};
>    F foo;
>    E *ep = &foo;
>    const A *cap = ep->g();
>
>    leaves cap pointing at a.  This is completely reasonable, trivial
> to implement, and is of utility in the devolopment of container classes.

I notice that in your example the override widens the type to a
non-const. If it had narrowed it from non-const to const, it could not
guarantee the const was honored.

        Tom

--
tob@world.std.com
TomBreton@delphi.com: Author of The Burning Tower





Author: jason@cygnus.com (Jason Merrill)
Date: 07 Mar 1995 00:18:27 GMT
Raw View
>>>>> Timothy Murphy <tmurphy@panix.com> writes:

> Include "const" in virtual function return type overriding.

This is already the case.

    10.3  Virtual functions                              [class.virtual]

4   A program is ill-formed if the return type of any  overriding  func-
    tion  differs from the return type of the overridden function unless
    the return type of the latter is pointer or reference (possibly  cv-
    qualified)  to  a  class  B,  and  the  return type of the former is
    pointer or reference (respectively) to a class D such that B  is  an
    unambiguous  direct  or  indirect base class of D, accessible in the
    class of the overriding function, and the  cv-qualification  in  the
    return  type of the overriding function is less than or equal to the
    cv-qualification in the return type of the overridden function.

Jason




Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: Tue, 7 Mar 1995 16:16:21 GMT
Raw View
In article <3jfiql$me4@panix3.panix.com>,
Timothy Murphy <tmurphy@panix.com> wrote:
>Include "const" in virtual function return type overriding.
>

.. covariant returns.

I agree const should be permitted. Better, rvalue conversions should
be supported too. Complaints this is hard to implement fall
on my deaf ears -- the rvalue case is _more_ useful.

 class X { public: virtual int f(); };
 class Y: public X { public: virtual double f(); };

Double converts to int. Thats an extreme case. However:

 struct Complex {
  virtual Complex abs()const;
 };
 struct Real : Complex {
  Real abs()const;
 };

is quite realistic and very useful. The implementation is:

 struct Real : Complex {
  Complex abs()const { return rabs(); }
  Real rabs()const;
 };

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189