Sie sind auf Seite 1von 58

Object Oriented Programming

(CS2133)
By

Dr. Muhammad Azhar Iqbal

Department of Computer Science,


Mohammad Ali Jinnah University, Islamabad
Fall Semester, 2013
Inheritance and Polymorphism
Objectives

 To develop derived classes from a base class through inheritan


ce
 To understand constructor and destructor chaining
 To know how to invoke the base class’s constructors
 To distinguish between overriding and overloading
 To understand polymorphism and dynamic binding using virtu
al functions
 To distinguish between static binding and dynamic binding
 To access protected members of the base class from derived cl
asses
 To declare abstract classes that contains pure virtual functions
 To cast an object of a base class type to a derived type using th
e dynamic_cast operator
Base Classes and Derived Classes
GeometricObject
-color: string The color of the object (default: white).
-filled: bool Indicates whether the object is filled with a color (default: false).
+GeometricObject() Creates a GeometricObject.
+GeometricObject(color: string, Creates a GeometricObject with the specified color and filled
filled: bool) values.
+getColor(): string Returns the color.
+setColor(color: string): void Sets a new color.
+isFilled(): bool Returns the filled property.
+setFilled(filled: bool): void Sets a new filled property.
+toString(): string Returns a string representation of this object.

Circle Rectangle
-radius: double -width: double
+Circle() -height: double
+Circle(radius: double) +Rectangle()
+Circle(radius: double, color: string, +Rectangle(width: double, height: double)
filled: bool) +Rectangle(width: double, height: double,
+getRadius(): double color: string, filled: bool)
+setRadius(radius: double): void +getWidth(): double
+getArea(): double +setWidth(width: double): void
+getPerimeter(): double +getHeight(): double
+getDiameter(): double +setHeight(height: double): void
+getArea(): double
+getPerimeter(): double
Base Classes and Derived Classes - Example

class GeometricObject GeometricObject::GeometricObject()


{ { color = "white"; filled = false; }
public:
GeometricObject(); GeometricObject::GeometricObject(string color, bool filled)
GeometricObject(string color, bool filled); { this->color = color; this->filled = filled; }
string getColor();
void setColor(string color); string GeometricObject::getColor()
bool isFilled(); { return color; }
void setFilled(bool filled);
string toString(); void GeometricObject::setColor(string color)
{ this->color = color; }
private: bool GeometricObject::isFilled()
string color; { return filled; }
bool filled;
}; void GeometricObject::setFilled(bool filled)
{ this->filled = filled; }
string GeometricObject::toString()
{ return "Geometric object color " + color +
" filled " + ((filled) ? "true" : "false");
}
Base Classes and Derived Classes - Example

class Circle: public GeometricObject Circle::Circle() { radius = 1; }


{
public: Circle::Circle(double radius)
{ this->radius = radius; }
Circle();
Circle(double); double Circle::getRadius()
Circle(double radius, string color, bool filled); { return radius; }
double getRadius();
void setRadius(double); void Circle::setRadius(double radius)
double getArea(); { this->radius = (radius >= 0) ? radius : 0;
double getPerimeter(); }
double getDiameter(); double Circle::getArea()
{ return radius * radius * 3.14159; }
private:
double radius; double Circle::getPerimeter()
}; { return 2 * radius * 3.14159; }
double Circle::getDiameter()
{ return 2 * radius; }
Base Classes and Derived Classes - Example
class Rectangle: public GeometricObject Rectangle::Rectangle()
{ { width = 1; height = 1; }
public: Rectangle::Rectangle(double width, double height)
Rectangle(); { this->width = width; this->height = height; }
Rectangle(double width, double height);
double getWidth(); double Rectangle::getWidth()
void setWidth(double); { return width; }
double getHeight();
void setHeight(double); void Rectangle::setWidth(double width)
double getArea(); { this->width = (width >= 0) ? width : 0; }
double getPerimeter();
double Rectangle::getHeight()
private: { return height; }
double width;
double height; void Rectangle::setHeight(double height)
}; { this->height = (height >= 0) ? height : 0; }
double Rectangle::getArea()
{ return width * height; }
double Rectangle::getPerimeter()
{ return 2 * (width + height); }
Inheritance – Introduction

 Perhaps the most powerful feature of OOP

 Concept similar to inheritance in real life

 New classes are created from existing classes

 New classes absorb all features of existing classes i


