Вы находитесь на странице: 1из 51

Oops teaching notes

C++ and Object Oriented Programming


UNIT I
The fundamental idea behind object-oriented languages is to combine both data and the functions
that operate on that data into a single unit. Such a unit is called an object.

Object-Oriented Programming is a methodology or paradigm to design a program using classes and


objects. It simplifies the software development and maintenance.

Objects are instances of classes and are used to interact amongst each other to create applications.
Instance means, the object of class on which we are currently working.

For Example : We consider human body as a class, we do have multiple objects of this class, with
variable as color, hair etc. and methods as walking, speaking etc.

Some of the main features of object oriented programming which you will be using in C++.

Objects

Classes

Abstraction

Encapsulation

Inheritance

Overloading
Oops teaching notes

Exception Handling

Objects
Objects are the basic unit of OOP. They are instances of class, which have data members and uses
various member functions to perform tasks.

Class
It is similar to structures in C language. Class can also be defined as user defined data type but it also
contains functions in it. So, class is basically a blueprint for object. It declare& defines what data
variables the object will have and what operations can be performed on the class's object.

Abstraction
Abstraction refers to showing only the essential features of the application and hiding the details. In
C++, classes provide methods to the outside world to access & use the data variables, but the
variables are hidden from direct access.

Encapsulation
It can also be said data binding. Encapsulation is all about binding the data variables and functions
together in class.

Inheritance
Inheritance is a way to reuse once written code again and again. The class which is inherited is called
base calls & the class which inherits is called derived class. So when, a derived class inherits a base
class, the derived class can use all the functions which are defined in base class, hence making code
reusable.

Polymorphism
Polymorphion makes the code more readable. It is a features, which lets is create functions with same
name but different arguments, which will perform differently. That is function with same name,
functioning in different

Overloading
Overloading is a part of polymorphion. Where a function or operator is made & defined many times,
to perform different functions they are said to be overloaded.

Exception Handling
Oops teaching notes

Exception handling is a feature of OOP, to handle unresolved exceptions or errors produced at


runtime.

Object Oriented Programming has great advantages over other programming styles:

Code Reuse and Recycling: Objects created can easily be reused in other programs.

Encapsulation (part 1): Once an Object is created, knowledge of its implementation is not necessary
for its use. In older programs, coders needed understand the details of a piece of code before using it.

Encapsulation (part 2): Objects have the ability to hide certain parts of themselves from
programmers. This prevents programmers from tampering with values they shouldn't.

Design Benefits: Large programs are very difficult to write. Object Oriented Programs force designers
to go through an extensive planning phase, which makes for better designs with less flaws.

Software Maintenance: An Object Oriented Program is much easier to modify and maintain. So
although some additional work is spent before the program is written, less work is needed to
maintain it over time.

Defining Class and Declaring Objects


When we define any class, we do not defining any data,but we just define a structure, as to what the
object of that class type will contain and what operations can be performed on that object.

Below is the syntax of class definition,

Class ClassName
{
Access specifier:
Data members;
MemberFunctions()
{

}
};

Here is an example, we have made a simple class named Student with appropriate members,

class Student
{
public:
introllno;
string name;
};

int main()
{
Oops teaching notes

Student A;
Student B;
}

Example:

#include<iostream>
using namespace std;

class Test
{
public:
int add(int a,int b)
{
int sum;
sum=a+b;
return sum;
}
int sub(int a,int b)
{
int dif;
dif=a-b;
return dif;
}
};
int main()
{
Test o1;
int a,b;
cout<<"\n\t\tEnter values ";
cin>>a>>b;
cout<<"\n\t\tAdditon is "<<o1.add(a,b)<<endl;
cout<<"\n\t\tDifference is "<<o1.sub(a,b)<<endl;

return 0;
}
Output:
Enter values 5
4
Addition is 9
Difference is 1

Here A and B are the objects of class Student, declared with the class definition.

Pointers to class members


Oops teaching notes

Just like pointers to normal variables and functions, we can have pointers to class member functions
and member variables.

Defining a pointer of class type

We can define pointer of class type, which can be used to point to class objects.

class Simple
{
public:
int a;
};

int main()
{
Simple z;
Simple*p; // Pointer of class type
p = &z;

cout<< z.a;
cout<< p->a; // Accessing member with pointer
}

In the above example we can see the declaration of a pointer of class type which points to class's
object.

We can access data members and member functions using pointer name with arrow -> symbol.

Constructors
Constructors are special class functions which perform initialization of every object. The Compiler calls
the Constructor whenever an object is created. Constructors initialize values to object members after
memory space is allocated to the object.
classTest
{
int x;
public:

Test(); //Constructor
};
Test::Test() // Constructor expansion
{
x=1;
}
Oops teaching notes

While defining a contructor we must remember that the name of constructor will be same as the
name of the class, and contructors never have return type.

Types of Constructors
Constructors are of three types:

1.Default Constructor 2. Parameterized Constructor 3. Copy Constructor

Default Constructor
Default constructor is the constructor which doesn't take any argument. It has no parameter.

Syntax :
class name ()
{
Constructor Definition
}

Example 1 :

class Cube
{
int side;
public:
Cube()
{
side=10;
}
};

void main()
{
Cube c;
cout<<c.side;
}

Output : 10

In this case, as soon as the object is created the constructor is called which initializes its data
members.

A default constructor is so important for initialization of object members, that even if we do not
define a constructor explicitly, the compiler will provide a default constructor implicitly.

class Cube
{
int side;
Oops teaching notes

};

void main()
{
Cube c;
cout<<c.side;
}
Output : 0

In this case, default constructor provided by the compiler will be called which will initialize the object
data members to default value,that will be 0 in this case.

Parameterized Constructor
These are the constructors with parameter. Using this Constructor you can provide different values to
data members of different objects, by passing the appropriate values as argument.

Example :
class Cube
{
int side;
public:
Cube(int x)
{
side=x;
}
};

