0% found this document useful (0 votes)
20 views42 pages

Unit II EE2415-Oops-Ds-Notes

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views42 pages

Unit II EE2415-Oops-Ds-Notes

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

EE2415 / DS AND OOP BE (EEE) II Year / III Sem

AND DS
UNIT II

INHERITANCE AND POLYMORPHISM

2.1 BASE CLASSES AND DERIVED CLASSES


Inheritance is the process by which new classes called derived classes are created from
existing classes called base classes. The derived classes have all the features of the base class
and the programmer can choose to add new features specific to the newly created derived class.

Inheritance is a way to form new classes (instances of which are called objects) using classes
that have already been defined. One class can use features from another class to extendits
functionality (an “Is a” relationship) i.e., a Car is an Automobile.

Advantages of Inheritance
Reusability
Inheritance helps the code to be reused in many situations. The base class is defined and
once it is compiled, it need not be reworked. Using the concept of inheritance, the programmer
can create as many derived classes from the base class as needed while adding specific features
to each derived class as needed.
Saves Time and Effort
The above concept of reusability achieved by inheritance saves the programmer time and
effort. Since the main code written can be reused in various situations as needed.
Defining derived class
The general form of defining a derived class is :
class derived_classname : visibility_mode base_classname
{
……..
……..
};

Page 1
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
Single Inheritance
A derived class with only one base class, is called single inheritance.
Example
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}

};
class B: public A
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()

Page 2
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
{
B b;
b.get();
b.add();
getch();

}
Output
Enter the value of a and b : 4 5
Sum = 9
Multiple inheritance
Deriving a class from more than one direct base class is called multiple inheritance.
Example
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
public:
void geta()
{
cout<< “Enter the value of a ”;
cin>> a;
}

};
class B
{
public:

Page 3
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
int b;
public:
void getb()
{
cout<< “Enter the value of a ”;
cin>> b;
}
};

class C: public A, public B


