[comp.lang.c++] Multiple inheritance and pointers to base class.

ahuttune@niksula.hut.fi (Ari Juhani Huttunen) (12/01/90)

How do you use multiple inheritance and pointers to a base class object at 
the same time? Suppose you have many different classes from which you wish
to construct objects using multiple inheritance and you also wish to access
these objects through a pointer to their common base class. Example:

Animal - AnimalWithWingsAndTeeth
       - AnimalWithWingsAndFeet
       - AnimalWithFeetAndScales
          ...

You access these through a pointer to Animal. You have implemented classes
named Wings, Teeth, Feet, Scales that implement functions fly, bite, run,
protect. (And NoWings, NoTeeth, NoFeet, NoScales that do not.)

The easy way to proceed would be:

class Animal {
public:
  virtual fly() = 0;
  virtual bite() = 0;
  virtual run() = 0;
  virtual protect() = 0;
};

class AnimalWithWingsAndTeeth : 
  public Wings, public Teeth, public NoFeet, NoScales
{};

class AnimalWithWingsAndFeet : 
  public Wings, public NoTeeth, public Feet, NoScales
{};

class AnimalWithFeetAndScales : 
  public NoWings, public NoTeeth, public Feet, Scales
{};

Instead you are forced to write:

class AnimalWithWingsAndTeeth : 
  public Wings, public Teeth, public NoFeet, NoScales {
public:
  fly() { Wings::fly(); }
  bite() { Teeth::bite(); }
  run() { NoFeet::run(); }
  protect() { NoScales::protect(); }
};

class AnimalWithWingsAndFeet : 
  public Wings, public NoTeeth, public Feet, NoScales {
public:
  fly() { Wings::fly(); }
  bite() { NoTeeth::bite(); }
  run() { Feet::run(); }
  protect() { NoScales::protect(); }
};

class AnimalWithFeetAndScales : 
  public NoWings, public NoTeeth, public Feet, Scales {
public:
  fly() { NoWings::fly(); }
  bite() { NoTeeth::bite(); }
  run() { Feet::run(); }
  protect() { Scales::protect(); }
};

My question: Is it really necessary to force a programmer to write this much
(and more since this is only a small example) unnecessary code? Why can't
the multiple inheritance of a non-virtual function, say Wings::fly(), 
re-define a virtual function Animal::fly() ? Am I missing something?
--
  ___  ___  ___  ___  ___  ___  ___  ___  ___  
__I I__I I__I I__I I__I I__I I__I I__I I__I I  Bird of Night: 2 cl Kahlua
 Ari Huttunen    (ahuttune@niksula.hut.fi)  I                 2 cl Jameson
____________________________________________I                 add ice cubes

randolph@ssd.kodak.com (Gary L. Randolph) (12/03/90)

In article <AHUTTUNE.90Nov30230346@wolverine.hut.fi> ahuttune@niksula.hut.fi (Ari Juhani Huttunen) writes:
>
>How do you use multiple inheritance and pointers to a base class object at 
>the same time? Suppose you have many different classes from which you wish
>to construct objects using multiple inheritance and you also wish to access
>these objects through a pointer to their common base class. Example:
>
>Animal - AnimalWithWingsAndTeeth
>       - AnimalWithWingsAndFeet
>       - AnimalWithFeetAndScales
>          ...
>
>You access these through a pointer to Animal. You have implemented classes
>named Wings, Teeth, Feet, Scales that implement functions fly, bite, run,
>protect. (And NoWings, NoTeeth, NoFeet, NoScales that do not.)
                                                  ^^^^^^^^^^^
              Not clear what you mean here.  The functions must be defined or the
   call to the member function is an error.  You may have null bodied functions
   here if you like, but you cannot keep the functions pure virtual and call them.

>
>The easy way to proceed would be:
>
>class Animal {
>public:
>  virtual fly() = 0;
>  virtual bite() = 0;
>  virtual run() = 0;
>  virtual protect() = 0;
>};
>
>class AnimalWithWingsAndTeeth : 
>  public Wings, public Teeth, public NoFeet, NoScales
>{};
>
>class AnimalWithWingsAndFeet : 
>  public Wings, public NoTeeth, public Feet, NoScales
>{};
>
>class AnimalWithFeetAndScales : 
>  public NoWings, public NoTeeth, public Feet, Scales
>{};
>
>Instead you are forced to write:
>
>class AnimalWithWingsAndTeeth : 
>  public Wings, public Teeth, public NoFeet, NoScales {
>public:
>  fly() { Wings::fly(); }
>  bite() { Teeth::bite(); }
>  run() { NoFeet::run(); }
>  protect() { NoScales::protect(); }
>};
>
  and so forth...
>
>My question: Is it really necessary to force a programmer to write this much
>(and more since this is only a small example) unnecessary code? Why can't
>the multiple inheritance of a non-virtual function, say Wings::fly(), 
>re-define a virtual function Animal::fly() ? Am I missing something?

Yes, you are missing quite a bit:-)

First, smile, because all you are asking for is simple to implement.

What you are trying for, is:

                        Animal
                         /...\
                        / ... \
                     Teeth... Feet
                       \  ... /
                        \ .../
                         \  /
                  AnimalWithTeethAndFeet

Where the elipsis are fill for NoTeeth, Wings, etc...


Since only one instance of Animal is necessary for each instance, the derived
classes will agree to share one Animal.  In C++ terms, Teeth, Feet, etc will
virtually derive from Animal.

In your code, you privately derived NoScales and Scales since you left out the
public reserved word.  That was probably just a (major) oversight.

The following will do precisely what you want, and notice that NOT ONCE, is the 
scope resolution operator used.

I am using 2.0 and therefore cannot inherit pure virtual functions, so in the
example below, I have null bodied functions. In 2.1 inheriting pure virtual
functions as remaining pure virtuals should be allowed (but you still don't call
them!)
------------------------------------------------------------------------------


#include <iostream.h>

class Animal{
	public:
		virtual void fly(){};
		virtual void bite(){};
		virtual void run(){};
		virtual void protect(){};
};

class Teeth:virtual public Animal{
	public:
		virtual void bite(){
			cout<<"\nMunching animal, chomp, chomp.";
		}
};

class NoTeeth:virtual public Animal{
	public:
		virtual void bite(){
			cout<<"\nLook out, I'll GUM you to death!";
		}
};


class NoFeet:virtual public Animal{
	public:
		void run(){
			cout<<"\nDon't ask me to run, I gots no feet!";
		}
};

class NoScales:virtual public Animal{
	public:
		void protect(){
			cout<<"\nI guess my lack of scales leaves me vulnerable.";
		}
};

class Wings:virtual public Animal{
	public:
		void fly(){"\nI put out my hand, and touch the face of God.";}
};

class AnimalWithWingsAndTeeth:
	public Wings,public Teeth, public NoFeet, public NoScales{};

main(){
AnimalWithWingsAndTeeth *flyingMunchy =new AnimalWithWingsAndTeeth;
Animal *ap = flyingMunchy;
ap->fly();
ap->bite();
ap->run();
ap->protect();
}
--------------------------------------------------------------------------
The output:

Munching animal, chomp, chomp.
Don't ask me to run, I gots no feet!
I guess my lack of scales leaves me vulnerable.


Gary