References for
Unit 4 these slides
Liang, Y.
Inheritanc
Daniel. Introduction
to Programming
with C++. Pearson
e and
Education India,
2011.
Gaddis, Tony, and
Polymorph Piyali Sengupta.
Starting out with C+
C++
+: from control
ism structures through
objects. Pearson,
2012.
Tamer A Ali
1
Contents
2
Introduction
3
What Is Inheritance?
Provides a way to create a new class from
an existing class
The new class is a specialized version of
the existing class
4
Example: Insects
5
The "is a" Relationship
Inheritanceestablishes an "is a"
relationship between classes.
– A car is a vehicle
– A flower is a plant
– A student is a person
6
Inheritance – Terminology and
Notation
Base class (or parent) – inherited from
Derived class (or child) – inherits from the base class
Notation: // base class
class Insect
{
. . .
};
// derived class
class Grasshopper : Insect
{
. . .
};
7
Inheritance – Terminology and
Notation
8
Ex: geom.getColor();
Inheritance Example
a Circle is a class Rectangle : GeometricObject
GeometricObjec
t
Ex: circle1.getColor();
Ex: circle1.getArea();
9
Inheritance
10
Three pillars of object-oriented
programming
Encapsulation
Inheritance
Polymorphism
11
#ifndef GEOMETRICOBJECT_H GeometricObject.h
#define GEOMETRICOBJECT_H
#include <string>
using namespace std;
class GeometricObject
{
public:
GeometricObject();
GeometricObject(const string& color, bool filled);
string getColor() const;
void setColor(const string& color);
bool isFilled() const;
void setFilled(bool filled);
string toString() const;
private:
string color;
bool filled;
}; // Must place semicolon here
#endif 12
#include "GeometricObject.h"
GeometricObject.cpp
GeometricObject::GeometricObject()
{
setColor("white");
setFilled(false);
}
GeometricObject::GeometricObject(const string& color, bool filled)
{
setColor(color);
setFilled(filled);
}
string GeometricObject::getColor() const
{
return color;
}
string GeometricObject::toString() const
{
return "Geometric Object";
}
… 13
#ifndef CIRCLE_H Circle.h
#define CIRCLE_H
#include "GeometricObject.h"
class Circle: public GeometricObject
{
public:
Circle();
Circle(double);
Circle(double radius, const string& color, bool filled);
double getRadius() const;
void setRadius(double);
double getArea() const;
double getPerimeter() const;
double getDiameter() const;
string toString() const;
private:
double radius;
}; // Must place semicolon here
#endif 14
#include "DerivedCircle.h"
Circle.cpp
// Construct a default circle object
Circle::Circle()
{
setRadius(1);
}
// Construct a circle object with specified radius
Circle::Circle(double r)
{
setRadius(r);
}
// Construct a circle object with specified radius,
// color and filled values
Circle::Circle(double r, const string& color, bool filled)
{
setRadius(r);
setColor(color); // color is inaccessible but setColor is
setFilled(filled);
} 15
Generic Programming
An object of a derived class can be used wherever an object of its base
class is required: generic programming.
void displayColor(const GeometricObject& geom)
{
cout << geom.getColor();//getColor defined in
base
}
int main()
{
Circle c1;
displayColor(c1);
return 0;
} 16
Calling Base Class Constructors
Constructors of a base class are NOT inherited in the
derived class.
They can only be invoked (explicitly or implicitly) from the
constructors of the derived classes.
DerivedClass(parameterList): BaseClass()
{
// Perform initialization
}
Or
DerivedClass(parameterList): BaseClass(argumentList)
{
// Perform initialization
}
17
Calling No-arg Base Class
Constructor
Circle::Circle( Circle::Circle() :
) Equivalent to GeometricObject()
{ {
radius = 1; radius = 1;
} }
Circle::Circle(double
Circle::Circle(double radius)
Equivalent to
radius) : GeometricObject()
{ {
this->radius = radius; this->radius =
} radius;
}
18
Constructors and Destructors
in Base and Child Classes
Child classes can have their own
constructors and destructors
When an object of a derived class is
created, the base class’s constructor is
executed first, followed by the derived
class’s constructor
When an object of a derived class is
destroyed, its destructor is called first, then
that of the base class
19
Constructor Chaining
Person()
Employee() {
Faculty() { // Person's
{ // Employee's tasks;
// Faculty's tasks; }
tasks; }
}
Destructor Chaining
~Person()
~Employee() {
~Faculty() { // Person's
{ // Employee's tasks;
// Faculty's tasks; }
tasks; }
}
20
class BaseClass
{
public:
BaseClass() // Constructor
{
cout << "This is the BaseClass constructor.\n";
}
~BaseClass() // Destructor
{
cout << "This is the BaseClass destructor.\n";
}
};
class DerivedClass : public BaseClass
{
public:
DerivedClass() // Constructor
{
cout << "This is the DerivedClass constructor.\n";
}
~DerivedClass() // Destructor
{
cout << "This is the DerivedClass destructor.\n";
}
};
21
int main()
{
cout << "We will now define a DerivedClass object.\n";
DerivedClass object;
cout << "The program is now going to end.\n";
return 0;
}
We will now define a DerivedClass object.
This is the BaseClass constructor.
This is the DerivedClass constructor.
The program is now going to end.
This is the DerivedClass destructor.
This is the BaseClass destructor.
22
no-arg constructor
If a class is to be extended, provide a no-arg
constructor
class Fruit
{
public:
Fruit(int id) { }
};
class Apple : public Fruit
{
public:
Apple() { } 'Fruit': no appropriate default
}; constructor available
23
#include "DerivedCircle.h"
Circle.cpp
// Construct a default circle object
Circle::Circle()
{
setRadius(1);
}
// Construct a circle object with specified radius
Circle::Circle(double r)
{
setRadius(r);
}
// Construct a circle object with specified radius,
// color and filled values
Circle::Circle(double r, const string& color, bool filled)
{
setRadius(r);
setColor(color); // color is inaccessible but setColor is
setFilled(filled);
} 24
#include "DerivedCircle.h"
Circle.cpp
// Construct a default circle object
Circle::Circle()
{
setRadius(1);
}
// Construct a circle object with specified radius
Circle::Circle(double r)
{
setRadius(r);
}
// Construct a circle object with specified radius,
// color and filled values
Circle::Circle(double r, const string& color, bool filled)
: GeometricObject(color, filled)
{
setRadius(r);
}
… 25
#include "DerivedCircle.h"
Circle.cpp
// Construct a default circle object
Circle::Circle() : Circle(1) // C++11 and after
{
// Construct a circle object with specified radius
Circle::Circle(double r)
{
setRadius(r);
}
// Construct a circle object with specified radius,
// color and filled values
Circle::Circle(double r, const string& color, bool filled)
: GeometricObject(color, filled)
{
setRadius(r);
}
… 26
#include "DerivedCircle.h"
Circle.cpp
// Construct a default circle object
Circle::Circle() : Circle(1) // C++11 and after
{
// Construct a circle object with specified radius
Circle::Circle(double r) : GeometricObject() // default
{
setRadius(r);
}
// Construct a circle object with specified radius,
// color and filled values
Circle::Circle(double r, const string& color, bool filled)
: GeometricObject(color, filled)
{
setRadius(r);
}
27
#include "DerivedCircle.h"
Circle.cpp
// Construct a default circle object
Circle::Circle() : Circle(1) // C++11 and after
{
// Construct a circle object with specified radius
Circle::Circle(double r) : GeometricObject() // default
{
setRadius(r);
}
// Construct a circle object with specified radius,
// color and filled values
Circle::Circle(double r, const string& color, bool
Not using
filled)
setRadiu
: GeometricObject(color, filled), radius(r) s
{
} 28
Passing Arguments to
Base Class Constructor
Allows selection between multiple base constructors
Specify arguments to base constructor on derived
constructor heading:
Square::Square(int side) :
Rectangle(side, side)
Can be done with inline constructors
Must be done if base has no default constructor
class Fruit class Apple : public Fruit
{ {
public: public:
Fruit(int id) { } Apple() {
: }
Fruit(1)
}; };}
{
};
29
Access Modifiers (Data Hiding)
How a base controls inheritance
There are three types of access modifiers:
– public
private:
– private double radius;
Not accessible by objects of derived class
– protected
like private, but accessible
protected: by objects of
derived class double radius;
30
Class Access Specifiers
How a derived class controls inheritance
class UnderGrad : public Student
{ ...
1) public: object of derived class can be
treated as object of base (not vice-versa)
2) protected – allows derived class to know
details of base but prevents objects of derived
Default
class from being treated as objects of base
classes
3) private – prevents objects of derived class
from being treated as objects of base classes.
31
Inheritance vs. Access
How base class
Base Class members appear in
members the derived class
class UnderGrad :
UnderGrad
Student
private: pv_x public Student pv_x NoAccess
protected: pt_x protected: pt_x
public: pb_x public: pb_x
class UnderGrad :
UnderGrad
Student
private: pv_x protected Student pv_x NoAccess
protected: pt_x protected: pt_x
public: pb_x protected: pb_x
class UnderGrad :
UnderGrad
private Student
Student
private: pv_x pv_x NoAccess
protected: pt_x private: pt_x
public: pb_x private: pb_x
32
Inheritance vs. Access
class Grade class Test : public Grade
private members: private members:
char letter; int numQuestions;
float score; float pointsEach;
void calcGrade(); int numMissed;
public members: public members:
void setScore(float); Test(int, int);
float getScore();
char getLetter();
private members:
int numQuestions:
When Test class inherits float pointsEach;
from Grade class using int numMissed;
public class access, it public members:
Test(int, int);
looks like this: void setScore(float);
float getScore();
char getLetter();
33
Inheritance vs. Access
class Grade class Test : protected
private members: Grade
private members:
char letter; int numQuestions;
float score; float pointsEach;
void calcGrade(); int numMissed;
public members: public members:
void setScore(float); Test(int, int);
float getScore();
char getLetter();
private members:
int numQuestions:
When Test class inherits float pointsEach;
from Grade class using int numMissed;
protected class access, it public members:
Test(int, int);
looks like this: protected members:
void setScore(float);
float getScore();
char getLetter();
34
Inheritance vs. Access
class Grade class Test : private Grade
private members: private members:
char letter; int numQuestions;
float score; float pointsEach;
void calcGrade(); int numMissed;
public members: public members:
void setScore(float); Test(int, int);
float getScore();
char getLetter();
private members:
int numQuestions:
When Test class inherits float pointsEach;
from Grade class using int numMissed;
private class access, it void setScore(float);
float getScore();
looks like this: char getLetter();
public members:
Test(int, int);
35
Inheritance vs. Access
protected and private inheritance are
not an is-a relationship
36
Redefining Base Class
Functions
Redefining function: function in a derived class
that has the same name and parameter list as a
function in the base class
Not the same as overloading – with overloading,
parameter lists must be different.
Base class objects use base class version;
derived class objects use derived class version
37
Invoke redefined function
geom.toString()
Redefinition, Not
circle1.toString() Overloading
MyRectangle.toString()
If you wish to invoke the toString function
defined in the GeometricObject class on the
calling object circle1:
circle1.GeometricObject::toString
()
Scope resolution operator
38
Class Hierarchies
39
Problem with Redefining
class GeomObj class Circle : public
{ GeomObj
public: {
string toString() public: Redefinition
{ string toString()
{
return "GeomObj";
return "Circle";
}
}
}; };
int main() void dispType(GeomObj&
{ geo)
GeomObj parent; {
dispType(parent); cout << geo.toString();
cout << endl;
Circle child; } Function calls are
Not what you wanted! bound at compile time.
dispType(child);
GeomObj This is static binding
}
GeomObj 40
Polymorphism and
Virtual Member
Functions
41
Three pillars of object-oriented
programming
Encapsulation
Inheritance
Polymorphism
Polymorphism
An object of base class can refer to an object
of a derived class.
42
Virtual Member Functions
Function in base class and is expected be
redefined in derived class
Defined in base class with key word virtual:
virtual void Y() {...}
A virtual function is dynamically bound to calls
at runtime.
– At runtime, C++ determines the type of
object making the call, and binds the function
to the appropriate version of the function.
43
Virtual Member Functions
class GeomObj Becomes virtual in class Circle : public
{ all derived classes GeomObj
public: {
virtual string toString() public: Overriding
{ string toString()
return "GeomObj"; {
} return "Circle";
}; }
};
int main() void dispType(GeomObj&
{ geo)
GeomObj parent; {
dispType(parent); cout << geo.toString();
cout << endl;
Circle child; }
Yaaay!! Function calls are bound
dispType(child); at run time.
}
GeomObj This is dynamic binding
Circle 44
Polymorphism and
Virtual Member
Functions
This type of behavior is known as
polymorphism: the ability to take many
forms.
Polymorphic behavior is only possible
when an object is referenced by a
reference variable or a pointer
void dispType(GeomObj& geo)
void dispType(GeomObj* geo)
45
Virtual Member Functions
int main() void dispType(GeomObj&
{ geo)
GeomObj parent; {
dispType(parent); cout << geo.toString();
Circle child; cout << endl;
dispType(child); }
}
int main() void dispType(GeomObj*
{ geo)
GeomObj parent; {
dispType(&parent); cout << geo-
Circle child; >toString();
dispType(&child); cout << endl;
} }
46
Virtual Member Functions
int main() void dispType(GeomObj&
{ geo)
GeomObj parent; {
dispType(parent); cout << geo.toString();
Circle child; cout << endl;
dispType(child); }
}
int main() void dispType(GeomObj*
{ geo)
GeomObj* ptr_parent= new {
GeomObj; cout << geo-
dispType(ptr_parent); >toString();
Circle* ptr_child = new Circle; cout << endl;
dispType(ptr_child); }
}
47
Use virtual functions?
If a function will not be redefined, it is
more efficient without declaring it virtual,
because it takes more time and system
resource to bind virtual functions
dynamically at runtime.
48
Base Class Pointers
Pointersto a base class may be
assigned the address of a derived class
object.
GeometricObject* ptrGeomObj1 = new Circle;
GeometricObject* ptrGeomObj2 = new
Rectangle(3,4); Member of the
base class
cout << ptrGeomObj1->getColor();
cout << ptrGeomObj1->getDiameter();
Member of the
derived class
49
Example
int main()
{
// An array of POINTERS of the base type
GeometricObject* geometricObjectList[4];
geometricObjectList[0] = new Rectangle(3,4);
geometricObjectList[1] = new Square(5);
geometricObjectList[2] = new Triangle;
geometricObjectList[3] = new Circle;
Member of the
for (int i = 0; i < 3; i++)
base class
{
cout << geometricObjectList[i]-
>getColor();
cout << endl;
cout << geometricObjectList[i]->getArea();
cout << endl;
Works as expected if defined on the base class as a
} virtual member, not just redefined in the derived classes
} 50
Example
int main()
{
// An array of POINTERS of the base type
GeometricObject* geometricObjectList[] = {
new Rectangle(3,4),
new Square(5),
new Triangle,
new Circle
};
Member of the
for (int i = 0; i < 3; i++)
base class
{
cout << geometricObjectList[i]-
>getColor();
cout << endl;
cout << geometricObjectList[i]->getArea();
cout << endl;
Works as expected if defined on the base class as a
} virtual member, not just redefined in the derived classes
} 51
Base Class Pointers
You cannot assign the address of a
GeometricObject object to a Circle
pointer.
Because Circle objects have capabilities
that go beyond those of a
GeometricObject object.
Circle* circle1 = new Circle;
GeometricObject* geometricObject1 = circle1; //
Works
GeometricObject* geometricObject2 = new
GeometricObject;
52
Virtual Destructors
Recommendation: Make destructors
virtual if the class could ever be used
as a base class.
53
Virtual Destructors
class Animal // Base class Dog : public Animal //
{ Derived
public: {
Animal() // Constructor public:
{ Dog() : Animal() // Constructor
cout << "Animal constructor\ {
cout << "Dog constructor\n";
n";
}
}
~Dog() // Destructor
~Animal() // Destructor {
{ cout << "Dog destructor\n";
cout << "Animal destructor\ }
n"; };
}
}; main()
int
{ Animal constructor
Animal* myPet = new Dog; executing.
delete myPet;
Dog constructor executing.
return 0;
Animal destructor executing.
}
54
Virtual Destructors
class Animal // Base class Dog : public Animal //
{ Derived
public: {
Animal() // Constructor public:
{ Dog() : Animal() // Constructor
cout << "Animal constructor\ {
cout << "Dog constructor\n";
n";
}
}
~Dog() // Destructor
virtual ~Animal() // {
Destructor cout << "Dog destructor\n";
{ }
cout << "Animal destructor\ };
n";
} main()
int
};
{ Animal constructor
Animal* myPet = new Dog; executing.
delete myPet; Dog constructor executing.
return 0; Dog destructor executing.
} Animal destructor executing.
55
C++ 11's override and
final Key Words
C++ 11 introduces the override and final key
words to help prevent subtle errors when
overriding virtual functions (enforce compile-time
errors).
The override key word tells the compiler that
the function is supposed to override a function in
the base class.
When a member function is declared with the
final key word, it cannot be overridden in a
derived class.
56
Abstract Base
Classes and Pure
Virtual Functions
57
Abstract Base Classes and
Pure Virtual Functions
Abstract base class:
can have no objects
servesas a basis for derived classes that
may/will have objects
To be an Abstract class, one or more of its
member functions should be a pure virtual
function
58
Abstract Base Classes and
Pure Virtual Functions
Pure virtual function:
A virtual member function that must be
overridden in a derived class that has
objects
virtual void Y() = 0;
The “= 0” indicates a pure virtual function
Must have no function definition in the
base class
59
Abstract Base Classes and
Pure Virtual Functions
class GeometricObject
{
protected:
GeometricObject();
GeometricObject(const string& color, bool filled);
public:
string getColor() const;
void setColor(const string& color);
bool isFilled() const;
void setFilled(bool filled);
string toString() const;
virtual double getArea() const = 0;
virtual double getPerimeter() const = 0;
private:
string color;
bool filled;
}; // Must place semicolon here
60
Abstract Base Classes and
Pure Virtual Functions
61
Multiple
Inheritance
62
Multiple Inheritance
A derived class can have more than one base class
Each base class can have its own access
specification in derived class's definition:
class Cube : public Square,
public RectSolid;
class class
square rectSolid
class
cube
63
Multiple Inheritance
Arguments can be passed to both base
classes' constructors:
Cube::Cube(int side) :
Square(side),
RectSolid(side, side,
side)
Base class constructors are called in
order given in class declaration, not in
order used in class constructor
64
Multiple Inheritance
Problem: what if base classes have member
variables/functions with the same name?
Solutions:
– Derived class redefines the multiply-defined function
– Derived class invokes member function in a particular
base class using scope resolution operator ::
Compiler errors occur if derived class uses base
class function without one of these solutions
65