You are on page 1of 90

Inheritance in C++

Lesson #6

Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL Program. The notes were subsequently revised by M. Deek.

Content
Base

and Derived Classes

Single

Inheritance
Declaration of derived classes
Order

of Constructor and Destructor Execution

Inherited

member accessibility
Multiple Inheritance
Virtual Base Classes
2

Base and Derived Classes


A

base class is a previously defined


class that is used to define new
classes

A derived class inherits all the data


and function members of a base class
(in addition to its explicitly declared
members.)

Single Inheritance
Implement

an is-a relationship
The derived class only has one base
class.

Example 1:
Student
name
id
major

Undergraduate
year
minor
etc.
5

Graduate
advisor
thesis
research
etc...

Example 2:
Publication:
publisher
date

Magazine:
# of issues per year
circulation

Book:
ISBN
author

Example:
Publication

#include FString.h"
class Publication {
public:
void SetPublisher( const FString & p )
{publisher.Assign(p);};
void SetDate( unsigned long dt )
{date = dt;};
FString GetPublisher(){return publisher;};
unsigned long GetDate(){return date;};
private:
FString publisher;
unsigned long date;
};

Publication
class Magazine :public Publication {
public:
void SetIssuesPerYear( unsigned n
){issuesPerYear=n;};
void SetCirculation( unsigned long n ){
circulation=n;};
unsigned GetIssuesPerYear(){return
issuesPerYear;};
unsigned long GetCirculation(){return circulation;};
private:
unsigned issuesPerYear;
unsigned long circulation;
};
8

class Book :public Publication {


public:
void SetISBN( const FString & s )
{ISBN.Assign(s);};
void SetAuthor( const FString & s )
{author.Assign(s);};
FString GetISBN()
{return ISBN;};
FString GetAuthor()
{return author;};
private:
FString ISBN;
FString author;
9 };

Publication

Publication

10

int main()
{Book B;
B.SetPublisher( "Prentice Hall" );
B.SetDate( 970101L );
B.SetISBN( "0-02-359852-2" );
B.SetAuthor( "Irvine, Kip" );
cout << B.GetPublisher()<<endl
<<B.GetDate()<<endl
<<B.GetISBN().CString()<<endl
<<B.GetAuthor().CString()<<endl;
Magazine M;
M.SetIssuesPerYear( 12 );
M.SetCirculation( 500000L );
cout << M.GetIssuesPerYear()<<endl
<<M.GetCirculation()<<endl;
return 0;
}//ex6pub(Fstring.h, fstring.cpp, ex6pub.cpp)

Different Views of an
Employee
Full-time

or part-time
Permanent or Temporary
How do you define its base class?
How td you define derived classes
based on this base class?

11

Declaring Derived Classes


Class class_name: access_specifieropt
or base_class { Member_list
}
access_specifier ::=
public|protected|private(default)
Equivalent to :
Subclass ::=<Id, SupeId, Ds, Ops, Intfc>
12

3D Point
class Point {
public:
Point();
Point( int xv, int yv );
void SetX( int xv );
void SetY( int yv );
private:
int x;
int y;
};

13

3D Point
class

Point3D :public Point {


public:
Point3D();
Point3D( int xv, int yv, int zv );
void SetZ( int zv );
private:
int z;
};
14