{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
{
C c;
c.geta();
c.getb();
c.add();
getch();

Page 4
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
Output
Enter the value of a : 4
Enter the value of b : 5
Sum = 9
Multilevel Inheritance
Deriving a class from another derived class is known as multilevel inheritance.
Example
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
public:
void geta()
{
cout<< “Enter the value of a ”;
cin>> a;
}

};
class B : public A
{
public:
int b;
public:
void getb()
{
cout<< “Enter the value of a ”;
cin>> b;

Page 5
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
}
};

class C: public B
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
{
C c;
c.geta();
c.getb();
c.add();
getch();

}
Output
Enter the value of a : 4
Enter the value of b : 5
Sum = 9
Hierarchical inheritance
Hierarchical inheritance is the process of deriving two or more classes from only one
base class.

Page 6
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
Example
#include<iostream.h>
#include<conio.h>
class A //Base Class
{
public:
int a,b;
void getnumber()
{
cout<<"\n\nEnter Number :::\t";
cin>>a;
}
};
class B : public A //Derived Class 1
{
public:
void square()
{
getnumber(); //Call Base class property
cout<<"\n\n\tSquare of the number :::\t"<<(a*a);
cout<<"\n\n\t ";
}
};
class C :public A //Derived Class 2
{
public:
void cube()
{
getnumber(); //Call Base class property
cout<<"\n\n\tCube of the number :::\t"<<(a*a*a);

Page 7
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
}
};
void main()
{
B b1; //b1 is object of Derived class 1
b1.square(); //call member function of class B
C c1; //c1 is object of Derived class 2
c1.cube(); //call member function of class C
getch();
}
Output
Enter Number ::: 2
Square of the number :::4
Enter Number ::: 3
Cube of the number :::9
Hybrid Inheritance
Hybrid Inheritance is a method where one or more types of inheritance are combined
together.
Example
#include<iostream.h>
class student
{
char name[10];
intrno;
public:
void getdata()
{
cout<<"\n Enter the name : ";
cin>> name;
cout<<" Enter rollno : ";

Page 8
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
cin>>rno;
}
void putdata()
{
cout<<"\n\tName = "<<name;
cout<<"\n\tRollno = "<<rno<<endl;
}
};
class test:public virtual student
{
protected:
float mark1, mark2;
public:
void getmarks()
{
cout<<" Enter Mark 1 : ";
cin>>mark1;
cout<<" Enter Mark 2 : ";
cin>>mark2;
}
void putmarks()
{
cout<<"\tMark1 = "<<mark1<<endl;
cout<<"\tMark2 ="<<mark2<<endl;
}
};
class sports:public virtual student
{
protected:
float score;

Page 9
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
public:
void getscore()
{
cout<<" Enter the score in sports:";
cin>>score;
}
Void putscore()
{
cout<<"\tScore = "<<score<<endl;
}
};
class result:public test,public sports
{
float total;
public:
void display()
{
total=mark1+mark2+score;
putdata();
putmarks();
putscore();
cout<<"\tTotal = "<<total<<endl;
}
};
void main()
{
clrscr();
result r;
r.getdata();
r.getmarks();

Page 10
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
r.getscore();
cout<<"\n\t\t Result ";
r.display();
getch();
}
Output
Enter the name : Sam
Enter rollno : 36
Enter Mark 1 : 92
Enter Mark 2 : 93
Enter the score in sports: 99
Result
Name = Sam
Rollno = 36
Mark1 = 92
Mark2 = 93
Score = 99
Total = 284
Virtual Base Class

Grandparent

Parent 1 Parent 2

Child

Page 11
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
Inheritance by the child might pose some problems. All the public and protected
members of „grandparent‟ are inherited into „child‟ twice, first via „parent1‟ again via „parent2‟.
This means child would have duplicate sets of the members inherited from „grandparent‟. This
introduces ambiguity and should be avoided.
The duplication of inherited members due to these multiple paths can be avoided by
making the common base class as virtual base class while declaring the direct or intermediate
base classes which is shown as follow:
class A //grandparent
{
………….
………….
………….
};
class B1 : virtual public A //parent1
{
………….
………….
………….
};
class B2 : virtual public A //parent2
{
………….
………….
………….
};
class C : public B1,public B2 //child
{
…………. // only one copy of A
…………. // will be inherited
………….

Page 12
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
AND DS
};
When a class is made a virtual base class, C++ takes necessary care to see that only one
copy of that class is inherited, regardless of how many inheritance path exist between the virtual
base class and a derived class.

2.2 PROTECTED MEMBERS


Data hiding is one of the important features of Object Oriented Programming which
allows preventing the functions of a program to access directly the internal representation of a
class type. The access restriction to the class members is specified by the labeled public,
private, and protected sections within the class body. The keywords public, private, and
protected are called access specifiers.
A class can have multiple public, protected, or private labeled sections. Each section
remains in effect until either another section label or the closing right brace of the class body is
seen. The default access for members and classes is private.
class Base {
public:
// public members go here
protected:
// protected members go here
private:
// private members go here
};
The public members
A public member is accessible from anywhere outside the class but within a program.
You can set and get the value of public variables without any member function as shown in the
following example:
#include <iostream.h>
class Line
{
public:
double length;
Page 13
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

void setLength( double len );


double getLength( void );
};
// Member functions definitions
double Line::getLength(void)
{
return length ;
}
void Line::setLength( double len )
{
length = len;
}
// Main function for the program
void main( )
{
Line line;
// set line length
line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
// set line length without member function
line.length = 10.0; // OK: because length is public
cout << "Length of line : " << line.length <<endl;
}
When the above code is compiled and executed, it produces the following result:
Length of line : 6
Length of line : 10
The private members
A private member variable or function cannot be accessed, or even viewed from outside
the class. Only the class and friend functions can access private members.

Page 14
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

By default all the members of a class would be private, for example in the following class
width is a private member, which means until you label a member, it will be assumed a private
member:
class Box
{
double width;
public:
double length;
void setWidth( double wid );
double getWidth( void );
};
Practically, we define data in private section and related functions in public section so
that they can be called from outside of the class as shown in the following program.
#include <iostream.h>
class Box
{
public:
double length;
void setWidth( double wid );
double getWidth( void );
private:
double width;
};
// Member functions definitions
double Box::getWidth(void)
{
return width ;
}
void Box::setWidth( double wid )
{

Page 15
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

width = wid;
}
// Main function for the program
void main( )
{
Box box;
// set box length without member function
box.length = 10.0; // OK: because length is public
cout << "Length of box : " << box.length <<endl;
// set box width without member function
// box.width = 10.0; // Error: because width is private
box.setWidth(10.0); // Use member function to set it.
cout << "Width of box : " << box.getWidth() <<endl;
}
When the above code is compiled and executed, it produces the following result:
Length of box : 10
Width of box : 10
The protected members
A protected member variable or function is very similar to a private member but it
provided one additional benefit that they can be accessed in child classes which are called
derived classes.
Following example is similar to above example and here width member will be accessible by any
member function of its derived class SmallBox.
#include <iostream.h>
class Box
{
protected:
double width;
};
class SmallBox:Box // SmallBox is the derived class.

Page 16
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

{
public:
void setSmallWidth( double wid );
double getSmallWidth( void );
};
// Member functions of child class
double SmallBox::getSmallWidth(void)
{
return width ;
}
void SmallBox::setSmallWidth( double wid )
{
width = wid;
}
// Main function for the program
void main( )
{
SmallBox box;
// set box width using member function
box.setSmallWidth(5.0);
cout << "Width of box : "<< box.getSmallWidth() << endl;
}
When the above code is compiled and executed, it produces the following result:
Width of box : 5

Page 17
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

2.3 PUBLIC, PRIVATE AND PROTECTED INHERITANCE


Accessibility in Public Inheritance

Accessibility private protected public

Accessible from own class? yes yes yes

Accessible from derived


class? no yes yes

Accessible outside derived


class? no no yes

Accessibility in Protected Inheritance

Accessibility private protected public

Accessible from own class? yes yes yes

Accessible from derived


class? no yes yes

Accessible outside derived


class? no no no

Accessibility in Private Inheritance

Accessibility private protected public

Accessible from own class? yes yes yes

Accessible from derived


class? no yes yes

Accessible outside derived


class? no no no

Page 18
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

Public Inheritance
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}
};
class B: public A
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
{
B b;
b.get();

Page 19
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

b.add();
getch();
}
Output
Enter the value of a and b : 4 5
Sum = 9
Private Inheritance
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}
};
class B: private A
{
public:
int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;

Page 20
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

}
};
void main()
{
B b;
b.get();
b.add();
getch();
}
Output
Enter the value of a and b : 4 5
Sum = 9
Protected Inheritance
#include<iostream.h>
#include<conio.h>
class A
{
public:
int a;
int b;
public:
void get()
{
cout<< “Enter the value of a and b”;
cin>> a >> b;
}
};
class B: protected A
{
public:

Page 21
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

int c;
public:
void add()
{
c = a + b;
cout<< “Sum=” << c;
}
};
void main()
{
B b;
b.get();
b.add();
getch();
}
Output
Enter the value of a and b : 4 5
Sum = 9

