Unit - 2 Data Encapsulation & Inheritance: Rofel Bba & Bca College, Vapi
Unit - 2 Data Encapsulation & Inheritance: Rofel Bba & Bca College, Vapi
VAPI
UNIT – 2
DATA ENCAPSULATION & INHERITANCE
Object Oriented Programming and Data Structures
protected:
public:
// public members go here
};
1. Public
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 –
class Line
{
public:
double length;
};
int main() {
Line line;
// set line length without member function
line.length = 10.0; // OK: because length is public
cout << "Length of line : " << line.length <<endl;
return 0;
}
2. Private
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.
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.
class Box
{
private:
double width;
public:
double length;
void setWidth( double wid );
double getWidth( void );
};
// Member functions definitions
void Box::setWidth( double wid )
{
width = wid;
}
double Box::getWidth(void)
{
return width ;
}
// Main function for the program
int 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;
return 0;
}
3. Protected
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.
class Box
{
protected:
double width;
};
class SmallBox:Box
{
// SmallBox is the derived class.
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
int main()
{
SmallBox box;
// set box width using member function
box.setSmallWidth(5.0);
cout << "Width of box : "<< box.getSmallWidth() <<
endl;
return 0;
}
Specifying a class
A class is a way to bind the data and its associated functions together. It allows
the data (and functions) to be hidden, if necessary, from external use. When
defining a class, we are creating a new abstract data type that can be treated like
any other build-in data type.
Generally, a class specification has two parts:
1. Class declaration
2. Class function definitions
The class declaration describes the type scope of its members. The class function
definitions describe how the class functions are implemented.
The general form of a class declaration is:
class class_name
{
private:
variable declaration;
function declaration;
public:
variable declaration;
function declaration;
};
The class contain variables and functions. These functions and variables are
collectively called class members. They are usually grouped under two visibility
modes namely public and private.
The class members that have been declared as private can be accesses only from
within the class. Public members can be accessed from outside the class. By
default the members of the class are private.
The variable declared inside the class are known as data members and the
functions are known as member functions.
Declaring Objects:
When a class is defined, only the specification for the object is defined; no
memory or storage is allocated. To use the data and access functions defined in
the class, you need to create objects.
Syntax:
ClassName ObjectName;
void getData();
void putData();
};
Here the identifier Employee is a user defined data type and can be used to
create objects that relate to different categories of the employee
Example :
Employee manager[3]; //array of manager
Employee foreman[15]; //array of foreman
Employee worker[75]; //array of worker
The array manager contains three objects(managers), namely, manager[0],
manager[1] and manager[2] of type Employee class. Similarly the foreman array
contains 15 objects(foremen) and the worker array contains 75 objects(workers).
Since an array of objects behave like any other array, we can use the usual array
accessing methods to access individual elements and then the dot member
operator to access the member functions.
For example the statement manager[i].putdata(); will display the data of the ith
element of the array manager. That is. This statement request the object
manager[i] to invoke the member function putdata().
An array of objects is stored inside the memory in the same way as a multi-
dimensional array. The array manager is represents in following diagram.
Example:
class Employee
{
int eno;
char name[20];
public:
void getData();
void putData();
};
void Employee::getData()
{
cout<<"Enter Eno : ";
cin>>eno;
cout<<"Enter Ename : ";
cin>>name;
}
void Employee::putData()
{
};
void Time::getTime(int h,int m)
{
hour=h;
min=m;
}
void Time::display()
{
cout<<"\n"<<hour<<" Hours and "<<min<<" Minutes";
}
Time Time::sum(Time t2)
{
Time t3;
t3.min=min+t2.min;
t3.hour=t3.min/60;
t3.hour=hour+t2.hour+t3.hour;
t3.min=t3.min%60;
return t3;
}
int main()
{
Time t1,t2,t3;
t1.getTime(5,50);
t2.getTime(3,30);
t3=t1.sum(t2);
t1.display();
t2.display();
t3.display();
getch();
return 0;
}
Types of Inheritance
1. Single inheritance
2. Multilevel inheritance
3. Multiple inheritance
4. Hierarchical inheritance
5. Hybrid inheritance
1. Single Inheritance
In single inheritance, a class is allowed to inherit from only one class. i.e. one
sub class is inherited by one base class only.
Syntax:
class base_classname
{
properties;
methods;
};
class B
Example:
class Employee
{
int eno;
char name[20];
public:
void getData();
void setData();
};
void Employee::getData()
{
cout<<"Enter ENO: ";
cin>>eno;
cout<<"Enter Name";
cin>>name;
}
void Employee::setData()
{
cout<<"\nEno: "<<eno;
cout<<"\nName: "<<name;
}
class Dept:public Employee
{
char dname[20];
char desig[20];
float salary;
public:
void getDept();
void display();
};
void Dept::getDept()
{
cout<<"Enter Dname: ";
cin>>dname;
cout<<"Enter Desig: ";
cin>>desig;
cout<<"Enter Salary: ";
cin>>salary;
}
void Dept::display()
{
cout<<"\nDname: "<<dname;
cout<<"\nDesig: "<<desig;
cout<<"\nSalary: "<<salary;
}
int main()
{
Dept ob;
ob.getData();
ob.getDept();
ob.setData();
ob.display();
getch();
return 0;
}
2. Multilevel Inheritance
When a class is derived from a class which is also derived from another class
such inheritance is called Multilevel Inheritance. The level of inheritance can be
extended to any number of level depending upon the relation. Multilevel
inheritance is similar to relation between grandfather, father and child.
Syntax:
class base_classname
{
properties;
methods;
};
class intermediate_classname:visibility_mode base_classname
{
properties;
methods;
};
class child_classname:visibility_modeintermediate_classname
{
properties;
methods;
};
Example:
class Student
{
int rno;
char name[20];
public:
void getData();
void putData();
};
void Student::getData()
{
cout<<"Enter Roll no: ";
cin>>rno;
cout<<"Enter Name: ";
cin>>name;
}
void Student::putData()
{
cout<<"\nRoll No.= "<<rno;
cout<<"\n Name= "<<name;
}
class Score:public Student
{
protected:
int sub1;
int sub2;
public:
void getMarks();
void putMarks();
};
void Score::getMarks()
{
cout<<"Enter Mark1: ";
cin>>sub1;
cout<<"Enter Mark2: ";
cin>>sub2;
}
void Score::putMarks()
{
cout<<"\n Sub1= "<<sub1;
cout<<"\n Sub2= "<<sub2;
}
class Result:public Score
{
int total;
int per;
public:
void display();
};
void Result::display()
{
total=sub1+sub2;
per=total/2;
cout<<"\n Total= "<<total;
cout<<"\n Per= "<<per;
}
int main()
{
clrscr();
Result r;
cout<<"Enter Students Information\n";
r.getData();
r.getMarks();
cout<<"\n ===Students Information===";
r.putData();
r.putMarks();
r.display();
getch();
return 0;
}
3. Multiple Inheritance
In multiple inheritance a class can inherit from more than one classes. i.e
one sub class is inherited from more than one base classes. It allow us to
combine the features of several existing classes into a single class.
Syntax:
class base_class1
{
properties;
methods;
};
class base_class2
{
properties;
methods;
};
class derived_classname : visibility_mode base_class1,
visibility_mode base_class2
{
properties;
methods;
};
Example:
#include<iostream.h>
#include<conio.h>
class M
{
protected:
int m;
public:
void get_m(int i)
{
m=i;
}
void set_m()
{
cout<<"\n M="<<m;
}
};
class N
{
protected:
int n;
public:
void get_n(int j)
{
n=j;
}
void set_n()
{
cout<<"\n N="<<n;
}
};
class P:public M,public N
{
public:
void display()
{
set_m();
set_n();
cout<<"\n m*n= "<<m*n;
}
};
int main()
{
clrscr();
P ob;
ob.get_m(10);
ob.get_n(20);
ob.display();
getch();
return 0;
}
4. Hierarchical inheritance
When more than one classes are derived from a single base class, such
inheritance is known as Hierarchical Inheritance, where features that are
common in lower level are included in parent class.
Syntax:
class base_classname
{
properties;
methods;
};
int x, y;
void getdata()
{
cout << "\nEnter value of x and y:\n";
cin >> x >> y;
}
};
class B : public A //B is derived from class base
{
public:
void product()
{
cout << "\nProduct= " << x * y;
}
};
class C : public A //C is also derived from class base
{
public:
void sum()
{
cout << "\nSum= " << x + y;
}
};
int main()
{
B obj1; //object of derived class B
C obj2; //object of derived class C
obj1.getdata();
obj1.product();
obj2.getdata();
obj2.sum();
return 0;
}
5. Hybrid inheritance
There could be situations where we need to apply two or more types of
inheritance to design a program. This type of inheritance is called as Hybrid
inheritance
class A class A
class D class D
Example:
class Student
{
int rno;
char name[20];
public:
void getData();
void putData();
};
void Student::getData()
{
cout<<"Enter Roll no: ";
cin>>rno;
cout<<"Enter Name: ";
cin>>name;
}
void Student::putData()
{
cout<<"\nRoll No.= "<<rno;
cout<<"\n Name= "<<name;
}
class Score:public Student
{
protected:
int sub1,sub2;
public:
void getMarks();
void putMarks();
};
void Score::getMarks()
{
cout<<"Enter Mark1: ";
cin>>sub1;
cout<<"Enter Mark2: ";
cin>>sub2;
}
void Score::putMarks()
{
cout<<"\n Sub1= "<<sub1;
cout<<"\n Sub2= "<<sub2;
}
class Sport
{
protected:
int sub;
public:
void getSport();
void putSport();
};
void Sport::getSport()
{
cout<<"Enter score: ";
cin>>sub;
}
void Sport::putSport()
{
cout<<"\n Score= "<<sub;
}
class Result:public Score,public Sport
{
int total;
int per;
public:
void display();
};
void Result::display()
{
total=sub1+sub2+sub;
per=total/3;
cout<<"\n Total= "<<total;
cout<<"\n Per= "<<per;
}
int main()
{
Result r;
cout<<"Enter Students Information\n";
r.getData();
r.getMarks();
r.getSport();
cout<<"\n ===Students Information===";
r.putData();
r.putMarks();
r.putSport();
r.display();
getch();
return 0;
}
// y is protected
// z is not accessible from protectedDerived
};
int base::get_x()
{
return x;
}
int base::get_y()
{
return y;
}
void base:: getdata()
{
x=100;
y=200;
}
void base::display()
{
cout<<x<<endl;
cout<<y<<endl;
}
void derived::sum()
{
getdata();
display();
cout<<"\n Sum is : "<<get_x()+get_y();
}
int main()
{
clrscr();
derived d;
d.sum();
}
In the above program, x and y are private data member defined in the class base.
Only the methods getdata () and display () in the class Base can access this field
directly by name from within its definition.
However, it is not accessible to any other class including the Derived subclass.
So to do sum of x and y in sum() we have to create another functions in public
section get_x() and get_y() that return the value of x and y respectively. After
calling that functions in sum function of derived class we can perform addition
on x and y.
‘Inheritance by the ‘child’ as shown in above figure might pose some problems.
All the public and protected members of ‘grandparent’ are inherited into ‘child’
twice, first via ‘parent1’ and 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 as shown below :
class A //grandparent
{
…….
…….
};
class B1 : virtual public A //parent1
{
…….
…….
};
class B2 : public virtual A //parent2
{
……..
…….
};
class c : public B1, public B2 //child
{
…….. //only one copy of A will be inherited
……..
};
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
paths exist between the virtual base class and a derived class.
m=0;
n=0;
}
}
When a class contain a constructor then when object is created, it will be
initialized automatically.
Like Integer int1; statement not only create the object int1 of type Integer but
also initializes its data member m and n to zero.
Characteristics:
o They should be declared in the public section.
o They are invoked automatically when the objects are created.
o They do not have return types, not even void and therefore they cannot
return values.
o They cannot be inherited, though a derived class can call the base call
constructor.
o They can have default arguments.
Following are types of constructors.
Integer(int a, int b)
{
m=a;
n=b;
}
Copy constructor: The parameters of a constructor can be of any type except
that of the class to which it belongs. A constructor can accept a reference to its
own class as a parameter. This type of constructor is called copy constructor.
E.g.,
Integer(Integer &I)
{
m=I.m;
n=I.n;
}
To invoked copy constructor we have to write a statement like, Integer I2(I1);
which copies the values of I1 into I2. In other words, it sets the value of every
data element of I2 to the value of the corresponding data element of I1
We can call constructor in two ways:
a. By calling the constructor explicitly.
b. By calling the constructor implicitly.
The following declaration illustrates the first method :
Integer int1=Integer(0,100); // Explicit call
This statement creates an integer object int1 and passes the values 0 and 100 to
it.
The following declaration illustrates the second method :
Integer int1(0,100); // Implicit call
This method, sometimes called the shorthand method.
image=b;
}
Complex(Complex &c)
{
real=c.real;
image=c.image;
}
friend void show(Complex);
friend Complex sum(Complex,Complex);
};
void show(Complex c)
{
cout<<c.real<<"+j"<<c.image<<endl;
}
Complex sum(Complex c1,Complex c2)
{
Complex c3;
c3.real=c1.real+c2.real;
c3.image=c1.image+c2.image;
return c3;
}
int main()
{
clrscr();
Complex c1(3); // invoked single parameterized constructor
Complex c2(5,3); // invoked two parameter constructor
Complex c3(c2);// invoked copy constructor
cout<<"C1 : ";show(c1);
cout<<"C2 : ";show(c2);
cout<<"C3 : ";show(c3);
Complex c4;
c4=sum(c1,c2); //invoked sum function
cout<<"C1 + C2 = ";show(c4);
getch();
return 0;
}
int m,n;
public:
integer()
{
m=0;
n=0;
}
}
When a class contain a constructor then when object is created, it will be
initialized automatically.
Like Integer int1; statement not only create the object int1 of type Integer but
also initializes its data member m and n to zero.
Characteristics:
o They should be declared in the public section.
o They are invoked automatically when the objects are created.
o They do not have return types, not even void and therefore they cannot
return values.
o They cannot be inherited, though a derived class can call the base call
constructor.
o They can have default arguments.
class String
{
int length;
char *name;
public:
String()
{
length=0;
name = new char[length+1];
}
String(char *s)
{
length=strlen(s);
name = new char[length+1];
strcpy(name,s);
}
void display()
{
Destructor
A destructor is a special member function that works just opposite to
constructor, unlike constructors that are used for initializing an object,
destructors destroy (or delete) the object.
Syntax:
~class_name()
{
//Some code
}
Similar to constructor, the destructor name should exactly match with the class
name. A destructor declaration should always begin with the tilde(~) symbol as
shown in the syntax above.
A destructor is automatically called when:
o The program finished execution.
o When a scope (the { } parenthesis) containing local variable ends.
o When you call the delete operator.
Destructor name should begin with tilde sign(~) and must match class name.
There cannot be more than one destructor in a class.
Unlike constructors that can have parameters, destructors do not allow any
parameter.
They do not have any return type, just like constructors.
When you do not specify any destructor in a class, compiler generates a default
destructor and inserts it into your code.
Example:
int count=0;
class Test
{
public:
Test()
{
count++;
cout<<"\n Object Created Number : "<<count;
}
~Test()
{
cout<<"\n Object Destroyed Number : "<<count;
count--;
}
};
int main()
{
clrscr();
cout<<"\n Inside Main Function";
Test t1;
{
cout<<"\n Inside Block";
Test t2,t3;
cout<<"\n Exit From Block";
}
cout<<"\n Inside Main Again";
Test t4;
cout<<"\n Exit From Main";
getch();
}
Since the derived class takes the responsibility of supplying initial values to its
base classes, we supply the initial values that are required by all the classes
together, when a derived class object is declare. C++ supports a special
argument passing mechanism for such situations.
The constructors of the derived class receives the entire list of values as its
arguments and pass them on to the base constructor in the order in which they
are declared in the derived class.
The bas constructors are called and executed before executing the statements in
the body of the derived constructor.
The general form of defining a derived constructor is :
D(int a1, int a2, float b1, float b2, int d1) :
A(a1,a2), //call to constructor A
B(b1,b2) //call to constructor B
{
d=d1; //Executes its own body
}
Here A(a1,a2) invokes the base constructor A() and B(b1,b2) invokes another bas
constructor B(). The constructor D() supplies the values for these four
arguments.
In addition, it has one argument of its own. The constructor D() has a total of
five arguments. D() may be invoked as follows:
D objD(5,12,2.5,7.54,30);
The values are assigned to various parameters by the constructor D() as follows :
5 a1
12 a2
2.5b1
7.54 b2
30 d1
The constructor for virtual base classes is invoked before any non virtual base
classes. If there are multiple virtual base classes, they are invoked in the order in
which they are declared.
Any non virtual bases are then constructed before the derived class constructor
is executed.
Method of Inheritance Order of execution
Class B : public A A(); base constructor
{ B();derived constructor
}
Class A: public B, public C B(); base(first)
{ C(); base(second)
} A(); derived
Class A : public B, virtual public C C(); virtual base
{ B(); ordinary base
} A(); derived
C++ support another method of initializing the class objects. This method
uses what is known as initialization list in the constructor function. This
takes the following form :
The assignment-section is nothing but the body of the constructor function and
is used to assign initial values to its data members. The part immediately
following the colon is known as the initialization section.
We can use this section to provide initial values to the base constructors and also
to initialize its own class members.
This means that we can use either of the sections to initialize the data members
of the constructor class.
The initialization section basically contains a list of initializations separated by
commas. This list is known as initialization list.
E.g.,
Class XYZ
{
int a;
int b;
public:
XYZ(int i , int j) : a(i) , b(2 * j) { }
};
int main()
{
XYZ x(2,3);
}
This program will initialize a to 2 and b to 6.
Destructor in inheritance
Destructor is used to destroy the object of the class. Destructors for a derived
class object are called in reverse order of the constructors for the object. It mean
constructors are invoked starting with the base class constructor and then
derived class constructor, whereas the destructor for the derived class is called
first when an object is destroyed, followed by the base class destructor.
Method of Inheritance Order of execution of
destructor
Class B : public A B(); derived destructor
{ A(); base destructor
}
Class A: public B, public C A();derived destructor
{ C();base destructor
} B();base destructor
Class A : public B, virtual public C A();derived destructor
{ C();base destructor
} B();base destructor
Example:
class A
{
public:
A()
{
cout<<"\nConstructor of Base Class A";
}
~A()
{
cout<<"\nDestructor of Base Class A";
}
};
class B
{
public:
B()
{
cout<<"\nConstructor of Base Class B";
}
~B()
{
cout<<"\nDestructor of Base Class B";
}
};
class C:public A,public B
{
public:
C()
{
// Container class
class second {
public:
void showf()
{
cout << "Hello from first class\n";
}
};
// Container class
class second {
// creating object of first
first f;
public:
// constructor
second()
{
// calling function of first class
f.showf();
}
};
int main()
{
// creating object of second
second s;
}
Inheritance is the ability for a class to inherit properties and behavior from a
parent class by extending it, while Containership is the ability of a class to
contain objects of different classes as member data.
If a class is extended, it inherits all the public and protected properties/behavior
and those behaviors may be overridden by the subclass. But if a class is
contained in another, the container does not get the ability to change or add
behavior to the contained.
Inheritance represents an “is-a” relationship in OOP, but Containership
represents a “has-a” relationship.