3D Point
Point3D::Point3D(
{

15

SetX( xv );

SetY( yv );

SetZ( zv );

int xv, int yv, int zv )

int main()
{
Point3D P;
P.SetX( 100 );
P.SetY( 200 );
P.SetZ( 300 );
return 0;
}

Order of Constructor and


Destructor Execution
Base

class constructors are always


executed first.
Destructors are executed in exactly
the reverse order of constructors
The following example, shows you the
ordering of constructors.
16

Class Employee{
Public:
Employee();
//
};
Class SalariedEmployee:public Employee{
Public:
SalariedEmployee();
//
};
Class ManagementEmployee:public SalariedEmployee{
Public:
ManagementEmployee();
//
};
ManagementEmployee M;

Example

17

Example
Point
Shape

1
1

Sphere

18

Coordinate

Point3D

19

#include <iostream.h>
class Coordinate {
public:
Coordinate() { cout << "Coordinate,"; }
~Coordinate() { cout << ~Coordinate,"; }
};
class Point {
public:
Point() { cout << "Point,"; }
~Point() { cout << ~Point,"; }
private:
Coordinate x;
Coordinate y;
};

Example

Example

20

class Point3D :public Point {


public:
Point3D() { cout << "Point3D,"; }
~Point3D() { cout << ~Point3D,"; }
private:
Coordinate z;
};
class Shape {
public:
Shape() { cout << "Shape,"; }
~Shape() { cout << ~Shape,"; }
};

class

21

Sphere :public Shape {


public:
Sphere() { cout << "Sphere"; }
~Sphere() { cout << "Sphere"; }
private:
Point3D center;
unsigned radius;
};
int main()
{ Sphere S;
Example
return 0;
}
//See Ex6-1.cpp

22

Overriding
A

function in the derived class with


the same function name will override
the functions variables in the base
class.
You can still retrieve the overridden
functions variables by using the scope
resolution operator ::.
23

24

#include <iostream.h>
#include <stdlib.h>
class A
{ int i;
public:
A(){i = 5;};
int get(){return i;};
};
class B: public A
{ int i;
public:
B(){i = 10;};
int get(){return i;};
};

Overriding
void main()
{

B b;
int x;

cout << b.get()<<endl;


cout << b.A::get()<<endl;
cout << sizeof(x)<<endl;

cout << sizeof(b)<<endl;


}//ex7overriding.cpp

Types of Class Members


private
protected
public

25

Types of Class Members


Public
Protected

Accessible to derived
classes and the
instances

Private

26

Derived
Class

not
accessible

Accessible
to derived
classes only

Types of Inheritance
public
private
protected

27

Public Inheritance
Public

and protected members of the


base class become respectively
public and protected members of the
derived class.

28

Public
Protected
Private
public
Public
Protected

Private

Functions(instances)
29

Class

#include

<iostream.h>
#include <assert.h>
class Item {
Item

int

Example

* ptr;

data;
public:
Item(){data = 0; ptr = NULL;};
Item(int i){data = i; ptr = NULL;
cout <<"Item::Item"<<i <<endl;
};
30

Example
void

setItem(int i){data = i;
cout <<"Item::setItem"<<i <<endl;
};
void setPtr(Item * i){ptr = i;
cout <<"Item::setPtr"<<endl;
};
int getData(){return data;};
Item * getPtr(){return ptr;};
};
31

class List {
Item * head, *first, *last;
public:
List(){
head = NULL;
first = head;
last = head;
}
Item * RemoveLast();
Item * RemoveFirst();
void PutFirst( Item * I );
void PutLast( Item * I );
protected:
int IsEmpty() const
{return (head==NULL);};
};

32

Example

33

Item * List::RemoveFirst()
{
Item * temp;
temp = first;
first = first -> getPtr();
cout <<"List:: RemoveFirst()"<<endl;
return temp;
};
Item * List::RemoveLast()
{
Item * temp;
temp = last;
last = last -> getPtr();
cout <<"List:: RemoveLast()"<<endl;
return temp;
};

Example

Example

34

void List::PutFirst(Item * I)
{
I->setPtr(first);
first = I;
cout <<"List::PutFirst"<<I->getData() <<endl;
};
void List::PutLast(Item * I)
{
I->setPtr(last);
first = I;
};

35

Example

class Stack :public List {


public:
void Push( Item * I );
Item * Pop();
};
void Stack::Push( Item * I )
{PutFirst( I );
cout <<"Stack::Push"<<I->getData() <<endl;
}
Item * Stack::Pop()
{cout <<"Stack::Pop()"<<endl;
return RemoveFirst();
}

Example

36

int main()
{Item anItem(50), *p;
Stack aStack;
aStack.Push( &anItem );
p = aStack.Pop();
cout <<"aStack.Pop"<< p->getData()<<endl<<endl;
anItem.setItem(100);
aStack.Push( &anItem );
p = aStack.RemoveFirst();
cout <<"aStack.RemoveFirst"<< p>getData()<<endl<<endl;
return 0;
}//ex6-2.cpp

37

38

Private Inheritance
Public

and protected members of the


base class become private members
of the derived class.

39

Public
Protected
Private
private
Public
Protected

Private

Function(instances)
40

Class

41

Example

class Queue :private List {


public:
void Enqueue( Item * I );
Item * Serve();
};
void Queue::Enqueue( Item * I )
{ List::PutFirst( I );
cout <<"Queue::Enqueue"<<I->getData() <<endl;
}
Item * Queue::Serve()
{cout <<"Queue::Serve"<<endl;
return List::RemoveFirst();
}

42

int main()
{Item anItem(50), *p;
Queue aQueue;
anItem.setItem(60);
aQueue.Enqueue(&anItem);
p = aQueue.Serve();
cout <<"aQueue.Serve"<< p>getData()<<endl<<endl;
anItem.setItem(600);
aQueue.Enqueue(&anItem);
p =aQueue.RemoveFirst(); //Unaccessible
//cout <<"aQueue.RemoveFirst"<< p>getData()<<endl;
return 0;
}//ex6-3.cpp

Example

43

Protected Inheritance
Public

and protected members of the


base class become protected
members of the derived class.

44

Public
Protected
Private
protected
Public
Protected

Private

Function(instances)
45

Class

46

Example

class Stack1 :protected List {


public:
void Push( Item * I );
Item * Pop();
};
void Stack1::Push( Item * I )
{PutFirst( I );
cout <<"Stack1::Push"<<I->getData() <<endl;
}
Item * Stack1::Pop()
{cout <<"Stack1::Pop()"<<endl;
return RemoveFirst();
}

47

Example

int main()
{Item anItem(50), *p;
Stack1 aStack1;
aStack1.Push( &anItem );
p = aStack1.Pop();
cout <<"aStack1.Pop"<< p->getData()<<endl<<endl;
anItem.setItem(100);
aStack1.Push( &anItem );
p = aStack1.RemoveFirst();//Unaccessible!
cout <<"aStack1.RemoveFirst"<< p->getData()
<<endl<<endl;
return 0;
}

48

The accessibility of inherited


members in a derived class
derived Public
member
Public
X

Protected Private

Protected X

Private

49

The accessibility of inherited


members for an instance
derived Public
member
Public
X
Protected
Private

50

Protected Private

Constructor- Initializers
Point3D::Point3D(param-list): ctorinitializer
{// function body
}
ctor-initializer is actually used to
transfer the parameters to the
constructors of the base-class
51

52

Publication

#include <iostream.h>
#include <string.h>
class Date
{
public:
Date( int mo, int dy, int yr )
{
month = mo; day = dy; year = yr;
cout << "Date constructor\n";
}
// Ex6pub2.cpp

Publication

Date( Date & D )


{

month = D.month; day = D.day; year = D.year;

cout << "Date copy constructor\n";


}
~Date() { cout << "Date destructor\n"; }
private:
int year;
int month;
int day;
};

53

54

class Publication
{
public:
Publication( char * publshr, Date & aDate )
: pubDate( aDate )
{
strcpy( publisher, publshr);
cout << "Publication constructor\n";
}
~Publication()
{ cout << "Publication destructor\n"; }
private:
char publisher[30];
Date pubDate;
};

Publication

55

Publication

class Magazine :public Publication


{public:
Magazine( char * publshr, Date & aDate,
int issues ): Publication( publshr, aDate )
{issPYear = issues;
cout << "Magazine constructor\n";
}
~Magazine() { "Magazine destructor\n"; }
private:
int issPYear; // issues per year
};
int main()
{ Magazine aMag( "Zipp", Date(10, 1, 95), 12 );
return 0;
}

56

Why use the


constructor-initializer?
Without

it, the default constructor for


the base class would be called, which
would then have to be followed by
calls to access functions to set
specific data members.
A constructor initailizer is therefore
more efficient.
57

Constructors in Derived
Classes
When

an object of a derived class is


created, the constructor of the object
must first explicitly call the constructor
of the base class.
This is the same as constructorinitializer.

58

Destructor Function
Destructors

are called implicitly


starting with the last derived class and
moving in the direction of the base
class.

59

Compatibility Between
Base and Derived Classes
An

object of a derived class can be


treated as an object of its base class.
The reverse is not true.

60

Nested Class Scope


A

public or protected base class


member that is hidden from the derived
class can be accessed using the scope
resolution operator ::
For example: base-class::member
The that of base class can not access
the members of its derived classes.
61

62

Class Parent {
public:
void Print() const;
//
}
class Child: public Parent {
public:
void Print() const{
Parent::print();// scope resolution !!!
cout <<age<<\n
<<school<<\n;
}
private;
int age;
Fstring school;
}

Example

Error
Void Parent::Print() {
cout<<name <<\n
<<Child::age <<\n;
//base can not access that of derived
}

63

Implicit Conversion of Derived


Pointers to Base Pointers
A

base type pointer can point to either


a base object or a derived object.
Point3D center;// Point3D is derived from Point
Point * p = &center;
Point3D *cp = new Point3D;
Point *p;
p = cp;

64

FString { };
Example
class Student {
public: //...
private:
long id;
};
class GraduateStudent :public Student {
public: //...
private:
FString thesisTitle;
};
class

65

Example
void

CalcTuition( Student & sp )


{ /* sp is a Student or a derived object */}
void RecordThesis( GraduateStudent * p )
{ /*... */ }
int main()
{Student * sp;
GraduateStudent * gp; //...
sp = gp; //...
RecordThesis( (GraduateStudent *) sp );
return 0;
}
66

Casting Base Pointers to


Derived Pointers
A

base pointer can not be implicitly


converted to a derived pointer.
This conversion is risky, because the
derived object can contain more than
the base object.

67

Example
void DoSomething(const GraduateStudent *
GS)
{ cout << GS->GetThesisTitle();}
Student * sp = new Student;
DoSomething(sp); //Error
DoSomething(GraduateStudent (sp));
Student * sp = new GraduateStudent;
DoSomething(GraduateStudent (sp));
68

Example

class Item {/* */}


class Student: public Item{/* */}
class Collection {
public:
void Append (const Item * ip);
Item * Get() const; }
const unsigned Count = 10;
Collection studentList;
Student * p;
for (int i=0; i<Count; i++ )
{p = new Student;
studentList.Append(p);}
p = (student*) studentList.Get();//explicit cast
69

Attention
Forcing class users to use explicit casting
often leads poor code.
class studentCollection:public Collection{
public:
student * Get() const
{ return (student *) Collection::Get(); }
//
}
studentCollection studentList;
student *p;
//
p = studentList.Get(); // no cast required

70

Multiple Inheritance
employee
Student
salaried

GraduateAssistant

71

72

#include <iostream.h>
#include "fstring.h"
typedef unsigned long ulong;
class Student {
public:
unsigned GetAge() const;
ulong GetId() const;
unsigned GetMajor() const;
void SetAge( unsigned n );
void SetId( ulong n );
void SetMajor( unsigned n );
private:
ulong id;
unsigned majorCode;
unsigned degreeCode;
float gpa;
unsigned age;
};

Example

73

class Employee {
public:
unsigned GetAge() const;
const FString & GetBenefits() const;
unsigned GetExemptions() const;
void SetAge( unsigned n );
void SetBenefits( const FString & benef );
void SetExemptions( unsigned n );
private:
unsigned age;
unsigned exemptions;
FString benefits;
};

Example

74

Example

class Salaried :public Employee {


public:
float GetSalary() const;
void SetSalary( float s );
private:
float salary;
};
class GradAssistant :public Student, public
Salaried {
public:
void Display() const;
};

75

void GradAssistant::Display() const


{ cout << GetId() << ','
<< GetMajor() << ','
<< GetSalary() << ','
<< GetExemptions() << endl;
}
int main()
{ GradAssistant GA;
GA.SetId(12345);
// GA.SetAge(22);
// error: ambiguous
GA.Student::SetAge(22); // ok - specific
GA.SetMajor(108);
GA.SetExemptions(2);
GA.SetSalary(10000);
GA.Display();
return 0;
}//ex6mulin.cpp

Example

76

77

78

Example

Question:
If we want to set a GradAssistant s
age by calling SetAge(), which
SetAge() should we use use?
1.

2.

79

Direct solution: Student::SetAge() or


Salaried::SetAge().
Abstract(Virtual) base classes

Virtual base classes


Person
employee
Student
salaried
Graduate Assistant
80

81

Example

#include <iostream.h>
#include "fstring.h"
typedef unsigned long ulong;
class Person {
public:
unsigned GetAge() const;
const FString & GetSocSecNum() const;
void SetAge( unsigned n );
void SetSocSecNum( const FString & ssn );
private:
unsigned age;
FString socSecNum;
};

Example

82

class Student :public virtual Person {


public:
unsigned GetMajor() const;
void SetMajor( unsigned n );
private:
unsigned majorCode;
unsigned degreeCode;
float gpa;
};

Example

83

class Employee :public virtual Person {


public:
const FString & GetBenefits() const;
unsigned GetExemptions() const;
void SetBenefits( const FString & benef );
void SetExemptions( unsigned n );
private:
unsigned exemptions;
FString benefits;
};

84

Example

class Salaried :public Employee {


public:
float GetSalary() const;
void SetSalary( float s );
private:
float salary;
};
class GradAssistant :public Student, public
Salaried {
public:
void Display() const;
};

Example
void GradAssistant::Display() const
{ cout << GetSocSecNum() << ','
<< GetAge() << ',
// ambiguous if not virtual
}
int main()
{ GradAssistant GA;
return 0;
}
85

86

Virtual Base Classes


The

function calls in

GradAssistant::Display() are ambiguous


unless Person is inherited as a virtual base
class.
Adding

virtual lets the compiler


decide which function and which
variable should be accessed.

87

Virtual Base Classes


Person(22)
Employee(22)
Student(8)
Salaried(4)
GraduateAssistant(0)

aGA(78)
88

Virtual Base Classes(end)


Person(22)
virtual

virtual

Employee(22)
Student(8)
Salaried(4)
GraduateAssistant(0)

aGA(56)
89

Readings
Readings
Chapter

90

6 Sections 6.1.3 6.5