2.4 OVERRIDING
If base class and derived class have member functions with same name and arguments
or if you create an object of derived class and write code to access that member function then,
the member function in derived class is only invoked, i.e., the member function of derived class
overrides the member function of base class. This feature in C++ programming is known as
function overriding.

Page 22
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

Accessing the Overridden Function in Base Class From Derived Class


To access the overridden function of base class from derived class, scope resolution
operator ::. For example: If you want to access get_data() function of base class from derived
class in above example then, the following statement is used in derived class.
A::get_data; // Calling get_data() of class A.
It is because, if the name of class is not specified, the compiler thinks get_data() function is
calling itself.

Page 23
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

2.5 THIS POINTER


The this pointer is used as a pointer to the class object instance by the member function.
The address of the class instance is passed as an implicit parameter to the member functions. this
pointer stores the address of the class instance, to enable pointer access of the members to the
member functions of the class .this pointer is not counted for calculating the size of the object.
this pointers are not accessible for static member functions. this pointers are not modifiable.
Example
#include<iostream.h>
#include<conio.h>
class sample

Page 24
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

{
int a;
public :
sample(int a)
{
this->a=a;
}
voiddisp()
{
cout<< “A=” << a;
cout<< this;
}
};
void main()
{
sample s(2);
s.disp();
}
Output
A=2

2.6 VIRTUAL FUNCTION


Run Time Polymorphism
The appropriate member function could be selected while the program is running. The
run-time polymorphism is implemented with inheritance and virtual functions.
Virtual Function
Virtual, as the name implies, is something that exists in effect but not in reality. The
concept of virtual function is the same as a function, but it does not really exist although it
appears in needed places in a program. The object-oriented programming language C++

Page 25
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

