Unit II EE2415-Oops-Ds-Notes
Unit II EE2415-Oops-Ds-Notes
AND DS
UNIT II
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;
}
};
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.
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
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
Page 23
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
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
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
Page 27
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
Page 28
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
Page 29
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
Page 30
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
Page 31
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
Concrete c(s);
c. printContent();
}
#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;
}
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";}
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.
Page 34
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
Page 35
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
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!
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
Page 41
EE2415 / DS AND OOP BE (EEE) II Year / III Sem
Page 42