Oodp-unit 3 Notes
Oodp-unit 3 Notes
Reaccessability is yet another feature of OOP's. C++ strongly supports the concept of reusability.
The C++ classes can be used again in several ways. Once a class has been written and tested, it can
be adopted by another programmers. This is basically created by defining the new classes, reusing
the properties of existing ones. The mechanism of deriving a new class from an old one is called
'INHERTTENCE'. This is often referred to as IS-A' relationship because very object of the class
being defined "is" also an object of inherited class. The old class is called 'BASE' class and the new
one is called'DERIEVED'class.
Single Inheritance
When a class inherits from a single base class, it is known as single inheritance. Following program
shows the single inheritance using public derivation.
#include<iostream.h>
#include<conio.h>
class worker
{
int age;
char name [10];
public:
void get ( );
};
void worker : : get ( )
{
cout <<”yout name please”
cin >> name;
cout <<”your age please” ;
cin >> age;
}
void worker :: show ( )
{
cout <<”In My name is :”<<name<<”In My age is :”<<age;
}
class manager :: public worker //derived class (publicly)
{
int now;
public:
void get ( ) ;
void show ( ) ;
};
void manager : : get ( )
{
worker : : get ( ) ; //the calling of base class input fn.
cout << “number of workers under you”;
cin >> now;
cin>>name>>age;
} ( if they were public )
void manager :: show ( )
{
worker :: show ( ); //calling of base class o/p fn.
cout <<“in No. of workers under me are: “ << now;
}
main ( )
{
clrscr ( ) ;
worker W1;
manager M1;
M1 .get ( );
M1.show ( ) ;
}
If you input the following to this program:
Your name please
Ravinder
Your age please
27
number of workers under you
30
Then the output will be as follows:
My name is : Ravinder
My age is : 27
No. of workers under me are : 30
The following program shows the single inheritance by private derivation.
#include<iostream.h>
#include<conio.h>
class worker //Base class declaration
{
int age;
char name [10] ;
public:
void get ( ) ;
void show ( ) ;
};
void worker : : get ( )
{
cout << “your name please” ;
cin >> name;
cout << “your age please”;
cin >>age;
}
void worker : show ( )
{
cout << “in my name is: “ <<name<< “in” << “my age is : “ <<age;
}
class manager : worker //Derived class (privately by default)
{
int now;
public:
void get ( ) ;
void show ( ) ;
};
void manager : : get ( )
{
worker : : get ( ); //calling the get function of base
cout << “number of worker under you”; class which is
cin >> now;
}
void manager : : show ( )
{
worker : : show ( ) ;
cout << “in no. of worker under me are : “ <<now;
}
main ( )
{
clrscr ( ) ;
worker wl ;
manager ml;
ml.get ( ) ;
ml.show ( );
}
The following program shows the single inheritance using protected derivation
#include<conio.h>
#include<iostream.h>
class worker //Base class declaration
{ protected:
int age; char name [20];
public:
void get ( );
void show ( );
};
void worker :: get ( )
{
cout >> “your name please”;
cin >> name;
cout << “your age please”;
cin >> age;
}
void worker :: show ( )
{
cout << “in my name is: “ << name << “in my age is “ <<age;
}
class manager:: protected worker // protected inheritance
{
int now;
public:
void get ( );
void show ( ) ;
};
void manager : : get ( )
{
cout << “please enter the name In”;
cin >> name;
cout<< “please enter the age In”; //Directly inputting the data
cin >> age; members of base class
cout << “ please enter the no. of workers under you:”;
cin >> now;
}
void manager : : show ( )
{
cout « "your name is : "«name«" and age is : "«age;
cout «"In no. of workers under your are : "«now;
main ( )
{
clrscr ( ) ;
manager ml;
ml.get ( ) ;
cout « "\n \n";
ml.show ( );
}
The below mentioned table summarizes how the visibility of members undergo modifications when
they are inherited
A Base class
C Derived class
#include<iostream.h>
#include<conio.h>
class worker // Base class declaration
{
int age;
char name [20] ;
public;
void get( ) ;
void show( ) ;
}
Private:
int age;
char name[20];
Protected:
Private:
int age;
char name[20];
Manager:Worker
Private:
int now;
Protected:
Public:
void get()
void show()
worker ::get()
worker ::get()
Ceo: Manager
Public:
Protected:
Public:
All the inherited
members
Multiple Inheritances
A class can inherit the attributes of two or more classes. This mechanism is known as ‘MULTIPLE
INHERITENCE’. Multiple inheritance allows us to combine the features
of several existing classes as a starring point for defining new classes. It is like the child inheriting
the physical feature of one parent and the intelligence of another. The syntax of the derived class is
as follows:
Where the visibility refers to the access specifiers i.e. public, private or protected. Following
program shows the multiple inheritance.
#include<iostream.h>
#include<conio . h>
class father //Declaration of base classl
{
int age ;
char flame [20] ;
public:
void get ( ) ;
void show ( ) ;
};
void father : : get ( )
{
cout << “your father name please”;
cin >> name;
cout << “Enter the age”;
cin >> age;
}
void father : : show ( )
{
cout<< “In my father’s name is: ‘ <<name<< “In my father’s age is:<<age;
}
class mother //Declaration of base class 2
{
char name [20] ;
int age ;
public:
void get ( )
{
cout << “mother’s name please” << “In”;
cin >> name;
cout << “mother’s age please” << “in”;
cin >> age;
}
void show ( )
{
cout << “In my mother’s name is: “ <<name;
cout << “In my mother’s age is: “ <<age;
}
class daughter : public father, public mother //derived class inheriting
{ //publicly
char name [20] ; //the features of both the base class
int std;
public:
void get ( ) ;
void show ( ) ;
};
void daughter :: get ( )
{
father :: get ( ) ;
mother :: get ( ) ;
cout << “child's name: “;
cin >> name;
cout << “child's standard”;
cin >> std;
}
void daughter :: show ( )
{
father :: show ( );
nfather :: show ( ) ;
cout << “In child’s name is : “ <<name;
cout << “In child's standard: “ << std;
}
main ( )
{
clrscr ( ) ;
daughter d1;
d1.get ( ) ;
d1.show ( ) ;
}
Diagrammatic Representation of Multiple Inheritance is as follows:
Father Mother
Private: Private:
int age; int age;
char name[20]; char name[20];
Protected: Protected:
Public: Public:
void get() void get()
void show() void show()
Protected:
Public:
//self
void get(); void showQ;
//from Father
void get(); void show();
//from Mother
void get(); void show();
Hierarchical Inheritance
Another interesting application of inheritance is to use is as a support to a hierarchical design of a
class program. Many programming problems can be cast into a hierarchy where certain features of
one level are shared by many others below that level for e.g.
Accounts
Fixed deposit
Mid term
In C++, such problems can be easily converted into hierarchies. The base class will include all the
features that are common to the subclasses. A sub-class can be constructed by inheriting the features
of base class and so on.
{
father :: get ( ) ;
cout << “your (son) name please” << “in”; cin >>name;
cout << “your age please” << “ln”; cin>>age;
}
void son :: show ( )
{
father : : show ( ) ;
cout << “In my name is : “ <<name;
cout << “In my age is : “ <<age;
}
class daughter : public father //derived class 2.
{
char name [15] ;
int age;
public:
void get ( )
{
father : : get ( ) ;
cout << “your (daughter’s) name please In” cin>>name;
cout << “your age please In”; cin >>age;
}
void show ( )
{
father : : show ( ) ;
cout << “in my father name is: “ << name << “
In and his age is : “<<age;
}
};
main ( )
{
clrscr ( ) ;
son S1;
daughter D1 ;
S1. get ( ) ;
D1. get ( ) ;
S1 .show( ) ;
D1. show ( ) ;
}
Hybrid Inheritance
There could be situations where we need to apply two or more types of inheritance to design a
program. Basically Hybrid Inheritance is the combination of one or more types of the inheritance.
Here is one implementation of hybrid inheritance.
public :
void get_m (int x, int y) {
parti = x; part 2 = y; }
void put_m (void) {
cout << “marks obtained: “ << “In”
<< “Part 1 = “ << part1 << “in”
<< “Part 2 = “ << part2 << “In”;
}
};
class sports // base for result
{
protected : int score;
public:
void get_s (int s) {
score = s }
void put_s (void) {
cout << “ sports wt. : “ << score << “\n\n”;}
};
class result : public test, public sports //Derived from test
& sports
{
int total;
public:
void display (void);
};
Let us say the 'child' has two direct base classes ‘parent1’ and ‘parent2’ which themselves has a
common base class ‘grandparent’. The child inherits the traits of ‘grandparent’ via two separate
paths. It can also be inherit directly as shown by the broken line. The grandparent is sometimes
referred to as ‘INDIRECT BASE CLASS’. Now, the inheritance by the child might cause some
problems. All the public and protected members of ‘grandparent’ are inherited into ‘child’ twice, first
via ‘parent1’ and again via ‘parent2’. So, there occurs a duplicacy which should be avoided.
The duplication of the inherited members can be avoided by making common base class as the
virtual base class: for e.g.
class g_parent
{
//Body
};
class parent1: virtual public g_parent
{
// Body
};
When a class is virtual base class, C++ takes necessary care to see that only one copy
of that class is inherited, regardless of how many inheritance paths exists between
virtual base class and derived class. Note that keywords ‘virtual’ and ‘public’ can be
used in either order.
};
void get (int) ; void show (void) ;
A r
1 ,
2
t
:
;
p
u p
b u
l b
i l
c i
c
A :
1 void get (int a)
, { r = a;}
v t =” << t ;
o }
i };
d main ( )
{
s clrscr ( ) ;
h A12 r ;
o r.A : : get (3) ;
w r.A1 : : get (4) ;
r.A2 :
( : get
v (5) ;
o r.get
i (6) ;
d r . show ( ) ;
) }
{
t
FRIENDLY FUNCTIONS:-
We know private members can not be accessed from outside the class. That is a
non -= member function can't have an access to the private data of a class. However there
could be a case where two classes manager and scientist, have been defined we should like
x a function income- tax to operate on the objects of both these classes.
to use
In such situations, c++ allows the common function lo be made friendly with both the
+ , there by following the function to have access to the private data of these classes
classes
.Such a function need not be a member of any of these classes.
y
To make an outside function "friendly" to a class, we have to simply declare this function
as a friend of the classes as shown below :
+
class ABC
z {
+
public:
r
#
i
n
c
l
u
d
e
<
i
o
s
t
r
e
a
m
19 P.T.O
PROGRAM FOR ILLUSTRATING THE USE OF FRIEND FUNCTION:
#include< iostream.h>
class account1;
class account2
{
private:
int balance;
public:
account2( ) { balance=567; }
void showacc2( )
{
cout<<”balanceinaccount2 is:”<<balance<<endl;
friend int transfer (account2 &acc2, account1 &acc1,int amount);
};
class acount1
{
private:
int balance;
public:
account1 ( ) { balance=345; }
void showacc1 ( )
{
cout<<”balance in account1 :”<<balance<<endl;
}
friend int transfer (account2 &acc2, account1 &acc1 ,int amount);
};
20 P.T.O
cout<<transfer ( bb,aa,100)<<endl;
}
return(0);
21 P.T.O
Virtual Functions
Virtual functions, one of advanced features of OOP is one that does not really exist but it« appears
real in some parts of a program. This section deals with the polymorphic features which are
incorporated using the virtual functions.
};
To make a member function virtual, the keyword virtual is used in the methods while it is declared in
the class definition but not in the member function definition. The keyword virtual precedes the
return type of the function name. The compiler gets information from the keyword virtual that it is a
virtual function and not a conventional function declaration.
For example
class point {
intx ;
inty ;
public:
virtual void display ( );
};
virtual void point: : display ( ) //error
{
Function Body
}
A virtual function cannot be a static member since a virtual member is always a member of a
particular object in a class rather than a member of the class as a whole.
class point {
int x ;
int y ;
public:
virtual static int length ( ); //error
};
int point: : length ( )
{
Function body
}
A virtual function cannot have a constructor member function but it can have the destructor member
function.
class point {
int x ;
int y ;
public:
virtual point (int xx, int yy) ; // constructors, error
void display ( ) ;
int length ( ) ;
};
A destructor member function does not take any argument and no return type can be specified for it
not even void.
class point {
int x ;
int y ;
public:
virtual point (int xx, int yy) ; //invalid
void display ( ) ;
int length ( ) ;
It is an error to redefine a virtual method with a change of return data type in the derived class with
the same parameter types as those of a virtuall method in the base class.
class base {
int x,y ;
public:
virtual int sum (int xx, int yy ) ; //error
};
class derived: public base {
intz ;
public:
virtual float sum (int xx, int yy) ;
};
The above declarations of two virtual functions are invalid. Even though these functions take
identical arguments note that the return data types are different.
virtual int sum (int xx, int IT) ; //base class
virtual float sum (int xx, int IT) ; //derived class
Both the above functions can be written with int data types in the base class as well as in the derived
class as
virtual int sum (int xx, int yy) ; //base class
virtual int sum (int xx, int yy) ; //derived class
Only a member function of a class can be declared as virtual. A non member function (nonmethod)
of a class cannot be declared virtual.
virtual void display ( ) //error, nonmember function
{
Function body
}
Late Binding
As we studied in the earlier unit, late binding means selecting functions during the execution.
Though late binding requires some overhead it provides increased power and flexibility. The late
binding is implemented through virtual functions as a result we have to declare an object of a class
either as a pointer to a class or a reference to a class.
For example the following shows how a late binding or run time binding can be carried out with the
help of a virtual function.
class base {
private :
int x;
float y;
public:
virtual void display ( ) ;
int sum ( ) ;
};
class derivedD : public baseA
{
private :
int x ;
float y;
public:
void display ( ); //virtual
int sum ( ) ;
};
void main ( )
{
baseA *ptr ;
derivedD objd ;
ptr = &objd ;
Other Program statements
ptr- >di splay ( ) ; //run time binding
ptr->sum ( ) ; //compile time binding
}
Note that the keyword virtual is be followed by the return type of a member function if a run time is
to be bound. Otherwise, the compile time binding will be effected as usual. In the above program
segment, only the display ( ) function has been declared as virtual in the base class, whereas the sum
( ) is nonvirtual. Even though the message is given from the pointer of the base class to the objects of
the derived class, it will not
access the sum ( ) function of the derived class as it has been declared as nonvirtual. The sum ( )
function compiles only the static binding.
The following program demonstrates the run time binding of the member functions of a class. The
same message is given to access the derived class member functions from the array of pointers. As
function are declared as virtual, the C++ compiler invokes the dynamic binding.
#include <iostream.h>
#include <conio.h>
class baseA {
public :
virtual void display () {
cout<< “One \n”;
}
};
class derivedB : public baseA
{
public:
virtual void display(){
cout<< “Two\n”; }
};
class derivedC: public derivedB
{
public:
virtual void display ( ) {
cout<< “Three \n”; }
};
void main ( ) {
//define three objects
baseA obja;
derivedB objb;
derivedC objc;
base A *ptr [3]; //define an array of pointers to baseA
ptr [0] = &obja;
ptr [1] = &objb;
ptr [2] = &objc;
for ( int i = 0; i <=2; i ++ )
ptr [i]->display ( ); //same message for all objects
getche ( ) ;
}
Output
One
Two
Three
The program listed below illustrates the static binding of the member functions of a class. In program
there are two classes student and academic. The class academic is derived from class student. The
two member function getdata and display are defined for both the classes. *obj is defined for class
student, the address of which is stored in the object of the class academic. The functions getdata ( )
and display ( ) of student class are invoked by the pointer to the class.
#include<iostream.h>
#include<conio.h>
class student {
private:
int rollno;
char name [20];
public:
void getdata ( );
void display ( );
};
class academic: public student {
private:
char stream;
public:
void getdata ( );
void display ( ) ;
};
void student:: getdata ( )
{
cout<< “enterrollno\n”;
cin>>rollno;
cout<< “enter name \n”;
cin>>name;
}
void student:: display ( )
{
cout<< “the student’s roll number is “<<rollno<< “and name is”<<name ;
cout<< endl;
}
void academic :: getdata ( )
{
cout<< “enter stream of a student? \n”;
cin >>stream;
}
void academic :: display ( ) {
cout<< “students stream \n”;
cout <<stream<< endl;
}
void main ( )
{
student *ptr ;
academic obj ;
ptr=&obj;
ptr->getdata ( ) ;
ptr->display ( ) ;
getche ( );
}
output
enter rollno
25
enter name
raghu
the student’s roll number is 25 and name is raghu
The program listed below illustrates the dynamic binding of member functions of a class. In this
program there are two classes student and academic. The class academic is derived from student.
Student function has two virtual functions getdata ( ) and display (). The pointer for student class is
defined and object . for academic class is created. The pointer is assigned the address of the object
and function of derived class are invoked by pointer to student.
#include <iostream.h>
#include <conio.h>
class student {
private:
introllno;
char name [20];
public:
virtual void getdata ( );
virtual void display ( );
};
class academic: public student {
private :
char stream[10];
public:
void getdata { };
void display ( ) ;
};
void student: : getdata ( )
{
cout<< “enter rollno\n”;
cin >> rollno;
cout<< “enter name \n”;
cin >>name;
}
void student:: display ( )
{
cout<< “the student’s roll number is”<<rollno<< “and name is”<<name;
cout<< end1;
}
void academic: : getdata ( )
{
cout << “enter stream of a student? \n”;
cin>> stream;
}
void academic:: display ( )
{
cout<< “students stream \n”;
cout<< stream << endl;
}
void main ( )
{
student *ptr ;
academic obj ;
ptr = &obj ;
ptr->getdata ( );
ptr->dlsplay ( );
getch ( );
}
output
enter stream of a student?
Btech
students stream
Btech
Pure Virtual Functions
Generally a function is declared virtual inside a base class and we redefine it the derived classes. The
function declared in the base class seldom performs any task.
The following program demonstrates how a pure virtual function is defined, declared and invoked
from the object of a derived class through the pointer of the base class. In the example there are two
classes employee and grade. The class employee is base class and the grade is derived class. The
functions getdata ( ) and display ( ) are declared for both the classes. For the class employee the
functions are defined with empty body or no code inside the function. The code is written for the
grade class. The methods of the derived class are invoked by the pointer to the base class.
#include<iostream.h>
#include<conio.h>
class employee {
int code
char name [20] ;
public:
virtual void getdata ( ) ;
virtual void display ( ) ;
};
class grade: public employee
{
char grd [90] ;
float salary ;
public :
void getdata ( ) ;
void display ( );
};
void employee :: getdata ( )
{
}
void employee:: display ( )
{
}
void grade : : getdata ( )
{
cout<< “ enter employee’s grade “;
cin> > grd ;
cout<< “\n enter the salary “ ;
cin>> salary;
}
void grade : : display ( )
{
cout«" Grade salary \n";
cout« grd« " "« salary« endl;
}
void main ( )
{
employee *ptr ;
grade obj ;
ptr = &obj ;
ptr->getdata ( ) ;
ptr->display ( ) ;
getche ( ) ;
}
Output
enter employee’s grade A
enter the salary 250000
Grade salary
A 250000
Object Slicing:
In C++, a derived class object can be assigned to a base class object, but the other way is not
possible.
Object Slicing happens when a derived class object is assigned to a base class object, additional
attributes of a derived class object are sliced off to form the base class object.
#include <iostream>
using namespace std;
class Base
{
protected:
int i;
public:
Base(int a) { i = a; }
virtual void display()
{ cout << "I am Base class object, i = " << i << endl; }
};
int main()
{
Base b(33); Derived
d(45, 54);
somefunc(b);
somefunc(d); // Object Slicing, the member j of d is sliced off return 0;
}
Output:
We can avoid above unexpected behavior with the use of pointers or references. Object slicing
doesn’t occur when pointers or references to objects are passed as function arguments since a
pointer or reference of any type takes same amount of memory. For example, if we change the
global method myfunc() in the above program to following, object slicing doesn’t happen.
Output:
We get the same output if we use pointers and change the program to following.
Output:
Object slicing can be prevented by making the base class function pure virtual there by disallowing
object creation. It is not possible to create the object of a class which contains a pure virtual method.
Abstract Class
Abstract Class is a class which contains atleast one Pure Virtual function in it. Abstract classes are
used to provide an Interface for its sub classes. Classes inheriting an Abstract Class must provide
definition to the pure virtual function, otherwise they will also become abstract class.
1. Abstract class cannot be instantiated, but pointers and refrences of Abstract class type can be
created.
2. Abstract class can have normal functions and variables along with a pure virtual function.
3. Abstract classes are mainly used for Upcasting, so that its derived classes can use its
interface.
4. Classes inheriting an Abstract Class must implement all pure virtual functions, or else they
will become Abstract too.
Pure virtual Functions are virtual functions with no definition. They start with virtual keyword and
ends with = 0. Here is the syntax for a pure virtual function,
int main()
{
Base obj; //Compile Time Error
Base *b;
Derived d;
b = &d;
b->show();
}
In the above example Base class is abstract, with pure virtual show() function, hence we cannot
31 P.T.O
create object of base class.
When we create a pure virtual function in Abstract class, we reserve a slot for a function in the
VTABLE(studied in last topic), but doesn't put any address in that slot. Hence the VTABLE will be
incomplete.
As the VTABLE for Abstract class is incomplete, hence the compiler will not let the creation of
object for such class and will display an errror message whenever you try to do so.
Statechart Diagrams
33 P.T.O
message.
Figure 2: Modeling Reactive Objects
Activity Diagrams
Activity Diagrams consist of activities, states and transitions between activities and states •
Activity Diagrams describe
– how activities are coordinated to provide a service
– the events needed to achieve some operation
– how the events in a single use case relate to one another
– how a collection of use cases coordinate to create a workflow for an organization.
– the service can be at different levels of abstraction
– in particular, use cases where activities may overlap and require coordination
Transitions
• A Transition is the movement from one activity to another, the change from one state to
another, or the movement between a state and an activity in either direction
• Transitions: unlabelled arrows from one activity to the next
• Transitions take place when one activity is complete and the next can commence