implements the concept of virtual function as a simple member function, like all member
functions of the class.
Properties of Virtual Functions
Virtual Functions are resolved during run-time or dynamic binding. Virtual functions are
also simple member functions. The main difference between a non-virtual C++ member function
and a virtual member function is in the way they are both resolved. A non-virtual C++ member
function is resolved during compile time or static binding. Virtual Functions are resolved during
run-time or dynamic binding. Virtual functions are member functions of a class. Virtual
functions are declared with the keyword virtual. Virtual function takes a different functionality in
the derived class.
Example
#include<iostream.h>
#include<conio.h>
class base
{
public:
virtual void show()
{
cout<<"\n Base class show:";
}
void display()
{
cout<<"\n Base class display:" ;
}
};
class drive : public base
{
public:
void display()
{

Page 26
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

cout<<"\n Drive class display:";


}
void show()
{
cout<<"\n Drive class show:";
}
};
void main()
{
clrscr();
base obj1;
base *p;
cout<<"\n\t P points to base:\n" ;
p=&obj1;
p->display();
p->show();
cout<<"\n\n\t P points to drive:\n";
drive obj2;
p=&obj2;
p->display();
p->show();
getch();
}
Output
P points to Base
Base class display
Base class show
P points to Drive
Base class Display
Drive class Show

Page 27
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

Pure Virtual Function


To declare a function virtual inside the base class and redefine it in the derived classes.
The function inside the base class is seldom used for performing any task. It only serves as a
placeholder. For example, the function display() in the base class has been defined empty. Such
functions are called “do-nothing” functions.
A “do-nothing” function may be defined as follows:
virtual void display() = 0
Such functions are called pure virtual functions. A pure virtual function is a function
declared in a base class that has no definition relative to the base class.

2.7 ABSTRACT BASE CLASSES AND CONCRETE CLASSES


