(Latest Revision: Wed Apr 2 23:34:56 PST 2003 ) ch08_Notes01_Inheritance

ch08 Notes on Inheritance


Notes on the text of chapter 8 -- INHERITANCE

  X
   \
    \
      Y
A class Y that has been derived from a class X is all that X was, and more. Y has additional data and/or function members.

However, Y may have its own versions of some of X's members. In that case, the members of Y are the ones that "respond."

For example if SoccerBall is a derived class of Sphere and both classes have methods called drawSelf then if I have a variable mySoccerBall of type SoccerBall and I make a call to mySoccerBall.drawSelf(), it will cause the version of drawSelf belonging to the SoccerBall class to be executed , and not the version of drawSelf derived from the Sphere class. (Presumably the result will be that the drawing will look more like a soccer ball and not like a plain sphere.)

Exception: A derived class inherits all the members of its base class, except the constructors and destructor.

The advantage of using inheritance is that you have less to program if you create a new class as a derived class of a pre-existing class. (Perhaps it is easier for people programming long-term in some particular application area to appreciate this advantage. )

For example, if you are using classes to model the acoustic properties of musical instruments, you could possibly save a lot of work by creating a class for a new instrument by treating it as a derived class of a preexisting instrument -- maybe like a new kind of horn being a derived class of horn -- all horns have some characteristics in common.

Note: Good documentation of the base class must be available. Otherwise programmers will not have enough information to know how to create derived classes.

The example of Inheritance from the text:
 //THIS IS THE BASE CLASS (SPHERE)
class sphereClass
{
public:

           /* constructors. */
   sphereClass(); 
   sphereClass(double InitialRadius); 

           /* copy constructor and destructor will be supplied
	      by the compiler */

           // sphere operations:
   void SetRadius(double NewRadius);
   double Radius() const;
   double Diameter() const;
   double Circumference() const;
   double Area() const;
   double Volume() const;
   void DisplayStatistics() const; 

private:
   double TheRadius;  // the sphere's radius
};  // end class
Here is how the derived class is declared -- less work to do here because we get all the declarations from the base class "for free"

 
const int MAX_STRING = 15;
class ballClass: public sphereClass

	 /* The line above says that we want ballClass to be
	    derived from sphereClass (publicly)*/
{
public:

   ballClass();  // default constructor

             /* Another constructor: Creates a ball with radius
		InitialRadius and name InitialName. */
   ballClass(double InitialRadius, const char InitialName[]); 

        /* copy constructor and destructor supplied
           by the compiler */

    /* It's important to notice what is NOT here:  all the
       member functions of sphereClass -- no need to re-declare
       -- we get all that automatically.  For example users
       will be able to make calls like:  ball.Volume() when
       ball is an instance of ballClass (variable of type
       ballClass). */

/* additional or revised operations: */

	   /* this operation is new in the derived class
	      Determines the name of a ball. */
   void GetName(char CurrentName[]) const;    

           /* this operation is new in the derived class
              Sets (alters) the name of an existing ball. */
   void SetName(const char NewName[]);  

          /* this operation is new in the derived class Sets
	     (alters) the radius and name of an existing ball
	     to NewRadius and NewName, respectively. */
   void ResetBall(double NewRadius, const char NewName[]);

          	/* this operation is re-defined in the derived
		   class.  It displays the statistics of a
		   ball. */
   void DisplayStatistics() const;

private:

         /* this data member is a new one -- in addition to
	    TheRadius, which we get from the parent class */
   char TheName[MAX_STRING+1];  // the ball's name  
};  // end class
Important characteristics:


Keywords Public, Private and Protected.

Public, Private, and Protected Inheritance.

Kinds of Inheritance:

Normally you would use public inheritance when you have an "is-A" relationship. A ball is a sphere, a kitchen is a room, and so on. Here every characteristic of the base class is also a characteristic of the derived class. Therefore when you give access to the derived class there is no reason to exclude access to the base class.

If the relationship is a "has-a" relationship but not a "is-a" relationship then do not use inheritance. Instead give one class an instance of another class as a data member. For example a ball-point pen has a ball, and a mammal has a heart. The class representing a ball-point pen could have a data member that is an instance of the ball class. A mammal class could be given a heart class data member.

Normally you would use private inheritance when you have a "as-a" relationship to represent. A stack can be thought of as a list of a certain kind. You can implement a stack by inheriting from a list class. However if you give access to the stack, you don't usually also want to give access to the list base class because that would allow the client to violate the LIFO structure of the stack.