Topic: inheritance and return types


Author: calvitti@cthulhu.ces.cwru.edu (Alan Calvitti)
Date: 6 Sep 94 12:45:33
Raw View
Given the two classes,

 /////////////////////////////
 class Base {
 public:
     Base() {}
     Base& foo() {cout << "foo" << endl; return *this;}
 };
 /////////////////////////////
 class Derived : public Base {
 public:
     Derived() {}
     Derived& bar() {cout << "bar" << endl; return *this;}
 };

The following function:

 /////////////////////////////
 void f() {
     Derived d;
     d.foo().bar();
 }

produces this error:
 test.cc: In function `void f()':
 test.cc:87: no member function `Base::bar()' defined

This makes sense, as Base::foo() returns a Base reference, but it's
annoying. it also makes at least one construct suggested in
Stroustrup's 'Design and Evolution' -- the emulation of keyword
arguments -- less flexible than he imagined.

Is there a way to cast the return type of a base member fn. to the
derived class when a object of the latter type invokes that member?

--
 Alan Calvitti
 Control Engineering, CWRU




Author: branzrpc@branz.org.nz (Rey Crisostomo)
Date: 7 Sep 1994 20:29:41 GMT
Raw View
In article <CALVITTI.94Sep6124533@cthulhu.ces.cwru.edu> calvitti@cthulhu.ces.cwru.edu (Alan Calvitti) writes:
>Given the two classes,
>
> class Base {
> public:
>     Base() {}
>     Base& foo() {cout << "foo" << endl; return *this;}
> };
> class Derived : public Base {
> public:
>     Derived() {}
>     Derived& bar() {cout << "bar" << endl; return *this;}
> };
>
>The following function:
>
> void f() {
>     Derived d;
>     d.foo().bar();
> }
>
>produces this error:
> test.cc: In function `void f()':
> test.cc:87: no member function `Base::bar()' defined
>
>This makes sense, as Base::foo() returns a Base reference, but it's
>annoying....

A recent addition to the standard is the 'relaxing rule for return types for
overriding functions'. Here is your sample adapted to apply this:

class Base {
public:
  Base() {}
  virtual Base& foo() {cout << "foo" << endl; return *this;}
};

class Derived : public Base {
public:
  Derived() {}
  virtual Derived& foo() { Base::foo(); return *this; }
  Derived& bar() {cout << "bar" << endl; return *this;}
};

Now function f() in your sample should compile and run as expected.
I don't know how many compilers have implemented this, but the one I
use (Borland C++ v 4.02) does.

Rey Crisostomo
branzrpc@branz.org.nz
CompuServe:100237,2164
Wellington, New Zealand