An interface describes the behavior or capabilities of a C++ class without committing to a
particular implementation of that class. The C++ interfaces are implemented using abstract
classes and these abstract classes should not be confused with data abstraction which is a concept
of keeping implementation details separate from associated data.
A class is made abstract by declaring at least one of its functions as pure virtual function.
A pure virtual function is specified by placing "= 0" in its declaration as follows:
class Box
{
public:
// pure virtual function
virtual double getVolume() = 0;
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
The purpose of an abstract class (often referred to as an ABC) is to provide an
appropriate base class from which other classes can inherit. Abstract classes cannot be used to

Page 28
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

instantiate objects and serves only as an interface. Attempting to instantiate an object of an


abstract class causes a compilation error.
Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the
virtual functions, which means that it supports the interface declared by the ABC. Failure to
override a pure virtual function in a derived class, then attempting to instantiate objects of that
class, is a compilation error.
Classes that can be used to instantiate objects are called concrete classes.
Abstract Class Example:
Consider the following example where parent class provides an interface to the base class
to implement a function called getArea():
#include <iostream.h>
// Base class
class Shape
{
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// Derived classes

Page 29
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

class Rectangle: public Shape


{
public:
int getArea()
{
return (width * height);
}
};
class Triangle: public Shape
{
public:
int getArea()
{
return (width * height)/2;
}
};
void main(void)
{
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total Rectangle area: " << Rect.getArea() << endl;
Tri.setWidth(5);
Tri.setHeight(7);
// Print the area of the object.
cout << "Total Triangle area: " << Tri.getArea() << endl;
}
When the above code is compiled and executed, it produces the following result:

Page 30
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

Total Rectangle area: 35


Total Triangle area: 17
All the other classes with no pure virtual functions are known as concrete classes.
C++ Program to Differentiate Between Concrete Class and Abstract Class
This C++ program differentiates between the concrete and abstract class. An abstract
class is meant to be used as a base class where some or all functions are declared purely virtual
and hence cannot be instantiated. A concrete class is an ordinary class which has no purely
virtual functions and hence can be instantiated. The following C++ program differentiates
between the concrete and abstract class.
#include <iostream.h>
#include <string.h>
class Abstract {
private:
string info;
public:
virtual void printContent() = 0;
};
class Concrete {
private:
string info;
public:
Concrete(string s) : info(s) { }
void printContent() {
cout << "Concrete Object Information\n" << info << endl;
}
};
void main()
{
string s;
s = "Object Creation Date : 23:26 PM 15 Dec 2013";

Page 31
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

Concrete c(s);
c. printContent();
}

2.8 VIRTUAL DESTRUCTORS


In C++ a destructor is generally used to deallocate memory and do some other cleanup
for a class object and it‟s class members whenever an object is destroyed. Destructors are
distinguished by the tilde, the „~‟ that appears in front of the destructor name. In order to define
a virtual destructor, all you have to do is simply add the keyword “virtual” before the tilde
symbol.
Example without a Virtual Destructor

#include< iostream.h>
class Base
{
public:
Base()
{
cout<<"Constructing Base";
}
// this is a destructor:
~Base()
{
cout<<"Destroying Base";
}
};
class Derive: public Base
{
public:
Derive()

Page 32
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

{
cout<<"Constructing Derive";
}
~Derive(){ cout<<"Destroying Derive";}
};
void main()
{
Base *basePtr = new Derive();
delete basePtr;
}

The output after running the code above would be:

Constructing Base
Constructing Derive
Destroying Base

Based on the output above, we can see that the constructors get called in the appropriate
order when we create the Derive class object pointer in the main function. But there is a major
problem with the code above: the destructor for the "Derive" class does not get called at all when
we delete „basePtr‟.
So, how can we fix this problem? we can make the base class destructor virtual, and that
will ensure that the destructor for any class that derives from Base (in our case, its the "Derive"
class) will be called.
]
Example with a Virtual Destructor
So, the only thing we will need to change is the destructor in the Base class and here‟s
what it will look like:

class Base
{

Page 33
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

public:
Base(){ cout<<"Constructing Base";}

// this is a virtual destructor:


virtual ~Base(){ cout<<"Destroying Base";}
};

Now, with that change, the output after running the code above will be:

Constructing Base
Constructing Derive
Destroying Derive
Destroying Base

Note that the derived class destructor will be called before the base class. One important
design paradigm of class design is that if a class has one or more virtual functions, then that class
should also have a virtual destructor.

2.9 CONSTRUCTORS AND DESTRUCTORS IN DERIVED CLASSES


During inheritance, base class may also contain constructor and destructor. In this case if
you create an instance for the derived class then base class constructor will also be invoked and
when derived instance is destroyed then base destructor will also be invoked and the order of
execution of constructors will be in the same order as their derivation and order of execution of
destructors will be in reverse order of their derivation in the derived class.
Example
#include<iostream.h>
class Base
{
public:
Base ( )
{

Page 34
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

cout << "Inside Base constructor" << endl;


}
~Base ( )
{
cout << "Inside Base destructor" << endl;
}
};
class Derived : public Base
{
public:
Derived ( )
{
cout << "Inside Derived constructor" << endl;
}
~Derived ( )
{
cout << "Inside Derived destructor" << endl;
}
};
void main( )
{
Derived x;
}
In the code above, when the object "x" is created, first the Base class constructor is
called, and after that the Derived class constructor is called. Because the Derived class inherits
from the Base class, both the Base class and Derived class constructors will be called when a
Derived class object is created.
When the main function is finished running, the object x's destructor will get called first,
and after that the Base class destructor will be called. So, here is what the output of the code
above would look like:

Page 35
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

Inside Base constructor


Inside Derived constructor
Inside Derived destructor
Inside Base destructor
2.10 DYNAMIC BINDING
In some programs, it is not possible to know which function will be called until runtime
(when the program is run). This is known as late binding (or dynamic binding). In C++, one way
to get late binding is to use function pointers. To review function pointers briefly, a function
pointer is a type of pointer that points to a function instead of a variable. The function that a
function pointer points to can be called by using the function call operator (()) on the pointer.
For example, the following code calls the Add() function:
#include<iostream.h>
#include<conio.h>
int Add(int nX, int nY)
{
return nX + nY;
}
int main()
{
clrscr();
// Create a function pointer and make it point to the Add function
int (*pFcn)(int, int) = Add;
cout << pFcn(5, 3) << endl; // add 5 + 3
return 0;
}
Calling a function via a function pointer is also known as an indirect function call. The
following calculator program is functionally identical to the calculator example above, except it
uses a function pointer instead of a direct function call:
#include <iostream.h>
#include<conio.h>

Page 36
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
int Add(int nX, int nY)
{
return nX + nY;
}
int Subtract(int nX, int nY)
{
return nX - nY;
}
int Multiply(int nX, int nY)
{
return nX * nY;
}
int main()
{
int nX;
cout << "Enter a number: ";
cin >> nX;
int nY;
cout << "Enter another number: ";
cin >> nY;
int nOperation;
do
{
cout << "Enter an operation (0=add, 1=subtract, 2=multiply): ";
cin >> nOperation;
} while (nOperation < 0 || nOperation > 2);
// Create a function pointer named pFcn (yes, the syntax is ugly)
int (*pFcn)(int, int);
// Set pFcn to point to the function the user chose
switch (nOperation)
{

Page 37
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
case 0: pFcn = Add; break;
case 1: pFcn = Subtract; break;
case 2: pFcn = Multiply; break;
}
// Call the function that pFcn is pointing to with nX and nY as parameters
cout << "The answer is: " << pFcn(nX, nY) << endl;
return 0;

Page 38
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

}
In this example, instead of calling the Add(), Subtract(), or Multiply() function directly,
we‟ve instead set pFcn to point at the function we wish to call. Then we call the function through
the pointer. The compiler is unable to use early binding to resolve the function call pFcn(nX,
nY) because it cannot tell which function pFcn will be pointing to at compile time!

2.11 CASTING CLASS POINTERS AND MEMBER FUNCTIONS


Upcasting
Upcasting is converting a derived-class reference or pointer to a base-class. In other
words, upcasting allows us to treat a derived type as though it were its base type. It is always
allowed for public inheritance, without an explicit type cast. This is a result of the is-
a relationship between the base and derived classes.
Here is the code dealing with shapes. We created Shape class, and derived Circle, Square,
and Triangle classes from the Shape class. Then, we made a member function that talks to the
base class:
void play(Shape& s)
{
s.draw();
s.move();
s.shrink();
....
}
The function speaks to any Shape, so it is independent of the specific type of object that
it's drawing, moving, and shrinking. If in some other part of the program we use the play(
) function like below:
Circle c;
Triangle t;
Square sq;
play(c);
play(t);