void main()
{
Cube c1(10);
Cube c2(20);
Cube c3(30);
cout<< c1.side;
cout<< c2.side;
cout<< c3.side;
}
OUTPUT : 10 20 30
By using parameterized constructor in above case, we have initialized 3 objects with user defined
values. We can have any number of parameters in a constructor.

Copy Constructor
These are special type of Constructors which takes an object as argument, and is used to copy values
of data members of one object into other object.

Example for Constructor (default, parameterized, copy) :


#include<iostream>
Oops teaching notes

using namespace std;


class Student
{
public:
int id;

Student():id(2)
{
//cout<<"\n\t\t Default constructor called"<<endl;
//id=-1;
}

Student(int x) //Parameterized constructor


{
cout<<"\n\t\t Parameterized constructor called"<<endl;
id=x;
}

Student(const Student &obj2) //copy constructor


{
id=obj2.id;
}
};
int main()
{
student obj1;
cout<<"\n\t\t Student id is "<<obj1.id<<endl;
obj1.id=7;
cout<<"\n\t\t Student id is "<<obj1.id<<endl;
student obj2=obj1;
cout<<"\n\t\t Student id is : "<<obj2.id<<endl;
student obj3(21);
cout<<"\n\t\t Student id is : "<<obj3.id<<endl;

return 0;
}

Output:
Student id is 2
Student id is 7
Student id is : 7
Parameterized constructor called
Student id is : 21

Constructor Overloading
Just like other member functions, constructors can also be overloaded. Infact when we have both
default and parameterized constructors defined in a classwe are having Overloaded Constructors, one
with no parameter and other with parameter.

we can have any number of Constructors in a class that differ in parameter list.
Oops teaching notes

class Student
{
Int rollno;
string name;

public:

Student(int x)
{
rollno=x;
name="None";
}

Student(int x, string str)


{
rollno=x ;
name=str ;
}
};

void main()
{
Student A(10);

Student B(1001,"Pushkal");
}
Example :

#include<iostream>
using namespace std;
class Area
{
private:
int length;
int breadth;
public:
Area():length(5),breadth(2)
{

}
Area(int l,int b):length(l),breadth(b)
{

}
void GetLength()
{
cout<<"\n\t\tEnter values ";
cin>>length>>breadth;
}
int Areacalc()
{
int A;
Oops teaching notes

A=length*breadth;
return A;
}
void DisplayArea(int temp)
{
cout<<"\n\t\t Area "<<temp<<endl;
}
};
int main()
{
Area A1,A2(2,1);
int temp;
cout<<"\n\t\t Default area when no argument is passed "<<endl;
temp=A1.Areacalc();
A1.DisplayArea(temp);

cout<<"\n\t\t Area when (2,1) is passed as argument "<<endl;


temp=A2.Areacalc();
A2.DisplayArea(temp);

return 0;

}
Output:
Default area when no argument is passed
Area 10
Area when (2,1) is passed as argument
Area 2
In above case we have defined two constructors with different parameters, hence overloading the
constructors.

One more important thing, if you define any constructor explicitly, then the compiler will not provide
default constructor and you will have to define it yourself.

Destructors
Destructor is a special class function which destroys the object as soon as the scope of object ends.
The destructor is called automatically by the compiler when the object goes out of scope.

The syntax for destructor is same as that for the constructor, the class name is used for the name of
destructor, with a tilde ~ sign as prefix to it.
class Test
{
public:
~Test();
};
Oops teaching notes

Destructors will never have any arguments.

Example to show how Constructor and Destructor is called


classTest
{
Test()
{
cout<< "Constructor called";
}

~Test()
{
cout<< "Destructor called";
}
};

void main()
{
Test z1; // Constructor Called for object z1
int x=1;

if(x)
{
Testz2; // Constructor Called for object z2
} // Destructor Called for obj z2
} // Destructor called for obj z1

Another Example for Destructor:

#include<iostream>
using namespace std;
class student
{
public:
int id;
~student()
{
cout<<"\n\t\tDestructor called for id: "<<id<<endl;
}
};
int main()
{
student obj1;
obj1.id=7;
int i=0;
while(i<5)
{
student obj2;
obj2.id=i;
i++;
}
Oops teaching notes

return 0;
}

Output:

Destructor called for id: 0


Destructor called for id: 1
Destructor called for id: 2
Destructor called for id: 3
Destructor called for id: 4
Destructor called for id: 7

What is a copy constructor?

A copy constructor is a member function which initializes an object using another object of the same
class. A copy constructor has the following general function prototype:

ClassName (constClassName&old_obj);
Following is a simple example of copy constructor.

classPoint
{
private:
intx, y;
public:
Point(intx1, inty1) { x = x1; y = y1; }

// Copy constructor
Point(constPoint&p2) {x = p2.x; y = p2.y; }

intgetX()
{ returnx; }

intgetY()
{ returny; }
};