ncluding their data and functions. Also enhance the
m by adding their own new features in form of new
data members and new member functions
Inheritance – Terminology

 Existing classes are called base classes


 New classes are called derived classes
 Objects of derived classes are more specialized as c
ompared to objects of their base classes

 Inheritance provides us a mechanism of software r


eusability which is one of the most important princi
ples of software engineering
Inheritance Limitations in C++

 Alldata members (but not private) and mem


ber functions of base class are inherited to de
rived class

 Constructors, destructors and = operator are


not inherited
Base Classes and Derived Classes

 A class can be derived from one or more than one classes, w


hich means it can inherit data and functions from single as w
ell as from multiple base classes.

Syntax
 To define a derived class, we use a class derivation list to spe
cify the base class(es). A class derivation list names one or m
ore base classes and has the form:
class derived-class: access-specifier base-class
 Where access-specifier is one of public, protected, or private,
and base-class is the name of a previously defined class. If th
e access-specifier is not used, then it is private by default.
Constructor and Destructor Chaining

 A base class constructor is called before the derived class con


structor.

 Constructing an instance of a class invokes the constructors


of all the base classes along the inheritance chain.

 Conversely, the destructors are automatically invoked in rev


erse order, with the derived class’s destructor invoked first.

 This is called constructor and destructor chaining.


Constructing and Destructor Chaining - Example
class Person {
public:
Person() void main()
{ cout << "Person's constructor \n" ; }
~Person() {
{ cout << "Person's destructor \n" ; } Faculty faculty;
}; }
class Employee: public Person{
public:
Employee()
{ cout << "Employee's constructor \n" ; }
~Employee()
{ cout << "Employee's destructor \n " ; }
};
class Faculty: public Employee{
public:
Faculty()
{ cout << "Faculty's constructor \n "; }
~Faculty()
{ cout << "Faculty's destructor \n"; }
};
no-arg constructor
If a class is designed to be extended, it is better to provide a no-arg
constructor to avoid programming errors.

class Fruit
{
public:
Fruit(int id)
{ }
};
class Apple: public Fruit
{
public:
Apple()
{ }
};
Calling Base Class Constructors

A constructor is used to construct an instance of a class. Unlike


data fields and functions, the constructors of a base class are not
inherited in the derived class. Base class constructors can only be
invoked from the constructors of the derived classes to initialize the
data fields in the base class. The syntax to invoke it is as follows:

DerivedClass(parameterList): BaseClass()
{ // Perform initialization }
Or
DerivedClass(parameterList): BaseClass(argumentList)
{ // Perform initialization }
Or
DerivedClass(optionalargumentList)
{
BaseClass::BaseClass(optionalargument);
}
No-Arg Constructor in Base Class

A constructor in a derived class must always invoke a constructor in


its base class. If a base constructor is not invoked explicitly, the base
class’s no-arg constructor is invoked by default. For example,

public Circle() public Circle(): GeometricObject()


{ is equivalent to {
radius = 1; radius = 1;
} }

public Circle(double radius) public Circle(double radius)


{ is equivalent to : GeometricObject()
this->radius = radius; {
this->radius = radius;
} }
The protected Keyword

 So far you have used the private and public


keywords to specify whether data fields and
functions can be accessed from the outside of the
class. Private members can only be accessed from
the inside of the class and public members can be
accessed from any other classes.

 A protected data field or a protected function in a


base class can be accessed by name in its derived
classes.
The protected Keyword

 The protected keyword is a member access modifier. A


protected member is accessible from within the class in
which it is declared, and from within any class derived
from the class that declared this member.

 A protected member of a base class is accessible in a


derived class only if the access takes place through the
derived class type.
Find Errors

class Base{ void main()


protected: int y; {
private: int x; Derived d;
public: int z; cout<<d.x;
Base( ) cout<<d.y;
{ x = 0; y = 0; z = 0; } cout<<d.z;
}; }
class Derived: public Base{
public:
void showX(){ cout<<"x = "<<x; }
void showY(){ cout<<"y = "<<y; }
void showZ(){ cout<<"z = "<<z; }
};
Protected keyword - Example
class B
{
public: int i;
protected: int j;
private: int k;
};
class A:public B{
public:
void display(){
cout<<i<<endl;
cout<<j<<endl;
// cout<<k<<endl;
}
};
void main(){
A a;
cout<<a.i<<endl;
// cout<<a.j<<endl;
// cout<<a.k<<endl;
}
}
Types of Inheritance specified by Access Specifiers
 public, protected, and private Inheritance
 While using different type of inheritance, following rules are applied:

 Public Inheritance: When deriving a class from a public base class, public
members of the base class become public members of the derived class an
d protected members of the base class become protected members of the
derived class. A base class's private members are never accessible directly fr
om a derived class, but can be accessed through calls to the public and prot
ected members of the base class.

 Protected Inheritance: When deriving from a protected base class, public


and protected members of the base class become protected members of th
e derived class.

 Private Inheritance: When deriving from a private base class, public and p
rotected members of the base class become private members of the derive
d class.
Types of Inheritance specified by Access Specifier
class A {
public: int x;
protected: int y; Public, Private, and
private: int z;
}; Protected Inheritance
class B : public A
{
// x remains public and accessible here
// y remains protected and accessible here
// z remains private and is not accessible here
};
class C : protected A
{
// x becomes protected and accessible here
// y remains protected and accessible here
// z remains private and is not accessible here
};
class D : private A
{
// x becomes private, accessible here but not in subclasses of class D
// y becomes private, accessible here but not in subclasses of class D
// z remains private and is not accessible here
};
Public, Private, Protected Inheritance – Example
class A {
public: int x;
protected: int y;
private: int z;
};
class B : public A{
void display(){ cout<<"x="<<x<<endl; cout<<"y="<<y<<endl;
cout<<"z="<<z<<endl; }
};
class C : protected A{
void display(){ cout<<"x="<<x<<endl; cout<<"y="<<y<<endl;
cout<<"z="<<z<<endl; }
};
class D : private A{
void display(){ cout<<"x="<<x<<endl; cout<<"y="<<y<<endl;
cout<<"z="<<z<<endl; }
};
class E : public D{
void display(){
cout<<"x="<<x<<endl; cout<<"y="<<y<<endl; cout<<"z="<<z<<endl;
}
};
Function Overloading and Function Overriding

 Overloading a function is a way to provide more


than one function with the same name but with
different signatures to distinguish them.

 In function overriding (redefine a function), the f


unction must be defined in the derived class usi
ng the same signature and same return type as i
n its base class.
Virtual Functions
 A virtual function is a member function that you expect
to be redefined in derived classes. When you refer to a d
erived class object using a pointer or a reference to the
base class, you can call a virtual function for that object
and execute the derived class's version of the function.

 Virtual functions ensure that the correct function is called


for an object, regardless of the expression used to make t
he function call

 The keyword virtual tells compiler that it should not perfo


rm early binding
Function Overriding and Polymorphism
 In C++, redefining a virtual function in a derived class is c
alled overriding a function.

 Polymorphism is a mechanism that allows you to implem


ent a function in different ways

 One of the key features of derived classes is that a pointer


to a derived class is type-compatible with a pointer to its b
ase class. Polymorphism is the art of taking advantage of t
his simple but powerful and versatile feature, that brings O
bject Oriented Methodologies to its full potential.
Example
class Base{
public: void main()
void show() {
{ cout<<"Base\n"; } Base b;
};
Derv1 d1;
class Derv1:public Base{ Derv2 d2;
public:
void show() b.show();
{ cout<<"derv1\n"; } d1.show();
}; d2.show();
class Derv2:public Base{ b = d1;
public: b.show();
void show()
{ cout<<"derv2\n"; }
}; b = d2;
b.show();
}
Need for Polymorphism - Example
class Base{
public: void main()
void show() {
{ cout<<"Base\n"; } Base *ptr;
}; Derv1 d1;
Derv2 d2;
class Derv1:public Base{
public: ptr = &d1;
void show() ptr->show();
{ cout<<"derv1\n"; } ptr = &d2;
}; ptr->show();
}
class Derv2:public Base{
public:
void show()
{ cout<<"derv2\n"; }
};
Need for Polymorphism - Example
class Base{
public: void main()
virtual void show() {
{ cout<<"Base\n"; } Base *ptr;
}; Derv1 d1;
Derv2 d2;
class Derv1:public Base{
public: ptr = &d1;
void show() ptr->show();
{ cout<<"derv1\n"; } ptr = &d2;
}; ptr->show();
}
class Derv2:public Base{
public:
void show()
{ cout<<"derv2\n"; }
};
Need for Polymorphism - Example
class C void displayObject(C x)
{ {
public: cout << x.toString()<<endl;
string toString() }
{ return "class C"; }
}; int main()
{
class B: public C displayObject(A());
{ public: displayObject(B());
string toString() displayObject(C());
{ return "class B"; } return 0;
}; }
class A: public B
{ public:
string toString()
{ return "class A"; }
};
Need for Polymorphism - Example
class C void displayObject(C *p)
{ {
public: cout << p->toString()<<endl;
virtual string toString() }
{ return "class C"; }
}; int main()
class B: public C {
{ A a;
public: B b;
string toString() C c;
{ return "class B"; }
}; displayObject(&a);
class A: public B displayObject(&b);
{ displayObject(&c);
public:
string toString() return 0;
{ return "class A"; } }
};
Need for Polymorphism - Example
class C void displayObject(C *p)
{ {
public: cout << p->toString()<<endl;
virtual string toString() }
{ return "class C"; }
}; int main()
class B: public C {
{ A a = A();
public: B b = B();
string toString() C c = C();
{ return "class B"; }
}; displayObject(&a);
class A: public B displayObject(&b);
{ displayObject(&c);
public: return 0;
string toString() }
{ return "class A"; }
};
Need for Polymorphism - Example
class C void displayObject(C *p)
{ {
public: cout << p->toString()<<endl;
virtual string toString() }
{ return "class C"; }
}; int main()
class B: public C {
{ A *a = new A();
public: B *b = new B();
string toString() C *c = new C();
{ return "class B"; }
}; displayObject(a);
class A: public B displayObject(b);
{ displayObject(c);
public: return 0;
string toString() }
{ return "class A"; }
};
Need for Polymorphism - Example
class C void displayObject(C *p)
{ {
public: cout << p->toString()<<endl;
virtual string toString() }
{ return "class C"; }
}; int main()
class B: public C {
{ // A *a = new C();
public: B *b = new B();
string toString() C *c = new C();
{ return "class B"; }
}; // displayObject(a);
class A: public B displayObject(b);
{ displayObject(c);
public: return 0;
string toString() }
{ return "class A"; }
};
Need for Polymorphism - Example
class C void displayObject(C *p)
{ {
public: cout << p->toString()<<endl;
virtual string toString() }
{ return "class C"; }
}; int main()
class B: public C {
{ A *a = new A();
public: B *b = new B();
string toString() C *c = new A(); //
{ return "class B"; }
}; displayObject(a);
class A: public B displayObject(b);
{ displayObject(c);
public: return 0;
string toString() }
{ return "class A"; }
};
Define Virtual Functions – Enable Dynamic Binding

To enable dynamic binding for a function, you need to do t


wo things:

 The function must be declared virtual in the base class.

The variable that references the object for the function


must contain the address of the object.
Note:
If a function is defined virtual in a base class, it is a
utomatically virtual in all its derived classes. It is no
t necessary to add the keyword virtual in the functi
on declaration in the derived class.
static matching vs. dynamic binding

 Matching a function signature and binding a function


implementation are two separate issues.

 The declared type of the variable decides which function to


match at compile time. The compiler finds a matching
function according to parameter type, number of
parameters, and order of the parameters at compile time.

 A virtual function may be implemented in several derived


classes. C++ dynamically binds the implementation of the
function at runtime, decided by the actual class of the object
referenced by the variable.
use virtual functions?

 If a function defined in a base class needs to be redefined


in its derived classes, you should declare it virtual to avoid
confusions and mistakes.

 On the other hand, 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.
Abstract Classes and Pure Virtual Functions
 In the inheritance hierarchy, classes become more specific
and concrete with each new derived class.
 If you move from a derived class back up to its parent and
ancestor classes, the classes become more general and less
specific.
 Class design should ensure that a base class contains
common features of its derived classes.
 Sometimes a base class is so abstract that it cannot have any
specific instances. Such a class is referred to as an abstract
class.
 For a class to be an abstract class, it must contain at least one
pure virtual function.
Abstract Classes and Pure Virtual Functions

 Pure virtual function (e.g. Show()) can be declared as:

virtual void show() = 0;

 Once you’ve placed a pure virtual function in the base


class, you must override it in all derived classes from
which you want to instantiate objects.

 If a class does not override the pure virtual function, it


becomes an abstract class itself.

 It is not possible to instantiate object of abstract class.


Abstract class and Pure Virtual Function - Example
class Base{
public: void main(){
virtual void show() = 0; // Base bs;
};
class Derv1:public Base{ Base *ptr;
public: Derv1 d1;
void show() Derv2 d2;
{
cout<<"derv1\n"; ptr = &d1;
}
}; ptr->show();
class Derv2:public Base{ ptr = &d2;
public: ptr->show();
void show() }
{
cout<<"derv2\n";
}
};
Virtual Destructors

 In C++, classes and class destructors can be virtual but


not constructors.

 If a base class destructor is not virtual then delete, like


a normal member function, calls the destructor for the
base class, not the destructor for the derived class.
Virtual Destructors

class Base void main()


{ {
public:
~Base() Base *p = new Derv;
{ delete p;
cout<<“ Base Destroyed \n”;
} }
};
class Derv: public Base
{
public:
~Derv()
{
cout<<“ Derv Destroyed \n”;
}
};
Virtual Destructors
class Base void main()
{ {
public:
virtual ~Base() Base *p = new Derv;
{ delete p;
cout<<“ Base Destroyed \n”;
} }
};

class Derv: public Base


{
public:
~Derv()
{
cout<<“ Derv Destroyed \n”;
}
};
Multiple Inheritance
Multiple Inheritance
 A class can be derived from more than one base class.
This is called Multiple Inheritance

 Example: Class C is derived from base classes A and B


Multiple Inheritance – Syntax
 The base classes from which C is derived are listed following
the colon in C’s specification and are separated by commas

class A
{
};

class B
{
};
class C : public A, public B
{
};
Constructor Chaining in Multiple Inheritance
class Base {
public:
Base()
{ cout<<"Base\n"; }
};
class DerivedBaseOne : public Base {
public:
DerivedBaseOne()
{ cout<<"DerivedBaseOne\n"; }
};
class DerivedBaseTwo : public Base {
public:
DerivedBaseTwo()
{ cout<<"DerivedBaseTwo\n"; }
};
class Derived : public DerivedBaseTwo, public DerivedBaseOne
{ };

Derived * dev = new Derived();


Constructor Chaining in Multiple Inheritance
class Base {
public:
Base()
{ cout<<"Base\n"; }
};
class DerivedBaseOne : virtual public Base {
public:
DerivedBaseOne()
{ cout<<"DerivedBaseOne\n"; }
};
class DerivedBaseTwo : virtual public Base {
public:
DerivedBaseTwo()
{ cout<<"DerivedBaseTwo\n"; }
};
class Derived : public DerivedBaseTwo, public DerivedBaseOne
{ };

Derived * dev = new Derived();


Ambiguity in Multiple Inheritance (Diamond Problem)
class A
{
public:
void show() { cout<<“A Function”; }
}; D objD;
//objD.show();
class B: public A
{
};

class C : public A
{
};
class D : public B, public C
{
};

 B and C, both contain a copy of show(), inherited from A. The


compiler cannot decide which copy to use, and signals an
error.
Virtual Classes

 In C++, classes can be virtual

 Virtual base classes, used in virtual inheritance, is a


way of preventing multiple "instances" of a given class
appearing in an inheritance hierarchy when using
multiple inheritance.

 In other words, Virtual base classes offer a way to save


space and avoid ambiguities in class hierarchies that
use multiple inheritance.
Ambiguity in Multiple Inheritance
class A
{
public: D objD;
void show() { cout<<“A Function”; } objD.show();
};

class B: virtual public A


{
};

class C : virtual public A


{
};
class D : public B, public C
{
};

 When a base class is inherited as a virtual class, it can act as an indirect


base more than once without duplication of its data members. A single
copy of its data members is shared by all the base classes that use it as a
virtual base.
Types of Inheritance
Exercise

 Create a Paintingclass that holds the painting title, artist


name, and value. All Paintings are valued at $400 unless
they are FamousPaintings.
 Include a display function that displays all fields. The
FamousPainting subclass overrides the Paintingvalue
and sets each Painting’s value to $25,000.
 Write a main() function that declares an array of 10
Painting objects. Prompt the user to enter the title and
artist for each of the 10 Paintings.
 Consider the Painting to be a FamousPainting if the artist
is one of the following: Degas, Monet, Picasso, or
Rembrandt. Display the 10 Paintings.
Exercise
 Create a base class named Book. Data fields include title
and author; functions include those that can set and
display the fields. Derive two classes from the Book class:
 Fiction, which also contains a numeric grade reading
level, and
 NonFiction, which contains a variable to hold the number
of pages
 The functions that set and display data field values for the
subclasses should call the appropriate parent class
functions to set and display the common fields, and
include specific code pertaining to the new subclass
fields.
 Write a main()function that demonstrates the use of the
classes and their functions.
Exercise

 Create a class named MusicalComposition that contains


fields for title, composer, and year written. Include a
constructor that requires all three values and an
appropriate display function.

 The child class NationalAnthem contains an additional


field that holds the name of the anthem’s nation. The
child class constructor requires a value for this additional
field. The child class also contains a display function.

 Write a main() function that instantiates objects of each


class and demonstrates that the functions work correctly.
Exercise
Create an Investmentclass that contains fields to hold the initial
value of an investment, the current value, the profit (calculated
as the difference between current value and initial value), and
the percent profit (the profit divided by the initial value).
Include a constructor that requires initial and current values and
a display function.
Create a House class that includes fields for street address and
square feet, a constructor that requires values for both fields,
and a display function.
Create a HouseThatIsAnInvestment class that inherits from
Investment and House. It includes a constructor and a display
function that calls the display functions of the parents. Write a
main()function that declares a HouseThatIsAnInvestmentand
displays its values.

Das könnte Ihnen auch gefallen