[comp.lang.c++] Return types of virtual member functions

bs@hplabsz.HPL.HP.COM (Bob Shaw) (05/27/89)

I'm trying to build a "bushy" single inheritance tree.  Many of the child
classes define a few member functions beyond those of the parent.  Most of 
the system deals with the various objects at the highest level of 
abstraction (i.e. only use the parent member functions), but parts of the
system change the level of abstraction and deal with the object as an
instance of a child class.

My question involves the return value types in virtual member functions.
If a parent class defines a virtual member function such as

 virtual parent* msg();

I would like a child (derived) class to be able to define its version of the
member function as

 virtual child* msg();     rather than    virtual parent* msg();.

It's my understanding that a child* can always be assigned to something
defined as a parent*, so I can't see why this should break the type system.
Obviously, children of such a child would be constrained to return a pointer
to child or something derived from it.

The code below does not work as I had hoped.  Can someone involved in the
ATT C++ 2.0 release tell me if this will work in 2.0 and, if not, whether
it's a bug or why it isn't a reasonable thing to do?


Thanks,
bs           <- obviously not the att one


----------------------------
Output from following code:


parent->msg()
  parent::msg entered

child->msg()
  child::msg entered

child_as_parent->msg()
  parent::msg entered       <---- I'd hoped for "child::msg entered"

----------------------------
#include <stream.h>

class parent
{
public:
  virtual parent* msg();
};


class child : public parent
{
public:
  virtual child* msg();
};


parent* parent::msg()
{
  cout << "  parent::msg entered\n";
  return this;
}


child* child::msg()
{
  cout << "  child::msg entered\n";
  return this;
}

void main()
{
  parent* presult;
  child*  cresult;

  parent* p    = new parent;
  child*  c    = new child;

  cout << "\nparent->msg()\n";
  presult = p->msg();

  cout << "\nchild->msg()\n";
  cresult = c->msg();

  cout << "\nchild_as_parent->msg()\n";
  p = c;
  presult = p->msg();

}

s_heising@iravcl.ira.uka.de (06/01/89)

In his article 
<3403@hplabsz.HPL.HP.COM>  bs@hplabsz.HPL.HP.COM (Bob Shaw) 
writes about his problems with return types of virtual 
member functions.


void main()
{
  parent* presult;                                                                      
  child*  cresult;

  parent* p    = new parent;
  child*  c    = new child;

  presult = p->msg();           <-- expectation correct

  cresult = c->msg();           <-- expectation correct

  p = c;                        <-- misunderstanding!
                                    change in value, 
                                    not in type
  presult = p->msg();           <-- still calls parent::msg
                                    not child::msg as expected

}

I'm not an experienced C++ or C-programmer, 
my interest is theoretically rather. 
But I think the solution to the problem is as follows:

Bob is mixing up assigning values and declaring types.
to be more concrete, that part of c's value p can hold.
It doesn't makes p to become an object of class child, 
of class parent, not the one of class child. 

Bye! 

randolph@ektools.UUCP (Gary L. Randolph) (06/02/89)

In article <3403@hplabsz.HPL.HP.COM> bs@hplabsz.HPL.HP.COM (Bob Shaw) writes:
>
>I'm trying to build a "bushy" single inheritance tree.  Many of the child
>classes define a few member functions beyond those of the parent.  Most of 
>the system deals with the various objects at the highest level of 
>abstraction (i.e. only use the parent member functions), but parts of the
>system change the level of abstraction and deal with the object as an
>instance of a child class.
>
>My question involves the return value types in virtual member functions.
>If a parent class defines a virtual member function such as
>
> virtual parent* msg();
>
>I would like a child (derived) class to be able to define its version of the
>member function as
>
> virtual child* msg();     rather than    virtual parent* msg();.
>
>It's my understanding that a child* can always be assigned to something
>defined as a parent*, so I can't see why this should break the type system.
>Obviously, children of such a child would be constrained to return a pointer
>to child or something derived from it.
>
>The code below does not work as I had hoped.  Can someone involved in the
                ^^^^^^^^^^^^^                      ^^^^^^^^^^^^^^^^^^^
                It does now.                       Will I do?

>ATT C++ 2.0 release tell me if this will work in 2.0 and, if not, whether
>it's a bug or why it isn't a reasonable thing to do?
        ^^^^           ^^^^^^^^^^^^^^^^^^^^^^
        NOT BUG         See below             
>
>
>Thanks,
 No prob
>bs           <- obviously not the att one
                      cute
>
/*
----------------------------
Output from following code:     <----Modified from your original


parent->msg()
  parent::msg entered

child->msg()
  child::msg entered

child_as_parent->msg()
  child::msg entered            <-----As you wished

----------------------------
*/

#include <stream.h>

class parent
{
public:
  virtual parent* msg();
};


class child : public parent
{
public:
  virtual parent* msg();
};


parent* parent::msg()
{
  cout << "  parent::msg entered\n";
  return this;
}


parent* child::msg()
{
  cout << "  child::msg entered\n";
  return this;
}

void main()
{
  parent* presult;
  parent*  cresult;

  parent* p    = new parent;
  parent*  c    = new child;

  cout << "\nparent->msg()\n";
  presult = p->msg();

  cout << "\nchild->msg()\n";
  cresult = c->msg();

  cout << "\nchild_as_parent->msg()\n";
  p = c;
  presult = p->msg();

}

All that was changed was the pointer types of c, the return type
of child::msg(), and cresult.  You seem to be close to understanding
virtual functions except that you need to understand that it is the
*object* being pointed to that makes the assignment to a base pointer
work.  You want the (modified) pointers above to be of type parent.
You can then have the parent pointers point to child objects.  I
believe that once you look this over, the pointer types will make
sense.

            Gary