voidmain()
{
Point p1(10, 15); // Normal constructor is called here
Point p2 = p1; // Copy constructor is called here

// Accessing the values assigned by constructor


cout<< "p1.x = "<< p1.getX() << ", p1.y = "<< p1.getY();

cout<< "\np2.x = "<< p2.getX() << ", p2.y = "<< p2.getY();


Oops teaching notes

Output:
p1.x = 10, p1.y = 15
p2.x = 10, p2.y = 15

In C++, a Copy Constructor may be called in following cases:


1. When an object of the class is returned by value.
2. When an object of the class is passed (to a function) by value as an argument.
3. When an object is constructed based on another object of the same class.
4. When compiler generates a temporary object.

UNIT II
Friend Functions in C++:-

It is a type of a function which has the permission to access the private and protected members of a
class. Normally private and protected members of a class could not be accessed from outside the
class but in some cases the program may have to access the private or protected variables to perform
the functionality. In that case we declare a function in a class with a friend keyword whose private
members are required to access by the program. Therefore, this function will be able to access
members .

Two classes having a common friend function

class B; // prior declaration

class A
{
private:
int a;
Oops teaching notes

public:
A()
{
a=25;
}
friend void show(A,B);
};

ClassB
{
private:
int b;
public:
B()
{
b=35;
}
friend void show(A,B);
};

void show(A x,By)


{
int r;
r= x.a + y.b;
cout<<”The value of class A object =”<<x.a<<endl;
cout<<”The value of class B object =”<<y.b<<endl;
cout<<”The sum of both values =”<<r<<endl;
}

voidmain( )
{
A obj1;
B obj2;
show(obj1, obj2);
getch( );
}

In the above program, first of all we have declared a class B, we are just declaring it, so when we write
a signatures of a friend function, we will use both classes A and B so that the compiler do not object.

In a class we will declare one integer type private data member and initialize it to a value 25 in a
constructor of A. Then we will define a function with the friend keyword which contains parameters
as both classes. Then we will write the definition of class B. This class will also declares a one private
data member and initialize it to a value 35 in a constructor of class B.

Then it will declare a function with a friend keyword whose signatures are both classes. Then we will
write the definition of a friend function show, in which we will show the value of the private data
members of both classes. Then in main function we will simply create the objects of these classes and
call the friend function Show to display their respective fields.
Oops teaching notes

Friend classes in C++:-

These are the special type of classes whose all of the member functions are allowed to access the
private and protected data members of a particular class is known as friend class. Normally private
and protected members could not be accessed from outside the class but in some situations the
program has to access them in order to produce the desired results. In such situations the friend
classes are used, the use of friend classes allows a class to access these members of another class.

The syntax of declaring a friend class is not very tough, simply if a class is declared in another class
with a friend keyword it will become the friend of this class.

The below example will completely illustrate the use of a friend classes.

class A
{
friend class B;

private:
int a;
public:
A( )
{
a=10;
}
};

class B
{
public:

void show(A obj)


{
cout<< ”The value of a: ”<< obj.a <<endl;
}
};

void main( )
{
A x;
B y;
y.show(x);
getch( );
}
In the above example we have declared two classes A and B. In A we simply declared an integer type
private data member and initialized them in a constructor. In this class we have also declared a class B
with a friend keyword which makes B the friend of class A. Therefore all the member functions of B
will be able to access the private data members of A. Then in class B we simply created a function
show( ) which have a permission to access the private members of class A. Then we will display the
values of the attributes of the object of class A.
Oops teaching notes

What is inline function :

The inline functions are a C++ enhancement feature to increase the execution time of a
program. Functions can be instructed to compiler to make them inline so that compiler can replace
those function definition wherever those are being called. Compiler replaces the definition of inline
functions at compile time instead of referring function definition at runtime.
NOTE- This is just a suggestion to compiler to make the function inline, if function is big (in term of
executable instruction etc) then, compiler can ignore the “inline” request and treat the function as
normal function.

How to make function inline:

To make any function as inline, start its definitions with the keyword “inline”.
Syntax : inline returntype functionName(arguments)

Example –

1 Class A
2 {
3 Public:
4 inline int add(int a, int b)
5 {
6 return (a + b);
7 };
8 }
9
10 Class A
11 {
12 Public:
13 int add(int a, int b);
14 };
15
16 inline int A::add(int a, int b)
17 {
18 return (a + b);
19 }

When to use -
Function can be made as inline as per programmer need. Some useful recommendation are
mentioned below-
1. Use inline function when performance is needed.
2. Use inline function over macros.
3. Prefer to use inline keyword outside the class with the function definition to hide implementation
details.

Pros:-
1. It speeds up your program by avoiding function calling overhead.
Oops teaching notes

2. It save overhead of variables push/pop on the stack, when function calling happens.
3. It save overhead of return call from a function.
4. It increases locality of reference by utilizing instruction cache.
5. By marking it as inline, you can put a function definition in a header file (i.e. it can be included in
multiple compilation unit, without the linker complaining)

Cons:-
1. It increases the executable size due to code expansion.
2. C++ inlining is resolved at compile time. Which means if you change the code of the inlined
function, you would need to recompile all the code using it to make sure it will be updated
3. When used in a header, it makes your header file larger with information which users don’t care.
4. As mentioned above it increases the executable size, which may cause thrashing in memory. More
number of page fault bringing down your program performance.
5. Sometimes not useful for example in embedded system where large executable size is not
preferred at all due to memory constraints.

Static class members:


We can define class members static using static keyword. When we declare a member of a class
as static it means no matter how many objects of the class are created, there is only one copy of the
static member.

A static member is shared by all objects of the class. All static data is initialized to zero when the first
object is created, if no other initialization is present. We can't put it in the class definition but it can
be initialized outside the class as done in the following example by redeclaring the static variable,
using the scope resolution operator :: to identify which class it belongs to.

Example program:
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;

// Constructor definition
Box(double l = 2.0, double b = 2.0, double h = 2.0) {
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;

// Increase every time object is created


objectCount++;
}
double Volume() {
return length * breadth * height;
}
Oops teaching notes

private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};

// Initialize static member of class Box


int Box::objectCount = 0;

int main(void)
{
Box Box1(3.3, 1.2, 1.5); // Declare box1
Box Box2(8.5, 6.0, 2.0); // Declare box2

// Print total number of objects.


cout << "Total objects: " << Box::objectCount << endl;
return 0;
}

Output :
Constructor called.
Constructor called.
Total objects: 2

Static Function Members :


By declaring a function member as static, you make it independent of any particular object of the
class. A static member function can be called even if no objects of the class exist and the static
functions are accessed using only the class name and the scope resolution operator ::.

A static member function can only access static data member, other static member functions and
any other functions from outside the class.

Static member functions have a class scope and they do not have access to the this pointer of the
class. You could use a static member function to determine whether some objects of the class have
been created or not.

