Week 7: Inheritance - The Is-a Relationship


OOP Overiew in Week 7


OOP is an approach relies on software reuse

Primary mechanism is a class - which is a template that describes all objects that share the same operations and data elements

Multiple object can be created from one of these classes

It then is called an instance of an object

New subclasses can be derived from an existing class through the use of inheritance

Inheritance allows programmers to create new subclasses that reuse the code and data in the base class without having to repeat them

Yet these new subclasses are customized to meet the specific needs of the application

Polymorphism is the ability of subclasses of the same class to respond to the same input message and produce different results

Polymorphism combines the concepts of inheritance and dynamic binding (realtime binding)

Some of the "tools" to allow us to do Polymorphism is function and operator polymorhpism



Object Oriented Relationship Overview


There are three main relationship in OOP

They are HAS-A, USE-A and IS-A relationships

HAS-A relationship is the same as "contain" relationship - For example, the Bank object contains People object, Account object, Report object, etc. Or, Lunch has a Banana.

USE-A relationship means an object uses another object's methods. A common way of description is that an object sends a message to another object through the public method. For example, cleint sending server a message for processing.

IS-A relationship is Inheritance. It can be described as the parent-child relationship.A child get all the stuffs inherits from the parent. Some people describe that as super class-sub class OR base class - derived class. Or, Banana is a Fruit.

IS-A relationship is the bases for software reuse (if design, implement and use correctly)



Syntax - Protected and Private


Up to this point, in our class definition, we only have private and public

C++ actually provides a keyword called protected

The protected keyword is like private that in the outside world can access class members in a protected section only by using the class members methods.

Keyword private and protected's difference comes into play only within classes derived from the base class

Members of a derived class can access protected members of a base class directly, BUT they cannot directly access private members of the base class

In short: Protected class members are private to the world at large, but public to a derived class

// Syntax example
// More later at the demo

// arraydb.h -- define array class
#ifndef _ARRAYDB_H_
#define _ARRAYDB_H_
#include <iostream.h>

class ArrayDb
	unsigned int size;			// number of array elements

	double * arr;                       // address of first element

	ArrayDb();                          // default constructor
	// create an ArrayDb of n elements, set each to val
	ArrayDb(unsigned int n, double val = 0.0);
	// create an ArrayDb of n elements, initialize to array pn
	ArrayDb(const double * pn, unsigned int n);
	ArrayDb(const ArrayDb & a);         // copy constructor
	~ArrayDb();                         // destructor
	unsigned int arsize() const {return size;}   // returns array size
	// overloaded operators
	double & operator[](int i);			// array indexing
	const double & operator[](int i) const;	// array indexing (no =)
	ArrayDb & operator=(const ArrayDb & a);
	friend ostream & operator<<(ostream & os, const ArrayDb & a);




Inheritance - A Is-A Relationship


C++ actually supports three types of inheritance - public, protected and private

Public inheritance is the most common and useful form

It models a IS-A relationship

It can be throught as a short hand for saying that an object of a derived class should also be an object of the base class

Anything you do with a base object, you should be able to do with a derived object

For example, we can derive a Banana class from the Fruit class. The new class would inherit all the data members of the original class, so a Banana object would have members representing the, say weight and caloric content of a banana. But Banana can have Banana specific info, such as "Peel color"

In general, inheritance can add properties to a base class; it does not remove properties from a base class



Other Inheritance


Public Inheritance is the most common form of inheritance. However, sometime we might need protected and private inheritance as well. Their main differences are the access authority of data. Here is a quick look:


Property Public Inheritance Protected Private Inheritance
public members become public members of the derived class
protected members of the derived class
private member of the derived class
protected members become protected members of the derived class
protected members of the derived class
private members of the derived class
private members become accessible only through the base class interface
accessible only through the base class interface
accessible only through the base class interface



Syntax for Declaring a Derived Class


Syntax rule by C++: When creating an object of a derived class, a program first calls the base class constructor, then the derived class constructor. When an object of a derived class expires, the program first calls the derived class destructor, if any, then the base class destructor.

// Example:

// aritharr.h -- derived array class with more arithmetic
#ifndef _ARITHARR_H_
#define _ARITHARR_H_

#include "arraydb.h"

class ArithArr : public ArrayDb  // derived from ArrayDb class
	// no new data members
	// base class constructors not inherited,
	// need ArrithArr constructors
	ArithArr(unsigned int n, double val = 0.0)
				: ArrayDb(n, val) {}
	ArithArr(const double *pn, unsigned int n)
				: ArrayDb(pn, n) {}
	ArithArr(const ArithArr & aa) : ArrayDb(aa) {}
	ArithArr(const ArrayDb & ad) : ArrayDb(ad) {}

	// destructor ArrrayDb part is inherited, but you can define a new one
	~ArithArr() {}

	// new methods
	double sum() const;
	double average() const;
	// overloaded operators
	ArithArr operator+(const ArithArr & a) const;
	ArithArr operator-(const ArithArr & a) const;
	ArithArr operator-() const;
	ArithArr operator*(const ArithArr & a) const;
	ArithArr operator*(double d) const;
	friend ArithArr operator*(double d, const ArithArr & a);


// For protected and private inheritance ... do the following:
class informer: protected witness
class gradeschool : private school



(Public) Inheritance Considerations


If your proposed derived class is not a particular kind of the base class, do not use public derivation. For example, do not derive a Computer class from a Programmer class ... you might make a Computer class object a member of the Programmer class

A base class pointer can point to a derived class object and that a base class reference can refer to a derived class object without an explicit type cast. But the reverse is not true (more on next week) ... you can not have a derived class pointer or reference refer to a base class object without explicit type cast. Depending upon the class declarations, such an explicit type cast (a downcast) may or may not make sense

Note: constructor are not inherited, you have to call them

If not init is done in the derived class, the base class's default constructor will be used

Destructors are not inherited as well

When object is destroyed, the program first calls the derived destructor, then the base destructor

If you overload the assignment operator '=', it will not be inherited. The system will not allow doing so. Otherwise, it will be a big mess

Inheritance is good, but avoid using it TOO much.

Only use Inheritance when needed. Some people said OOD is an art and can be perfected by practice (read try, then success or fail ...) A good example is the MSVC++ version 1.0 ... almost every component is inherited.

If used correctly, Inheritance is the most powerful tool in C++




Employee.hpp (class definition)

Employee.cpp (class implementation)

Manager.hpp (class definition)

Manager.cpp (class implementation)

week7.cpp (source code main line)

week7.out (output)