C++ Notes
C++ Notes
The concept of Object Oriented Programming focuses on real life objects which are very close to reality.
To remove the drawbacks of traditional programming, OOP approach came into existence. In OOP
approach, a new concept of structural programming is used with new as well as power concepts that
emphasize on data and functions so that large and complex programs can be designed and implements
easily. The main idea behind the development of OOP is to secure the data i.e. data should not flow
freely around the systems. OOP ties data to the functions that operate on it and prevent it from accidental
change due to external functions. In OOP data and functions are combined into a single unit so that only
embedded functions can operate on that data and this single unit is called as object. Therefore, OOP is
such a programming approach which allows the programmer to decompose a problem into number of
entities called objects. Data of the object can be accessed and used only by the functions of that object.
Different objects can communicate with one another by sending messages.
Object A Object B
Object A
Data Data
Communication
Functions Functions
Object C
Object A
Data
Functions
Basically, objects can communicate with each other by calling one another’s member functions.
Member functions are known as Methods and Data Items are referred as Instance variables. Calling an
object’s member function is referred to as sending a message to the object.
1
2. DIFFERENCE BETWEEN OBJECT ORIENTED AND PROCEDURE ORIENTED
PROGRAMMING
1. Program is divided into small parts Program is divided into parts called objects.
called functions.
2. Importance is not given to data but to Importance is given to the data rather than
functions as well as sequence of actions to procedures or functions because it works as
be done. a real world.
3. It follows Top Down approach. It follows Bottom Up approach.
4. The emphasis is on the functions. The emphasis is on the data rather than
functions.
5. This approach does not represent real world This approach represents real-world
modelling modelling.
6. It does not have any access specifier. It has access specifiers named Public,
Private, Protected, etc.
7. Data can move freely from function to Objects can move and communicate with
function in the system. each other through member functions.
8. To add new data and function is not so easy. It provides an easy way to add new data and
function.
9. Most function uses Global data for sharing Data cannot move easily from function to
that can be accessed freely from function to function, it can be kept public or private so
function in the system. we can control the access of data.
10. It does not have any proper way for hiding It provides Data Hiding so provides more
data so it is less secure. security
12. Example of POP are : C, VB, FORTRAN, Example of OOP are : C++, JAVA,
Pascal VB.NET, C#.NET.
2
3. CONCEPTS OF OBJECT ORIENTED PROGRAMMING
• Objects : Objects are the basic run time entities in an object-oriented system. They may
represent a person, a place, a bank account, a table of data or any item that the program has to
handle. They may also represent user-defined data such as vectors, time and lists. Programming
problem is analyzed in term of objects and the nature of communication between them. Program
objects should be chosen such that they match closely with the real-world objects. Objects take
up space in the memory and have an associated address like a record in Pascal, or a structure in
C.
When a program is executed, the objects interact by sending messages to one another.
For example, if “customer” and “account” are to object in a program, then the customer object
may send a message to the count object requesting for the bank balance. Each object contain
data, and code to manipulate data. Objects can interact without having to know details of each
other’s data or code. It is a sufficient to know the type of message accepted, and the type of
response returned by the objects. Following figure shows the notation that are popularly used
in object oriented analysis and design.
• Classes: We just mentioned that objects contain data, and code to manipulate that data. The
entire set of data and code of an object can be made a user-defined data type with the help of
class. In fact, objects are variables of the type class. Once a class has been defined, we can
create any number of objects belonging to that class. Each object is associated with the data of
type class with which they are created. A class is thus a collection of objects similar types. For
examples, Mango, Apple and orange members of class fruit. Classes are user-defined that types
and behave like the built-in types of a programming language. The syntax used to create an
3
object is not different then the syntax used to create an integer object in C. If fruit has been
defines as a class, then the statement
fruit mango;
• Data Abstraction: Abstraction refers to the act of representing essential features without
including the background details or explanation. Classes use the concept of abstraction and are
defined as a list of abstract attributes such as size, wait, and cost, and function operate on these
attributes. They encapsulate all the essential properties of the object that are to be created. The
attributes are sometime called data members because they hold information. The functions that
operate on these data are sometimes called methods or member function.
• Encapsulation: The wrapping up of data and function into a single unit (called class) is known
as encapsulation. Data and encapsulation is the most striking feature of a class. The data is not
accessible to the outside world, and only those functions which are wrapped in the class can
access it. These functions provide the interface between the object’s data and the program. This
insulation of the data from direct access by the program is called data hiding or information
hiding.
• Inheritance: Inheritance is the process by which objects of one class acquired the properties of
objects of another classes. It supports the concept of hierarchical classification. For example,
the bird, ‘robin’ is a part of class ‘flying bird’ which is again a part of the class ‘bird’. The
principal behind this sort of division is that each derived class shares common characteristics
with the class from which it is derived as illustrated in following figure.
In OOP, the concept of inheritance provides the idea of reusability. This means that we can add
additional features to an existing class without modifying it. This is possible by deriving a new
4
class from the existing one. The new class will have the combined feature of both the classes.
The real appeal and power of the inheritance mechanism is that it allows the programmer to
reuse a class i.e almost, but not exactly, what he wants, and to tailor the class in such a way that
it does not introduced any undesirable side-effects into the rest of classes.
Fig. 1.7 illustrates that a single function name can be used to handle different number and
different types of argument. This is something similar to a particular word having several
different meanings depending upon the context. Using a single function name to perform
different type of task is known as function overloading.
Shape
Draw
Polymorphism plays an important role in allowing objects having different internal structures
to share the same external interface. This means that a general class of operations may be
accessed in the same manner even though specific action associated with each operation may
differ. Polymorphism is extensively used in implementing inheritance.
• Dynamic Binding: Binding refers to the linking of a procedure call to the code to be executed
in response to the call. Dynamic binding means that the code associated with a given procedure
call is not known until the time of the call at run time. It is associated with polymorphism and
inheritance. A function call associated with a polymorphic reference depends on the dynamic
type of that reference.
Consider the procedure “draw” in figure above by inheritance, every object will have this
procedure. Its algorithm is, however, unique to each object and so the draw procedure will be
redefined in each class that defines the object. At run-time, the code matching the object under
current reference will be called.
5
3. Establishing communication among objects.
Objects communicate with one another by sending and receiving information much the same
way as people pass messages to one another. The concept of message passing makes it easier
to talk about building systems that directly model or simulate their real world counterparts.
A Message for an object is a request for execution of a procedure, and therefore will invoke a
function (procedure) in the receiving object that generates the desired results. Message passing
involves specifying the name of object, the name of the function (message) and the information
to be sent. Example:
Object has a life cycle. They can be created and destroyed. Communication with an object is
feasible as long as it is alive.
• Emphasis on data: OOP give more emphasis on data rather than functions. Data hiding helps
the programmer to build secure programs that cannot be invaded by code in other parts of the
program.
• Eliminate redundant code: Through inheritance one can eliminate the redundant code and
extend the use of existing code.
• Easily upgraded: Object oriented systems can be easily upgraded from small to large systems.
• Simplicity: Software object model real-world objects, this reduces complexity and makes the
program structure very clear.
• Reduces maintenance cost: Due to encapsulation and reusability of code, maintenance cost is
reduced. New functions can be easily incorporated.
• Real world modelling: This real-world modelling is based on objects rather than the data and
procedures. So real-world problems are easily modelled in complete fashion than traditional
method.
• Faster development: Reuse of code enables faster development of program. Code once
development and compiled can be reused in future projects.
6
• Modifiability: It is easy to make changes in the procedure or data representation in an object-
oriented program. If you make any change inside a class, it will not affect any other part of the
program.
• New data type: With the help of object oriented programming user can create new complex
data type as per requirement.
• Design benefit: Large programs are very difficult to write. In Object Oriented Programming
programs are easy to write than non-object oriented ones because better designs are made and
large programs are divided into functions and managed easily.
While it is possible to incorporate all these features in an object-oriented system, their importance
depends on the type of the project and the preference of the programmer. There are a number of issues
that need to be tackled to reap some of the benefits stated above. For instance, object libraries must be
available for reuse. The technology is still developing and current product may be superseded quickly.
Strict controls and protocols need to be developed if reuse is not to be compromised.
OOP has become one of the programming buzzwords today. There appears to be a great deal of
excitement and interest among software engineers in using OOP. Applications of OOP are beginning
to gain importance in many areas. The most popular application of object-oriented programming, up to
now, has been in the area of user interface design such as window. Hundreds of windowing systems
have been developed, using the OOP techniques.
Real-business system are often much more complex and contain many more objects with complicated
attributes and method. OOP is useful in these types of application because it can simplify a complex
problem. The promising areas of application of OOP include:
• Real-time system
• Simulation and modeling
• Object-oriented data bases
• Hypertext, Hypermedia, and expertext
• AI and expert systems
• Neural networks and parallel programming
• Decision support and office automation systems
• CIM/CAM/CAD systems
• System Software
• Image Processing System
• Distributed System and Network Management System etc.
The object-oriented paradigm sprang from the language, has matured into design, and has recently
moved into analysis. It is believed that the richness of OOP environment will enable the software
industry to improve not only the quality of software system but also its productivity. Object-oriented
technology is certainly going to change the way the software engineers think, analyze, design and
implement future system.
7
6. SPECIAL OPERATORS
C++ has a rich set of special operators. All C operators are valid in C++. In addition, C++ introduces
some new operators. Following are some special operators used in C++:
C++ is a block structured language. Blocks and scopes can be used in constructing program. We
know that the same variable name can be used to have different meanings in different blocks. The
scope of the variable extends from the point of its declaration till the end of the block containing
the declaration. A variable declared inside a block is said to be local to that block.
. . . .
. . . .
{
int x = 10;
. . . . . .
. . . . . .
}
. . . . .
. . . . .
{
int x = 1;
. . . . .
. . . . .
}
The two declarations of x refer to two different memory locations containing different values.
Statements in the second block cannot refer to the variable x declared in the first block, and vice
versa.
. . . . .
. . . . .
{
int x = 10;
. . . . .
. . . . .
{
int x = 1;
Block 1
. . . . . Block 2
. . . . .
}
. . . .
}
Block 2 is contained in block 1. Note that a declaration in an inner block hides a declaration of the
same variable in an outer block and, therefore, each declaration of x causes it to refer to a different data
object. Within the inner block, the variable x will refer to the data object declared therein.
8
In C, the global version of a variable cannot be accessed from within the inner block. C++ resolves this
problem by introducing a new operator :: called the scope resolution operator. This can be used to
uncover a hidden variable. It takes the following form:
:: variable-name
int main()
{
int m = 20; //local m
{
int m = 30; //local m
cout<<"Inner Block m = "<<m<<"\n";
cout<<"Global m = "<<::m<<"\n";
}
cout<<"Outer Block m = "<<m<<"\n";
cout<<"Global m = "<<::m<<"\n";
return 0;
}
Inner Block m = 30
Global m = 10
Outer Block m = 20
Global m = 10
In the above program, the variable m is declared at three places, namely, outside the main() function,
inside the main( ) function and inside the inner block. It is to be noted that ::m will always to refer to
the global m.
In C++, two operators new and delete performs the task of allocating and freeing the memory. Since
these operators manipulate memory on the free store, they are also known as free store operators.
An object can be created by using new, and destroyed by using delete. A data object created inside a
block with new, will remain in existence until it is explicitly destroyed by using delete. Thus, the
lifetime of an object is directly under our control and is unrelated to the block structure of the program.
• The new operator : The new operator can be used to create objects of any type. It takes the following
general form:
9
pointer-variable = new data-type;
Here pointer-variable is a pointer of type data-type. The new operator allocates sufficient memory to
hold a data object of type data-type and returns the address of the object. The pointer-variable holds
the address of the memory space allocated
For example:
where p is a pointer of type int and q is a pointer of type float. Here p and q must have already been
declared as pointers of appropriate types.
*p = 25;
*q = 7.5;
Assign 25 to the newly created int object and 7.5 to the float object.
new operator can be used to create a memory space for any data type including user-defined types such
as arrays, structures and classes. The general form for a one-dimensional array is:
Here, size specifies the number of elements in the array. For example, the statement
creates a memory space for an array of 10 integers. p[0] will refer to the first element, p[1] to the second
element and so on.
The delete operator: When a data object is no longer needed, it is destroyed to release the memory
space for reuse. The general form of delete is:
delete pointer-variable;
The pointer-variable is the pointer that points to a data object created with new.
For example
delete p;
delete q;
If we want to free a dynamically allocated array, we must use the following form of delete
10
new and delete operators
#include<iostream>
using namespace std;
int main()
{
int *arr;
int size;
delete arr;
return 0;
}
___________________________________________________________________________
MANIPULATORS
Manipulators are operators that are used to formal the data display. The most commonly used
manipulators are endl and setw.
* The endl manipulator, when used in an output statement, causes a linefeed to be inserted. It has the
same effect as using the newline character “\n”. For example, the statement:
cout<<”Hello”<<endl;
cout<<”Welcome”<<endl;
would causes two lines of output, one for each word (Hello and Welcome).
* The setw operator sets the width of the variable. Consider the following statements:
cout<<”m = “<<m<<endl;
cout<<”n = “<<n<<endl;
cout<<”p = “<<p<<endl;
If we assume the values of the variables as 3456, 55, 667, the output will appear as follows:
m=2597
n =14
p =667
11
Since the numbers are right justified, the setw manipulator does this job. The following statement
cout<<setw(5)<<m<<endl;
cout<<setw(5)<<n<<endl;
cout<<setw(5)<<p<<endl;
The manipulator setw(5) specifies a field width 5 for printing value of the variables. The value is right
justified within the field as shown below:
m= 2597
n = 14
p = 667
Use of Manipulators
#include<iostream>
using namespace std;
int main()
{
int basic = 1000, allowance = 500, Total = 1500;
return 0;
}
Basic 1000
Allowance 500
Total 1500
C++ permits explicit type conversion of variables or expression using the type cast operator. Type
cast operator syntax is:
type-name (expression)
For example
int main()
12
{
int intvar=25;
float floatvar=35.87;
cout<<"intvar = "<<intvar<<endl;
cout<<"floatvar = "<<floatvar<<endl;
cout<<"float(intvar) = "<<float(intvar)<<endl;
cout<<"int(floatvar) = "<<int(floatvar)<<endl;
return 0;
}
intvar = 25
floatvar = 35.87
float(intvar) = 25
int(floatvar) = 35
13
CLASS
A class is a way to bind the data and its associated functions together. It allows the data and the functions
to be hidden. When defining a class, we are creating a new abstract data type that can be treated like
any other built-in data type. Generally a class specification has two parts:
1. Class declaration
2. Class function definitions
The class declaration describes the type and scope of its members. The class function definition describe
how the class functions are implemented.
class class-name
{
private:
variable declarations;
function declarations;
public:
variable declarations;
function declarations;
};
The class declaration is similar to struct declaration. The keyword class specifies, that what follows is
an abstract data of type class-name. The body of the class is enclosed within braces and terminated by
a semicolon. The class body contains the declaration of variables and functions. These functions and
variables are collectively called class members.
Class members are usually grouped under two sections namely private and public to denote which of
the members are private and which of these are public. The keywords private and public are known as
visibility labels. These keywords are followed by a colon (:).
The class members that have been declared as private can be accessed only from within the class. On
the other hand, public members can be accessed from outside the class also. The data hiding (using
private declaration) is the key feature of object-oriented programming. The use of the keyword private
is optional. By default, the members of the class are private. If both the labels are missing, then, by
default, all the members are private. Such a class is completely hidden from the outside world and does
not serve any purpose.
The variables declared inside the class are known as data members and the functions are known as
member functions. Only the member functions can have access to the private data members and private
functions. However, the public members (both function and data) can be accessed from outside the
class. This is illustrated in following figure. The binding of data and functions together into a single
class-type variable is known as encapsulation.
14
For example, a typical class declaration would look like:
class item
{
int number; //variable declaration
float cost; //private by default
public:
void getdata(int a, float b); //function declarations
void showdata();
};
We usually give a class some meaningful name, such as item. This name now becomes a new type
identifier that can be used to declare instances of that class type. The class item contains two data
members and two member functions. The data members are private by default while both the functions
are public by declaration. The function getdata( ) can be used to assign values to the member variables
number and cost, and showdata( ) for displaying their values. These functions provide the only access
to the data members from outside the class. This means that the data cannot by accessed by any function
that is not a member of the class item.
Creating Objects:
Once the class has been declared, we can create variables of that type by using the class name. For
example:
item x;
creates a variable x of type item. In C++, the class variables are known as objects. Therefore x is called
an object of type item.
We may also declare more than one object in one statement. For example,
item x, y, z;
The declaration of the object is similar to that of a variable of any basic type.
15
Accessing Class Data Members and Member functions
The private data of a class can be accessed only through the member functions of that class. The main()
cannot contains statements that access number and cost directly. The following is the format of calling
a member function.
object-name function-name(actual-arugments);
x.getdata(100,75.5);
is valid and assigns the value 100 to number and cost of the object x by implementing the getdata( )
function.
x.putdata();
1. Function Definition Outside the class definition: Member functions that are declared inside
a class have to be defined separately outside the class. Their definitions are very much like the
normal function. They should have a function header and a function body.
The membership label class-name:: tells the compiler that the function function-name belongs
to the class class-name. That is, the scope of the function is restricted to the class-name
specified in the header line. The symbol :: is called the scope resolution operator.
For example, consider the member function getdata( ) and showdata( ). They may be coded
as follows:
16
{
cout<<”Number is :”<<number <<”\n”;
cout<<”Cost is :”<<cost<<”\n”;
}
Following program shows the concept of function definition outside the class:
class item
{
int number;
float cost;
public:
void getdata(int a, float b);
void showdata();
};
void item::showdata()
{
cout<<"Number is "<<number<<"\n";
cout<<"Cost is "<<cost<<"\n";
}
int main()
{
item i;
i.getdata(20,45.55);
i.showdata();
return 0;
}
2. Function Definition Inside the Class Definition: Another method of defining a member
function is to replace the function declaration by the actual function definition inside the class.
For example, we could define the item class as follows:
class item
{
int number;
float cost:
public:
void getdata(int a, float b)
{
number=a;
cost=b;
}
void showdata()
17
{
cout<<”Number is “<<number<<”\n”;
cout<<”Cost is “<<cost<<”\n”;
}
}
#include<iostream>
using namespace std;
class item
{
int number;
float cost;
public:
void getdata(int a, float b)
{
number=a;
cost=b;
}
void showdata()
{
cout<<"Number is "<<number<<"\n";
cout<<"Cost is "<<cost<<"\n";
}
};
int main()
{
item i;
i.getdata(10,25.45);
i.showdata();
return 0;
}
18
SECTION – B
1. FRIEND FUNCTION
The private members cannot be accessed from outside the class. That is, a non-member function cannot
have an access to the private data of class. However, there could be a situation where we would like
two classes to share a particular function. In such situations, C++ allows the common function to be
made friendly with both the classes, thereby allowing the function to have access to the private data of
these classes. Such a function need not be a member of any of these classes.
To make an outside function “friendly” to a class, we have to simply declare this function as a friend
of the class as shown below:
class ABC
{
…………………………
…………………………
public:
…………………………
…………………………
friend void xyz(void); // declaration
};
The function declaration should be preceded by the keyword friend. The function is defined elsewhere
in a program like a normal C++ function. The function definition does not use either the keyword friend
or the scope operator (::). A function can be declared as a friend in any number of classes. A friend
function although not a member function and has full access rights to the private members of the class.
#include<iostream>
using namespace std;
class sample
{
int a,b;
public:
void setvalue()
{
a=25;
b=40;
}
19
friend void mean(sample s)
{
float m=(s.a + s.b)/2.0;
cout<<"Mean value = "<<m;
}
};
int main()
{
sample x;
x.setvalue();
mean(x);
return 0;
}
The friend function accesses the class variables a and b by using the dot operator and the object passed
to it. The function call mean(x) passes the object x by value to the friend function.
#include<iostream>
#include<conio.h>
using namespace std;
class second;
class first
{
private:
int a;
public:
void get_a()
{
a=50;
}
friend int max(first,second);
};
class second
{
private:
int b;
public:
void get_b()
{
b=40;
}
friend int max(first, second);
};
int main()
{
first F;
second S;
F.get_a();
S.get_b();
20
int val =max(F,S);
cout<<"Maximum value = "<<val;
return 0;
}
The function max() has arguments from both first and second classes. When the function max is
declared as a friend in first for the first time, the compiler will not acknowledge the presence of second
class unless its name is declared in the beginning as
class second;
2. INLINE FUNCTION
One of the objectives of using functions in a program is to save some memory space. Every time a
function is called, it takes a lot of extra time in executing a series of instructions for tasks such as:
To eliminate the cost of calls to small functions, C++ proposes a new feature called inline function. An
inline function is a function that is expanded in line when it is invoked. The inline function is defined
as follows:
c = cube(3);
It is easy to make a function inline. But we should exercise care before making the function inline. The
speed benefits of inline function reduce as the function grows in size.
Some of the situations where inline expansion may not work are:
21
• If function contains static variables.
• If inline functions are recursive.
int main()
{
float a=12.345;
float b=9.82;
cout<<mul(a,b);
return 0;
}
121.28
A data member of a class can be qualified as static. A static member variable has certain special
characteristics. These are:
• It is initialized to zero when the first object of its class is created. No other initialization in
permitted.
• Only one copy of that member is created for the entire class and is shared by all the objects of
that class.
• It is visible only within the class, but its lifetime is the entire program.
Static variables are normally used to maintain values common to the entire class. Following program
illustrates the use of a static data member.
22
int item :: cnt;
int main()
{
item a,b,c;
a.getcount();
b.getcount();
c.getcount();
a.getdata(100);
b.getdata(200);
c.getdata(300);
a.getcount();
b.getcount();
c.getcount();
return 0;
}
The output of the above program is :
count:0
count:0
count:0
count:3
count:3
count:3
The static variable cnt is initialized to zero when the objects are created. The cnt is incremented
whenever the getdata() function is called. Since the getdata() function is called three times by three
different objects, the count is incremented three times. Because there is only one copy of cnt is shared
by all three objects, all the three output statements cause the value 3 to be displayed. The following
figure shows how a static variable is used by the objects.
cnt
3
The type and scope of each static member variable must be defined outside the class definition. This is
necessary because the static data members are stored separately rather than as a part of an object. Since
they are associated with the class itself rather than with any class object, they are known as class
variables.
23
4. STATIC MEMBER FUNCTION
• A static function can have access to only other static members (functions or variables) declared
in the same class.
• A static member function can be called using the class name (instead of its objects) as follows:
class-name::function-name;
int test::cnt;
int main()
{
test t1,t2,t3;
t1.setcode();
t2.setcode();
t3.setcode();
test::showcount();
t1.showcode();
t2.showcode();
t3.showcode();
return 0;
}
count : 2
count : 3
Object Number :1
Object Number :2
Object Number :3
24
5. FUNCTION OVERLOADING
Overloading refers to the use of the same thing for different purposes. C++ permits overloading of
functions. This means that we can use the same function name to create functions that perform a variety
of different tasks.
Using the concept of function overloading, we can design a number of functions with one function name
but with different argument lists. The function would perform different operations depending on the
argument list in the function call. The correct function to be invoked is determined by checking the
number and type of argument. For example, an overloaded add( ) function handles different types of
data as shown below:
//Declarations
int add(int a, int b); //prototype 1
int add(int a, int b, int c); //prototype 2
double add(double x, double y); //prototype 3
double add(int p, double q); //prototype 4
double add(double p, int q); //prototype 5
//Function calls
cout << add(5,10); //uses prototype 1
cout << add(15, 10.0); //uses prototype 4
cout << add(12.5, 7.5); //uses prototype 3
cout << add(5, 10, 15); //uses prototype 2
cout << add(0.75, 5); //uses prototype 5
A function call first matches the prototype having the same number and type of arguments and then
calls the appropriate function for execution.
Function Overloading
#include<iostream>
#include<conio.h>
using namespace std;
int area(int, int);
int area(int);
float area(float);
int main()
{
25
}
6. ARRAY OF OBJECTS
We know that an array can be of any data type. Similarly, we can also have array of type class. Such
variables are called array of objects. Consider the following example:
class employee
{
char name[20];
int age;
public:
void getdata();
void showdata();
};
The identifier employee is a user-defined data type and can be used to create objects that relate to
different employees. For Example:
employee emp[3];
The array emp contains five objects namely emp[0], emp[1], and emp[2]. Since an array of objects
behaves like any other array, we can use the usual array-accessing methods to access individual
elements, and then the dot membership operator to access the member functions. For example, the
statement
for(int i=0;i<3;i++)
{
emp[i].getdata();
}
26
name
emp[0]
age
name
emp[1]
age
name
emp[2]
age
Array of Objects
#include<iostream>
using namespace std;
class employee
{
char name[20];
int age;
public:
void getdata()
{
cout<<"Enter name :";
cin>>name;
cout<<"Enter age :";
cin>>age;
}
void putdata()
{
cout<<"Name : "<<name<<"\n";
cout<<"Age : "<<age<<"\n";
}
};
int main()
{
employee emp[3];
cout<<"Enter the details of Employees :"<<"\n";
for(int i=0;i<3;i++)
{
emp[i].getdata();
}
cout<<"The detail of employees are :"<<"\n";
for(int i=0;i<3;i++)
{
emp[i].putdata();
}
return 0;
}
The output of the above program is:
27
Enter age : 33
As variables of type int, char, float, double and the like can be passed to function as arguments, in the
similar way objects of a class can also be passed as argument to the function. The objects can be passed
in two ways:
1. Pass by value: In pass by value method, copy of actual object is passed to the function as an
argument. Actual object and its copy, both are stored in different memory locations. Thus, any
changes made to the copy of object don’t reflect in the actual object. By default, in a function,
an object of a class is passed as argument by using pass by value method.
void time::gettime()
{
cout<<"Enter the hours and minutes :";
cin>>hours>>minutes;
}
void time::showtime()
{
cout<<"hours = "<<hours<<" minutes = "<<minutes<<endl;
}
int main()
{
time T1,T2,T3;
T1.gettime();
T2.gettime();
T3.sum(T1,T2);
T1.showtime();
T2.showtime();
28
T3.showtime();
return 0;
}
2. Pass by Reference: Objects can also be passed to functions as an argument by using pass by
reference. In this method, alias of the passed object is created in the called function and not
the copy of the object. Thus any modifications performed to the reference object in the called
function are automatically updated in actual object passed also.
#include<iostream>
#include<conio.h>
using namespace std;
class time
{
private:
int hours, minutes;
public:
void gettime();
void showtime();
void sum(time,time);
};
void time::gettime()
{
cout<<"Enter the hours and minutes :";
cin>>hours>>minutes;
}
void time::showtime()
{
cout<<"hours = "<<hours<<" minutes = "<<minutes<<endl;
}
int main()
{
time T1,T2,T3;
T1.gettime();
T2.gettime();
T3.sum(T1,T2);
T1.showtime();
T2.showtime();
T3.showtime();
return 0;
}
29
PASS BY VALUE
Pass by value
#include<iostream>
using namespace std;
void swap(int, int);
int main()
{
int a,b;
cout<<"Enter values of a and b :";
cin>>a>>b;
swap(a,b);
cout<<"In main value of a is "<<a<<endl;
cout<<"In main value of b is "<<b<<endl;
return 0;
}
void swap(int a, int b)
{
int t;
t=a;
a=b;
b=t;
cout<<"In swap the value of a is "<<a<<endl;
cout<<"In swap the value of b is "<<b<<endl;
}
In main value of a is 4
In main value of b is 5
PASS BY REFERENCE
Pass by Reference
#include<iostream>
using namespace std;
void swap(int &, int &);
int main()
{
int a,b;
cout<<"Enter values of a and b :";
cin>>a>>b;
swap(a,b);
cout<<"In main value of a is "<<a<<endl;
cout<<"In main value of b is "<<b<<endl;
return 0;
}
void swap(int &a, int &b) //values pass by reference
{
int t;
t=a;
a=b;
b=t;
cout<<"In swap the value of a is "<<a<<endl;
cout<<"In swap the value of b is "<<b<<endl;
}
30
The output of the above program is:
In main value of a is 5
In main value of b is 4
POINTERS TO OBJECT
Pointers can point to objects as well as to simple data types and arrays. We’ve seen many examples of
objects defined and given a name, in statements like
Distance dist;
Sometimes, however, we don’t know, at the time that we write the program, how many objects we want
to create. When this is the case we can use new to create objects while the program is running. As we’ve
seen, new returns a pointer to an unnamed object. Let’s look at a short example program, that compares
the two approaches to creating objects.
Pointers to Objects
#include <iostream>
using namespace std;
class Distance
{
private:
int feet;
float inches;
public:
void getdist()
{
cout << “\nEnter feet: “;
cin >> feet;
cout << “Enter inches: “;
cin >> inches;
}
void showdist()
{
cout << feet << “ feet ” << inches << “ inches”;
}
};
int main()
{
Distance dist;
dist.getdist();
dist.showdist(); //with dot operator
return 0;
}
31
CONSTRUCTOR
A constructor is a special member function whose task is to initialize the objects of its class. It is special
because its name is same as the class name. A constructor is invoked whenever the object of its
associated class is created. It is called constructor because it constructs the values of data members of
the class.
Example:
class integer
{
int m,n;
public:
integer() //constructor
{
m=0;
n=0;
}
}
When a class contains a constructor, an object created by the class will be initialized automatically. For
example:
integer i1;
The above instruction will create the object i1 as well as initializes its data members m and n to zero.
There is no need to write any statement to invoke the constructor function.
TYPES OF CONSTRUCTORS
• Default Constructor: A constructor that accepts no parameters is called the default constructor.
32
• Parameterized Constructor: A constructor that can take arguments is called parameterized
constructor.
For example,
class integer
{
int m,n;
public:
integer(int x, int y) //parameterized constructor
{
m=x;
n=y;
}
}
When a constructor has been parameterized, we must pass the initial values as arguments to the
constructor function when an object is declared. We can pass the arguments in two ways:
33
The output of the Program would be
OBJECT 1
m = 10
n = 100
OBJECT 2
m = 25
n = 75
COPY CONSTRUCTOR
A copy constructor is used to declare and initialize an object from another object. For example
integer i2(i1);
would define the object i2 and initialize it to the values of i1. Another form of this statement is:
integer i2 = i1;
A process of initializing through a copy constructor is known as copy initialization. A copy constructor
takes a reference to an object of the same class as itself as an argument.
Copy Constructor
#include<iostream>
using namespace std;
class code
{
int id;
public:
code(int a)
{
id = a;
}
code(code & a)
{
id = a.id;
}
void display()
{
cout<<id<<"\n";
}
};
int main()
{
code A(100);
code B(A); //copy constructor called
code C=A; //copy constructor called again
A.display();
B.display();
C.display();
}
34
MULTIPLE CONSTRUCTORS IN A CLASS
We can use more than one constructor in a class. This concept is also known as constructor overloading.
Consider the following code:
class integer
{
int m,n;
public:
integer() //constructor 1
{
m=0;
n=0;
}
This declares three constructors for an integer object. The first constructor receives no arguments, the
second receives two integer arguments and the third receives one integer object as an argument. For
example, the declaration
integer i1;
would automatically invoke the first constructor and set both m and n of i1 to zero.
The statement
integer i2(20,40);
would call the second constructor which will initialize the data members m and n of i2 to 20 and 40
respectively.
integer i3(i2);
would invoke the third constructor which copies the values of i2 to i3. In other words, it sets the value
of every data element of i3 to the value of the corresponding data element of i2.
35
Multiple Constructors in a Class (Constructor Overloading)
#include<iostream>
using namespace std;
class integer
{
int m,n;
public:
integer() //constructor 1
{
m=0;
n=0;
}
void display()
{
cout<<"m = "<<m<<"\n";
cout<<"n = "<<n<<"\n";
}
};
int main()
{
integer i1;
integer i2(20,40);
integer i3(i2);
cout<<"Constructor 1 :"<<"\n";
i1.display();
cout<<"Constructor 2 :"<<"\n";
i2.display();
cout<<"Constructor 3 :"<<"\n";
i3.display();
}
Constructor 1 :
m = 0
n = 0
Constructor 2 :
m = 20
n = 40
Constructor 3 :
m = 20
n = 40
36
DESTRUCTOR
A destructor as the name implies, is used to destroy the objects that have been created by a constructor.
Like a constructor, a destructor is a member function whose name is the same as the class name but is
preceded by a tilde (~). For example, the destructor of a class integer can be defined as shown below:
~integer( )
{ }
A destructor never takes any argument nor does it returns any value. It will be invoked implicitly by the
compiler upon exit from the program to clean up the storage that is no longer accessible.
Characteristics of Destructor
1. Destructor has the same name as that of the class it belongs and preceded by ~ (tilde) sign.
2. Destructor invoked automatically when the object go out of the scope.
3. Destructor should be declared in public section.
4. Like Constructor, it cannot be declared as static and const.
5. Destructor cannot be overloaded as there can be only one destructor in the class.
6. Destructor has no return type, not even void.
7. Destructor cannot be inherited.
8. Destructor do not have any arguments or parameters.
9. Destructor can be virtual.
Destructor
#include<iostream>
using namespace std;
int cnt=0;
class test
{
public:
test()
{
cnt++;
cout<<"Object created "<<cnt<<"\n";
}
~test()
{
cout<<"Object destroyed "<<cnt<<"\n";
cnt--;
}
};
int main()
{
test t1,t2,t3;
return 0;
}
37
OPERATOR OVERLOADING
Operator overloading provides a flexible option for the creation of new definitions for most of the C++
operators. It is the main feature of C++. It is an important technique that enhanced the power of
extensibility of C++. We can overload all the C++ operators excepts the following:
To define an additional task to an operator, we must specify what is means in relation to the class to
which the operator is applied. This is done with the help of special function, called operator function,
which describes the task. The general form of an operator function is
where return-type is the type of value returned by the specified operation and op is the operator being
overloaded. operator op is the function name, where operator is a keyword.
Consider the unary minus operator. A minus operator when used as unary, takes just one operand. We
know that this operator change the sign of an operand when applied to a basic data item. By using
operator overloading it can be applied to an object as same way as it is applied to an int or float variable.
The unary minus when applied to an object should change the sign of its data items.
38
z=-z;
}
};
int main()
{
space s;
s.getdata();
cout<<"Before Operator Overload :"<<"\n";
s.display();
Binary operators can also be overloaded like unary operators. Binary operators work on two operands.
Only single parameter is passed to operator function.
class complex
{
float x,y;
public:
complex()
{}
complex(float real, float imag)
{
x=real;
y=imag;
}
complex operator+(complex c)
{
complex temp;
temp.x = x + c.x;
temp.y = y + c.y;
return(temp);
}
void display()
{
cout<<x<<" + j"<<y<<"\n";
}
};
int main()
{
39
complex c1,c2,c3;
c1=complex(2.5, 3.5);
c2=complex(1.6, 2.7);
c3=c1+c2;
cout<<"c1 = ";
c1.display();
cout<<"c2 = ";
c2.display();
cout<<"c3 = ";
c3.display();
return 0;
}
c1 = 2.5 + j3.5
c2 = 1.6 + j2.7
c3 = 4.1 + j6.2
The operator+ function is expected to add two complex values and return a complex value as the
results but receives only one value as argument.
We know that the member function can be invoked only by an object of the same class. Here, the object
C1 takes the responsibility of invoking the function and C2 plays the role of an argument that is passed
to the function. The above invocation statement is equivalent to
Therefore, in the operator+( ) function, the data members of C1 are accessed directly and the data
members of C2 (that is passed to an argument) are accessed using the dot operator. Thus, both the
objects are available for the function. For example, in the statement
temp.x = x + c.x;
c.x refers to the object C2 and x refers to the object C1.temp.x is the real part of temp that has been
created specially to hold the results of addition of C1 and C2. The function returns the complex temp
to be assigned to C3.
40
TYPE CONSVERSIONS
Type conversion is required when an expression consists of different types of variables and constants.
Same type of variables does not require any conversion. For implicit data types, compiler automatically
performs conversion known as implicit conversion. To perform explicit type conversion, cast operator
is used by programmer to direct the compiler to convert of one basic type to another. These conversions
are easily understood by the compiler. But the compiler has no idea about the user-defined data types
and their conversion from one type to another, therefore to perform this type of conversion, the
programmer needs to write the separate function that convert basic type to user-defined type or vice
versa.
Three types of situations might arise in the data conversion between incompatible types:
1. Conversion from basic type to class type
2. Conversion from class type to basic type.
3. Conversion from one class type to another class type.
The conversion from basic type to class type is easy to accomplish. It may be performed with the
help of constructor with one parameter. These should be the member functions of the class and
receive parameter of basic type. The constructor receives parameter of basic type and converts that
into user-defined type. This is accomplished by following statement:
time t = minutes;
i.e. left hand side operand of = sign must be of class type and right hand operand must be of basic
type.
To understand the conversion from basic from user-defined type, let us consider the following
program
class rupee
{
int r, p;
public:
rupee(int m)
{
r=m/100;
p=m%100;
}
void display()
{
cout<<"Rupees is "<<r<<" and paise "<<p;
}
};
int main()
{
int paise=1550;
rupee r1 = paise; //type conversion from basic to user-defined
r1.display();
41
return 0;
}
To perform this type of conversion, member function is written by the programmer. Member
function consists of number of instructions which convert user-defined data into basic type of data.
This is also known as Overloading of Typecast operator. To overload the cast operator function
specify the keyword operator followed by the data-type to which you convert data in its declaration.
This function must be a class member function.
The general form of an overloaded casting operator function, usually referred to as a conversion
function, is
operator typename()
{
. . . . .
Function statements
. . . . .
}
Here typename is any of the basic datatype and this function does not have any return type not even
void.
When call for this function is made, compiler will first search from main( ) for the keyword operator
followed by data-type and conversion function will execute. It does not take any parameter. It is
necessary that left hand side operand must be of basic type and right hand side operand must be of
user defined data-type.
The following program shows the concept of class to basic type conversion:
class rupee
{
int r, p, paise;
public:
rupee(int rs, int ps)
{
r=rs;
p=ps;
}
operator int()
{
paise=(100*r)+p;
}
};
42
int main()
{
int pa;
rupee r1(20,50);
pa=r1;
cout<<"Money in paise is:"<<pa<<”paise”;
return 0;
}
We can also convert objects of one class type to another class type. Consider the following statement:
objX is an object of class X and objY is an object of class Y. The class Y type data is converted to Class
X type data and the converted value is assigned to the objX. Since the conversion takes place from class
Y to class X, Y is known as the source class and X is known as the destination class.
Such conversions between objects of different classes can be carried out in two ways:
1. by using constructor or
2. a conversion function.
class celsius
{
float c;
public:
celsius(float cs)
{
c=cs;
}
celsius()
{
c=0.0;
}
void display()
{
cout<<"Temperature in Celsius is :"<<c;
}
};
class farenheit
{
float cel, f;
public:
43
farenheit(float fn)
{
f=fn;
}
operator celsius()
{
cel=(f-32.0)*(5.0/9.0);
return(cel);
}
};
int main()
{
farenheit f(90);
celsius c;
c=f;
c.display();
return 0;
}
44
SECTION - C
INHERITANCE
Reusability is an important feature of Object Oriented Programming. C++ strongly supports the concept
of reusability. This is basically done by creating a new class, reusing the properties of the existing ones.
The mechanism of deriving a new class from an old one is called inheritance. The old class is referred
to as the base class and the new one is called the derived class.
TYPES OF INHERITANCE
1. Single Inheritance: A derived class with only one base class is called single inheritance.
2. Multiple Inheritance: A derived class with several base classes is called multiple inheritance.
3. Hierarchical Inheritance: A base class with several derived classes is called hierarchical
inheritance.
4. Multiple Inheritance: The mechanism of deriving a class from other derived class is called
multiple inheritance.
5. Hybrid Inheritance: The combination of more than one type of inheritance is called hybrid
inheritance.
A derived class can be defined by specifying its relationship with the base class in addition to its own
details. The general form of defining a derived class is:
45
The colon (:) indicates that the derived-class-name is derived from the base-class-name. The visibility
mode is optional and if given, it may be either private or public. The default visibility mode is private.
- When the base class is privately inherited by a derived class, public members of the base class
become private members of the derived class and therefore the public members of the base class
can only be accessed by the member functions of the derived class. They are inaccessible to the
objects of the derived class.
- When the base class is publicly inherited by the derived class, public members of the base class
become public members of the derived class and therefore they are accessible to the objects of
the derived class.
- In both cases, the private members of the base class are not inherited, therefore the private
members of the base class will never become the members of its derived class.
SINGLE INHERITANCE
• Single Inheritance (Public): Following program shows the concept of single inheritance with
public visibility mode.
Program : Single Inheritance by Public derivation
#include<iostream>
using namespace std;
class student
{
int roll_no;
char name[20];
public:
void getdata()
{
cout<<"Enter the roll number and name of student :";
cin>>roll_no>>name;
}
void showdata()
{
cout<<"Roll Number is "<<roll_no<<"\n";
cout<<"Name is "<<name<<"\n";
}
};
int main()
{
marks m;
46
m.getdata();
m.showdata();
m.getmarks();
m.showmarks();
return 0;
}
The class marks is a public derivation of the base class student. Therefore, marks inherit all the public
members of class student. Thus the public members of the base class student is also a public members
of the derived class marks. The private members of student class cannot be inherited by the class
marks.
• Single Inheritance (Private): The following program shows the concept of single inheritance
with private derivation.
Program : Single Inheritance by Private derivation
#include<iostream>
using namespace std;
class student
{
int roll_no;
char name[20];
public:
void getdata()
{
cout<<"Enter the roll number and name of student :";
cin>>roll_no>>name;
}
void showdata()
{
cout<<"Roll Number is "<<roll_no<<"\n";
cout<<"Name is "<<name<<"\n";
}
};
47
int main()
{
marks m;
m.getmarks();
m.showmarks();
return 0;
}
MULTILEVEL INHERITANCE
The mechanism of deriving a class from another derived class is known as multilevel inheritance. This
means in multilevel inheritance; a derived class becomes base class of another derived class and so on.
Each derived class must have a kind of relationship with its immediate base class. To implement this
kind of inheritance at least three classes are required.
A Base Class
C Derived Class
The class A serves as a base class for the derived class B, which in turn serves as a base class for the
derived class C. The B is known as intermediate base class since it provides a link for the inheritance
between A and C. The chain A-B-C is known as inheritance path.
MULTILEVEL INHERITANCE
#include<iostream>
using namespace std;
class student
{
int roll_no;
char name[20];
public:
void getdata()
{
cout<<"Enter the roll number and name of student :";
cin>>roll_no>>name;
}
void showdata()
{
cout<<"Roll Number is "<<roll_no<<"\n";
48
cout<<"Name is "<<name<<"\n";
}
};
MULTIPLE INHERITANE
It is a process of deriving a new class from multiple base classes. A class can inherit the attribute of two
or more classes. Multiple inheritance allows us to combine the features of several existing classes for
defining new classes. In this derived class must have a kind of relationship with its base class. In the
figure, there are two base classes base1 and base2 and a derived class derived.
49
Base1 Base2
Derived
where visibility may be either public or private. The base classes are separated by commas.
Example:
Multiple Inheritance
#include<iostream>
using namespace std;
class M
{
protected:
int m;
public:
void get_m()
{
m=20;
}
};
class N
{
protected:
int n;
public:
void get_n()
{
n=10;
}
};
50
public:
void display()
{
total=m+n;
cout<<"m + n = "<<total;
}
};
int main()
{
P obj;
obj.get_m();
obj.get_n();
obj.display();
return 0;
Occasionally, we may face a problem in using the multiple inheritance, when a function with the same
name appears in more than one base class, Consider the following two classes:
class A
{
public:
void display()
{
cout<<”display() in class A”;
}
};
class B
{
public:
void display()
{
Cout<<”display() in class B”;
}
};
which display( ) function is used by derived class when we inherit these two classes? We can solve this
problem by defining a named instance using the class resolution operator with the function as shown
below:
int main()
{
C obj; //derived class object
obj.display(); //invokes display() in derived class C
obj.A::display(); //invokes display() in base class A
obj.B::display(); //invokes display() in base class B
return 0;
}
51
Following program shows how to resolve ambiguity in multiple inheritance
class B
{
public:
void display()
{
cout<<"Display function of class B "<<"\n";
}
};
int main()
{
C obj;
obj.display();
obj.A::display();
obj.B::display();
return 0;
}
HIERARCHICAL INHERITANCE
The properties of one class may be inherited by more than one class. This process is known as
hierarchical inheritance. In this type of inheritance base class has all the properties and methods that are
common to the inherited classes.
Hierarchical inheritance follows one-to-many relationship in which multiple classes can be derived.
Base
52
Following program shows the concept of hierarchical inheritance
Hierarchical Inheritance
#include<iostream>
using namespace std;
class person
{
char name[20];
long int contact_no;
public:
void getdata()
{
cout<<"Enter the name :";
cin>>name;
cout<<"Enter the contact number :";
cin>>contact_no;
}
void showdata()
{
cout<<"Name is "<<name<<"\n";
cout<<"Contact No. is "<<contact_no<<"\n";
}
};
53
int main()
{
student s;
employee e;
cout<<"Enter the student details :"<<"\n";
s.get_stdinfo();
cout<<"\nThe student details are :"<<"\n";
s.show_stdinfo();
cout<<"\nEnter the employee details :"<<"\n";
e.get_empinfo();
cout<<"\nThe employee details are :"<<"\n";
e.show_empinfo();
}
Name is Rajvir
Contact No. is 112234455
Roll No. is 23
Course is BCA
Name is sonu
Contact No. is 33333333
Employee id is 321
Designation is teacher
HYBRID INHERITANCE
Hybrid inheritance means to implement more than one form of inheritance like multiple, multilevel etc.
This form of inheritance is used when we want to use features of different classes in some other classes.
Hybrid inheritance allows us to derive a class from another derived class using multiple base classes.
The following diagram shows the concept of hybrid inheritance. It shows the combination of multilevel
and multiple inheritance
54
student
marks practical
result
Hybrid Inheritance
#include<iostream>
using namespace std;
class student
{
int roll_no;
char name[20];
public:
void getdata()
{
cout<<"Enter the roll number and name of student :";
cin>>roll_no>>name;
}
void showdata()
{
cout<<"Roll Number is "<<roll_no<<"\n";
cout<<"Name is "<<name<<"\n";
}
};
class sports
{
public:
int sp_marks;
void getspmarks()
{
cout<<"Enter the marks in sports :";
cin>>sp_marks;
}
void showspmarks()
{
cout<<"The marks in sports is "<<sp_marks<<"\n";
55
}
};
student
theory practical
student
Inheritance by the ‘result’ class as shown in figure might pose some problems. All the public and
protected members of student class are inherited into ‘result’ twice, first via ‘theory’ class and again via
‘practical’ class. This means that ‘result’ would have duplicate sets of the members inherited from
‘student’. This introduces ambiguity and should be avoided.
56
The duplication of inherited members due to these multiple paths can be avoided by making the
common base class as a virtual base class. When a class is made a virtual base class, only one copy
that class is inherited, regardless of how many inheritance paths exist between the virtual base class
and a derived class.
57
}
} ;
int main()
{
result r;
r.getdata();
r.getmarks();
r.getpractical();
r.showdata();
r.showmarks();
r.showpractical();
r.display();
return 0;
}
58
POLYMORPHISM
Polymorphism is one of the important feature of OOP. It simply means ‘one name, multiple forms’.
The concept of polymorphism is implemented using the overloaded functions and operators. The
overloaded member functions are selected for invoking by matching arguments, both type and number.
This information is known to the compiler at the compile time and therefore compiler is able to select
the appropriate function for a particular call at the compile time itself. This is called early binding or
static binding. It is also known as compile time polymorphism.
Now, consider the following situation where the function name and prototype is the same in both the
base and derived classes. For example, consider the following class definition:
class A
{
int x;
public:
void show()
{
. . . .
}
};
class B
{
int y;
public:
void show()
{
. . . .
}
};
How do we use the member function show() to print the values of objects of both the classes A and B?
Since the prototype of show() is the same in both the places, the function is not overloaded and therefore
static binding does not apply.
It would be nice if the appropriate function could be selected while the program in running. This is
known as run time polymorphism. C++ supports a mechanism known as virtual function to achieve
run time polymorphism.
At run time, when it is known what class objects are under consideration, the appropriate version of the
function is invoked. Since the function is linked with a particular class much later after the compilation,
59
this process is termed as late binding. It is also known as dynamic binding because the selection of the
appropriate function is done dynamically at run time.
Dynamic Binding is one of the powerful feature of C++. This requires the use of pointers to objects.
Pointer is one of the key aspects of C++. It is a derived data type that refers to another data variable by
storing the variable’s memory address rather than data. A pointer variable defines where to get the value
of a specific data variable instead of defining actual data.
data-type *pointer-variable
Here pointer-variable is the name of the pointer, and the data-type refers to one of the valid C++ data
types, such as int, char, and so on. The data-type is followed by an asterisk (*) symbol, which
distinguishes a pointer variable from other variables to the compiler.
POINTERS TO OBJECTS
A pointer can point to an object created by a class. Consider the following statement:
item x;
where item is a class and x is an object defined to be of type item. Similarly we can define a pointer
it_ptr of type item as follows:
item *it_ptr;
Object pointers are useful in creating objects at run time. We can also use an object pointer to access
the public members of an object.
class item
{
int code;
float price;
public:
void getdata(int a, float b)
{
code=a;
price=b;
}
void show()
{
cout<<”code is :”<<code<<endl;
cout<<”Price is :”<<price;
}
};
60
item x;
item *prt = &x;
x.getdata(100,75.50);
x.show()
are equivalent to
ptr->getdata(10075.50);
ptr->show();
We can also create objects using pointers and new operator as follows:
This statement allocates enough memory for the data members in the object structure and assigns the
address of the memory space to ptr. Then ptr can be used to refer to the members as shown below.
ptr->show();
We can also create an array of objects using pointers. For example, the statement
Pointer to Objects
#include<iostream>
using namespace std;
class item
{
int code;
float price;
public:
void getdata(int a, float b)
{
code=a;
price=b;
}
void show()
{
cout<<"Code is :"<<code;
cout<<"Price is :"<<price;
}
};
61
int main()
{
item *p = new item;
int x;
float y;
return 0;
}
VIRTUAL FUNCTIONS
When we use the same function name in both the base and derived classes, the function in base class is
declared as virtual using the keyword virtual preceding its normal declaration. When a function is made
virtual, C++ determines which function to use at run time based on the type of object pointed to by the
base pointer, rather than the type of the pointer. Thus, by making the base pointer to point to different
objects, we can execute different version of the virtual function.
Virtual Functions
#include<iostream>
using namespace std;
class Base
{
public:
void display()
{
cout<<"\n Display base ";
}
62
}
virtual void show()
{
cout<<"\n Show Derived ";
}
};
int main()
{
Base B;
Derived D;
Base *bptr;
return 0;
}
Display base
Show base
Display base
Show Derived
63
PURE VIRTUAL FUNCTION
It is normal practice to declare a function virtual inside the base class and redefine it in the derived
classes. The function inside the base class is rarely used for performing any task. It only serves as a
placeoholder. Such functions are called do-nothing functions.
Such functions are called pure virtual functions. A pure virtual function is a function declared in a base
class that has no definition relative to the base class. In such cases, the compiler requires each derived
class to either define the function or redeclare it as a pure virtual function. A class containing pure
virtual functions cannot be used to declare any objects of its own. Such classes are called abstract base
classes.
int main()
{
Base *b;
Derived d;
b = &d;
b->show();
}
64
SECTION – D
EXCEPTION HANDLING
The two most common type of errors in C++ programs are logic errors and syntactic errors. The logic
error occurs due to poor understanding of the problem and solution procedure. The syntactic errors arise
due to poor understanding of the language itself.
Exceptions are the run time anomalies or unusual conditions that a program may encounter while
executing. These anomalies might include conditions such as division by zero, access to an array
outside to its bounds or running out of memory or disk space. When a program encounters an
exceptional condition, it is important that it is identified and dealt with effectively.
The purpose of the exception handling mechanism is to provide means to detect and report an
“exceptional circumstance” so that appropriate action can be taken. The mechanism suggests a separate
error handling code that performs the following tasks:
C++ exception handling mechanism is basically built upon three keywords namely try, throw and catch.
The keyword try is used to preface a block of statements surrounded by braces which may generate
exceptions. This block of statements is known as try block.
When an exception is detected, it is thrown using a throw statement in the try block.
A catch block defined by the keyword catch. It catches the exception thrown by the throw statement in
the try block, and handles it appropriately.
65
When the try block throws an exception, the program control leaves the try block and enters the catch
statement of the catch block. The exceptions are objects used to transit information about a problem. If
the type of object thrown matches the arg type in the catch statement, then catch block is executed for
handling the exception. If they do not match, the program is aborted with the help of the abort()
function, which is invoked by default. When no exception is detected and thrown, the control goes to
the statement immediately after the catch block. That is, the catch block is skipped.
THROWING MECHANISM
When an exception that is desired to be handled to be detected, it is thrown using throw statement in
one of the following forms:
throw(exception);
throw exception;
throw;
The object exception may be of any type, including constants. It is also possible to throw objects not
intended for error handling.
When an exception is thrown, t will be caught by the catch statement associated with the try block.
That is the control exits the current try block, and is transferred to the catch block after the try block.
CATCHING MECHANISM
The code for handling exceptions is included in catch blocks. A catch block looks like a function
definition and is of the form
The type indicates the type of exception that catch block handles. The parameter arg is an optional
parameter name. The exception-handling code is placed between two braces. The catch statement
catches an exception whose type matches with the type of catch argument.
int main()
{
int a,b,div;
cout<<"Enter the values of a and b :";
cin>>a>>b;
try
{
if(b==0)
throw (b);
66
else
cout<<"Division is : "<<a/b;
}
catch(int i)
{
cout<<"Division by zero is not allowed ";
}
return 0;
First Run
Second Run
Program detects and catches a division-by-zero problem. The output of the first run shows a successful
execution. When no exception is thrown, the catch block skipped. In the second run, the denominator b
becomes zero, and therefore a division-by-zero situation occurs. The exception is thrown using the
object b. Since the exception object is and int type, the catch statement containing int type argument
catches the exception and displays necessary message.
It is possible that a program segment has more than one condition to throw an exception. In such cases
we can associate more than one catch statement with a try as shown below:
try
{
//try block
}
catch(type1 arg)
{
// catch block 1
}
catch(type2 arg)
{
// catch block 2
}
. . . . . .
. . . . . .
67
catch(typeN arg)
{
//catch block N
}
When an exception is thrown, the exception handlers are searched in-order for an appropriate match.
After finding a match, the control goes to the concerned catch block. When no match is found, the
program is terminated.
void test(int x)
{
try
{
if(x==1)
throw x; //int
else if(x==0)
throw 'x'; //char
else if(x==-1)
throw 1.0; //double
}
catch(char c)
{
cout<<"Caught a character \n";
}
catch(int m)
{
cout<<"Caught an integer \n";
}
catch(double d)
{
cout<<"Caught a double \n";
}
cout<<"End of try-catch statement \n\n";
}
int main()
{
cout<<"Testing multiple catches :\n";
cout<<"x==1\n";
test(1);
cout<<"x==0\n";
test(0);
cout<<"x==-1\n";
test(-1);
cout<<"x==2\n";
test(2);
return 0;
}
68
The output of the above program is:
x==0
Caught a character
End of try-catch statement
x==-1
Caught a double
End of try-catch statement
x==2
End of try-catch statement
The program when executed, invokes the function test( ) with x=1 and therefore throws x an int
exception. This matches the type of the parameter m in catch2 and therefore catch2 handler is executed.
Immediately after the execution, the function test( ) is again invoked with x=0. This time the function
throws ‘x’, a character type exception and therefore the first handler is executed. Finally the handler
catch3 is executed when a double type exception is thrown.
When the try block does not throw any exceptions and it completes normal execution,
In some situations, we may not be able to predict all possible types of exceptions and therefore may not
be able to design independent each catch handlers to catch them. In such circumstances, we can force
a catch statement to catch all exceptions instead of a certain type. This could be achieved by defining
the catch statement using ellipses as follows:
catch(...)
{
//statements for processing all exceptions
}
void test(int x)
{
try
{
if(x==0)
throw x; //int
if(x==-1)
throw 'x'; //char
if(x==1)
throw 1.0; //float
69
}
catch(...)
{
cout<<"Caught an exception \n";
}
}
int main()
{
cout<<"Testing Generic Catch \n";
test(-1);
test(0);
test(1);
return 0;
}
RETHROWING AN EXCEPTION
A handler may decide to rethrow the exception caught without processing it. In such situations, we may
simply invoke throw without any arguments as shown below:
throw;
This causes the current exception to be thrown to the next enclosing try/catch sequence and is caught
by a catch statement listed after that enclosing try block.
Rethrown an Exception
#include<iostream>
catch(double)
{
cout<<"Caught double inside function \n";
70
throw;
}
int main()
{
cout<<"Inside main \n";
try
{
divide(10.5,2.0);
divide(20.0,0.0);
}
catch(double)
{
cout<<"Caught double inside main \n";
}
cout<<"End of main \n";
return 0;
}
Inside main
Inside function
Division = 5.25
End of function
Inside function
Caught double inside function
Caught double inside main
End of main
When an exception is rethrown, it will not be caught by the same catch statement or any other catch in
that group. Rather, it will be caught by an appropriate catch in the outer try/catch sequence only.
A catch handler itself may detect and throw an exception. Here again, the exception thrown will not be
caught by any catch statements in that group. It will be passed on to the next outer try/catch sequence
for processing.
71