Example program :
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;
// Constructor definition
Box(double l = 2.0, double b = 2.0, double h = 2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
Oops teaching notes

height = h;

// Increase every time object is created


objectCount++;
}
double Volume()
{
return length * breadth * height;
}
static int getCount()
{
return objectCount;
}

private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};

// Initialize static member of class Box


int Box::objectCount = 0;

int main(void)
{
// Print total number of objects before creating object.
cout << "Inital Stage Count: " << Box::getCount() << endl;

Box Box1(3.3, 1.2, 1.5); // Declare box1


Box Box2(8.5, 6.0, 2.0); // Declare box2

// Print total number of objects after creating object.


cout << "Final Stage Count: " << Box::getCount() << endl;

return 0;
}
Output :
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2

What is this pointer?

Every object has a special pointer called "this" which points to the very object itself.

This pointer is accessible to all members of the class but not to any static members of the class.

this pointer can be used to find the address of the object in which the function is a member.

Example:
Oops teaching notes

#include<iostream>
using namespace std;
class Test
{
public:
int d;
Test()
{ d=100; };
void Print1();
void Print2();
};

void Test :: Print1() // without using this pointer

{
cout<< d <<endl;
}

void Test::Print2() // By Using this pointer

{
cout<< "My address = " << this <<endl;
cout<< this->d <<endl;
};
int main()
{
Test a;
a.Print1( );
a.Print2( );
return 0;
}

Output:
100
My address = 0x24fe40
100

Inheritance :

Inheritance allows a programmer to define a new class in terms of an existing class, which makes it
easier to create and maintain an application. This also provides an opportunity to reuse the code
functionality and fast implementation time.

The derived class inherits all features from a base class and it can have additional features of its own.
Oops teaching notes

This existing class is called the base class, and the new class is referred to as the derived class. The
derived class inherits all the capabilities of the base class. Reusing existing code saves time and
money and increases a program’s reliability. Inheritance can also help in the original
conceptualization of a programming problem, and in the overall design of the program.

In C++, we have 5 different types of Inheritance. Namely,

1.Single Inheritance

2.Multiple Inheritance

3. Hierarchical Inheritance

4. Multilevel Inheritance

5. Hybrid Inheritance (also known as Virtual Inheritance)

Single Inheritance
In this type of inheritance one derived class inherits from only one base class. It is the most simplest
form of Inheritance.
Oops teaching notes

Syntax of Single inheritance

class derived-class : access-specifier base-class

Where access-specifier is one of public, protected, or private, and base-class is the name of a
previously defined class. If the access-specifier is not used, then it is private by default.

Example for Single inheritance

class Rectangle
{
... .. ...
};
class Area : public Rectangle
{
... .. ...
};

class Perimeter : public Rectangle


{
.... .. ...
};

Example for single inheritance:

#include<iostream>
using namespace std;

class Parent
{
public:
int id_p;
};

class Child : public Parent


{
public:
int id_c;
};
int main()
{

Child obj1;
obj1.id_c=7;
obj1.id_p=70;
cout<<"\n\t\tChild id is "<<obj1.id_c<<endl;
cout<<"\n\t\tParent id is "<<obj1.id_p<<endl;

return 0;
Oops teaching notes

Output:

Child id is 7
Parent Id is 70

Multiple Inheritance
In this type of inheritance a single derived class may inherit from two or more than two base classes.

Syntax of Multiple Inheritance:


A C++ class can inherit members from more than one class and here is the extended syntax:

class derived-class: access base A, access base B....

Where access is one of public, protected, or private and would be given for every base class and they
will be separated by comma as shown above.

Example for multiple inheritance

#include<iostream>
using namespace std;

class Vehicle
{
public:
Vehicle()
{
cout<<"\n\t\tThis is a vehicle"<<endl;
}
};

class FourWheeler
{
public:
Oops teaching notes

FourWheeler()
{
cout<<"\n\t\tThis is a 4 wheeler Vehicle"<<endl;
}
};
class Car : public Vehicle, public FourWheeler
{

};
int main()
{
Car obj1;

return 0;
}

Output:
This is a vehicle
This is a 4 wheeler Vehicle

Example for multiple inheritance

#include<iostream>
using namespace std;
class Names
{
public:
Names()
{
char name[20];
cout<<"\n\t\tEnter student name ";
cin>>name;
cout<<"\n\t\tName of the student is "<<endl;
cout<<name;
}
};

class Marks
{
public:
Marks()
{
int m1,m2,m3,total;
cout<<"\n\t\tEnter the marks ";
cin>>m1>>m2>>m3;
total=m1+m2+m3;
cout<<"\n\t\tTotal Marks of the student "<<total<<endl;
}
};
class Info : public Names, public Marks
{

};
int main()
Oops teaching notes

{
Info obj1;

return 0;
}

Output:
Enter student name ABC
Name of the student is ABC
Enter the marks 91
92
93
Total Marks of the student 276

Hierarchical Inheritance
In this type of inheritance, multiple derived classes inherit from a single base class.

Example for Hierarchical inheritance

#include<iostream>
using namespace std;
class Vehicle
{
public:
Vehicle()
{
cout<<"\n\t\tThis is a vehicle"<<endl;
}
};
class FourWheeler : public Vehicle
{
public:
FourWheeler()
{
cout<<"\n\t\tThis is a 4 wheeler Vehicle"<<endl;
}
};
class Car : public FourWheeler
{
public:
Car()
Oops teaching notes

{
cout<<"\n\t\tCar has 4 wheels"<<endl;
}
};
int main()
{
Car obj1;
return 0;
}

Output:
This is a vehicle
This is a 4 wheeler Vehicle
Car has 4 wheels

Example for hierarchical inheritance(marks incre/decre using scope resolution)

#include<iostream>
using namespace std;
class marks
{
public: int m;
public: int readm()
{
cout<<"\n\t\tEnter m value : "<<endl;
cin>>m;
cout<<m<<endl;
return 0;
}
};
class markincr:public marks
{
public:
int i;
public:
int incr()
{
i=marks::m+1;
cout<<i<<endl;
return i;
}
};
class markdecr:public marks
{
public:
int i;
public:
int decr()
{
i=marks::m-1;
cout<<i<<endl;
return i;
}
};
Oops teaching notes

int main()
{
markincr mk;
markdecr md;
mk.readm();
cout<<mk.incr()<<endl;
md.readm();
cout<<md.decr()<<endl;

return 0;
}

Output:
Enter m value: 90
90
91
91
Enter m value: 91
91
90
90

Multilevel Inheritance
In this type of inheritance the derived class inherits from a class, which in turn inherits from some
other class. The Super class for one, is sub class for the other.

Example for Multilevel inheritance


#include<iostream>

using namespace std;

class Vehicle
{
public :
void vehicle()
{
cout << " This is a Vehicle. " << endl;
}
};
Oops teaching notes

class Fourwheeler : public Vehicle


{
public :
void fourwheeler()
{
cout << " This is a 4 wheeler. " << endl;
}
};

class Car : public Fourwheeler


{
public:
void car()
{
cout << " The car has four wheels." << endl;
}
};

int main()
{
Car c;
c.car();

return 0;
}

Output:
This is a Vehicle.
This is a 4 wheeler.
The car has four wheels.

Hybrid (Virtual) Inheritance


Hybrid Inheritance is combination of Hierarchical and Mutilevel Inheritance.

Access Control in Classes :


Oops teaching notes

Access specifiers are keywords in object-oriented languages that set the accessibility of classes,
methods, and other members.

Access specifiers in C++ class defines the access control rules. C++ has 3 new keywords introduced,
namely,

public, private and protected.

These access specifiers are used to set boundaries for availability of members of class be it data
members or member functions.

Public
Public, means all the class members declared under public will be available to everyone. The data
members and member functions declared public can be accessed by other classes too. Hence there
are chances that they might change them. So the key members must not be declared public.
ClassA
{
public: // public access specifier
int x; // Data Member Declaration
void display(); // Member Function declaration
}
Private
Private keyword, means that no one can access the class members declared private outside that
class. If someone tries to access the private member, they will get a compile time error. By default
class variables and member functions are private.
ClassB
{
private: // private access specifier
int x; // Data Member Declaration
void display(); // Member Function decaration
}

A member function of a class can always access class members, whether they are public or private.
But an object declared externally can only invoke (using the dot operator, for example) public
members of the class. It’s not allowed to use private members.

Protected
Protected, is the last access specifier, and it is similar to private, it makes class member inaccessible
outside the class. But they can be accessed by any subclass of that class.
ClassC
{
Oops teaching notes

protected: // protected access specifier


int x; // Data Member Declaration
void display(); // Member Function declaration
}

Access Control and Inheritance:

A derived class can access all the non-private members of its base class. Thus base-class members
that should not be accessible to the member functions of derived classes should be declared private
in the base class.

We can summarize the different access types in the following way:

Access Public protected Private

Same class Yes Yes Yes

Derived classes Yes Yes No

Outside classes Yes No No

A derived class inherits all base class methods with the following exceptions:

Constructors, destructors and copy constructors of the base class.

Overloaded operators of the base class.

The friend functions of the base class.

When deriving a class from a base class, the base class may be inherited through public,
protected or private inheritance. The type of inheritance is specified by the access-specifier as
explained above.

We hardly use protected or private inheritance, but public inheritance is commonly used. While
using different type of inheritance, following rules are applied:
Oops teaching notes

Public Inheritance: When deriving a class from a public base class,public members of the base class
become public members of the derived class and protected members of the base class
becomeprotected members of the derived class. A base class's privatemembers are never accessible
directly from a derived class, but can be accessed through calls to the public and protected members
of the base class.

Protected Inheritance: When deriving from a protected base class,public and protected members of
the base class become protected members of the derived class.

Private Inheritance: When deriving from a private base class,public and protected members of the
base class become privatemembers of the derived class.

Example :

class A
{
public:
int x;
protected:
int y;

private:
int z;
};

class B : public A
{
// x is public
// y is protected
// z is not accessible from B
};

class C : protected A
{
// x is protected
// y is protected
// z is not accessible from C
};

class D : private A // 'private' is default for classes


{
// x is private
// y is private
// z is not accessible from D
};
Oops teaching notes

IMPORTANT NOTE: Classes B, C and D all contain the variables x, y and z. It is just question of
access.

UNIT III

Virtual Base Classes


Suppose there are two derived classes B and C that have a common base class A, and also there is
another class D that inherits from B and C. We can then declare the base class A as virtual to ensure
that B and C share the same subobject of A.

In the following example, an object of class D has two distinct subobjects of class L, one through
class B1 and another through class B2. We can use the keyword virtual in front of the base class
specifiers in the base lists of classes B1 and B2 to indicate that only one subobject of type L, shared
by class B1 and class B2, exists.

For example:

class L
{
/* ... */
}; // indirect base class

class B1 : virtual public L


{
/* ... */
};

class B2 : virtual public L


{
/* ... */
};

class D : public B1, public B2


{
/* ... */
}; // valid
Oops teaching notes

Using the keyword virtual in this example ensures that an object of class D inherits only one
subobject of class.

Example for Virtual Base Class:

#include<iostream>
using namespace std;
class A
{
public:
int i;
};
class B: virtual public A
{
public:
int j;
};
class C:virtual public A
{
public:
int k;
};
class D:public B,public C
{
public:
int sum;
};

int main()
{
D ob;
ob.i=10;
ob.j=20;
ob.k=30;
ob.sum=ob.i+ob.j+ob.k;
cout<<"\n\t"<<ob.i<<endl;
cout<<"\t"<<ob.j<<endl;
cout<<"\t"<<ob.k<<endl;
cout<<"\n\t\tSum of the numbers is "<<ob.sum<<endl;

return 0;
}

Output:
10
20
30
Sum of the numbers is 60

Container class and its types in C++.


Oops teaching notes

A container stores many entities and provide sequential or direct access to them. List, vector and
strings are such containers in standard template library. The string class is a container that holds
chars. All container classes access the contained elements safely and efficiently by using iterators.

Container class is a class that hold group of same or mixed objects in memory. It can be
heterogeneous and homogeneous. Heterogeneous container class can hold mixed objects in
memory whereas when it is holding same objects, it is called as homogeneous container class.

A class is said to be a container class which is utilized for the purpose of holding objects in memory
or persistent media. A generic class plays a role of generic holder. A container class is a good blend of
predefined behavior and an interface that is well known. The purpose of container class is to hide
the topology for the purpose of objects list maintenance in memory.

A container class is known as heterogeneous container, when it contains a set of different objects. A
container class is known as homogeneous container when it contains a set of similar objects.

C++ standardized container classes?


The following are the standardized container classes :
1. std::map :
Used for handle sparse array or a sparse matrix.
2. std::vector :
Like an array, this standard container class offers additional features such as bunds checking through
the at () member function, inserting or removing elements, automatic memory management and
throwing exceptions.
std::string :
A better supplement for arrays of chars.

Function Overloading :
C++ allows specification of more than one function of the same name in the same scope. These
are called overloaded functions and are described in detail in Overloading. Overloaded functions
enable programmers to supply different semantics for a function, depending on the types and
number of arguments.

In C++ programming, two functions can have same name if number and/or type of arguments
passed are different.

These functions having different number or type (or both) of parameters are known as overloaded
functions.

For example:
int test() { }
Oops teaching notes

int test(int a) { }
float test(double a) { }
int test(int a, double b) { }
Here, all 4 functions are overloaded functions because argument(s) passed to these functions are
different.

Notice that, the return type of all these 4 functions are not same. Overloaded functions may or may
not have different return type but it should have different argument(s).
// Error code
int test(int a) { }
double test(int b){ }
The number and type of arguments passed to these two functions are same even though the return
type is different. Hence, the compiler will throw error.

Example : Function Overloading


#include <iostream>
using namespace std;

void display(int);
void display(float);
void display(int, float);

int main() {

int a = 5;
float b = 5.5;

display(a);
display(b);
display(a, b);

return 0;
}

void display(int var) {


cout << "Integer number: " << var << endl;
}

void display(float var) {


cout << "Float number: " << var << endl;
}

void display(int var1, float var2) {


cout << "Integer number: " << var1;
cout << " and float number:" << var2;
}
Output :
Integer number: 5
Float number: 5.5
Integer number: 5 and float number: 5.5
Here, the display() function is called three times with different type or number of arguments.
Oops teaching notes

The return type of all these functions are same but it's not necessary.

Function Overriding
If we inherit a class into the derived class and provide a definition for one of the base class's function
again inside the derived class, then that function is said to be overridden, and this mechanism is
called Function Overriding.

Requirements for Overriding


Inheritance should be there. Function overriding cannot be done within a class. For this we require a
derived class and a base class.

Function that is redefined must have exactly the same declaration in both base and derived class,
that means same name, same return type and same parameter list.
Example of Function Overriding
#include<iostream>
using namespace std;
class A
{
public:
void show()
{
cout<<"\n\t\tBase class";
}
};
class B: public A
{
public:
void show()
{
cout<<"\n\t\tDerived class";
}
};

int main()
{
A *p;

B b;
p=&b;
p->show();
}
Output:
Base class

In this example, function show() is overridden in the derived class


Oops teaching notes

Operator Overloading

Operator Overloading is a feature of C++ through which one can assign special meanings to the
operators. We can create new definition for the operators. For example, the addition operator ( + )
can be overloaded to work among two objects. All operators can be overloaded except some
operators like scope resolution operator ( :: ) , sizeof operator, conditional operator ( ? : ) and class
member access operator ( .), (.* ).

Example to Overloadunary–(minus)operator

Class Test
{
int a, b;

public :
Test() { }
Test(intvar1, int var2)
{
a = var1;
b = var2;
}

Void displayValues()
{
cout<< "a : " << a << " b : " << b <<endl;
}
Void operator-()
{ // overload unary (-) operator
a = -a;
b = -b;
}
};

void main()

Test z(7, 2);


z.displayValues();

-z; // calling overloaded operator


z.displayValues();

}
Output : a: 7 b: 2

a: -7 b: -2
Oops teaching notes

Overloading binary + operator

The following example demonstrates how to overload + operator.

class Test
{
int a, b;

public :
Test( ) { }
Test(int var1, int var2)
{
a = var1;
b = var2;
}

Void displayValues()
{
cout<< "a : " << a << " b : " << b <<endl;
}

Test operator+(Test&x)
{
Test temp_obj;
temp_obj.a = this->a + x.a;
temp_obj.b = this->b + x.b;
return temp_obj;
}
};

void main()

{
Test z1(7, 2), z2(9, 3);
cout<< "Displaying object1 values : ";
z1.displayValues();
cout<< "Displaying object2 values : ";
z2.displayValues();
Test sum_obj = z1 + z2; // call overloaded (+) operator
cout<< "After adding 2 objects : ";
sum_obj.displayValues();

}
Oops teaching notes

UNIT IV
Dynamic binding or late binding (run time polymorphism)

If you want to execute the member function of derived class then, you can declare display( ) in the
base class as virtual which makes that functions binding to be postponed till runtime.

/* Example to demonstrate the working of virtual function in C++ programming. */

#include <iostream>

class B
{
public:
virtual void display() /* Virtual function */

{ cout<<"Content of base class.\n"; }


};

class D1 : public B
{
public:
void display()
{ cout<<"Content of first derived class.\n"; }
};

class D2 : public B
{
public:
void display()
{ cout<<"Content of second derived class.\n"; }
};

void main()
{
B *b;
D1 d1;
Oops teaching notes

D2 d2;
b = &d1;
b->display(); /* calls display() of class derived D1 */
b = &d2;
b->display(); /* calls display() of class derived D2 */
return 0;
}

Output:

Content of first derived class.


Content of second derived class.

After the function of base class is made virtual, the code b->display( ) will call the display( ) of the
appropriate derived class depending upon the content of pointer.

Static binding (compile time binding)

If a base class and derived class has same function and if you write code to access that function using
pointer of base class then, the function in the base class is executed even if, the object of derived
class is referenced with that pointer variable.

This can be demonstrated by an example.

#include <iostream.h>

class B
{
public:
void display()

{ cout<<"Content of base class.\n"; }


};

class D : public B
{
public:
void display()

{ cout<<"Content of derived class.\n"; }


};

void main()
{
B *b;
D d;

b = &d; /* Address of object d given to parent class pointer variable b */


Oops teaching notes

b->display();

}
Output:

Content of base class.

In above program, even if the object of derived class d is put in pointer to base class, display( ) of the
base class is executed. The reason is static binding or early binding of the methods to the name of
the parent pointer at compile time itself.

Virtual Function :
A virtual function is a member function in base class that you expect to redefine in derived classes.

Syntax : virtual returntype functionName(arguments list)

Pure virtual function, Abstract class

If expression =0 is added to a virtual function then, that function is becomes pure virtual function.
Note that, adding =0 to virtual function does not assign value, it simply indicates the virtual function
is a pure function.

If a base class contains at least one virtual function then, that class is known as Abstract class.

#include <iostream>

class Shape /* Abstract class */


{
protected:
float l;
public:
voidget_data() /* Note: this function is not virtual. */
{
cin>>l;
}

virtual float area() = 0; /* Pure virtual function */


};

class Square : public Shape


{
public:
Oops teaching notes

float area()
{ return l*l; }
};

class Circle : public Shape


{
public:
float area()
{ return 3.14*l*l; }
};

void main()
{
Square s;
Circle c;
cout<<"Enter length to calculate area of a square: ";
s.get_data();
cout<<"Area of square: "<<s.area();
cout<<"\nEnter radius to calculate area of a circle:";
c.get_data( );
cout<<"Area of circle: "<<c.area();

In this program, pure virtual function virtual float area() = 0; is defined inside class Shape, so this
class is an abstract class and one cannot create object of class Shape.

Constructor/destructor under inheritance

Base class constructors are always called in the derived class constructors. Whenever you create
derived class object, first the base class default constructor is executed and then the derived class's
constructor finishes execution.

1. Whether derived class's default constructor is called or parameterised is called, base class's
default constructor is always called inside them.

2. To call base class'sparameterised constructor inside derived class's parameterisedconstructor,


we must mention it explicitly while declaring derived class's parameterized constructor.

Whenever we kill the derived class object, first the derived class destructor is executed and then
the parent class's destructor finishes execution.

Example for constructor under inheritance:


Oops teaching notes

#include<iostream>
using namespace std;
class Base
{
int x;
public:
Base()
{
cout<<"\n\t\tBase default constructor";
}
};
class Derived:public Base
{
int y;
public:
Derived()
{
cout<<"\n\t\tDerived default constructor";
}
Derived(int i)
{
cout<<"\n\t\tDerived parameterized contructor";
}
};
int main()
{
//Base b;
//Derived d1;
Derived d2(10);
return 0;
}
Output:
Base default constructor
Derived parameterized constructor

Example for destructor under inheritance:


#include<iostream>
using namespace std;
class Base
{
int x;
public:
~Base()
{
cout<<"\n\t\tBase default destructor"<<endl;
}
};
class Derived
{
int y;
public:
~Derived()
{
Oops teaching notes

cout<<"\n\t\tDerived default destructor"<<endl;


}
};
int main()
{
Base b;
Derived d1;

return 0;
}

Output:
Derived default destructor
Base default destructor

Virtual Destructors
Destructors in the Base class can be Virtual. Whenever Upcasting is done, Destructors of the Base
class must be made virtual for proper destrucstion of the object when the program exits.

NOTE : Constructors are never Virtual, only Destructors can be Virtual.

Let’s first see what happens when we do not have a virtual Base class destructor.

class Base
{
public:
~Base( )
{cout<< "Base Destructor\t"; }
};

classDer:public Base
{
public:
~Der()
{ cout<< "Derived Destructor"; }
};

int main()
{
Base* b = new Der; //Upcasting
delete b;0
}

Output : Base Destructor


Oops teaching notes

In the above example, delete b will only call the Base class destructor, which is undesirable because,
then the object of Derived class remains undestructed, because its destructor is never called. Which
results in memory leak. We must take care to use virtual destructor concept during Upcasting.

Now let’s see what happens when we have Virtual destructor in the base class.

class Base
{
public:
virtual ~Base()
{cout<< "Base Destructor\t"; }
};

Class Der: public Base


{
public:
~Der()
{ cout<< "Derived Destructor"; }
};

int main()
{
Base* b = new Der; //Upcasting
delete b;
}

Output :

Derived Destructor
Base Destructor

When we have Virtual destructor inside the base class, then first Derived class's destructor is called
and then Base class's destructor is called, which is the desired behaviour.
Oops teaching notes

UNIT V
Function templates
Template is a feature which provides support for generic programming. Template allows creation of
generic type elements. For e.g, if we define a function which takes int type parameters, the function
can operate on integer elements only but using templates, we can define a generic function which
can operate on any data type.

Templates can be applied to functions and classes.

Function Templates

In the following program, we implement a swap( ) function which can perform swapping of two
elements of any data type

template <class T>


void swapValues(T &a, T&b)
{
T temp;
temp = a;
a = b;
b = temp;
}

void main()
{
int a = 5, b = 7;
float x = 65.39, y = 27.89;
Oops teaching notes

char p = 'A', q = 'B';


cout<< "Before Swapping :- " <<endl;
cout<< "a = " << a << " b = " << b <<endl;
cout<< "x = " << x << " y = " << y <<endl;
cout<< "p = " << p << " q = " << q <<endl;

/* swap the values stored in variables */


swapValues(a, b); // swap two integer values
swapValues(x, y); // swap two float values
swapValues(p, q); // swap two character values
cout<< "\nAfter Swapping :- " <<endl;
cout<< "a = " << a << " b = " << b <<endl;
cout<< "x = " << x << " y = " << y <<endl;
cout<< "p = " << p << " q = " << q <<endl;
}

Class Templates
Consider a class which supports three relational operations ( getMax(), getMin() and isEqual() ).
Following program makes the class generic using class template to perform the operations on
different data types :

/* Define a generic class to perform relational operation */


template<class T>
class relational
{
T x, y;
public :
relational(T var1, T var2)
{
x = var1;
y = var2;
}

TgetMin()
{
return ((x < y) ? x : y);
}
T getMax()
{
return ((x > y) ? x : y);
}
};

void main()
{
relational<int> r1(11, 17); // object r1 with integer data members
relational<double> r2(7.1, 6.9); // 'T' is replaced with 'double' type
intmin = r1.getMin(); // get min value of object r1
doublemax = r2.getMax(); // get max value of object r2
cout<< "Minimum Element of object r1 : " << min <<endl;
Oops teaching notes

cout<< "Maximum Element of object r2 : " << max <<endl;


}

Templates with Multiple Parameters

We can also define a template with multiple parameters. See the program below

// define a template class with two parameters ( T1 and T2 )

template<class T1, class T2>

class X
{
T1 a;
T2 b;
public :
X(T1 var1, T2 var2)
{
a = var1;
b = var2;
}
void display()
{
cout<< "a : " << a << " b : " << b <<endl;
}
};

void main()
{
X<int, char>obj1(7, 'M'); // T1 is integer and T2 is character
X<float, int>obj2(65.71, 8); // T1 is float and T2 is integer
obj1.display();
obj2.display();

Exception handling in C++

Exceptions are unusual conditions or problems that arise during the execution of a program like
divide by zero, running out of memory or accessing an array out of its bounds. Exception Handling is
a mechanism to handle such conditions at run time and prevent abnormal termination or crashing of
the program.

Throwing and Catching Exceptions


Oops teaching notes

We can throw an exception from any part of the program using throw keyword whenever an
anomalous situation occurs at runtime and then appropriate action is taken after catching the
exception.

The part of the code which is protected by exception handling is enclosed within try ... catch block.
Following program illustrates the use of throw , try and catch keywords :

To catch exceptions we must place a portion of code under exception inspection. We can do this by
putting that portion of code in a try block. So, when an exceptional circumstance arises an exception
is thrown. This in turn transfers the control to the exception handler. If there are no exceptions
thrown, the code will continue normally and all handlers are ignored.

float divide(floatnum, floatdenom)


{
if ( denom == 0 )
{
throw "Divide by Zero Error";
}
else
{
return (num / denom);
}
}
void main()
{
float x = 5, y = 0;
/* protect the piece of code using try ... catch block and prevent
crashing of the program */

try
{
float result = divide(x, y);
cout<< "Result : " << result <<endl;
}
catch (const char *err_msg)
{
cout<< "Exception Caught : " <<err_msg<<endl;
}
}

In the above program, we have thrown an exception of type const char * and then caught it. We can
have multiple catch blocks to catch different types of exception.
Oops teaching notes

File Handling

Files are a means to store data in a storage device. C++ file handling provides a mechanism to store
output of a program in a file and read from a file on the disk. we know by using <iostream> header
file it provide functions cin and cout to take input from console and write output to a console
respectively.

Now, we look at another header file <fstream> which provides data types or classes
( ifstream , ofstream , fstream ) to read from a file and write to a file.

File Opening Modes

A file can be opened in different modes to perform read and write operations. Function to open a file
i.e open( )takes two arguments : char *filename and ios :: mode. C++ supports the following file open
modes :

Mode Explanation
ios :: in Open a file for reading
ios :: out Open a file for writing
ios :: app Appends data to the end of the file
File pointer moves to the end of the file but allows to
ios :: ate
writes data in any location in the file
ios :: binary Binary File
ios :: trunk Deletes the contents of the file before opening

If a file is opened in ios :: out mode, then by default it is opened in ios :: trunc mode also i.e the
contents of the opened file is overwritten. If we open a file using ifstream class, then by default it is
opened in ios :: in mode and if we open a file using ofstream class, then by default it is opened in ios ::
out mode. The fstream class doesn't provide any default mode.

File Operations using ifstream and ofstream

Open a file for writing

#include<iostream>
#include<fstream>

void main()
{
ofstreamofile; // declaring an object of class ofstream
ofile.open("file.txt"); // open "file.txt" for writing data

/* write to a file */
ofile<< "This is a line in a file" <<endl;
ofile<< "This is another line" <<endl;

/* write to a console */
Oops teaching notes

cout<< "Data written to file" <<endl;


ofile.close(); // close the file

Open a file for reading

#include<iostream>
#include<fstream>
using namespace std;

void main()
{
char data[100]; // buffer to store a line read from file
ifstreamifile; // declaring an object of class ifstream

ifile.open("file.txt"); // open "file.txt" for reading


cout<< "Reading data from a file :-" <<endl<<endl;
while (!ifile.eof())
{
// while the end of file [ eof() ] is not reached
ifile.getline(data, 100); // read a line from file
cout<< data <<endl; // print the file to console
}

ifile.close(); // close the file

In the first program, a file " file.txt " is created and some data is written into it. The file is created in
the same directory in which the program file is saved.

In the second program, we read the file line by line using and then print each line on the console. The
while loop continues till the end of file is reached. We ensure that using the condition

While ( ! ifile.eof( ) )

Вам также может понравиться