Page 39
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

play(sq);

Upcasting allows us to treat a derived type as though it were its base type. Here the
assumption is "You're a Shape, I know you can move(), draw(), and shrink( ) yourself, do it, and
take care of the details correctly." Thus, the objects of all the classes are passed to the function
shape.
class Parent {
public:
void sleep() {}
};
class Child: public Parent {
public:
void gotoSchool(){}
};
int main( )
{
Parent parent;
Child child;
// upcast - implicit type cast allowed
Parent *pParent = &child;
// downcast - explicit type case required
Child *pChild = (Child *) &parent;
pParent -> sleep();
pChild -> gotoSchool();
return 0;
}
A Child object is a Parent object in that it inherits all the data members and member
functions of a Parent object. So, anything that we can do to a Parent object, we can do to
a Child object. Therefore, a function designed to handle a Parent pointer (reference) can perform
the same acts on a Child object without any problems. The same idea applies if we pass a pointer

Page 40
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

to an object as a function argument. Upcasting is transitive: if we derive a Child class


from Parent, then Parent pointer (reference) can refer to aParent or a Child object.
Upcasting can cause object slicing when a derived class object is passed by value as a
base class object, as in foo(Base derived_obj).
Downcasting
The opposite process, converting a base-class pointer (reference) to a derived-class
pointer (reference) is called downcasting. Downcasting is not allowed without an explicit type
cast. The reason for this restriction is that the is-a relationship is not, in most of the cases,
symmetric. A derived class could add new data members, and the class member functions that
used these data members wouldn't apply to the base class.
As in the example, we derived Child class from a Parent class, adding a member
function, gotoSchool(). It wouldn't make sense to apply the gotoSchool() method to
a Parent object. However, if implicit downcasting were allowed, we could accidentally assign the
address of a Parent object to a pointer-to-Child
Child *pChild = &parent; // actually this won't compile
// error: cannot convert from 'Parent *' to 'Child *'
and use the pointer to invoke the gotoSchool() method as in the following line.
pChild -> gotoSchool();
Because a Parent isn't a Child (a Parent need not have a gotoSchool() method), the
downcasting in the above line can lead to an unsafe operation.
C++ provides a special explicit cast called dynamic_cast that performs this conversion.
Downcasting is the opposite of the basic object-oriented rule, which states objects of a derived
class, can always be assigned to variables of a base class.
Because implicit upcasting makes it possible for a base-class pointer (reference) to refer
to a base-class object or a derived-class object, there is the need for dynamic binding. That's why
we have virtual member functions.

2.12 IMPLICIT DERIVED-CLASS OBJECT TO BASE-CLASS OBJECT


CONVERSION
1. Assigning base class object to base class pointer is possible.

Page 41
EE2415 / DS AND OOP BE (EEE) II Year / III Sem

2. Assigning derived class object to derived class pointer is possible.


3. Assigning derived class object to base class pointer is possible.
4. Assigning base class object to derived class pointer is not possible.

Page 42

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy