BCS 031
BCS 031
1.0 Introduction 5
1.1 Objectives 5
1.2 Program and Programming 6
1.3 Programming Languages 8
1.4 Structured Programming Paradigm 9
1.5 Object-Oriented Programming Paradigm 11
1.6 Structured Vs. Object-Oriented Programming 12
1.7 Object-Oriented Programming Concepts 13
1.8 Benefits of OOPs 20
1.9 Summary 21
1.10 Answers to Check Your Progress 22
1.11 Further Readings 23
1.0 INTRODUCTION
The computer programs are the means used by human beings for communication with
the machines especially the computers. As you all know, programs or the software
contain instructions for the hardware to accept inputs, to process those inputs
according to the instructions and to produce information as per the instructions
contained in the program. The term ‘programming’ today is used to define the
solution to a specific problem to be solved with the help of programs and it is said to
define its solutions in terms of its design, creation, testing, debugging, implementation
and its maintenance. Throughout the history of programming, ever increasing
complexity of the problems to be solved using computers has encouraged the
researchers and developers to evolve better means to manage this complexity.
Complexity and intended areas of application coupled with some other factors have
led to the evolution of a number of programming paradigms. Various programming
languages are in use today depending upon various existing programming paradigms.
This unit starts with a discussion on what a program is and what the programming is
all about. It further highlights various important programming paradigms focussing
basically on the structured and OOP paradigms. Subsequently, you will learn the main
concepts involved in the OOP have been presented along with the benefits of OOP.
1.1 OBJECTIVES
5
Basics of Object Oriented know about various major computer programming paradigms;
Programming & C++
explain the structured and OOP paradigms and to appreciate the differences
between these two;
gain insight into various concepts that support the OOP; and
describe the benefits of OOP.
As you might be aware, the two essential components of any computer system are
hardware and software. Both hardware and software have their own sets of
functionalities which can be interdependent or independent of each other. A computer
system is designed to produce the desired results by making the functionalities of both
the hardware and the software to converge. The hardware is what we can see, touch
and feel e.g. keyboard, mouse, visual display units like monitors, printers etc. Once it
has been designed and manufactured to provide a certain set of functionalities, it can
not be modified easily. Any modification in the hardware requires lot of effort, time
and money. That is why we don’t change our hardware very frequently. If the
computers are required to carry out only a few predefined operations, these can be
very easily embedded in the design of its hardware. But this kind of a computer
completely lacks flexibility. In order to provide flexibility to perform some different
operation in a computer, most of the existing hardware requires to be replaced with a
newer one; whenever a new operation is added or older operations are to be
abandoned or modified. Therefore, a computer system always contains a minimum
basic hardware which is used by the software to provide lot of flexibility of
operations. The software can be modified / replaced with lesser effort, time and
money.
As such, a computer is essentially a data processing machine which requires two kinds
of inputs for its operations and these are: data and instructions. The hardware of a
computer can not produce the desired results unless it is given the requisite
instructions and data by the user(s). The data is what needs to be processed by the
hardware and the instructions (from within the set of its functionalities) tell this
(minimum basic) hardware how to process that data step by step within the realms of
A software is an set of functionalities so that expected results are achieved. Do you know what is
integrated set of software all about? The software deals with the instructions. The examples of
interrelated software are Microsoft Office, Microsoft Windows 7, Red Hat Linux, Railways
programs which Reservation System, Microsoft Internet Explorer, Google Search Engine etc.
instruct the
hardware as to what A program as an independent entity or as part of a software is intended to instruct the
to do and how; and
hardware to carry out specific task(s) to the satisfaction of the user(s) by providing
is responsible for specific outcomes. So how do you define a program? A program can be defined to be
getting the desired a set of instructions written in a programming language which are given in a fixed
jobs executed by the sequence to the hardware of a specific computer and executed by its hardware to
computer to produce predetermined and expected outcomes. The instructions in a program are
produce the written mostly in natural languages (e.g. English, Hindi, French, German, and Chinese
predetermined etc.) following the syntax (form) and semantics (meaning) of the programming
outputs. language chosen for writing the program. There are a variety of programming
languages available for writing the programs e.g. BASIC, C, C++, Java, Prolog, Lisp,
HTML, PHP etc. The sequence of instructions is very important because if the
sequence is not correct, the expected results cannot be achieved by the program.
Now, let us see what does programming mean to us? The meaning of the term
programming (or computer programming) has been changing rapidly since the idea of
a first program was envisaged. Initially the computers were used to solve the
mathematical problems with the help of calculations. Hartee in 1950 suggested that
6
the process of preparing a calculation for a machine can be broken down into two Object Oriented
parts, ‘programming’ and ‘coding’. He described programming as the process of Programming
drawing up the schedule of the sequence of individual operations required to carry out
the calculation. Before the availability of assemblers, coding was in fact, a very
tedious and time consuming task. Soon, programming became the major activity in
this process.
In 1958, Booth proposed that the process of organizing a calculation can be divided
into two parts, a) the mathematical formulation, and b) the actual programming. With
the passage of time, the definition of programming has kept on evolving and at
present programming is considered to be the process of writing programs and may
include activities as diverse as designing, writing, testing, debugging and maintaining
the code of a program. In normal conversation, programming is described as the
process of instructing the computer to do something desired and useful for the user
with the help of a programming language.
1) Why can hardware of a computer not produce the desired results in the absence
of instructions (program / software)?
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
7
Basics of Object Oriented
Programming & C++ 1.3 PROGRAMMING LANGUAGES
You must appreciate the fact that the programming languages are created by, we,
human beings. These languages are used to communicate instructions to the machines
especially computers so that the programs can control the behaviour of the hardware
of the machines to get desired results. Basically, the hardware of the computers
understands only the language of the hardware which is called the machine language.
The hardware is unable to understand and decipher any program written in any other
programming language. Moreover, every type of a CPU has its own machine
language. Therefore, in order to make the hardware of a computer understand the
instructions contained in a program written in any other programming language, a
mechanism called ‘translator’ is required. This translator converts the program written
in programming languages other than the native machine language of the CPU
(hardware) into the native machine language of a particular CPU on which this
program is intended to be executed. Every programming language must have its own
translator for the programs written in it to be executed or run on the computer
hardware. Various types of translators available can be categorized into assemblers,
interpreters or compilers.
The primitive or the first generation of programming languages were called machine
languages and the symbols like ‘0’ and ‘1’ were used to write programs under this
category of programming languages. The second generation of programming
languages were called the assembly languages and mainly used mnemonics to
construct a program. Both of these generations of programming languages were CPU
dependent i.e., every type of a CPU will have its own machine and assembly
language. The third generation of programming languages was called high level
languages as these programming languages were independent of the CPU of the
hardware being used and the instructions written in the programs were just like the
instructions given in natural languages. The third generation languages are known as
3GL languages. The current generation of the programming languages are called the
fourth generation languages or the 4GLs. These languages represent the class of
programming languages that are closest to the human (natural) languages.
Based on the intended use of domain of use, the programming languages are broadly
classified as imperative programming languages where imperative sentences are used
in a program to issue commands in terms of instructions; and declarative
programming languages where declarative instructions are used in a program to assert
the desired result. But a more common paradigm classifies these languages into
imperative, functional, logic programming and object-oriented languages. Table 1.1
presents the summary of main features of these programming paradigms.
Table 1.1: Summary of Main Features of Programming Paradigms
8
Table 1.2 shows some of the examples of programming Paradigms. Object Oriented
Programming
Table 1.2: Programming Languages under Programming Paradigms
Paradigm Example
Imperative Algol, Pascal, C, Ada
Functional Lisp, Refal, Planner, Scheme
Logic Prolog
Object- Smalltalk, Eiffel, C++, Java
oriented
There exist certain programming languages that inherit the features of more than one
paradigms and the examples of some modern programming languages are presented in
Table 1.3.
Paradigms Example
Imperative + Object- Object Pascal, C++, Java, Ada-
oriented 95
Functional + Object- Clos
oriented
Logic + Object-oriented Object Prolog
The structured programming follows the principle of divide and conquer. A solution
of a problem can be said to consist of (or include) a set of tasks, on the same lines, a
program can also be designed to perform a set of tasks by dividing it into the task
performing blocks.
Under unstructured programming paradigm, a) mostly, all the program code is written
in a single continuous main program, b) logic is difficult to follow within the program,
9
Basics of Object Oriented c) code from other programs is hard to incorporate, d) it is difficult to test specific
Programming & C++ portions of a program, and e) program is difficult to debug and maintain. In contrast,
structured programming is defined as a programming paradigm which follows certain
set of quality standards to create programs that are more reliable and readable; and
easier to maintain. Under this paradigm, the aim is that before the code is written, the
structure of a program is required to be defined clearly and a decision to attach other
programs and libraries be taken.
Some of the major advantages and disadvantages of structured programming are given
below:
a) Since GOTO statement is not used, the structure of the program needs to be
planned meticulously.
b) Lack of encapsulation.
c) Same code repetition.
d) Lack of information hiding.
e) Change of even a single data structure in a program necessitates changes at many
places throughout it, and hence, the changes become very difficult to track even in
a reasonably sized program.
f) Not much reusability of code.
g) Can support the software development projects easily up to a certain level of
complexity. If complexity of the project goes beyond a limit, it becomes difficult
to manage.
Simula was the first programming language developed in the mid-1960s to support the
object-oriented programming paradigm followed by Smalltalk in the mid-1970s that is
known to be the first ‘pure’ object-oriented language. Eiffel, Java, C++, Object
Pascal, Visual Basic, C# etc are the other OOP languages that came into existence
later on, all having different complexities of syntax and dynamic semantics.
10
The main motive of the developers of programming languages over the years has Object Oriented
always been to create such programming languages that are close to human (i.e. Programming
natural) languages. The way we perceive and interact with the things in our day-to-
day lives, the representation of programming constructs should closely match the
The real world can be
same. Hence came into existence the concept of ‘objects’ and ‘object-oriented
considered to be made up
programming paradigm’.
of various objects with
which the human beings
Every object has certain defining properties which distinguish it not only from
regularly interact e.g. a
different types of other objects but from the similar types of objects too. If we take an
ball pen, a tooth brush, a
example of an object like a ball pen, its defining property may be the colour in which
vehicle, a foot bear or a
it can write, length, shape, unique manufacturing code etc. Some of these properties
house etc.
not only distinguish the ball pen object from the tooth brush object but also
distinguish individual ball pens objects. It must be understood clearly that no two
objects in the physical world, even of same type, are identical since no two objects
can have the value of all its defining properties same.
Likewise, every object has certain functions associated with it and all similar types of
objects are supposed to support these. Although, Some of these functions can be the
same as associated with different types of objects. In case of a ball pen, one of the
functions associated with each type of ball pen object, is to write and another
associated function is the provision to hold it in hands conveniently. All the ball pen
objects support both these functions. Incidentally, all the tooth brush objects also
support the function of holding them in the hands conveniently but, in addition,
support other functions like brushing the teeth too.
This concept of objects borrowed from the real world has been the basis of the object-
oriented programming (OOP) paradigm and this paradigm is a direct consequence of
an effort to have a programming language closely matching the human behaviour.
This OOP paradigm is all about creating program(s) dealing with objects where these
objects interact with one another to achieve the overall objectives of the program.
Every object in the programs has certain defining properties called attributes (or
instance variables) possessing supporting values for each of the attributes and some
associated functions (normally called methods or operations). As in the real world
objects, no two objects in a program can have the same values of all the attributes.
Therefore, we can say that a class is used to represent a set of objects having same
structure and behaviour. So, how do we define a class? A class is defined to be a
template or a prototype so that a collection of attributes and methods can be described
within it and this definition can be used for creating different objects within a
program. It is this concept of encapsulating the data and methods within the objects
that provides the programmers with flexibility within the OOP paradigm because an
object can be extended or modified without making changes to its external interface or
other classes/objects in the program. Various classes may exhibit features like
inheritance and polymorphism of methods.
11
Basics of Object Oriented
Programming & C++ When a program is executed, various objects are created with their corresponding
states and these objects interact with one another by exchanging messages, the
messages thereby causing the modification of their states. Modification in the state of
an object is said to have occurred when the values of one or more of its attributes
(instance variables) change due to the interaction. All the objects created are made to
exhibit a behaviour through their corresponding methods such that the program
produces the desired results once its execution is over. A program in this paradigm
therefore, becomes a collection of cooperating and interacting objects instead of just a
list of objects.
For the sake of an example, a Maruti Wagon-R could be an object. It would have a
state depend upon whether its engine is running or not. Also it would have a
behaviour, like starting ignition of its engine or stopping the ignition of its engine and
this behaviour is responsible for changing its state from ‘engine is not running’ to
‘engine is running’ or from ‘engine is running’ to ‘engine is not running’.
In a different example, we can take object ABC representing a student having a state
defined by its attribute named RESULT. A part of the behaviour of this object could
be reflected through ‘compute result’. If this student has not appeared in the
examination yet, the state of this object defined by the attribute RESULT may be
NOT DECLARED. But once this student has appeared in the examination and the
marks obtained by this student are available, the behaviour of this object changes the
state of the object ABC by using the method ‘compute result’ from NOT
DECLARED to either FAIL or PASS with percentage of marks.
1) OOP is closer to the phenomena in real world due to the use of objects whereas
structured programming is a bit away from the natural way of thinking of human
beings.
2) Structured programming is a subset of object-oriented programming. Therefore,
OOP can help in developing much larger and complex programs than structured
programming.
3) Under structured programming, the focus of a program is on procedures or
functions (behaviour) and the data is considered separately (data structures are not
well organized within the program) whereas in OOP, data (structure) and methods
(behaviour) both are in collective focus.
4) In OOP, the basic units of manipulation are the objects whereas in case of
structured programming, functions or procedures are the basic units of
manipulation.
5) The focus of a program is on manipulation of data in structured programming
whereas the focus of OOP is on both data (structures and states of objects) as
well as on its manipulation (behaviour of objects).
6) In OOP, data is hidden within the objects and its manipulation can be strictly
controlled whereas in structure programming the data in the form of variables is
exposed to unintended manipulation too.
12
7) The OOP promotes the reuse of classes and their parts of the code too. In addition, Object Oriented
it also supports the inheritance of state and behaviour. This feature is missing in Programming
structured programming.
8) The OOP supports polymorphism of operations.
9) The concepts of OOP have got integrated with most of the prominent object-
oriented methodologies of software development in a better way and help in
reducing the development effort and time as compared with that of structured
methodologies based on structured programming.
10) The structured programming normally emphasized on single exit point in their
constituent functions or procedures. Since each function/procedure allocates some
memory to itself for storing the values of its variables and code, before the exit,
there must be a provision for deallocating this memory. Otherwise, more and
more of the memory gets occupied by each function/procedure and in large
programs, there may occur a shortage of memory for use by other
functions/procedures and the processing can get slower or even completely halted.
When in any function/procedure, memory is allocated, but not deallocated, a
memory leak is said to have occurred (the memory has leaked out of the
computer) in it.
Abstraction (data)
13
Basics of Object Oriented included in the program. Same is true for behaviour depicted by the methods of the
Programming & C++ class ‘student’.
Information Hiding
Information or data hiding in an object is characterised by its knowledge of a design
decision which it hides from all other objects. The interface of an object is chosen to
reveal only the desired data or working of the object. According to the definition of
information/data hiding given by Booch in 1991, it is the process of hiding all details
of an object that do not contribute to its essential characteristics; typically, the
structure of an object as well as the implementation of its methods is hidden from
other objects. There can be two types of information hiding: functional information
hiding related to the hiding of implementation details of methods (behavioural
information of a particular object) and data hiding (structural information of a
particular object). As in the case of abstraction, there are varying degrees of
information hiding. Some languages like C++ also allow varying degree of visibility
of objects like public, private and protected. So the mechanism of information hiding
is said to provide a strictly controlled access to the information enclosed within the
capsule.
Encapsulation
Method n Method 3
Do you think information hiding and encapsulation mean the same thing? No,
information hiding cannot be treated as encapsulation, both are related but altogether
different aspects e.g. an array or a record structure also encloses the information but
this information cannot be said to be hidden. It is true that the encapsulation
mechanism like classes and objects hide information but these also provide visibility
of some of their information through well defined interfaces.
A class is a collection of similar entities which have same structure and exhibit same
behaviour. These are used to describe something in the real world like places,
14
organizations, roles, things, occurrences etc. A class is said to describe the structure Object Oriented
and behaviour of these sets of similar entities called objects. As opposed to actual Programming
objects, the class gives a general description of these objects like a template, blueprint
or a pattern; and contains the definitions of all the attributes and methods which will
become the part of each object created from the class. Only after a class has been
defined, specific instances of the class can be created and these instances are called
the instances of that class. The process of creation of these instances as objects of the
class is called instantiation. Table 1.4 cites certain examples of classes and their
objects for your ready reference.
Teacher :Teacher
Name: String Name = Ajay Object
Class Age: Integer Age = 21
evaluate() evaluate ()
{ {
… …
} }
Message Passing
In object oriented languages, you can consider a running program under execution as
a pool of objects where objects are created for ‘interaction’ and later destroyed when
their job is over. This interaction is based on ‘messages’ which are sent from one
object to another asking the recipient object to apply one of its own methods on itself
and hence, forcing a change in its state. The objects are made to communicate or
interact with each other with the help of a mechanism called message passing. The
methods of any object may communicate with each other by sending and receiving
messages in order to change the state of the object. An Object may communicate with
other objects by sending and receiving messages to and from their methods in order to
15
Basics of Object Oriented change either its own state or the state of other objects taking part in this
Programming & C++ communication or that of both. An object can both send and receive messages.
The messages are sent and received by passing various variables among specific
methods using the signatures (a term that is not prevalent in common parlance) of the
methods. Every method has a well defined and structured signature. The signature of a
method is composed of: a) a type, associated with the variable whose value after
execution of the method, would be returned to the object that would invoke the
method; b) the types of a specific number of variables and the order associated with
these variables whose values would be passed to the method before execution of the
method starts. All these variables have a well defined format and corresponding
values at any instant of time available for communication during the execution of the
program. Figure 1.3 shows an example of a signature for a method ‘evaluate’.
Interface
Every class defines an interface for itself and its objects use only this interface for all
types of communications. We may say that an interface of a class or an object is the
collection of signatures of all the methods contained in the class or the object. It is
through this interface, the objects communicate with themselves or with other objects
by passing value of variables to and fro and hence, in the process, changing their own
state or hat of other objects or that of both. As the signatures of various methods of
an object are well structured and precisely defined, therefore, the interface of an object
also has a well defined precise structure. As you can see, figure 1.4 shows the
mechanism of message passing between two objects through their interfaces. Various
OOP languages have different mechanisms to implement the interfaces.
Interfaces
Object A Object B
Message Passing
Association
The classes and hence the corresponding objects in OOP languages are in relationship
with one another. Various kinds of vital relationships are association, aggregation,
inheritance etc. An association is the term used to represent the relationships among
various objects of one or more classes. An illustration of association is given in figure
16
1.5. The association here has been represented by a simple straight line whereas the Object Oriented
classes have been represented by rectangles. Programming
Inheritance
Can you guess what inheritance is? Inheritance is a mechanism by virtue of which the
classes inherit the attributes and methods of some other class(s). In a sense, we can
say, inheritance is a way to reuse the code of some existing or already defined classes.
The classes, in this case, are said to have ‘a-kind-of’ and ‘is-a’ relationship with the
other classes. Using this property of OOP, one class can extend other classes by
including additional methods and/or attributes (variable). The original class is called
the ‘superclass’ of the extending class and the extended class is called the ‘subclass’
of the class that is being extended. The subclass is sometimes known with the name of
‘derived’ class and the superclass with the name of ‘base’ class. The derived or
subclasses classes can further be used to have their own derived subclasses. This kind
of a relationship of classes through inheritance gives rise to an inheritance hierarchy
of the classes. Can you explain, why?
As an example, if you take ‘car’ as a superclass; then you can treat SUV, sedan, sports
car, roadster as its subclasses. All or some of these subclass cars have some common
attributes (structure) and methods (behaviour). But the structure and behaviour of
these subclass cars is not restricted to those of the superclass ‘car’. A subclass car can
contain methods and attributes in addition to those inherited from the superclass ‘car’
e.g. a sports car will generally have only two doors whereas a sedan will have four.
The subclasses can also contain methods that override the methods they have inherited
to have unique implementation of these methods. Another example of inheritance can
be that of a ‘geometric figure’ as a superclass and a ‘circle’ and a ‘triangle’ as its
subclasses as shown in figure 1.6.
17
Basics of Object Oriented
Programming & C++
GeometricFigure
x: Integer
y: Integer
Superclass display()
move()
remove()
Inheritance
Circle Triangle
radius: Integer length: Integer
setRadius() breadth: Integer
getPerimeter() display()
move()
setLength()
Subclass setBreadth()
Various categories of Inheritance which are often used in OOP are single level, multi-
level, multiple inheritance etc.
Polymorphism
Polymorphism or the ability to appear in many forms, is one of the vital primary
characteristic concepts of OOP. ‘Poly’ means ‘many’ and ‘morph’ means ‘form’. In
reference to OOP, it is an ability of assigning different meanings to entities such as
variable, methods or objects so that these can be made to exhibit more than one form.
It provides the programmers with the flexibility of processing any object differently
depending upon their data types. Using this concept, a programmer can redefine
various methods of the classes derived from their base classes. Objects of different
types can receive the same message and respond in different ways provided these
objects have the same method definition (i.e. interface). The calling object, also
sometimes known as the client, need not know what type of object it is calling, the
only thing that it needs to know or ensure is that the called object has a method of a
specific name with defined arguments. Polymorphism is more often than not applied
to derived classes, where the methods of the parent class are replaced with those
having different behaviours. It is the concepts like inheritance and polymorphism that
together make OOP flexible and easy to extend.
Do you know how many categories of polymorphisms exist? There are two categories
of polymorphisms; static or compile-time and dynamic or run-time. In static
polymorphism, which form of the method (from among the various available forms) is
to be called and executed is decided during the time of compilation, the example
being ‘Method Overloading’. In method overloading, same method name having
different parameters is used more than once in the same class. Which method is to be
called and executed depends upon the parameters passed by the calling method and is
decided during the compilation of the program. The dynamic polymorphism is applied
in the form of method overriding which means there can exist two or more methods in
a program which have the same signature (name; return type; type, number and order
18
of arguments to be passed) having different implementations. In figure 1.7 these two Object Oriented
types of polymorphisms are explained. Programming
Method Overloading
Method Overriding
class Square
{ Base Class
public int side;
public double getArea(side)
{
return side * side; Overridden methods
} (with same signature but
} different implementations)
Class Cube
{
public double getArea(side) Derived
{ Class
return side * side * side;
}
…
}
19
Basics of Object Oriented a) Identity which means the quantization of data in terms of entities called the
Programming & C++ objects that are discrete and distinguishable;
b) Classification into classes i.e. grouping of objects of same structure and
behaviour;
c) Polymorphism i.e. depiction of different behaviour of same operations on
different classes; and
d) Inheritance in terms of sharing of structure and behaviour among classes in a
hierarchical relationship.
But, what about the languages that support similar kinds of features? As such, there
are certain languages that may support some of these feature but not all. The
languages that support only some of these features like identity and classification (and
may be polymorphism too) do not qualify to be called object-oriented programming
languages. These programming languages are called object-based programming
languages. Visual Basic is one such programming language which supports objects
and classes but not inheritance and that is why it is called an object-based
programming language. In contrast, VB.NET is an object-oriented programming
language. Fortran 90 is another example of object-based programming language that
does not support inheritance. Another example is JavaScript, a language that does not
have classes. In this language, the objects can be made to inherit code and data
directly from the template objects.
1) As OOP is closer to the real world phenomena, hence, it is easier to map real
world problems onto a solution in OOP.
2) The objects in OOP have the state and behaviour that is similar to the real world
objects.
3) It is more suitable for large projects.
4) The projects executed using OOP techniques are more reliable.
5) It provides the bases for increased testability (automated testing) and hence higher
quality.
6) Abstraction techniques are used to hide the unnecessary details and focus is only
on the relevant part of the problem and solution.
7) Encapsulation helps in concentrating the structure as well as the behaviour of
various objects in OOP in a single enclosure.
8) The enclosure is also used to hide the information and to allow strictly controlled
access to the structure as well as the behaviour of the objects.
9) OOP divides the problems into collection of objects to provide services for
solving a particular problem.
10) Object oriented systems are easier to upgrade/modify.
11) The concepts like inheritance and polymorphism provide the extensibility of the
OOP languages.
12) The concepts of OOP also enhance the reusability of the code written.
13) Software complexity can be better managed.
14) The use of the concept of message passing for communication among the objects
makes the interface description with external system much simpler.
15) The maintainability of the programs or the software is increased manifold. If
designed correctly, any tier of the application can be replaced by another provided
20
the replaced tier implements the correct interface(s). The application will still Object Oriented
work properly. Programming
1.9 SUMMARY
The programs are the means through which we can make the computers produce the
useful desired outputs. Out of a variety of programming paradigms being used by
practitioners as well as the researchers, the structured and the object-oriented
programming paradigm and corresponding structured and object-oriented
programming have been in focus for quite some time now. In this unit, you studied
that the structured programming languages initially helped in coping with the inherent
complexity of the softwares of those times but later on, were found wanting in the
handing the same as far as the software of present days are concerned. In the backdrop
21
Basics of Object Oriented of this, you also studied the advantages and the disadvantages of the structured
Programming & C++ programming.
1) c 2) c 3) d
22
Check Your Progress 2 Object Oriented
Programming
Answers to Objective type Questions:
1) a 2) c 3) b
23
Basics of Object Oriented
Programming & C++ UNIT 2 INTRODUCTION TO C+ +
Structure Page Nos.
2.0 Introduction 24
2.1 Objectives 26
2.2 Basics of C++ 26
2.2.1 C++ Character Set
2.2.2 Identifiers
2.2.3 Keywords
2.3 A Simple C++ Program 28
2.4 Some Simple C++ Programs 31
2.5 Difference between C and C++ 34
2.6 Data Types in C++ 34
2.6.1 Built in Data Types
2.6.2 Derived Data Types
2.6.3 User- Defined Data Types
2.7 Type Conversion 37
2.8 Variables 38
2.9 Literals or Constants 39
2.10 Operators in C++ 40
2.10.1 Arithmetic Operators
2.10.2 Relational Operators
2.10.3 Logical Operators
2.10.4 Bitwise Operators
2.10.5 Precedence of Operators
2.10.6 Special Operators
2.10.7 Escape Sequence
2.11 Control Structure in C++ 45
2.11.1 Selection or conditional statements
2.11.2 Iterative or looping statement
2.11.3 Breaking Statement
2.12 I/O Formatting 56
2.12.1 Comments in C++
2.12.2 Unformatted console I/O formats
2.12.3 setw()
2.12.4 inline()
2.12.5 setprecision()
2.12.6 showpoint bit format flags
2.12.7 Input and output stream flags
2.13 Summary 60
2.14 Answers to Check Your Progress 61
2.15 Further Readings and References 64
2.0 INTRODUCTION
In the previous unit, we have discussed concept of Objects Oriented Programming and
benefit from this Object Oriented Language. In this unit we shall discuss something
about Data Types, Operators and control structures used in C++. Data Type in C++ is
used to define the type of data that identifiers accepts in programming and operators
are used to perform a special task such as addition, multiplication, subtraction, and
division etc of two or more operands during programming.
24
Introduction to C++
Object: Students
DATA
Name
Class
Subject
|
|
|
FUNCTION
Read ()
Play ()
Fee ()
|
|
|
The data part contains the Name, Class and Subject and function part contains three
functions such as: read ( ), Play ( ) and Fee ( ). Thus, the various objects in the object-
oriented language interact with each other through their respective codes or functions
as shown in Figure 2.2.
25
Basics of Object Oriented
Programming & C++
It may be noted here that the data of an object can be accessed only by the functions
associated with that object. However, functions of one object can access the functions
of other objects.
2.1 OBJECTIVES
After studying this unit, you should be able to do the following:
In any language, there are some fundamentals you need to learn before you begin to
write even the most elementary programs. This chapter includes these fundamentals;
26
basic program constraints, variables, and Input/output formats. C++ is a superset of C Introduction to C++
language. It contains the syntax and features of C language. It contains the same
control statements; the same scope and storage class rules; and even the arithmetic,
logical, bitwise operators and the data types are identical. C and C++ both the
languages start with main function.
The object oriented feature in C++ is helpful in developing the large programs with
clarity, extensibility and easy to maintain the software after sale to customers. It is
helpful to map the real-world problem properly. C++ has replaced C programming
language and is the basic building block of current programming languages such as
Java, C# and Dot.Net etc.
Character set is a set of valid characters that a language can recognise. The character
set of C++ is consisting of letters, digits, and special characters. The C++ has the
following character set:
There are 62 letters and digits character set in C++ (26 Capital Letters + 26 Small
Letters + 10 Digits) as shown above. Further, C++ is a case sensitive language, i.e. the
letter A and a, are distinct in C++ object oriented programming language. There are
29, punctuation and special character set in C++ and is used for various purposes
during programming.
A character that is used to produce blank space when printed in C++ is called white
space character. These are spaces, tabs, new-lines, and comments.
Tokens:
A token is a group of characters that logically combine together. The programmer can
write a program by using tokens. C++ uses the following types of tokens:
2.2.2 Identifiers
In addition, variable identifiers always have to begin with a letter. In no case can they
begin with a digit. Another rule for declaring identifiers is that they cannot match any
keyword of the C++ programming language. The rules for the formation of identifiers
can be summarised as:
27
Basics of Object Oriented An identifier may include of alphabets, digits and/or underscores.
Programming & C++ It must not start with a digit.
C++ is case sensitive, i.e., upper case and lower case letters are considered different
form each other. It may be noted that TOTAL and total are two different identifier
names.
A member function with the same name as its class is called constructor and it is used
to initialize the objects of that class type with an initial value. Objects generally need
to initialize variables or assign dynamic memory during their process of creation to
become operative and to avoid returning unexpected values during their execution.
For example, to avoid unexpected results in the example given below we have
initialized the value of rollno as 0 and marks as 0.0.
2.2.3 Keywords
There are some reserved words in C++ which have predefined meaning to complier
called keywords. These are also known as reserved words and are always written or
typed in lower cases. There are following keywords in C++ object oriented language:
List of Keywords:
28
Output: Introduction to C++
Hello World!
This is one of the simplest programs that can be written in C+ programming language.
It contains all the fundamental components which every C++ program can have. Line
by line explanation of the codes of this program and its sections is given below:
#include <iostream.h>
Lines beginning with a hash sign (#) are directives for the pre-processor. They are not
regular code lines with expressions but indications for the compiler's pre-processor. In
this case the directive #include <iostream> tells the pre-processor to include the
iostream standard file. This specific file (iostream) includes the declarations of the
basic standard input-output library in C++, and it is included because its functionality
is going to be used later in the program.
All the elements of the standard ANSI C++ library are declared within namespace
std;. The syntax of this command is: using namespace std;. In order to access its
functionality we declare all the entities inside namespace std;. This line is very often
used in C++ programs that use the standard library and defines a scope for the
identifiers that are used in a program.
int main ()
This line corresponds to the beginning of the definition of the main function. The
main function is the point by where all C++ programs start their execution,
independently of its location within the source code. It does not matter whether there
are other functions with other names defined before or after it - the instructions
contained within this function's definition will always be the first ones to be executed
in any C++ program. For that same reason, it is essential that all C++ programs have a
main function.
The word main is followed in the code by a pair of parentheses (()). That is because it
is a function declaration: In C++, what differentiates a function declaration from other
types of expressions is these parentheses that follow its name. Optionally, these
parentheses may enclose a list of parameters within-them.
Right after these parentheses we can find the body of the main function enclosed in
braces ({}). What is contained within these braces is what the function does when it is
executed.
This line is a C++ statement. A statement is a simple or compound expression that can
actually produce some effect. In fact, this statement is used to display output on the
29
Basics of Object Oriented screen of the computer. cout is the name of the standard output stream in C++, and the
Programming & C++ meaning of the entire statement is to insert a sequence of characters.
cout is declared in the iostream standard file within the std namespace, so that's why
we needed to include that specific file and to declare that we were going to use this
specific namespace earlier in our code.
Notice that the statement ends with a semicolon character (;). This character is used to
mark the end of the statement and in fact it must be included at the end of all
expression statements in all C++ programs.
return 0;
b) iostream.h _______________
is a header file
pre-processor directives
user-defined function
both a and b
30
Introduction to C++
3) What do you mean by data types in C++?
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
Program: 1
// Printing a message
#include <iostream.h>
int main(void)
{
cout << “Hello, this is my first C++ program” << endl;
return 0;
}
Output:
Program: 2
// Printing name
#include <iostream.h>
# include<conio.h>
main()
{
char name [15];
clrscr();
cout << "Enter your name:”;
cin >> name;
cout<<”Your name is: “ <<name;
return0;
}
Output:
31
Basics of Object Oriented
Programming & C++ Program: 3
Output:
Result = 4
Program: 4
// initialization of variables
#include <iostream.h>
using namespace std;
int main ()
{
int a=5; // initial value = 5
int b(2); // initial value = 2
int result; // initial value undetermined
a = a + 3;
result = a - b;
cout << result;
return 0;
}
Output:
Result = 6
32
Program: 5 Introduction to C++
// my first string
#include <iostream.h>
#include <string>
using namespace std;
int main ()
{
string mystring;
mystring = "This is the initial string content";
cout << mystring << endl;
mystring = "This is a different string content";
cout << mystring << endl;
return 0;
}
Output:
Program: 6
Output:
Circle = 31.4258714
Program: 7
#include <iostream.h>
# include<conio.h>
main()
{
int num, num1;
clrscr();
cout << "Enter two numbers:”;
cin >> name>>num1;
cout<<”Entered numbers are : “ ;
cout <<num<<”\t”<<num1;
return0;
}
33
Basics of Object Oriented Output:
Programming & C++
Enter two numbers: 9, 15
Entered numbers are 9, 15
The variable declaration in C, must occur at the top of the function block and
it must be declared before any executable statement. In C++ variables can be
declared anywhere in the program.
C Language follows the top-down approach while C++ follows both top-
down and bottom-up design approach.
The memory in computer system is organized in bits and bytes. A byte is the
minimum amount of memory that we can manage in C++. A byte can store a
relatively small amount of data: one single character or a small integer. In addition,
the computer can manipulate more complex data types that come from grouping
several bytes, such as long numbers or non-integer numbers.
Data Type in C++ is used to define the type of data that identifiers accepts in
programming and operators are used to perform a special task such as addition,
multiplication, subtraction, and division etc of two or more operands during
programming.
34
C++ supports a large number of data types. The built in or basic data types supported Introduction to C++
by C++ are integer, floating point and character type. A brief discussion on these
types is shown in Figure 2.3 which are shown below:
There are four types of built-in data types as shown in the fig: 2. Let us discuss each
of these and the range of values accepted by them one by one.
An integer is an integral whole number without a decimal point. These numbers are
used for counting. For example 26, 373, -1729 are valid integers. Normally an integer
can hold numbers from -32768 to 32767.
Short
Long
Unsigned
The short int data type is used to store integer with a range of – 32768 to 32767,
However, if the need be, a long integer (long int) can also be used to hold integers
from -2, 147, 483, 648 to 2, 147, 483, 648. The unsigned int can have only positive
integers and its range lies up to 65536.
A floating point number has a decimal point. Even if it has an integral value, it must
include a decimal point at the end. These numbers are used for measuring quantities.
Examples of valid floating point numbers are: 27.4, -92.7, and 40.03.
A float type data can be used to hold numbers from 3.4*10-38 to 3.4*10+38 with six
or seven digits of precision. However, for more precision a double precision type
(double) can be used to hold numbers from 1.7*10-308 to 1.7*10+308 with about 15
digits of precision.
35
Basics of Object Oriented Summary of Basic fundamental data types as well as the range of values accepted by
Programming & C++ each data type is shown in the following table.
It specifies the return type of a function when the function is not returning any
value.
It indicates an empty parameter list on a function when no arguments are passed.
A void pointer can be assigned a pointer value of any basic data type.
It is used to store character values in the identifier. Its size and range of values is
given in Table 2.1.
Note: The values of the column Size and Range given in the table above, depends on
the computer system on which the program is compiled. The values shown above are
those found on 32-bit computer systems. But for other systems, the general
specification is that int has the natural size suggested by the system architecture (one
"word") and the four integer type‟s char, short, int and long must each one be at least
as large as the one preceding it, with char being always one byte in size. The same
applies to the floating point types float, double and long double, where each one must
provide at least as much precision as the preceding one.
36
2.6.2 Derived Data types Introduction to C++
C++ also permits four types of derived data types. As the name suggests, derived data
types are basically derived from the built-in data types. There are four derived data
types. These are:
Array
Function
Pointer, and
Reference
C++ also permits four types of user defined data types. As the name suggests, user
defined data types are defined by the programmers during the coding of software
development. There are four user defined data types. These are:
Structure
Union
Class, and
Enumerator
We will discuss these data types in the later units of this course.
a) Automatic
When an expression consists of more than one type of data elements in an expression,
the C++ compiler converts the smaller data type element in larger data type element.
This process is known as implicit or automatic conversion.
b) Typecasting
This statement allows the programmer to convert one data type into another data type
by writing the following syntax:
Here in the above syntax char variable will be converted into int Variable after
execution of the syntax in the C++ program.
37
Basics of Object Oriented
Programming & C++ 2.8 VARIABLES
A variable is the most fundamental aspect of any computer language. It is a location in
the computer memory which can store data and is given a symbolic name for easy
reference. The variables can be used to hold different values at different values at
different times during the execution of a program.
In equation (i), a value 20.00 has been stored in a memory location Total. The variable
Total is used in statement (ii) for the calculation of another variable Net. The point
worth noting is that the variable Total is used in statement (ii) by its name not by its
value. Before a variable is used in a program, it has to be defined. This activity
enables the compiler to make available the appropriate type of location in the
memory. The definition of a variable consists of the type name followed by the name
of the variable.
Declaration of variables:
In order to use a variable in C++, we must first declare it specifying which data type
we want it to be. The syntax to declare a new variable is to write the specifier of the
desired data type (like int, bool, float, etc.) followed by a valid variable identifier. For
example:
int a;
float mynumber;
These are two valid declarations of variables. The first one declares a variable of type
int with the identifier a. The second one declares a variable of type float with the
identifier mynumber. Once declared, the variables a and mynumber can be used
within the rest of their scope in the program.
If you are going to declare more than one variable of the same type, you can declare
all of them in a single statement by separating their identifiers with commas. For
example:
int a,b,c;
This declares three variables (a, b and c), all of them of type int, and has exactly the
same meaning as:
int a;
int b;
int c;
float Total;
float Net;
38
(i) int count; Introduction to C++
(ii) int i, j, k;
(iii) char ch, first;
(iv) float total, Net;
(v) long int sal;
Let us now discuss scope of variables in C++ programming. A variable can be either
of global or local scope. A global variable is a variable declared in the main body of
the C++ source code, outside all the functions. Global variables can be called from
anywhere in the code, even inside functions, whenever it is after its declaration.
The local variable is one declared within the body of a function or a block. To
illustrate the scope of global variable and local variable, let us look at the figure 4.
The scope of local variables is limited to the block enclosed in braces ({}) where they
are declared. For example, if they are declared at the beginning of the body of a
function (like in function main), their scope is between its declaration point and the
end of that function.
39
Basics of Object Oriented In the example above, this means that if another function existed in addition to main,
Programming & C++ the local variables, declared in main could not be accessed from the other function and
vice versa.
Arithmetical operators
Relational operators
Logical operators
Bitwise operators
Precedence of operators
Special operators
Escape sequence
40
Introduction to C++
Table 2.2:Operators Meaning with Example
Operator Meaning Example Answer
+ addition 8+5 13
- subtraction 8-5 3
* multiplication 8*5 40
/ division 10/2 5
% modulo 5%2 1
The relational operators shown in Table 2.3 are used to test the relation between two
values. All relational operators are binary operators and therefore require two
operands. A relational expression returns zero when the relation is false and a non-
zero when it is true.
The (!) operator is the C++ operator to perform the Boolean operation NOT. It has
only one operand, located at its right, and the only thing that it does is to inverse the
value of it, producing false if its operand is true and true if its operand is false.
Basically, it returns the opposite Boolean value of evaluating its operand. Logical
operators of C++ are given in Table 2.4.
To understand the use of these operators in C++, let us take following example:
Example:
!(5 == 5) // evaluates to false because the expression at its right (5 == 5) is true.
!(6 <= 4) // evaluates to true because (6 <= 4) would be false.
!true // evaluates to false
!false // evaluates to true.
The logical operators && and || are used when evaluating two expressions to obtain a
single relational result. The operator && corresponds with Boolean logical operation
AND. This operation results true if both its two operands are true and false otherwise.
The Table 2.5 shows the result of operator && by evaluating the expression a && b:
41
Basics of Object Oriented Table 2.5: Use of && Operator
Programming & C++
Operand (a) Operand (b) Result
true True True
true False False
false True False
false False False
The operator || corresponds with Boolean logical operation OR. This operation results
true if either one of its two operands is true, thus being false only when both operands
are false themselves. To understand the use || OR operator, let us take the possible
results of a || b in Table 2.6.
Example:
In C++ programming language, bitwise operators are used to modify the bits of the
binary pattern of the variables. Table 2.7 gives use of some bitwise operators:
Table 2.7: Use of Bitwise Operator
In case of several operators in an expression, we may have some doubt about which
operand is evaluated first and which later. For example, let us take following
expression:
a=5+7%2
Here we may doubt if it really means:
A = 5 + (7 % 2) // with a result of 6, or
a = (5 + 7) % 2 // with a result of 0
42
The correct answer is the first of the two expressions, with a result of 6. Precedence Introduction to C++
order of some operators in C++ programming language is given in the Table 2.8.
Level of
Operator Description Grouping
Precedence
1 :: scope Left-to-right
() [] . -> ++ -- dynamic_cast
2 static_cast reinterpret_cast postfix Left-to-right
const_cast typeid
++ -- ~ ! sizeof new delete unary (prefix)
indirection and
3 *& Right-to-left
reference (pointers)
+- unary sign operator
4 (type) type casting Right-to-left
5 .* ->* pointer-to-member Left-to-right
6 */% multiplicative Left-to-right
7 +- additive Left-to-right
8 << >> shift Left-to-right
9 < > <= >= relational Left-to-right
10 == != equality Left-to-right
11 & bitwise AND Left-to-right
12 ^ bitwise XOR Left-to-right
13 | bitwise OR Left-to-right
14 && logical AND Left-to-right
15 || logical OR Left-to-right
16 ?: conditional Right-to-left
= *= /= %= += -= >>= <<= &=
17 assignment Right-to-left
^= |=
18 , comma Left-to-right
Grouping defines the precedence order in which operators are evaluated in the case
that there are several operators of the same level in an expression. Thus if you want to
write complicated expressions and you are not completely sure of the precedence
levels, always include parentheses. It will also make your code easier to read.
Apart from the above operators that we have discussed above so far, C++
programming language supports some special operators. Some of them are:
increment and decrement operator; size of operator; comma operator etc.
43
Basics of Object Oriented Increment and Decrement Operator
Programming & C++
In C++ programming language, Increment and decrement operators can be used in
two ways: they may either precede or follow the operand. The prefix version before
the operand and postfix version comes after the operand. The two versions have the
same effect on the operand, but they differ when they are applied in an expression.
The prefix increment operator follows “change then use” rule and post fix operator
follows “use then change” rule.
The size of operator
We know that different types of variables, constant, etc. require different amount of
memory to store them. The sizeof operator can be used to find how many bytes are
required for an object to store in memory.
Example:
sizeof (char) returns 1
sizeof (int) returns 2
sizeof (float) returns 4
if k is integer variable, the sizeof (k) returns 2.
The sizeof operator determines the amount of memory required for an object at
compile time rather than at run time.
The comma operator
The comma operator gives left to right evaluation of expressions. It enables to put
more than one expression separated by comma on a single line.
Example:
int i = 20, j = 25;
In the above statements, comma is used as a separator between the two statements.
There are some characters which can‟t be typed by keyboard in C++ programming
language. These are called non-graphic characters. An escape sequence is represented
by backslash (\) followed by one or more characters. The Table 2.9 gives a listing of
common escape sequences.
Table 2.9: Escape Sequence
Sequence Task
\a Bell (beep)
\b Backspace
\f Formatted
\n Newline or line feed
\r Carriage return
\t Horizontal tab
\v Vertical tab
\? Question mark
\\ Backslash
\‟ Single quote
\” Double quote
\ xhh Hexadecimal number (hh represents the number in hexadecimal)
\ 000 Octal number (00 represents the number in octal)
\0 Null
44
Punctuators Introduction to C++
Before we discuss control structures, let us first discuss a new concept: the compound-
statement or block, which is very much needed to understand well the flow of control
in a program.
A block is a group of statements which are separated by semicolons (;) like all C++
statements, but grouped together in a block enclosed in braces: { }: for example:
{
statement1;
statement2;
statement3;
...
}
In C++ object oriented programming, the control structure can be classified into
following three categories:
Let us discuss the above control statement and their types in the following section.
45
Basics of Object Oriented 2.11.1 Selection or conditional statement
Programming & C++
In this type of statement, the execution of a block depends on the next condition. If the
condition evaluates to true, then one set of statement is executed, otherwise another
set of statements is executed. C++ provides following types of selection statements:
If;
If-else;
Nested if;
Switch
conditional
a) if statement:
The syntax of if statement is
If (expression)
{
(Body of if)
Statements;
}
Where, expression is the condition that is being evaluated. If this condition is true,
statement is executed. If it is false, statement is ignored (not executed) and the
program continues right after this conditional structure.
Program: 1
# include <iostream.h>
main()
{ int a, b;
a=10;
b=20;
if (a<b)
cout <<”a is less than b”;
}
Output:
a is less than b.
Since here in the program value of a is less than the value of b, so the output of the
program 1 is “a is less than b”
b) if-else statement:
If (expression)
{
(Body of if)
Statements 1;
}
else
{
(Body of else}
Statement 2
}
46
Where, expression is the condition that is being evaluated. If this condition is true, Introduction to C++
statement - 1 is executed. If it is false, then if statement is skipped and the body of else
statement is executed.
Program: 2
# include <iostream.h>
main()
{ int a, b;
a=10;
b=20;
if (a<b)
cout <<”a is less than b”;
}
else
{
cout<< “b is less than a”
}
Output:
a is less than b.
Since here in the program value of a is less than the value of b so the output of the
program 1 is “a is less than b”
c) Switch statement:
Switch statement is used for multiple branch selection. The syntax of switch statement
is
switch (expression)
{
case exp 1:
First case body;
Break;
case exp 2:
Second case body;
Break;
case exp 3:
Third case body;
Break;
default:
default case body;
}
Here, expression is the condition that is being evaluated. If the case 1 condition is
true, First case body is executed, otherwise case exp 2 is checked and so on....If none
of case expressions is true then the value of default case body is executed.
47
Basics of Object Oriented Program: 3
Programming & C++
# include <iostream.h>
# include <conio.h>
int main()
{
clrscr();
int d_o_w;
cout <<”Enter number of week‟s day (1-7)”;
cin>>d_o_w;
switch(d_o_w)
{
Output:
Wednesday
d) Nested if statement:
A nested if statement is a statement that has another if in its if‟s body or in its else‟s
body. The syntax of switch statement is
if (expression 1)
statement 1;
else if (expression 2)
statement 2;
else if (expression 3)
statement 3;
.
.
.
else
statement;
48
Introduction to C++
Here, expression is the condition that is being evaluated. If the case 1 condition is
true, First case body is executed, otherwise it is skipped and next else expression is
evaluated and so on.....
Program Segment: 4
# include <iostream.h>
# include <conio.h>
void main(void)
{
float a,b,c,d:
cout<< “Enter any four numbers \n”;
cin >>a >>b >>c >>d;
if (a > b) {
if (a > c) {
if (a > d)
cout << "largest = “ << a << end1;
else
cout << “largest = “ << d << end1;
}
else
{
if (c > d)
cout << " largest = “ << c << end1;
else
cout << “largest = “ << d << end1;
}
} // end of outer if part
else
if (b > c) {
if (b > d)
cout << "largest = “ << b << end1;
else
cout << largest = “ << d << end1;
}
else {
if (c > d)
cout<< “largest = “ << c << end1;
else
cout << “largest = “ << d << end1;
}
} // end of main program
Output:
largest = 35
49
Basics of Object Oriented 2.11.2 Iterative or looping statement
Programming & C++
In C++ , programming language looping statement is used to repeat a set of
instructions until certain condition is fulfilled. The iteration statements are also called
loops or looping statement. C++ allows following four kinds of iterative loops:
for loop
while loop
do-while loop and
nested loops
a) for loop
This loop is easiest amongst all loops in C++ programming. The syntax of this loop is:
This loop is specially designed to perform a repetitive action with a counter which is
initialized and increased on each iteration
Program: 5
Output:
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE!
b) while loop
If we do not know the number of iterations before starting the loop then while loop is
used. Its syntax is as follows:
50
Introduction to C++
The functionality of this loop is simply to repeat statement while the condition set in
expression is true.
initialization;
while (expression)
{
statement;
increment;
}
Program: 6
Output:
When execution of program starts, the user is prompted to insert a starting number for
the countdown. Then the while loop begins, if the value entered by the user fulfils the
condition n>0 (that n is greater than zero) the block that follows the condition will be
executed and repeated while the condition (n>0) remains being true.
Unlike for and while loops, the do-while is an exit-controlled loop i.e., it evaluates its
test – expression at the bottom of the loop after executing its loop-body statement.
This means that a do-while loop always executes at least once, even when the test –
expression evaluates to false initially.
do
{
statement
}
while (test condition);
51
Basics of Object Oriented
Programming & C++ Program: 7
// number echoer
#include <iostream.h>
using namespace std;
int main ()
{
unsigned long n;
do
{
cout << "Enter number (0 to end): ";
cin >> n;
cout << "You entered: " << n << "\n";
}
while (n != 0);
return 0;
}
Output:
The do-while loop is usually used when the condition that has to determine the end of
the loop is determined within the loop statement itself, like in the previous case, where
the user input within the block is what is used to determine if the loop has to end.
If a loop is placed inside the same loop then it is called nested for loop in C++
programming language. To understand, it let us take the following program:
Program: 8
// Program to print the pyramid of numbers by using a nested for loop
#include <iostream.h>
#include <conio.h>
#include <math.h>
void main ()
{
clrscr();
int n, i, j, k;
cout << "Enter the number of rows in the pyramid:”;
cin>> n;
for (i=1; i<=n-i; i++)
{
for (j=1; j<=n-i; j++)
{
cout << " ";
52
Introduction to C++
}
for (k=1; k<+i; k++)
{
cout<< k;
}
cout << end;
}
getch();
}
Output:
Using break, we can leave a loop even if the condition for its end is not fulfilled. It
can be used to end an infinite loop, or to force it to end before its natural end. In this
section, we will discuss following breaking statements:
break statement
continue statement
goto statement and
exit statement
a) break statement
The break statement is used to terminate the execution of the loop program. It
terminates the loop in which it is written and transfers the control to the immediate
next statement outside the loop. The break statement is normally used in the switch
conditional statement. To understand, it let us take the following C++ program:
Program: 9
Output:
b) continue statement
The continue statement causes the program to skip the rest of the loop in the current
iteration as if the end of the statement block had been reached, causing it to jump to
the start of the following iteration. For example, we are going to skip the number 5 in
our countdown:
Program: 10
int main ()
{
for (int n=10; n>0; n--) {
if (n==5) continue;
cout << n << ", ";
}
cout << "FIRE!\n";
return 0;
}
Output:
10, 9, 8, 7, 6, 4, 3, 2, 1, FIRE!
c) goto statement
The goto statement is used to transfer control to some other parts of the program. It is
used to alter the execution sequence of the program. To illustrate goto statement, let
us take the following C++ program:
Program: 11
Output:
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE!
d) exit () statement
The exit statement is used to terminate the execution of the program. It is used when
we want to stop the execution of the program depending on some condition. When we
use exit () statement, we have to include other library functions such as process.h, or
stdio.h file. To illustrate exit () statement, let us take the following C++ program:
Program: 12
// Program for exit statement
#include <iostream.h>
#include <conio.h>
void main ()
{
clrscr();
int i, number;
i = 1;
while(i<5)
{
cout <<”Enter the number:";
cin>>number;
if number>5
{
cout <<”The number is greater than five or equal to” <<end1;
exit();
}
cout << "The number is: “<<number<<end1;
i++
}
getch();
}
Output:
55
Basics of Object Oriented
Programming & C++ 2.12 I/O FORMATTING
In this section, we will discuss those functions which are used to format the Input and
output of a C++ program. These functions are helpful in managing the I/O operations
in C++ programming.
C + + supports input/output statements which can be used to feed new data into the
computer or obtain output on an output device such as: VDU, printer etc. It provides
both formatted and unformatted stream I/O statements. The following C + + streams
can be used for the input/output purpose. In this section, we will discuss following I/O
formatting functions:
Comments in C++
Unformatted Console I/O Functions
Setw I/O Formatting in C++
Inline Functions
Input/Output
Output is accomplished by using cout, which opens a “stream” to the standard output
device (the screen). Data is inserted into the output stream using the << (insertion)
operator. Input is accomplished by using cin, which opens a “stream” from the
standard input device (keyboard). Data is retrieved from the stream by using the >>
(extraction) operator.
Note: Every cin should be prefaced by a cout to prompt the user.
56
// Comment line... Introduction to C++
However, if there are multiple lines in a comment, it is enclosed between the two
symbols /* and */
Everything between /* and */ is ignored by the complier. The syntax of multiple line
comment is
/* Start of multiple line comment
................
................
.............End of multiple line comment */
Output:
Program 2
#include <iostream.h>
using namespace std;
int exforsys (into);
void main ( )
{
int x;
cout << "n Enter the Input Value: ";
cin>>x;
cout << "n The Output is: " << exforsys(x);
}
58
Output: Introduction to C++
To understand the use of this function, let us take the following C++ program:
Program 3
# include <iostream.h>
# include <iomanip.h>
void main (void)
{
float x,y,z;
x = 11;
y = 7;
z = x/y;
cout << setprecision(1) << z << end1;
cout << setprecision(2) << z << end1;
cout << setprecision(3) << z << end1;
cout << setprecision(4) << z << end1;
cout << setprecision(5) << z << end1;
}
Output:
1.6
1.57
1.571
1.5714
1.57142
This flag is used to show the decimal point for all floating point values. By default, it
takes six decimal point values in C++ programming. The syntax of this flag is given
as follows:
cout.setf(ios::shpowpoint);
59
Basics of Object Oriented To understand the use of this flag, let us take the following C++ program:
Programming & C++
Program 4
# include <iostream.h>
void main ()
{
float w,x,y,z;
w = 2.34567845612
x = 11.34567653433;
y = 7.2345458765432;
z = - 2345.5677225844;
cout.setf (ios::showpoint);
cout << “w = “ << w << “\n”;
cout << “x = “ << x << “\n”;
cout << “y = “ << y << “\n”;
cout << “z = “ << z << “\n”;
}
Output:
w = 2.345678
x= 11.345677
y = 7.234546
z = -2345.567723
To use many of the (I/O) manipulators, I/O streams have a flag field that specifies the
current setting of decimal places and upper and lower case of alphabets in the output
of a C++ program.
Some of the I/O flag name and their meaning are given in the table above.
60
Introduction to C++
2.13 SUMMARY
In this unit you have learnt the features of object oriented programming, particularly
that of C++ language. We have explained the C+ character set, tokens which include
variables, constants and operators and data types used. In C++, the interchanging of
data takes place automatically or by the programmer. The concept of input/output
statement has been explained. The concept of comment statement which makes the
program more readable is also given. Finally, we have also discussed control structure
in C++ which is used to control execution sequence during the compilation and
execution of program. At the end, you should be able to write a C++ program which
will take input from the user, manipulate and print it on the screen by reading this
unit.
a) - 1, b) - 1 c) - 2 d) – 3
61
Basics of Object Oriented Answers to short answer type questions
Programming & C++
1) There are some reserved words in C++ which have predefined meaning to
complier called keywords. These are also known as reserved words and are
always written or typed in lower cases.
2) A symbolic name is generally known as an identifier. The identifier is a sequence
of characters taken from C++ character set. Valid identifiers are a sequence of one
or more letters, digits or underscore characters (_). Neither spaces nor punctuation
marks or symbols can be part of an identifier.
3) Data Type in C++ is used to define the type of data that identifiers accepts in
programming and operators are used to perform a special task such as addition,
multiplication, subtraction, and division etc of two or more operands during
programming.
4) A variable is the most fundamental aspect of any computer language. It is a
location in the computer memory which can store data and is given a symbolic
name for easy reference. The variables can be used to hold different values at
different values at different times during the execution of a program.
A number which does not change its value during execution of a program is
known as a constant or literals. Any attempt to change the value of a constant will
result in an error message. A keyword const is added to the declaration of an
identifier to make that identifier constant. A constant in C++ can be of any of the
basic data types.
1) A global variable is a variable declared in the main body of the C++ source code,
outside all the functions. Global variables can be called from anywhere in the
code, even inside functions, whenever it is after its declaration.
The local variable is one declared within the body of a function or a block.
2) A string literal consists of zero or more characters from the source character set
surrounded by double quotation marks ("). A string literal represents a sequence
of characters that, taken together, form a null-terminated string.
String literals may contain any graphic character from the source character set
except the double quotation mark ("), backslash (\), or newline character. They
may contain the same escape sequences supported by C++ language. C++ strings
have these types:
Array of char[n], where n is the length of the string (in characters) plus 1 for the
terminating '\0' that marks the end of the string.
Array of wchar_t, for wide-character strings.
3) Scope of a variable in C++ can be defined as: a variable can be either of global or
local scope. A global variable is a variable declared in the main body of the C++
source code, outside all the functions. Global variables can be called from
anywhere in the code, even inside functions, whenever it is after its declaration.
1) C++ has a rich set of operators. Operators is the term used to describe the action
to be taken between two data operands. Expressions are made by combining
operators between operands. C++ supports six types of operators:
Arithmetical operators
Relational operators
Logical operators
Bitwise operators
Precedence of operators
Special operators
2) C++ program is usually not limited to a linear sequence of instructions but it may
bifurcate, repeat code or may have to take decisions during the process of coding.
For that purpose, C++ provides control structures which are used to control the
flow of program.
In C++ object oriented programming, the control structure can be classified into
following three categories:
3) I/O functions are those functions which are used to format the Input and output of
a C++ program. These functions are helpful in managing the I/O operations in
C++ programming.
C + + supports input/output statements which can be used to feed new data into
the computer or obtain output on an output device such as: VDU, printer etc. It
provides both formatted and unformatted stream I/O statements. The following C
+ + streams can be used for the input/output purpose. C++ supports following I/O
formatting functions:
Comments in C++
Unformatted Console I/O Functions
Setw I/O Formatting in C++
Inline Functions
1) # include <iostream.h>
# include <conio.h>
int main()
{
clrscr();
int d_o_w;
cout <<”Enter number of week‟s day (1-7)”;
cin>>d_o_w;
switch(d_o_w)
{ 63
case 1: cout<<”/n Sunday”;
Basics of Object Oriented
Programming & C++
break;
case 2: cout<<”/n Monday”;
break;
case 3: cout<<”/n Tuesday”;
break;
case 4: cout<<”/n Wednesday”;
break;
case 5: cout<<”/n Thursday”;
break;
case 6: cout<<”/n Friday”;
break;
case 7: cout<<”/n Saturday”;
break;
default: cout<<”/n Wrong number of day”;
}
return 0;
}
Output:
Wednesday
Reference Websites:
(1) www.sciencedirect.com
(2) www.ieee.org
(3) www.webpedia.com
(4) www.microsoft.com
(5) www.freetechbooks.com
(6) www.computer basics.com
(7) www.youtube.com
64
Objects and Classes
UNIT 3 OBJECT AND CLASSES
Structure Page Nos.
3.0 Introduction 65
3.1 Objectives 65
3.2 Classification 66
3.3 Class 67
3.3.1 Defining a Class
3.3.2 Encapsulation
3.3.3 Accessibility Rules/Labels
3.4 Objects 70
3.4.1 Instantiating Object
3.5 Member Functions 74
3.5.1 Nesting of Member Function
3.5.2 Passing Objects as Arguments:
3.6 Friend Function 81
3.7 Static Members 84
3.8 Summary 87
3.9 Answers to Check Your Progress 87
3.10 Further Reading s 92
3.0 INTRODUCTION
In this Unit, we can begin with the concept of classification which is foundation in
Object-Oriented programming. This is followed by what and how C++ supports
classes, objects and how objects are used in problem solving. The classes are the
crucial components for developing applications in C++. The accessibility rule that
controls the visibility of class members (data and methods) is discussed. Moreover,
member functions and friend functions are also discussed. This unit also covers a
special kind of member function known as static function. Illustrative examples that
facilitate you in understanding of the concept are presented with adequate emphasis.
3.1 OBJECTIVES
Suppose you have several objects like dog, cat, cow, elephant, car, airplane, fighter-
plane, rocket, cup, mountain bike, racing bike, tandem bike. There are four animal
objects grouped together in the animal class, three plane objects are grouped together
into a plane class, and three bike objects group in bike class. The single car is in
separate class as is a cup.
Can you tell how did we classify the objects? Yes, of course we can classify, based on
the similar properties, common operations, a common relationship to the other objects
in the class, and common semantics. But how will we classify the objects based on the
concept of common semantics? The term common semantics in classifying objects is
best described by an example. Consider two classes, Bus and House given as follows:
If you look at the above classes, you can observe that both have same set of attributes
and service functions. Naturally, one can raise the questions. Whether both of these
objects be considered of the same class or should they belong to different classes?
These questions can be answered by looking at the semantics of two classes. If the
underlying semantics is based on object usage, then two classes should not be
combined even if their attributes and services are the same but if the underlying
semantics is based on the object‟s asset, then both Bus and House belong to a
common class Asset.
From the above discussion, we have understood the concept of classification and how
it is used to reduce hundreds or thousands of objects into smaller groups/class, based
on their characteristics.
66
Objects and Classes
3.3 CLASS
In this section, we will discuss what is class? What is importance of class in C++?
We will define a class and also discuss encapsulation which is one of the striking A class is set of
features of a class. objects that shares a
common definition
According to the Webster‟s New World dictionary, a class is defined as “ A number of described by data
people or things grouped together because of certain likeness; kind; sort”. In other and methods.
words, we can say that class is an object template. Every object under that class has
the same data format, definition and responds in the same manner to an operation.
A class is a user defined data type like any other built-in data type for example int,
char, float, .. etc. It is most important feature of C++. It makes C++ an Object-
Oriented language. Can you tell the difference between structure and class ? Yes, of
course, the only difference between a structure and a class in C++ is that by default,
the members of a class are private, while by default the members of a structure are
public. In the next section, we will see as to how we will define and use a class in the
program.
A class has a class name, a set of attributes (data members/characteristics) and a set of
actions or services(function members/methods). Now, let us see how a class is defined
in C++. The common syntax of a class declaration/specification/definition is given as
follows:
class Class_name
{
private :
variable declaration;
function declaration;
public :
variable declaration;
function declaration;
protected :
variable declaration;
function declaration;
};
It can be easily seen that a class is defined by the keyword class. The class specifies
the type and scope of variables and functions declared inside the class. The
variables(data) declared inside the class are known as data members and the
functions(methods) are known as member functions. Being the part of the class, data
and function are called members of the class. The body of the class is enclosed within
braces and terminated by the colon. The keywords private, public and protected are
known as visibility labels, which defines the visibility of members. We will discuss
the visibility of members in the next section. It is common practice to declare data
members as private and member functions as public. Let us see an example to
understand how the class is defined.
Before defining a class, you should decide about the members of class i.e. who will be
the members of a class. Actually, it depends on the problem domain i.e which type of
data problems needs to keep in the class and also which type of operations will be
needed to manipulate the data.
67
Basics of Object Oriented Based on the above discussion, suppose we want to define a Employee class. We are
Programming & C++ interested to display the basic information like ID, name, department etc. For this, first
we have to decide the data members and their types required to represent the basic
information, then we need a member functions to display basic information. We also
need the member function to take information from the real world.
class Employee
{
int id;
char name[25];
char deptt[25];
public:
void get_data(void)
{
cout<< “Enter Employee ID:” <<endl;
cin>>id;
cout<<”Enter name:”<<endl;
cin>>name;
cout<< “Enter department:”<<endl;
cin>>deptt;
}
void display_information(void)
{
cout<< “Employee ID=” <<id<<endl;
cout<< “Employee Name=” <<name<<endl;
cout<< “Employee Department=” <<deptt<<endl;
}
};
We, generally, give a class some meaningful name by reflecting information it holds.
In the above declaration of the class, the name of the class is Employee. Now,
Employee becomes a new data type. It is used to define instances of class data type.
3.3.2 Encapsulation
If the implementation details are not known to the user, it is called information hiding.
Restrictions of external access to features of a class results in data hiding. The user‟s
interface is not affected by changing the implementation mechanism. A change in the
implementation is done easily without affecting the interface. This leads to
implementation independence.
68
3.3.3 Accessibility Rules/Labels Objects and Classes
You can see, in class declaration, we have used three terms private, public and
protected. Can you tell what is the purpose of these terms in the program? Right,
private, public and protected are known as visibility labels, used to control the access
to members (data members and member functions) of a class.
Why do we need to control the access of members of a class? Well, as we know that
purpose of data encapsulation is to prevent accidental modification of information of a
class. Data can be protected from external tempering by users and access to specific
methods can also be controlled. However, an entire program cannot be hidden. A part
of the program needs to be accessed by users. For this and many other reasons, we
need to access the members of a class in controlled way. It is achieved by imposing a
set of rules-the manner in which a class is to be manipulated and data and functions of
the class can be accessed. The set of rules is known as accessibility rules. This
accessibility rules are achieved by using three keywords private, public and protected.
These keywords are called access-control specifiers (visibility mode). The visibility of
class members is summarized in Table 3.1.
Table 3.1: Visibility of class members
Access-control Accessible to
specifiers Own class members Objects of a class
private yes no
protected yes no
public yes yes
From the above table, you can observe that private and protected members of a class
are accessible only from within other members of the same class. They are not
accessible by the objects of a class. Further, public members are accessible both from
members of the same class and objects of a class. They are accessible from anywhere
where the object is visible. Members of a class without any access specifier are private
by default. A class which is totally private is hidden from the external world and will
not serve any useful purpose. Can you access the private member of a class from
outside a class? Yes, we can have a mechanism to access private data using friends,
pointers to members etc. from outside the class.
3.4 OBJECTS
In this section, we will study about object. What is object? What is the relationship
between object and class? How will we create object? We shall make an attempt to all
such address this question.
Webster‟s New World Dictionary defines object as “A thing that can be seen or
touched; material thing; a person or thing to which action, thought or feeling is
directed”. In Object-Oriented domain an object is one of the many things that together
constitute the problem domain. You can look around and find many real world
examples of objects like person, customer, student, employee, car, dog, table, bike
…etc. An object may stand alone or it may belong to a class of similar objects.
Examples of objects that may stand alone are knife, frame … etc. Examples of objects
An object may that belong to a class of similar objects are: your car, your table … etc.
have a name, a
set of attributes, Can you tell the difference between object and class? Well, objects are the basic run-
and a set of time entities in Object-Oriented programming language. They occupy space in
actions or memory that keeps its state and is operated on by the defined operations on the object,
services. while a class defines a possible set of objects. What is the relationship between object
and class? The relationship between a class and objects of that class is similar to the
relationship between a type and elements of that type. A class represents a set of
objects that share a common structure and a common behavior, whereas an object is
an instance of a class. In the next section we will see as to how object is created.
70
Objects and Classes
3.4.1 Instantiating Object
The declaration of a class does not define any object but only specify the structure of
objects i.e. what they will contain. A class must be instantiated in order to make use of
the services provided by it. This process of creating objects (variables) of the class is
called class instantiation or instantiating of objects. Thus, an object is an instantiation
of a class. The common syntax of instantiating object of a class / declaration of a
object is as follows:
For example, let us see, how will we create the object of the Employee class discussed
in class section?
class Employee emp1;
or
Employee emp1;
You can see that the declaration of an object is similar to that of any basic type. You
can also notice that keyword class is optional. Employee class creates object emp1.
More than one object can also be created with a single statement as follows.
Employee emp1, emp2,emp3;
Objects can also be created by placing their names immediately after the closing brace
as we do in the case of structure. Thus, the definition
class Employee
{
.
.
.
}emp1,emp2,emp3;
would create objects emp1, emp2 and emp3 of the class Employee.
Now let us see, how will we assess the members of a class? We can assess the
member of a class using the member assess operator, dot(.). The syntax for assessing
data member of a class is given as follows:
objectName.dataMember;
The syntax for assessing member functions of a class is given as follows.
objectName.functionName(actualArguments);
Let us consider the snapshot of a program which illustrates use of dot (.) operator:
class ABC
{
int x;
int y;
void f1(void);
public:
int z;
void f2(void);
};
.
.
void main()
71
Basics of Object Oriented
Programming & C++ {
ABC a;
If you look at the above snapshot of C++ program, you can observe that private data
like x and private member function like f1() cannot be accessed through object while
public data like z and public member function like f2() are accessed through object.
Furthermore, this program shows that you can access the members of a class through
dot (.) operator.
Let us consider the complete program employee.cpp which illustrates the declaration
of the class Employee with the operations on its object. Further, it is also seen that
how we will access the members of a class. This program reads the basic information
of employee like id, name, age etc. from the keyboard and display on the screen.
//program:employee.cpp
#include<iostream.h>
#include<string.h>
class Employee
{
int id;
int age;
char name[25];
public:
int salary;
void get_data(void)
{
cout<<"Enter ID :"<<endl;
cin>>id;
cout<<"Enter Name:"<<endl;
cin>>name;
cout<<"Enter Age:"<<endl;
cin>>age;
cout<<"Enter Salary :"<<endl;
cin>>salary;
}
void display_info(void)
{
cout<<"\nID :" <<id<<endl;
cout<<"Name :"<<name<<endl;
cout<<"Age :"<<age<<endl;
cout<<"Salary :"<<salary<<endl;
}
};
72
Objects and Classes
void main()
{
73
Basics of Object Oriented This program shows how we can access the members of a class with the help of the
Programming & C++ object. Furthermore, it also illustrates that the various operation on the objects of the
class Employee. In main(), the statements Employee e1;
Employee e2;
create two objects called e1 and e2 of the employee class. The statements
e1.get_data();
e2.getdata();
initialize the data members of the objects e1 and e2. The statements
e1.display_info();
e2.display_info();
call their display_info() to display the contents of data members namely id, name, age
and salary of the employee objects e1 and e2.
In this section, we will discuss what is member function? How will we define a
member function?
class Number
{
int x, y, z;
public:
void get_data(void); //declaration
void maximum(void); //declaration
void minimum(void) //definition
{
int min;
min=x;
if (min>y)
min=y;
if (min>z)
min=z;
cout<<"\n Minimum value is ="<<min<<endl;
}
};
if you look at the above declaration of class number you can observe that the member
function get_data() and maiximun() are declared, but they are not defined. The only
member function which is defined in the class body is minimum(). When a function is
defined inside a class, it is treated as a inline function. Thus, member function
minimum is a inline function. Generally, only small functions are defined inside the
class.
Now let us see how we can define the function outside the class body. Member
functions that are declared inside a class have to be defined outside the class. Their
definition is very much like the normal function. Can you tell how does a compiler
know to which class outside defined function belong? Yes, there should be a
mechanism of binding the functions to the class to which they belong. This is done by
the scope resolution operator (::). It acts as an identity-label. This label tells the
compiler which class the function belongs to. The common syntax for member
function definition outside the class is as follows:
public:
void get_data(void); //declaration
75
Basics of Object Oriented void maximum(void); //declaration.
Programming & C++
.
.
};
void Number :: get_data(void)
{
cout<< "\n Enter the value of fist number(x):"<<endl;
cin>>x;
cout<< "\n Enter the value of second number(y):"<<endl;
cin>>y;
cout<< "\n Enter the value of third number(z):"<<endl;
cin>>z;
}
void Number :: maximum(void)
{
int max;
max=x;
if (max<y)
max=y;
if (max<z)
max=z;
cout<<"\n Maximun value is ="<<max<<endl;
}
if you look at the above declaration of class Number, you can easily see that the
member function get_data() and maiximun() are declared in the class. Thus, it is
necessary that you have to define this function. You can also observe in the above
snapshot of C++ program identity label (::) which are used in void Number ::
get_data(void) and void Number ::maximum(void) tell the compiler the
functionget_data() and maximum() belong to the class Number.
Now, let us see the complete C++ program to find out the minimum and maximum of
three given integer numbers:
#include<iostream.h>
class Number
{
int x, y, z;
public:
void get_data(void); //declaration
void maximum(void); //declaration
void minimum(void) //definition
{
int min;
min=x;
if (min>y)
min=y;
if (min>z)
min=z;
cout<<"\n Minimum value is ="<<min<<endl;
}
};
void Number :: get_data(void)
{
76
Objects and Classes
void main()
{
Number num;
num.get_data();
num.minimum();
num.maximum();
}
A member function of a class can call any other member function of its own class
irrespective of its privilege. This is known as nesting of member functions.
Consider the problem of finding the largest of n given number which illustrates the
above concept.
#include<iostream.h>
#define MAX_SIZE 100
class Data
{
int num[MAX_SIZE];
int n;
77
Basics of Object Oriented
Programming & C++ public:
void get_data(void); //declaration
int largest(void); //declaration
void display(void); //declaration
};
void Data :: get_data(void)
{
cout<< "\n Enter the total numbers(n):"<<endl;
cin>>n;
cout<< "\n Enter the number:"<<endl;
for (int i=0;i<n; i++)
{
cout<< "\n Enter the numer"<<i+1<<": ";
cin>>num[i];
}
}
int Data :: largest(void)
{
int max;
max=num[0];
for(int i=1; i<n; i++)
{
if (max<num[i])
max=num[i];
}
return max;
}
void Data :: display(void)
{
cout<<"The largest number:"<<largest()<<endl;
}
void main()
{
Data num;
num.get_data();
num.display();
}
The class Data has the member function display having the statement cout<<"The
largest number:"<<largest()<<endl;. It calls the member function largest () to compute
the largest of n given numbers.
We can pass objects as arguments to a function like any other data type. This can be
done by a pass-by-value and a pass-by-reference. In pass-by-value, a copy of the
object is passed to the function and any modifications made to the object inside the
function are not reflected in the object used to call the function. While, in pass-by-
reference, an address of the object is passed to the function and any changes made to
the object inside the function is reflected in the actual object. Furthermore, we can
also return object from the function like any other data type.
78
Consider the following C++ program for addition and multiplication of two square Objects and Classes
matrices which illustrates the above concepts.
#include<iostream.h>
#define MAX_SIZE 10
int n;
class Matrix
{
int item[MAX_SIZE][MAX_SIZE];
public:
void get_matrix(void);
void display_matrix(void);
Matrix add(Matrix m);// Matrix object as argumentand as return: pass by value
void mul(Matrix &mat, Matrix m);// Matrix object as argument: pass by
reference and pass by value
};
void Matrix :: get_matrix(void)
{
cout<< "\n Enter the order of square matrix(nXn):"<<endl;
cin>>n;
cout<< "\n Enter the element of matrix:"<<endl;
for (int i=0;i<n; i++)
for (int j=0;j<n; j++)
cin>>item[i][j];
}
void Matrix :: display_matrix(void)
{
cout<<"\n The element of matrix is :"<<endl;
for (int i=0;i<n; i++)
{
for (int j=0;j<n; j++)
cout<<item[i][j]<<"\t";
cout<<endl;
}
}
Matrix Matrix :: add(Matrix m)
{
Matrix temp; // object temp of Matrix class
If you look at the above program, you can observe that in main(), the statement
Result=X.add(Y);
in which X.add(Y) invokes the member function add() of the class matrix by the
object X with the object Y as arguments. The members of Y can be accessed only by
using the dot operator (like m.item[i][j]) within the add() member. Any modification
made to the data members of the object Y is not visible to the caller‟s actual
parameter. The data members of X are accessed without the use of the class member
access operator. The statement in the function add(),
return(temp);
returns the object temp as a return object. The result has become the return object
temp which stores the sum of X and Y. This illustrates that function also return object.
Further, in main(), the statement
X.mul(Result, Y);
transfers the object result by reference and Y by value to the member function mul().
When mul() is invoked with result and Y the objects parameters, the data members of
X are accessed without the use of the class member access operator, while the data
members of result and Y are accessed by using their names in association with the
name of the object to which they belong. Modifications which are carried out on result
object in the called function will also be reflected in the calling function.
80
4) Define a class to represent a bank account. Include the following members: Objects and Classes
Data Members:
Member Functions:
5) Write a interactive program in C++ for the above problem. Assume a bank has
maintained two types of account: Saving account and Current account. You should
open a saving account with minimum Rs 500 and also keep minimum balance of
Rs. 500 and current account with Rs. 5000 and also keep minimum balance of Rs.
5000.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
As we have discussed that the private members cannot be accessed from outside the
class. It implies that a non-member function cannot have an access to the private data
of a class. Let us suppose, we want a function operate on objects of two different
classes. In such situations, C++ provides the friend function which is used to access
the private members of a class. Friend function is not a member of any class. So, it is
defined without scope resolution operator. The syntax of declaring friend function is
given below:
class class_name
{
…
…
public:
…
…
friend return type function_name(arguments);
}
81
Basics of Object Oriented Let us consider the complete C++ program to find out sum of n given numbers to
Programming & C++ understand the concept of friend function.
#include<iostream.h>
#define MAX_SIZE 100
class Sum
{
int num[MAX_SIZE];
int n;
public:
void get_number(void);
friend int add(void);
};
void Sum :: get_number(void)
{
cout<< "\n Enter the total number(n):"<<endl;
cin>>n;
cout<< "\n Enter the number:"<<endl;
for (int i=0;i<n; i++)
cin>>num[i];
}
int add(void)
{
Sum s;
int temp=0;
s.get_number();
for (int i=0;i<s.n; i++)
temp+=s.num[i];
return temp;
}
void main()
{
int res;
res=add();
cout<<"The sum of n value is="<<res<<endl;
}
If you look at the above program, you can easily see that the function add is declared
as a friend function of class Sum. The add function accesses the private data, adds the
numbers of array and returns value to the main function where it is called upon.
Furthermore, you can also see that friend function add() is defined without scope
resolution operator(::), because it does not belong to a class.
82
Objects and Classes
friend int min(One, Two);
};
class Two
{
int b;
public:
void get_b(void);
friend int min(One, Two);
};
void One :: get_a(void)
{
cout<<"Enter the value of a:"<<endl;
cin>>a;
}
void Two :: get_b(void)
{
cout<<"Enter the value of b:"<<endl;
cin>>b;
}
int min (One o, Two t)
{
if(o.a<t.b)
return o.a;
else
return t.b;
}
void main()
{
One one;
Two two;
int minvalue;
one.get_a();
two.get_b();
minvalue=min(one,two);
cout<<"Minimum="<<minvalue<<endl;
}
You can observe that the above program contains two classes named one and two.
The function min() is declared in the both the classes with the keyword friend. An
object of each class has been passed as an argument to the function min (). Being a
friend function, it can access the private members of both classes through these
arguments. Now, let us note some special properties possessed by friend function:
(i) A friend function is not in the scope of the class to which it has been declared as
friend.
(ii) A friend function cannot be called using the object of that class. It can be
invoked like a normal function without the use of any object.
(iii) Unlike member functions, it can not access the members directly. However, it
can use the object and dot membership operator with each member name to
access both private and public members.
(iv) It can be declared either in the public or the private part of a class without
affecting its meaning.
(v) Generally, it has got objects as arguments.
83
Basics of Object Oriented
Programming & C++ 3.7 STATIC MEMBERS
The members of a class can be made static (data member and function member both).
Can you tell, what is static? Well, static is a storage class specifier/qualifier that
provides information about locality and visibility of variables. Let us discuss the static
data member. Sometimes, we need to have one or more common data member, which
are accessible to all objects of a class. For example, we need to keep the status as to
how many objects of a class are created and how many of them are currently active in
the program. In such situation, and many others, C++ provides static data member.
Static data member is initialized to zero when the first object of its class is created. No
other initialization is permitted.
A variable that is part of a class, yet is not the part of an object of that class, is called a
static data member. There is exactly one copy of static data member instead of one
copy per object, as for ordinary non-static data members. Similarly, a function that
needs access to members of a class, yet doesn‟t need to be invoked for a particular
object is called a static member function. The common syntax of defining static data
member is given as follows:
class class_name
{
…..
….
static data_type data member;
….
….
};
data_type class_name :: data member=initial_value;
Static data member must be defined outside the class. Initialization of static data
member is optional. Let us consider the following C++ program to understand the
concept of static data members.
#include<iostream.h>
class Counter
{
static int count; // static member: count is static
static int n; // static member: number is static
public:
void get_data(int num) // initializes object's member
{
n=num;
count++;
}
void show_count(void)
{
cout<<"Number of times calls made to function 'get_data()' through any object:";
cout<<count<<endl;
cout<<"n:"<<n<<endl;
}
};
int Counter :: count=0; // definition and initialization(optional) of a static data
member
84
Objects and Classes
int Counter :: n; // definition of static data member
void main()
{
Counter x,y,z;
x.show_count();
y.show_count();
z.show_count();
x.get_data(25);
y.get_data(50);
z.get_data(75);
cout<<"After reading data :"<<endl;
x.show_count();
y.show_count();
z.show_count();
}
The above program shows the concept of static data member. There are two static
variables count and n. The variables count and n are initialized zero when their
object is created. The static data member count is incremented and data n is assigned
with parameter value. Whenever the get_data() function is called. Since get_data()
member function is called three times by the object x, y, and z, the data member count
is incremented three times. Furthermore, the variable n is assigned with values 25, 50
and 75 respectively by each function call get_data(). All the statements print the value
of count as 3 and n as a 75 because there is only one copy of count and one copy of n
which are shared by all three objects.
Now, let us discuss about static member function. Like static data member variable,
we can also have a static member function. The static function can only access the
static member(data or function) declared in the same class. There is one important
difference between static member function and member function. A static member
function is called using the class name instead of its object. The following program
illustrates the concept of the static member function:
#include<iostream.h>
class Counter
{
static int count; // static member: count is static
int n; // static member: number is static
public:
void set_data(void) // initializes object's member
{
count++;
n=count;
}
void show_value_of_n(void)
{
cout<< "The value of n is ="<<n<<endl;
}
void static show_count(void)
{
cout<<"Count :"<<count<<endl;
}
};
int Counter :: count=0; // definition and initialization(optional) of a data
member
85
Basics of Object Oriented
Programming & C++ void main()
{
Counter c1,c2;
Counter::show_count();
c1.set_data();
c2.set_data();
Counter::show_count();
Counter c3;
c3.set_data();
Counter::show_count();
c1.show_value_of_n();
c2.show_value_of_n();
c3.show_value_of_n();
}
If you look at the above program, you can easily see that the static function show
count() displays the number of objects created till that moment. A count on the
number of objects is maintained by static variable count. The function show_value()
displays the value of the non-static variable n.
3) Discuss memory requirements for classes, objects, data members and member
functions.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
4) Bring out the differences between the memory requirements of static data
members and non-static data members.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
86
Objects and Classes
3.8 SUMMARY
In this unit, we have seen and discussed the concept of class as well as object which
are the basic components used in C++ programming. Class declaration and object
creation have been discussed and illustrated with examples. The members viz., data
members and function members of a class, defining member functions were explained
and elaborated. We have seen the way to pass objects as arguments to the functions
with call by value and call by reference. Furthermore, static members, Friend function
and Friend class are also discussed with examples.
1. Structures and classes in C++ are given same set of features. A class in C++ is
identical to structure in C++. In C++, the difference between structures and classes
is that, by default, structure members have public accessibility while class
members have private access control unless otherwise explicitly stated.
3. Though the main reason for using a class is to encapsulate data and code. It is,
however, possible to have a class that has neither data nor code. In other words, it
is possible to have empty classes. The declaration of empty classes is as follows:
class ABC{};
class Employee{};
class xyz
{
};
During the initial stage of development of a project, some of the class are either
not fully identified, or not fully implemented. In such cases, they are implemented
as empty classes.
4.
#include<iostream.h>
#define MAX_SIZE 25
class Sum
{
int number[MAX_SIZE];
int n;
int total;
public:
void get_data(void)
{
int i;
cout<<"Enter Total Number :"<<endl;
cin>>n;
cout<<"Enter Number One by One:"<<endl;
for(i=0; i<n; i++)
{
cout<<"Enter Number"<<i+1<<":"<<endl;
cin>>number[i]; 87
Basics of Object Oriented
Programming & C++ }
}
void cal_sum(void)
{
total=0;
int i;
for (i=0; i<n; i++)
total=total+number[i];
}
void display_sum(void)
{
cout<<"\nSum :"<<total<<endl;
}
};
void main()
{
Sum s;
s.get_data();
s.cal_sum();
s.display_sum();
}
1. The scope resolution operator (::) especially defined in C++. They are used in two
ways: (1) for resolving the class member function (2) for resolving the global
variable.
2. If your function is very small and make this inline, then you can define your
function in the class because all defined function within class are, by default, inline
functions. If you are using much control statements and looping, you have to
define your function outside the class.
4.
#include<iostream.h>
#include<stdlib.h>
#define MAX_SIZE 25
// unit3e3.cpp
class Account
{
char depositor_name[25];
int account_no;
int type_of_account;
int balance;
public:
88
Objects and Classes
void assign_initial_value(void);
void deposit(void);
void withdraw(void);
void account_info(void);
};
void Account :: assign_initial_value(void)
{
cout<< "\n Enter the depositor name:"<<endl;
cin>>depositor_name;
cout<< "\n Enter the account no.:"<<endl;
cin>>account_no;
cout<< "\n Enter the type of account(1-for saving, 2-for current):"<<endl;
cin>>type_of_account;
cout<< "\n Enter the amount to be deposited(For saving min:500 & current min:5000"<<endl;
cin>>balance;
}
void Account :: deposit(void)
{
int da;
cout<< "\n Enter the amount to be deposited:"<<endl;
cin>>da;
balance=balance+da;
}
void Account :: withdraw(void)
{
int aw;
int d;
89
Basics of Object Oriented
Programming & C++ }
int main()
{
Account a;
int choice;
while(1)
{
cout<< "\n Account operation:..."<<endl;
cout<< "\n 1. Assign initial value";
cout<< "\n2. Deposit Ammount";
cout<< "\n3. Withdraw Amount";
cout<< "\n4. Balance Enquiry";
cout<< "\n5. Quit";
cout<< "\n Enter choice :"<<endl;
cin>>choice;
switch(choice)
{
case 1: a.assign_initial_value();
break;
case 2: a.deposit();
break;
case 3: a.withdraw();
break;
case 4: a.account_info();
break;
case 5: exit(1);
break;
default: cout<<"Bad option selected";
break;
}
}
}
1. We can define a class as friend of another class, granting that second class access to
the protected and private members of the first one. A class declared as a friend of
another class, it possesses the rights of access to the private member of this class
using objects.
#include<iostream.h>
class X
{
int x;
public:
void get_x(void)
{
cout <<" Enter the value of x:"<<endl;
cin>>x;
}
friend class Y;
};
class Y
{
int y;
public:
90
Objects and Classes
void get_y(void)
{
cout <<" Enter the value of y:"<<endl;
cin>>y;
}
void add(void)
{
X objx;
objx.get_x();
get_y();
y=y+objx.x;
}
void display()
{
cout<<"The Sum="<<y;
}
};
void main()
{
Y objy;
objy.add();
objy.display();
}
2. There are the following situations in which the friend function needed.
Function operating on objects of two different classes.
Friend functions can be used to increase the versatility of overloaded
operators.
Sometimes, a friend allows a more obvious syntax for calling a function rather
than what a member function can do.
3. When a class is declared, memory is not allocated to data members but allocated to
only member functions. When an object of a particular class is created, memory is
allocated only to its data members. Thus, all objects of that class have access to the
same area in the memory where the member functions are stored. It is logically also
true as the member functions are same for all objects and there is no need to allocate
a separate copy for each and every object created. However, storage space for data
member is allocated for every object‟s data members. This is essential because data
member will hold different data values for different objects.
4. Whenever a class is instantiated, the memory is allocated for the created objects.
Memory space for static data members is allocated only once during class
declaration while memory space of on-static data members is allocated when
objects of a class are created. Therefore, all objects of the class have access the
same memory area allocated to static data members. When one of them modifies
the static data member, the effect is visible to all the instance of the class i.e.
objects.
91
Basics of Object Oriented
Programming & C++ 3.10 FURTHER READINGS
92
Constructors and Destructors
UNIT 4 CONSTRUCTORS AND
DESTRUCTORS
Structure Page Nos.
4.0 Introduction 93
4.1 Objectives 94
4.2 Constructors and Destructors 94
4.2.1 Characteristics of Constructors
4.2.2 Declaration of Constructors
4.2.3 Application of Constructors
4.2.4 Constructors with Arguments
4.3 Types of Constructor 100
4.3.1 Default Constructor
4.3.2 Parameterized Constructor
4.3.3 Copy Constructor
4.3.4 Constructor Overloading
4.3.5 Constructing two Dimensional Constructor
4.4 Destructors 107
4.5 Declaration of Destructor 107
4.6 Application of Destructor 109
4.7 Private Constructors and Destructors 109
4.8 Programs on Constructors and Destructors 110
4.9 Memory Management 114
4.10 Summary 116
4.11 Answers to Check your Progress 116
4.12 Further Readings and References 119
4.0 INTRODUCTION
In the previous unit, we have discussed concept of Objects and Class and their use in
object oriented programming. In this unit we shall discuss about constructors and
destructors and their use in memory management for C++ programming.
C++ allows different categories of data types, that is, built-in data types (e.g., int,
float, etc.) and user defined data types (e.g., class). We can initialize and destroy the
variable of user defined data type (class), by using constructor and destructor in object
oriented programming.
Whenever an object is created, the special member function, that is, constructor will
be executed automatically. Constructors are used to allocate the memory for the newly
created object and they can be overloaded so that different form of initialization can
be accommodated. If a class has constructor, each object of that class will be
initialized. It is called constructor because it constructs the value of data members of
the class.
Let us take an example to illustrate the syntax and declaration of constructor and
destructor, inside a class in object oriented programming.
93
Basic of Object Oriented
Programming & C++
Example: A constructor is declared and defined as follows:
class integer
{
int m, n;
public:
integer (void); // constructor declared
…………
…………
};
In the above example class integer contains a constructor, and the object created by
the class is initialized automatically.
4.1 OBJECTIVES
To illustrate the use of constructor, let us take the following C++ program:
94
C++ Program to illustrate constructor: Constructors and Destructors
# include<iostream.h>
# include<conio.h>
class student
{
public:
student() // user defined constructor
{
cout<< “object is initialized”<<end1;
}
};
void main ()
{
student x,y,z;
getch();
}
Output:
Object is initialized
Here in the above program, one default constructor student has been created which is
similar to the class name student. When objects of the student class are created, then
default constructor is automatically executed, and three times it displays the output
“Object is initialized”. Since here, three objects, x, y and z have been defined for
every execution student constructor.
95
Basic of Object Oriented Limitations of Constructor:
Programming & C++
C++ constructors have the following limitations:
No return type
A constructor cannot return a result, which means that we cannot signal an
error, during the object initialization. The only way of doing it is to throw an
exception from a constructor.
Naming
A constructor should have the same name as the class, which means we
cannot have two constructors that both take a single argument.
Compile time bound
At the time when we create an object, we must specify the name of a concrete
class which is known at compile time. There is no way of dynamic binding
constructors at run time.
There is no virtual constructor
We cannot declare a virtual constructor. We should specify the exact type of
the object at compile time, so that the compiler can allocate memory for that
specific type. If we are constructing derived object, the compiler calls the base
class constructor first and the derived class hasn't been initialized yet. This is
the reason why we cannot call virtual methods from the constructor.
class student
{
private:
int rollno;
float marks;
public:
.
.
student ()
{
// constructor student declared having same name as
// that of its class
rollno = 0;
// constructor value initialized
marks = 0.0;
}
.
.
}
96
Constructors and Destructors
In the above example class student has the constructor function defined with the same
name and its values are initialized after creating it. When a class contains a
constructor like one defined above, it is granted and understood that an object created
by the class will be initialized automatically.
The output of the above C++ program is: rollno and marks of the student class.
When you create an object, if you do not declare a constructor, the compiler would
create one for your program; this is useful because it lets all other objects and
functions of the program know that this object exists. This compiler created Generally, a
constructor is called the default constructor. If you want to declare your own constructor should be
constructor, simply add a method with the same name as the object in the public defined under the
section of the object. When you declare an instance of an object, whether you use that public section of a
object or not, a constructor for the object is created and signals itself. class, so that its
objects can be created
A class can have multiple constructors for various situations. Constructors in any function.
overloading are used to increase the flexibility of a class by having more number of
constructor for a single class. To illustrate this let us take the following C++ program
# include <iostream.h>
class Overclass
{
public:
int x;
int y;
Overclass() { x = y = 0; }
Overclass(int a) { x = y = a; }
Overclass(int a, int b) { x = a; y = b; }
};
int main()
{
Overclass A;
Overclass A1(4);
Overclass A2(8, 12);
Output:cout << "Overclass A's x, y value:: " << A.x << " , "<< A.y << "\n";
cout << "Overclass A1's x,y value:: "<< A1.x << " ,"<< A1.y << "\n";
coutA's
Overclass << x,
"Overclass
y value:: 0A2's
, 0 x,y value:; "<< A2.x << " , "<< A2.y << "\n";
return 0;
Overclass A1's x, y value:: 4 ,4
}
Overclass A2's x, y value:; 8 , 12
Here in the above example, the constructor "Overclass" is overloaded thrice with
different initialized values.
97
Basic of Object Oriented difference. Properly, parameters appear in procedure definitions; arguments appear in
Programming & C++ procedure calls.
By contrast, the arguments are the values actually supplied to the procedure when it is
called. Unlike the parameters, which form an unchanging part of the procedure's
definition, the arguments can, and often do, vary from call to call. Each time a
procedure is called, the part of the procedure call that specifies the arguments is called
the argument list. Many programmers use parameter and argument interchangeably,
depending on context to distinguish the meaning.
The function sum has two parameters, named addend1 and addend2. It adds the values
passed into the parameters, and returns the result
The code which calls the sum function might look like this:
int sumvalue;
int value1 = 40;
int value2 = 2;
sumvalue = sum(value1, value2);
The variables value1 and value2 are initialized with values. Value1 and value2 are
both arguments to the sum function in this context.
At runtime, the values assigned to these variables are passed to the function sum as
arguments. In the sum function, the parameters addend1 and addend2 are evaluated,
yielding the arguments 40 and 2, respectively.
The values of the arguments are added, and the result is returned to the caller, where it
is assigned to the variable sumvalue.
1) one parameter
2) two parameters
3) no parameters
4) character type parameter
98
b) A constructor is called when ever _______________ Constructors and Destructors
1) An object is declared
2) An object is used
3) A class is declared
4) A class is used
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
99
Basic of Object Oriented
Programming & C++ 4.3 TYPES OF CONSTRUCTOR
In object oriented programming (OOP’s), a constructor in a class is used to initialize
the value of the object. It prepares the new object for use by initializing its legal value.
We will discuss main types of constructors, their features and applications in the
following section:
If no user-defined constructor exists for a class A and one is needed, the compiler
implicitly declares a default parameter less constructor A::A(). This constructor is an
inline public member of its class. The compiler will implicitly define A::A() when the
compiler uses this constructor to create an object of type A. The constructor will have
no constructor initializer and a null body. For instance, consider the following
example
class A {
int i;
public:
void getval(void);
void prnval(void);
// member function definitions
}
A 0b 1;
// uses default constructor for creating 0b1. Since user can use it,
// that means, this implicitly defined default constructor is public
// member of the class
0b1. Getval();
0b1. Getval();
Having a default constructor simply means that an application can declare instances of
the class. The compiler first implicitly defines the implicitly declared constructors of
the base classes and non-static data members of a class A before defining the
implicitly declared constructor of A. No default constructor is created for a class that
has any constant or reference type members.
A constructor of a class A is trivial if all the following statements are true:
It is implicitly defined
A has no virtual functions and no virtual base classes
All the direct base classes of A have trivial constructors
The classes of all the non-static data members of A have trivial constructors
The default constructor provided by the compiler does not do anything
specific. It simply allocates memory to data members of the object.
We can write a constructor in C++ which can accept parameters for its invocation.
Such constructor that can take the arguments are called parameterized constructor.
100
declare an instance of the class. To illustrate parameterized constructor well, let us Constructors and Destructors
write the syntax and take one example:
Syntax:
class <cname>
{
//data
public: cname(arguments); // parameterized constructor
.........
.........
};
Examples:
class student
{
char name[20];
int rno;
public: student(char,int); //parameterized constructor
};
student :: student(char n,int r)
{
name=n;
rno=r;
}
In the above example parameterized constructor has been shown by comment line.
When the constructor is parameterized, we must provide appropriate arguments for
the constructor.
integer 12(11);
would define the object 12 and at the same time initialize it to the value of 11.
Another form of this statement is
integer 12 = 11;
Thus the process of initializing through a copy constructor is known as copy
initialization. A copy constructor is always used when the compiler has to create a
temporary object of a class object. The copy constructors are used in the following
situations
Normally, the copy constructor takes an object of their own class as arguments
and produces such an object.
#include<iostream>
#include<conio.h>
using namespace std;
class student
{
int roll;
char name[30];
public:
student() // default constructor
{
roll =10;
strcpy(name,"x");
}
student( student &O) // copy constrcutor
{
roll =O.roll;
strcpy(name, O.name);
}
void input_data()
{
cout<<"\n Enter roll no :"; cin>>roll;
cout<<"\n Enter name :"; cin>>name;
}
void show_data()
{
cout<<"\n Roll no :"<<roll;
cout<<"\n Name :"<<name;
}
};
int main()
{
student s; // default construtor
s.show_data();
student A(s); // copy constructor
A.show_data();
getch();
return 0;
}
Here in the above C++ program we have taken a user defined class student and used
copy constructor to initialize another object student rollno and name from the student
constructor.
102
4.3.4 Constructor Overloading Constructors and Destructors
When more than one constructor function is defined in a class, then it is called
constructor overloading or use of multiple constructor in a class. It is used to increase
the flexibility of a class by having more number of constructors for a single class.
Overloading constructors in C++ programming gives us more than one way to
initialize objects in a class.
#include<iostream>
#include<conio.h>
using namespace std;
class student
{
int roll;
char name[30];
public:
student(int x, char y[]) // parameterized constructor
{
roll =x;
strcpy(name,y);
}
student() // normal constructor
{
roll =100;
strcpy(name,"y");
}
void input_data()
{
cout<<"\n Enter roll no :"; cin>>roll;
cout<<"\n Enter name :"; cin>>name;
}
void show_data()
{
cout<<"\n Roll no :"<<roll;
cout<<"\n Name :"<<name;
}
};
int main()
{
student s(10,"z");
s.show_data();
getch();
return 0;
}
The above C++ program is used to create a constructor student inside the class
student. Here in this program, the student constructor has been defined in many ways
and the output of the program is student name and his roll no.
103
Basic of Object Oriented
Programming & C++
// overloading class constructors
#include <iostream>
using namespace std;
class CRectangle
{
int width, height;
public:
CRectangle ();
CRectangle (int,int);
int area (void)
{
return (width*height);
}
};
CRectangle::CRectangle ()
{
width = 5;
height = 5;
}
int main ()
{
CRectangle rect (3,4);
CRectangle rectb;
cout << "rect area: " << rect.area() << endl;
cout << "rectb area: " << rectb.area() << endl;
return 0;
}
Output:
rect area: 12
rectb area: 25
In this case, rectb was declared without any arguments, so it has been initialized with
the constructor that has no parameters, which initializes both width and height with a
value of 5.
In the same way, a two dimensional array is a grid containing rows and columns in
which each element is uniquely specified by means of its row and column coordinates.
Two-dimensional character arrays hold an array of strings wherein a row represents a
string and a column represents a single character in each of the strings.
104
Constructors and Destructors
Declaration of Two Dimensional Arrays:
char arrayname[x][y];
where 'x' is the number of rows and 'y' is the number of columns.
The number of rows should be equal to the number of strings in the array.
For example, if there are seven strings in an array and the length of the longest string
is nine, the array can be declared in the following manner:
char cWeekdays[7][10];
The rules for initializing two-dimensional arrays are the same as for one-dimensional
arrays.
For example, to declare and initialize an array that would hold the days of the week,
the array definition would be as follows:
In the above example, cWeekdays[0] will refer to the string "Sunday" and
cWeekdays[4][1] would refer to the character 'h' of the string "Thursday".
We have discussed the constructor and their types in the above paragraphs and we
have come to the end of constructor with the discussion of two dimensional array in
object oriented programming.
We will discuss destructor and memory management in coming pages of this unit. The
function of destructor is opposite to that of constructor and is used to free the memory
which was allocated for the creation of constructor. Let us now discuss the destructor
in detail in the next paragraph.
105
Basic of Object Oriented Check Your Progress 2
Programming & C++
a) An object is declared
b) An object is used
c) A class is created
d) A class is used
2: A destructor takes
a) One argument
b) Two argument
c) Three argument
d) Zero argument
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
106
Constructors and Destructors
4.4 DESTRUCTORS
For example the destructor for the class students will bear the name ~student().
Destructor takes no arguments or specifies a return value, or explicitly returns a value
not even void. It is called automatically by the compiler when an object is destroyed.
A destructor cleans up the memory that is no longer required or accessible. To
understand the syntax of destructor let us take following example.
Let us take the following C++ program to illustrate the declaration of destructor
Program: 1
#include<iostream.h>
#include<conio.h>
class student // student is a class
{
public :
~student() // destructor declaration
{
cout <<"Thanx for using this program" <<endl;
}
};
main()
{
clrscr();
student s1; // s1 is an object
getch();
}
Here in the above program ~student () function has been used for destroying the use
of memory which was allocated to constructor class by the operating system.
107
Basic of Object Oriented Program: 2
Programming & C++
#include<iostream>
#include<conio.h>
using namespace std;
class xyz
{
public:
xyz()
{
cout<<"\n Constructor ";
}
~xyz() // use of destructor with -- tilde
{
cout<<"\n Destructor ";
}
};
int main()
{
{
xyz B;
}
getch();
return 0;
}
Here in the above program ~xyz() function has been used for destroying the use of
memory which was allocated during the initialization of the constructor to constructor
class.
Destructors are less complicated than constructors. You don't call them explicitly
(they are called automatically for you), and there's only one destructor for each object.
The name of the destructor is the name of the class, preceded by a tilde (~).
Only the function having access to a constructor and destructor of a class can define
objects of this class types otherwise compiler reports error at the time of compilation
of the program. Generally, a destructor should be defined under the public section of
the class, so that its objects can be destroyed in any function.
Further, destructors are usually used to de-allocate memory and do other cleanup for a
class object and its class members when the object is destroyed. A destructor is called
for a class object when that object passes out of scope or is explicitly deleted. A
destructor is a member function with the same name as its class prefixed by a ~ (tilde).
For example:
class X
{
public:
// Constructor for class X
X();
// Destructor for class X
~X();
};
108
A destructor takes no arguments and has no return type. Its address cannot be taken. Constructors and Destructors
Destructors cannot be declared const, volatile, const volatile or static. A destructor can
be declared virtual or pure virtual.
1. Destructor functions are invoked automatically when the objects are destroyed.
2. We can have only one destructor for a class, i.e. destructors can’t be overloaded.
3. If a class have destructor, each object of that class will be de initialized before the
object goes out of the scope
4. Destructor function, also obey the usual access rules of as other member function
do.
5. No argument can be provided to a destructor, neither does it return any value.
6. Destructor can’t be inherited.
7. A destructor may not be static.
8. It is not possible to take the address of destructor.
9. Member function may be called from within a destructor.
10. An object of a class with a destructor can’t be a member of a union.
11. We may make an object const if it does not change any of its data value.
Limitations of destructors:
109
Basic of Object Oriented
Programming & C++ Student () {}
public:
student & instances()
{
Static student * aGlobalInsts = new student ();
Return * student;
}
}
In the above example, private constructor student has been defined in the private
section of the program and can be accessed within the private section only. The output
of the above C++ program is details of student.
#include<iostream.h>
#include<conio.h>
class stu
{
private: char name[20],add[20];
int roll,zip;
public: stu ( );//Constructor
~stu( );//Destructor
void read( );
void disp( );
};
stu :: stu( )
{
cout<<”This is Student Details”<<endl;
}
void stu :: read( )
{
cout<<”Enter the student Name”;
cin>>name;
cout<<”Enter the student roll no “;
cin>>roll;
cout<<”Enter the student address”;
cin>>add;
cout<<”Enter the Zipcode”;
cin>>zip;
}
void stu :: disp( )
{
110
Constructors and Destructors
cout<<”Student Name :”<<name<<endl;
cout<<”Roll no is :”<<roll<<endl;
cout<<”Address is :”<<add<<endl;
cout<<”Zipcode is :”<<zip;
}
stu : : ~stu( )
{
cout<<”Student Detail is Closed”;
}
void main( )
{
stu s;
clrscr( );
s.read ( );
s.disp ( );
getch( );
}
Output:
Enter the student Name
Sushil
Enter the student roll no
01
Enter the student address
Delhi
Enter the Zipcode
110092
Student Name : Sushil
Roll no is : 01
Address is : Delhi
Zipcode is :110092
#include<iostream.h>
#include<conio.h>
class copy
{
int var,fact;
public:
copy(int temp)
{
var = temp;
}
double calculate()
{
fact=1;
for(int i=1;i<=var;i++)
{
fact = fact * i;
111
Basic of Object Oriented
Programming & C++ }
return fact;
}
};
void main()
{
clrscr();
int n;
cout<<"\n\tEnter the Number : ";
cin>>n;
copy obj(n);
copy cpy=obj;
cout<<"\n\t"<<n<<" Factorial is:"<<obj.calculate();
cout<<"\n\t"<<n<<" Factorial is:"<<cpy.calculate();
getch();
}
Output:
Enter the Number: 5
Factorial is: 120
Factorial is: 120
C++ Program for Add two time variables using constructor and destructor
#include<iostream.h>
#include<conio.h>
class Time
{
int minutes,hours,a;
static int i;
public:
Time(int a)
{
this->a=hours=a;
this->a+=5;
minutes=i++;
cout<<"\nObj address : "<<this;
cout<<"\nAddress of i : "<<&i;
cout<<"\na= "<<this->a<<"\t\t"<<a;
getch();
}
~Time()
{
cout<<endl<<"\t\t"<<hours<<" : "<<minutes;
getch();
}
};
int Time ::i;
void main()
{
clrscr();
Time t3(10),t2(1);
}
112
A C++ program by taking a "patient" class and by using constructor and destructor Constructors and Destructors
#include <iostream>
#include <string>
class Patient {
public:
Patient(string name, int heartRate = 0, double moneyOwed = 0.0);
Patient()
{
//default constructor for string, _name, implicitly called
_heartRate = 0; //Bad for business
_moneyOwed = 0.0;
}
private:
int _heartRate;
double _moneyOwed;
string _name;
};
int main()
{
Patient jk("John",70,0.0);
113
Basic of Object Oriented
Programming & C++ jk.setMoneyOwed(1000.0);
jk.setHeartRate(140);
cout << "Patient " << jk.getName() << " owes " << jk.getMoneyOwed()
<< endl;
cout << "His heart rate is " << jk.getHeartRate() << endl;
return 0;
}
Memory management is a large subject area and will be discussed length other
courses of BCA. However, we will have a brief discussion on memory management in
this unit of constructor and destructor for the learners.
C++ offers a wide range of choices for the management of memory. There are various
techniques to manage the memory in object oriented programming such as C++. Some
of the techniques for memory management are given as follows:
Manual Memory Management: Up until the mid 1990s, the majority of
programming languages used in industry supported manual memory management.
Today, C++ is the main manually memory management languages. Manual memory
management refers to the usage of manual instructions by the programmer to identify
and de-allocate unused objects, or garbage.
new
delete
These two memory management operators are used for allocating and freeing memory
blocks in efficient and convenient way.
The fundamental issue is the determination of when an object is no longer needed (i.e.
is garbage), and arranging for its underlying storage to be returned to the free store so
that it may be re-used to satisfy future memory requests.
Constructors and destructor are used in C++ programming language to initialize and
destroy the memory blocks, when it is no longer required by the program. In manual
memory allocation, this is also specified manually by the programmer; at the time of
writing the codes by programmer.
114
Constructors and Destructors
Manual Memory Management and Correctness
Manual memory management is known to enable several major classes of
bugs into a program, when used incorrectly.
When an unused object is never released back to the free store, this is known
as a memory leak in C++ programming. In some cases, memory leaks may be
tolerable, such as a program which "leaks" a bounded amount of memory over
its lifetime, or a short-running program which relies on an operating system to
de-allocate its resources when it terminates.
When an object is deleted more than once, or when the programmer attempts
to release a pointer to an object not allocated from the free store, catastrophic
failure of the dynamic memory management system can result and cause bugs
in the program.
2. What punctuation is used to signal the beginning and end of code blocks?
A. { }
B. -> and <-
C. BEGIN and END
D. ( and )
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
115
Basic of Object Oriented 2: What do you mean by private constructor and destructor?
Programming & C++
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
4.10 SUMMARY
A class constructor is a class method having the same name as the class name. The
constructor does not have a return type. A constructor may take zero or more
parameters. If we don’t apply a constructor, the compiler provides a no-argument
default constructor. It is important to understand that if we write our own constructor,
the compiler does not provide the default constructor. A class may define one or more
constructor. It is up to us to decide which constructor to call during object creation by
passing an appropriate parameter list to the constructor. We may set the default value
for the constructor parameter.
A class destructor is a class method having the same name as the class name and is
prefixed with tilde (~) sign. The destructor does not return anything and does not
accept any argument. A class definition may contain one and only one destructor. The
runtime calls the destructor, if available, during the object creation. A destructor is
typically used for freeing the resources allocated in the class constructor.
1: A member function with the same name as its class is called constructor and it is
used to initialize the objects of that class type with an initial value. Objects generally
need to initialize variables or assign dynamic memory during their process of creation
to become operative and to avoid returning unexpected values during their execution.
116
2: There are various techniques to manage the memory in C++ programming. These Constructors and Destructors
are:
1) a 2) d 3) c
class A { int i;
public:
void getval(void);
void prnval(void);
.
. // member function definitions
}
2: A copy constructor is used to declare and initialize an object from another object.
For example, the statement
integer 12(11);
would define the object 12 and at the same time initialize it to the value of 11.
Another form of this statement is
integer 12 = 11;
117
Basic of Object Oriented 3: We can write a constructor in C++ which can accept parameters for its invocation.
Programming & C++ Such constructor that can take the arguments are called parameterized constructor.
4: When more than one constructor function is defined in a class, then it is called
constructor overloading or use of multiple constructor in a class. It is used to increase
the flexibility of a class by having more number of constructors for a single class.
Overloading constructors in C++ programming gives us more than one way to
initialize objects in a class.
1) c 2) a 3) b
1: A destructor, as the name implies, is used to destroy the objects that have been
created by using constructor. They de-initialize objects when they are destroyed. A
destructor is invoked when an object of the class goes out of scope, or when the
memory occupied by it is de allocated using the delete operator. A destructor is a
function that has the same name as that of the class but is prefixed with a ~ (tilde). For
example the syntax of class student could be written as follows
~student()
1. Destructor functions are invoked automatically when the objects are destroyed.
2. We can have only one destructor for a class, i.e. destructors can’t be overloaded.
3. If a class have destructor, each object of that class will be de initialized before the
object goes out of the scope
4. Destructor function, also obey the usual access rules of as other member function
do.
5. No argument can be provided to a destructor, neither does it return any value.
6. Destructor can’t be inherited.
7. A destructor may not be static.
8. It is not possible to take the address of destructor.
9. Member function may be called from within a destructor.
118
4: A C++ program by using destructor is given as follows Constructors and Destructors
#include<iostream.h>
#include<conio.h>
class student // student is a class
{
public :
~student() // destructor declaration
{
cout <<"Thanx for using this program" <<endl;
}
};
main()
{
clrscr();
student s1; // s1 is an object
getch();
}
5) Bjarne AT&T Labs Murray Hill, New Jersey Stroustrup, Basics of C++
Programming, Special Edition, Publisher: Addison-Wesley Professional.
Reference Websites:
(1) www.sciencedirect.com
(2) www.ieee.org
(3) www.webpedia.com
(4) www.microsoft.com
(5) www.freetechbooks.com
(6) www.computer basics.com
(7) www.youtube.com
119
Inheritance
UNIT 1 INHERITANCE
Structure Page No.
1.0 Introduction 5
1.1 Objectives 5
1.2 Concept of Re-usability 6
1.3 Inheritance 6
1.3.1 Derived and Base Class 8
1.3.2 Declaration of Derived Class 9
1.3.3 Visibility of Class Members 9
1.4 Types of Inheritance 12
1.5 Single Inheritance 12
1.6 Multiple Inheritance 15
1.7 Multi-level Inheritance 17
1.8 Constructors and Destructors in Derived Classes 21
1.9 Summary 26
1.10 Answers to Check Your Progress 27
1.11 Further Readings 34
1.0 INTRODUCTION
There is a great surge of interest today in Object Oriented Programming (OOP) due to
obvious reasons. One of the most fundamental concepts of the object-oriented
paradigm is inheritance that has profound consequences on the development process.
In OOP, it is possible to define a class as inheriting from another. Object Oriented
Software Development involves a large number of classes. Many of the classes
extension of others. Object Oriented Programming has been widely acclaimed as a
technology that will support the creation of re-usable software, particularly because of
the inheritance facility. In OOP, inheritance is a re-usability technique. We can show
similarities between classes by means of inheritance and describe their similarities in a
class which other classes can inherit. Thus, we can re-use common descriptions.
Therefore, inheritance is often promoted as a core idea for reuse in the software
industry. The abilities of inheritance, if properly used, is a very useful mechanism in
many contexts including reuse. This unit starts with a discussion on the re-usability
concept. This is followed by the inheritance which is prime feature of object oriented
paradigm. It focuses on the standard form of inheritance by extension of a base class
with a derived class. Moreover, in this unit, different types of inheritance, the time of
its use and methods of its implementation are also discussed. Base classes, derived
classes, visibility of class members, and constructors and destructors in derived
classes are introduced. Illustrative examples that facilitate understanding of the
concept are presented.
1.1 OBJECTIVES
Now, can you tell how the re-use is achieved in program? Re-use in OOP language
can be achieved by two ways basically: The first is through class definition-every time
a new object of class is defined, we reuse all the code and declarations of that class.
This type of re-use can be supported in the function-oriented approach also. The other
type of re-use, which is particular to OOP language, can be supported by inheritance.
Inheritance provides the idea of reusability. This means that we can add additional
features to an existing class without modifying it. This is possibly by deriving a new
class from the existing one. You have already seen the first type of reusability through
class. In the next section, we shall see, how will we achieve the reusability through
inheritance?
1.3 INHERITANCE
6
Inheritance is a technique of organizing information in a hierarchical form. It is a Inheritance
relation between classes that allows for definition and implementation of one class
based on the definition of existing classes.
Inheritance is often
You can look around and find many real world examples of inheritance like referred to as an “is-
Inheritance between parent and child, employee and manager, person and student, a” relationship
vehicle and light motor vehicle, and animal and mammal etc. Why are we interested because every object
in inheritance and how will we use this concept? Well, Let us take the example to of the class being
understand this concept. Suppose we want to use the classes Employee and Manager defined “is” carries
in the C++ program. For the time being, let us assume that we do not know the an object of the
concept of the inheritance. Now, we define the Employee and Manager classes as inherited class also.
follows:
class Employee
{
public:
int id_number;
char Name_of_Employee[25];
int age;
char Department_Name[25];
int salary;
char Address[25];
// Member functions
void display_name(void);
void display_id(void);
void raise_salary(float percent);
.
.
.
};
class Manager
{
public:
int id_number;
char Name_of_Employee[25];
int age;
char Department_Name[25];
int salary;
char Address[25];
char Name_of_secretary[25];
Employee *team_members;
void display_name(void);
void display_id(void);
void display_secretary_name(void);
void raise_salary(float percent);
.
.
.
};
If you look at the above declarations of the classes Employee and Manager, you can
make the observation that there are some common attributes and behavior in
Employee and Manager class. We have shown the common attributes and behavior in
Manager class again. Now, we introduce the concept of the inheritance. As we know
that generally Managers are treated differently from other employees in the
organization. Their salary raises are computed differently, they have access to a
secretary, they have a group of employee under them and so on. There are some
7
Inheritance and common data members as well as member functions like name, age, salary, address,
Polymorphism in C + + display_name(),display_id() etc . This is a kind of situation in which we use the
concept of inheritance. Why? Well, we can retain some of what we have already laid
down and defined in the Employee class in terms of data members and member
functions. Employee and Manager classes are declared as follows:
class Employee
{
public:
int id_number;
char Name_of_Employee[25];
int age;
char Department_Name[25];
int salary;
char Address[25];
// Member functions
void display_name(void);
void display_id(void);
void raise_salary(float percent);
.
.
.
};
class Manager :: public Employee
{
public:
char name_of_secretary[25];
Employee *team_members;
void display_secretary_name(void);
void raise_salary(float percent);
.
.
.
};
You can look at the above declaration and observe that we did not declare the
common attributes and functions again in the Manager class. Thus, we have reused
the previous declarations of data members and functions. We can also observe that we
have redefined raise_salary function in the Manager class due to different way to
compute salary of the Manager. From the above discussion, we can conclude that
what is meant by the application of inheritance and how it is supporting the concept of
re-usability by adding additional feature to an existing classes without modifying it.
As we know, when Class A inherits the feature from class B, then Class A is called
the derived class and B is called Base class. A derived class extends its features by
inheriting the properties (features) from another class called the base class while
adding features of its own. In next section, we will see as to how we will define a
derived class.
8
1.3.2 Declaration of Derived Class Inheritance
The declaration of a derived class shows its relationship with the base class in addition
to its own details. The common syntax of declaring a derived class is given as follows:
class A
{
private:
int privateA; // private member of base class A
protected:
int protectedA; // protected member of base class A
public:
int publicA; // public member of base class A
int getPrivateA() //public function of base class A
{
return privateA;
}
};
10
Inheritance
The above first statement is illegal but second and third statements are valid. It is so
because in the first statement protected member protectedA of the base class A has
protected visibility status in class C. However in the second and third statements both
publicA and getPrivateA() have their public visibility status in class C, so they are
accessible.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
In previous section, we discussed inheritance. In this section, we will discuss the types
of inheritance. As we know, the derived class inherits some or all of the features from
the base class depending on the visibility mode. A derived class can also inherit
properties from more than one class or from more than one level. We can classify
inheritance into the following type accordingly:
Single Inheritance: Derivation of a class from only one base class is called a
single inheritance.
In next sections, we shall discuss in detail single inheritance, multiple inheritance and
multi-level inheritance.
Now, let us discuss about single inheritance. In Single Inheritance, derived class
inherits the feature of one base class. If a class is derived from one base class, it is
called Single Inheritance.
12
Figure 1.1 depicts single inheritance: Inheritance
Class
A
Class
B
Figure 1.1: Single Inheritance
A derived class
Class A is the base class and class B is the derived class. The following are the
can be declared if
common steps to implement an inheritance. First, declare a base class and second
its base class is
declare a derived class. The syntax of single inheritance of the above figure is given as
follows: already declared.
class A
{
// members of class A
};
class B :[public/private/protected] A
{
// members of class B
};
Let us understand the concept of single inheritance with Example1. In the example 1
given below, it is seen that how a single inheritance is implemented:
#include <iostream.h>
class A
{
int a;
public :
int b;
void input_ab(void);
void output_a(void);
int get_a(void);
};
class B : public A
{
int c,d;
public :
void input_c(void);
void display(void);
void sum(void);
};
void A :: input_ab()
{
cout<< “\n Enter the value of a and b :”<<endl;
cin>>a>>b;
}
void A :: output_a()
{
cout<<”\\n The Value of a is :”<<a<<endl;
}
13
Inheritance and
Polymorphism in C + + int A :: get_a()
{
return a;
}
void B :: input_c()
{
cout<< “\n Enter the value of c :”<< endl;
cin>>c;
}
void B :: sum()
{
d=get_a()+b+c;
}
void B :: display()
{
cout<< “\n The value of b is :”<<b<< endl;
cout<< “\n The value of c is :”<<c<< endl;
cout<< “\n The value of d(sum of a,b and c) is :”<<d<< endl;
}
void main()
{
B objb;
14
The above example shows a base class A and a derived class B. The base class A Inheritance
contains one private data member a, one public data member b, and three public
member functions input_ab(), output_a() and get_a(). The class B contains two private
data c and d and three public functions input_c(), display() and sum(). The class B is a
derived publicly by class A. Therefore, B inherits all the public members (data and
functions) of class A and retains their visibility. Hence, the public members of class A
is also a public members of class B. But the private members of class A cannot be
inherited by class B. Thus, the derived class B will have more members than what it
contains at the time of declaration.
In the above example, we can see that the member functions sum() and display() are
not able to access the private data member of class A because it cannot be inherited.
However, the data member functions sum() and display() of derived class are able to
access the private data of class A through an inherited member function get_a() of
class A. In the main part of the program, we can also observe that the object of B can
directly access the data member b of class A, because data member b is publically
defined in A.
Now, let us discuss the multiple inheritance. In multiple inheritance, derived class
inherits features from more than one parent classes (base classes). In other way we can
say that if a class is derived from more than one parent class (base classes), then it is
called multiple inheritance. Figure 2.2 depicts multiple inheritance.
class class B
A
class C
class A
{
// members of class A
};
class B
{
// members of class B
};
15
Inheritance and In the example 2 given below, it is seen that how multiple inheritance is
Polymorphism in C + + implemented?
#include <iostream.h>
class A
{
int a;
public :
void input_a(void);
void output_a(void);
int get_a(void);
};
class B
{
int b;
public :
void input_b(void);
void output_b(void);
int get_b(void);
};
class C : public A, public B
{
int c,d;
public :
void input_c(void);
void display(void);
void sum(void);
};
void A :: input_a()
{
cout<< “\n Enter the value of a :”<< endl;
cin>>a;
}
void A :: output_a()
{
cout<< “\n The value of a is :”<<a <<endl;
}
int A :: get_a()
{
return a;
}
void B :: input_b()
{
cout<< “\n Enter the value of b :”<< endl;
cin>>b;
}
void B :: output_b()
{
cout<< “\n The value of b is :”<<b<<endl;
}
int B :: get_b()
{
return b;
}
void C :: input_c()
16
Inheritance
{
cout<< “\n Enter the value of c :”<< endl;
cin>>c;
}
void C :: sum()
{
d=get_a()+get_b()+c;
}
void C ::display()
{
cout<< “\n The value of c is :”<<c<<endl;
cout<< “\n The value of d (sum of a, b and c) is :”<<d<<endl;
}
void main()
{
C objc;
The above example shows multiple inheritance. It contains three classes A, B and C.
The class A and class B are parent classes (base classes) and class C is derived class.
This class inherits the feature of class A and class B.
Now, let us discuss the Multi-level inheritance. In multi-level inheritance, the class
inherits the feature of another derived class. If a class C is derived from class B which
in turn is derived from class A and so on. It is called multi-level inheritance. Figure
1.3 depicts the multi-level inheritance.
17
Inheritance and
Polymorphism in C + +
Class Base Class
A
The syntax of the multi-level inheritance of the above figure is given as follows:
class A
{
// members of class A
};
class B : [public/private/protected] A
{
// members of class B
};
class C :[public/private/protected] B
{
// members of class C
};
#include <iostream.h>
class A
{
int a;
public :
void input_a(void);
void output_a(void);
int get_a(void);
};
class B : public A
{
int b;
public :
void input_b(void);
void output_b(void);
int get_b(void);
};
class C : public B
{
int c,d;
public :
18
Inheritance
void input_c(void);
void display(void);
void sum(void);
};
void A :: input_a()
{
cout<< “\n Enter the value of a :”<< endl;
cin>>a;
}
void A :: output_a()
{
cout<< “\n The value of a is :”<<a<<endl;
}
int A :: get_a()
{
return a;
}
void B :: input_b()
{
cout<< “\n Enter the value of b :”<< endl;
cin>>b;
}
void B :: output_b()
{
cout<< “\n The Value of b is :”<<b<<endl;
}
int B :: get_b()
{
return b;
}
void C :: input_c()
{
cout<< “\n Enter the value of c :”<< endl;
cin>>c;
}
void C:: sum()
{
d=get_a()+get_b()+c;
}
void C ::display()
{
cout<< “\n The value of c is :”<<c<<endl;
cout<< “\n The value of d (sum of a, b and c) is :”<<d<<endl;
}
void main()
{
C objc;
objc.input_a(); // member function of class A
objc.input_b(); // member function of class B
objc.input_c(); // member function of class C
objc.output_a(); // member function of class A
objc.output_b(); // member function of class B
objc.sum(); // member function of class C
objc.display(); // member function of class C
}
19
Inheritance and The output of the example3 is given below.
Polymorphism in C + +
Enter the value of a:
10
Enter the value of b:
20
Enter the value of c:
30
The value of a is : 10
The value of b is : 20
The value of c is : 30
The value of d(sum of a, b and c) is : 60
The above example shows multi-level inheritance. It contains three classes A, B, and
C. The class A is the base class. The class B is derived class. It inherits the features of
A. The class C is derived from intermediate derived class B. The class C, after
inheritance from A through B, would contain the following members:
private :
int c,d; //own member
public :
void input_a(void); // inherited from A via B
void output_a(void); // inherited from A via B
int get_a(void); // inherited from A via B
2) Write a interactive program in c++ which reads the two integer number a and b
then performs the following operation:
(i) a+b
(ii) a-b
(iii) a*b
(iv) a/b
Design the function a+b and a-b in a base class and design a*b and a/b in a derived
class.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
20
3) What is multi-level inheritance? Inheritance
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
4) What are the ways to inherit properties of one class into another class?
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
You have already learnt about the constructors and destructors in Unit 4 of Block 1 of The constructors are
this course. As we know, constructors and destructors play an important role in object used to initialize
initialization and remove the resources allocated to the object. Now, we will discuss object‟s data members
as to how the constructors and destructors are used in derived classes. and to allocate the
required resources
Constructors in Derived Classes: such as memory.
Can you tell when and why we need a constructor in derived class? Well, the derived
class need not have a constructor as long as base class has a no-argument constructor.
However, if any base class contains a constructor with arguments (one or more), it is
necessary for the derived class to have a constructor and pass the arguments to the
base class constructors. In inheritance, generally derived class objects are created
instead of the base class. Thus, it makes sense for the derived class to have a
constructor and pass arguments to the constructor of the base class. When an object of
a derived class is created, the constructor of the base class is executed first and later
on the constructor of the derived class. Let us consider example 4 given below in
which both base and derived class have constructor with parameter.
#include<iostream.h>
class A
{
private:
int a;
protected:
int b;
public:
A(int i, int j)
{
a=i;
b=j;
cout<< “A initialized”<<endl;
21
Inheritance and
Polymorphism in C + + }
void display_ab(void)
{
cout<< “\nThe value of a is : ”<<a;
cout<< “\nThe value of b is : ”<<b;
}
int get_a(void)
{
return a;
}
};
class B
{
private:
int c;
protected:
int d;
public:
B(int i, int j)
{
c=i;
d=j;
cout<< “\nB initialized”<<endl;
}
void display_cd(void)
{
cout<< “\nThe value of c is : ”<<c;
cout<< “\nThe value of d is : ”<<d;
}
int get_c(void)
{
return c;
}
};
public:
void C(int m, int n, int o, int p, int q, int r): A(m,n), B(o,p)
{
e=q;
f=r;
cout<< “ \nC initialized”;
}
void sum(void)
{
total=get_a()+b+get_c()+d+e+f;
}
void display(void)
{
cout<< “\nThe value of e is : ”<<e;
cout<< “\nThe value of f is : ”<<f;
cout<< “\nThe sum of a,b,c,d,e and f is : ”<<total;
22
Inheritance
}
};
void main()
{
C objc(10,20,30,40,50,60);
objc.display_ab();
objc.display_cd();
objc.sum();
objc.display();
}
Unlike constructor in class hierarchy, destructors are invoked in the reverse order of
the constructor invocation. Whenever object goes out of scope, the destructor of that
23
Inheritance and class, whose constructor was executed last while building object of that class, will be
Polymorphism in C + + executed first. Let us take example 5 given below which shows the order of calling
constructors and destructors in Inheritance:
#include<iostream.h>
class A
{
protected:
int a,b;
public:
A(int i, int j)
{
a=i;
b=j;
cout<< “A initialized”<<endl;
}
~A()
{
cout<< “\Destructor in base class A”<<endl;
}
void display_ab()
{
cout<< “\nThe value of a is : ”<<a;
cout<< “\nThe value of b is : ”<<b;
}
};
class B
{
protected:
int c,d;
public:
B(int i, int j)
{
c=i;
d=j;
cout<< “\nB initialized”<<endl;
}
~B()
{
cout<< “\Destructor in base class B”<<endl;
}
void display_cd()
{
cout<< “\nThe value of c is : ”<<c;
cout<< “\nThe value of d is : ”<<d;
}
};
class C : public B, public A
{
Int e,f, total;
public:
C(int m, int n, int o, int p, int q, int r): A(m,n), B(o,p)
{
24
Inheritance
e=q;
f=r;
cout<< “ \nC initialized”;
}
~C()
{
cout<< “\Destructor in derived class C”<<endl;
}
void sum(void)
{
total=a+b+c+d+e+f;
}
void display(void)
{
cout<< “\nThe value of e is : ”<<e;
cout<< “\nThe value of f is : ”<<f;
cout<< “\nThe sum of a,b,c,d,e and f is : ”<<total<<endl;
}
};
void main()
{
C objc(10,20,30,40,50,60);
objc.display_ab();
objc.display_cd();
objc.sum();
objc.display();
}
B initialized
A initialized
C initialized
The value of a is :10
The value of b is :20
The value of c is :30
The value of d is :40
The value of e is :50
The value of f is :60
The sum of a,b,c,d,e,f is :210
Destructor in derived class C
Destructor in base class A
Destructor in base class B
The above example shows the three classes A, B and C. The class A have one
parametric constructor, class B have also one parametric constructor and C is derived
class that inherits the feature of class A and class B. The class C also have a
parametric constructor. It is mandatory to have a parametric constructor in class C.
Here you can observe that the class B is initialized first, because the class B has been
declared first in the derived class header before the class A. You can also see that the
constructors are invoked in the order of B(), A() and C() whereas the destructors are
invoked in the order of C(), A() and B() which is in reverse order.
25
Inheritance and Check Your Progress 3
Polymorphism in C + +
2) What are base and derived classes? Create a base class called Stack and a derived
class called MyStack. Write an interactive program to show the operations of
stack.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
1.9 SUMMARY
26
Inheritance
1) There are many benefits that can be derived from the proper use of inheritance.
They are code reuse, ease of code maintenance and extension, and reduction in the
time to market. The following situations explain benefits of inheritance:
When inherited from another class, the code that provides a behavior
required in the derived class does not need to be rewritten.
When multiple classes inherit from the same super class, there is a sufficient
guarantee that the behavior they inherit will be same in all cases.
Whenever there are similarities between two or more classes, you can
apply inheritance.
3) Access specifiers are used to control the accessibility of data members and
member functions of class. It helps classes to prevent unwanted exposure of
members (data and functions) to outside world.
4) There are many advantages of re-usability. They can be applied to reduce cost,
effort and time of software development. It also increases the productivity,
portability and reliability of the software product.
2)
#include <iostream.h>
#include<stdlib.h>
class A
{
int a,b;
public :
void input_ab(void);
int get_a(void);
int get_b(void);
int add(void);
int sub(void);
};
class B : public A
{
public :
int mul(void);
int div(void);
void display(int opt, int res);
};
void A :: input_ab()
{
cout<< “\n Enter the value of a and b :”<<endl;
cin>>a>>b;
}
int A :: get_a()
{
return a;
}
int A :: get_b()
{
return b;
}
int A :: Add()
{
return (a+b);
}
int A :: Sub()
{
return (a-b);
}
void B :: Mul()
{
28
Inheritance
return(get_a()*get_b());
}
void B :: Div()
{
return(get_a()/get_b());
}
void B :: display(int choice, int result)
{
cout<< “\n The value of a is :”<<a<< endl;
cout<< “\n The value of b is :”<<b<< “endl;
switch(choice)
{
case 1 : cout << “\n The sum of a and b is :” <<result<<endl;
break;
case 2 : cout << “\n The subtraction of a and b is :” <<result<<endl;
break;
case 3 : cout << “\n The multiplication of a and b is :” <<result<<endl;
break;
case 4 : cout << “\n The division of a and b is :” <<result<<endl;
break;
}
}
void main()
{
B objb;
int choice;
int result;
objb.input_ab();
while (1)
{
cout <<” Operations on two numbers …”<<endl;
cout <<” 1. Addition”<<endl;
cout <<” 2. Subtraction”<<endl;
cout <<” 3. Multiplication”<<endl;
cout <<” 4. Division”<<endl;
cout <<” 5. Quit”<<endl;
cout <<” Enter choice:”<<endl;
cin>>choice;
switch(choice)
{
case 1 : result=objb.add();
objb.display(choice,result);
break;
case 2 : result=objb.sub();
objb.display(choice,result);
break;
case 3 : result=objb.mul();
objb.display(choice,result);
break;
case 4 : if (b!=0)
{
result=objb.div();
objb.display(choice,result);
}
else
cout<< “\nDivide by zero error:”<<endl;
break;
29
Inheritance and
Polymorphism in C + + case 5 : exit(1);
break;
default :
cout <<” Bad option selected”<<endl;
continue;
}
}
}
4) There are two ways to inherit properties of one class into another class as follows:
(i) Inheritance
(ii) Object Composition
ObjectName.BaseClassName::MemberName(...).
2) Inheritance is a property by which one class inherits the feature of another class.
The class which inherits the feature from another class is called derived class and
class from which another class takes feature is called base class.
#include <iostream.h>
#include<stdlib.h>
#define Max_Size 5 //Maximum stack size
class Stack
{
protected :
int stack[Max_Size];
int top;
public :
Stack (void)
30
Inheritance
void push (int item);
void pop (int &item);
};
class MyStack : public Stack
{
public :
int push(int item);
int pop(int &item);
void stackContent(void);
};
Stack::Stack()
{
top=-1; //Stack empty
}
void Stack::push(int item)
{
top++;
stack[top]=item;
}
void Stack::pop(int &item)
{
item=stack[top];
top--;
}
int MyStack :: push(int item)
{
If (top<Max_Size-1)
{
Stack::push(item);
return 1; //push operation successful
}
cout<< “\n Stack Overflow :”<< endl;
return 0;
}
int MyStack :: pop(int &item)
{
If (top>=0)
{
Stack::pop(item);
return 1; //push operation successful
}
cout<< “\n Stack Underflow :”<< endl;
return 0;
}
void MyStack :: stackContent(void)
{
int stop;
stop=top;
for (int i=0; i<=stop;i++)
cout<< “:”<<stack[i];
}
void main()
{
MyStack stack;
int choice;
int item;
while (1)
31
Inheritance and
Polymorphism in C + + {
cout << “\nStack Operation …”<<endl;
cout << “\n1. Item to push?”<<endl;
cout << “2. Item to pop”<<endl;
cout << “3. Quit”<<endl;
cout << “Enter choice:”<<endl;
cin>>choice;
switch(choice)
{
case 1 :cout<< “Enter the item:”<<endl;
cin>>item;
cout<< “\n Stack content before push operation:”;
stack.stackContent();
if ((stack.push(item))==1)
{
cout<< “\n Stack content after push operation:”;
stack.stackContent();
}
break;
case 2 : cout<< “\n Stack content before pop operation:”;
stack.stackContent();
if ((stack.pop(item))==1)
{
cout<< “\n Stack content after pop operation:”;
stack.stackContent();
cout<< “popped item:” <<item;
}
break;
case 3 : exit(1);
break;
default :
cout <<” Bad option selected”<<endl;
continue;
}
}
}
Inherited methods, which must be prepared to deal with arbitrary subclasses, are
often slower than specialized codes.
Message passing by its very nature is a more costly than the invocation of
simple procedures.
Albeit object oriented programming is often touted as a solution to the problem
of software complexity, overuse or improper use of inheritance can simply
transfer one form of complexity to another form.
32
4) Inheritance
#include<iostream.h>
#include<string.h>
class Student
{
int roll_no;
char name[25];
public:
void ReadStudentData(void);
void DisplayStudentData(void);
};
class Exam :public Student
{
protected:
int marks[6];
public :
void ReadExamMarks(void);
void DisplayExamMarks(void);
};
class Result : public Exam
{
int total_marks;
public :
void Display(void);
};
void Student :: ReadStudentData()
{
cout<<"\n Enetr the Name:"<<endl;
cin>>name;
cout<< "\n Enter the Roll No.:"<<endl;
cin>>roll_no;
}
void Student :: DisplayStudentData()
{
cout<<"\n Name :"<<name<<endl;
cout<<"\n Roll No. :"<<roll_no;
}
void Exam::ReadExamMarks()
{
cout <<"\nEnter Marks :"<<endl;
for (int i=0; i<6; i++)
{
cout<<"\n Marks scored in subject"<<i+1<<"<Max:100>"<<endl;
cin>>marks[i];
}
}
void Exam::DisplayExamMarks()
{
for (int i=0; i<6; i++)
cout<<"\n Marks scored in subject"<<i+1<<":"<<marks[i];
}
void Result::Display()
{
total_marks=0;
for (int i=0; i<6; i++)
total_marks=total_marks+marks[i];
cout<<"\n Total Marks scored in six subjects :"<<total_marks;
} 33
Inheritance and
Polymorphism in C + + void main()
{
Result objr;
objr.ReadStudentData();
objr.ReadExamMarks();
objr.DisplayExamMarks();
objr.Display();
}
34
Operator Overloading
UNIT 2 OPERATOR OVERLOADING
Structure Page Nos.
2.0 Introduction 35
2.1 Objectives 35
2.2 Function Overloading 36
2.2.1 How Function Overloading is Achieved
2.2.2 How Function Calls are Matched with Overload Functions
2.3 Function Overloading and Ambiguity 42
2.3 Ambiguous Matches
2.4 Multiple Arguments 43
2.5 Operator Overloading 45
2.5.1 Why to overload operators
2.5.2 Member vs. non-member operators
2.5.3 General rules for operator overloading
2.5.4 Why some operators can‘t be overload
2.6 Defining operator overloading 48
2.6.1 Syntax
2.7 Summary 70
2.8 Answers to Check Your Progress 70
2.9 Further Readings 73
2.0 INTRODUCTION
When you create an object (a variable), you give a name to a region of storage.
A function is a name for an action. By making up names to describe the system at
hand, you create a program that is easier for people to understand and change.
Function overloading is one of the defining aspects of the C++ programming
language. Not only does it provide support for compile time polymorphism, it also
adds flexibility and convenience. In addition, function overloading means that if you
have two libraries that contain functions of the same name, they won‘t conflict as long
as the argument lists are different. We‘ll look at all these factors in detail across this
unit.
In C++, you can overload most operators so that they perform special operations
relative to classes that you create. When an operator is overloaded, none of its original
meanings are lost. Operator overloading allows the full integration of new class type
into programming environment. After overloading the appropriate operators, you can
use objects in expressions in just the same way that you use C++‘s built-in data types.
Operator overloading also forms the basis of C++‘s approach to I/O. Function
overloading and operator overloading really aren‘t very complicated. By the time you
reach the end of this unit, you shall learn when to use them and also underlying
mechanisms that implement them during compiling and linking.
2.1 OBJECTIVES
Function overloading refers to using the same thing for different purposes. C++
permits the use of different functions with the same name. However such functions
essentially have different argument list. The difference can be in terms of number or
type of arguments or both. These functions can perform a variety of different tasks.
Overloading of
This process of using two or more functions with the same name but differing in the
functions with
signature is called function overloading. It is only through these differences that the
different return
compiler knows which function to call in any given situations.
types are not
allowed. Consider the following function:
This trivial function adds two integers. However, what if we also need to add two
floating point numbers? This function is not at all suitable, as any floating point
parameters would be converted to integers, causing the floating point arguments to
lose their fractional values.
One way to work around this issue is to define multiple functions with slightly
different names:
However, for best effect, this requires that you define a consistent naming standard,
remember the name of all the different flavors of the function, and call the correct one
(calling add() for addition of double type numbers with integer parameters may
produce the wrong result due to precision issues).
36
{ Operator Overloading
return p + q;
}
Which version of add () gets called depends on the arguments used in the call — if we
provide two ints, C++ will know we mean to call add(int, int). If we provide two
floating point numbers, C++ will know we mean to call add (double, double). In fact,
we can define as many overloaded add () functions as we want, so long as each add ()
function has unique parameters.
Consequently, it‘s also possible to define add () functions with a differing number of
parameters:
Even though this add () function has 3 parameters instead of 2, because the parameters
are different than any other version of add (), this is valid.
One thing that might be coming to your mind is, how will the compiler know when to
call which function, if there are more than one function of the same name. The answer
is, you have to declare functions in such a way that they differ either in terms of the
number of parameters or in terms of the type of parameters they take. What that
means is, nothing special needs to be done, you just need to declare two or more
functions having the same name but either having different number of parameters or
having parameters of different types. In overloaded functions, the function call
determines which function definition will be executed. The biggest advantage of
overloading is that it helps us to perform same operations on different datatypes
without having the need to use separate names for each version. For example, an
overloaded test() function handles different types of data as shown below:
// Declarations
int test (int x); //prototype 1
int test (int x, int y); //prototype 2
double test (int a, double b); //prototype 3
// Function call
Cout<< test (23); //uses prototype 1
Cout<< test (45, 55); //uses prototype 2
Cout<< test (12, 3.25); //uses prototype 3
37
Inheritance and Following example illustrates the function overloading:
Polymorphism in C + +
// Example: Function overloading to find the absolute value of any number int,
long, float,
double
#include<iostream>
using namespace std;
int abslt(int );
long abslt(long );
float abslt(float );
double abslt(double );
int main()
{
int intgr=-5;
long lng=34225;
float flt=-5.56;
double dbl=-45.6768;
cout<<\" absoulte value of \"<<intgr<<\" = \"<<abslt(intgr)<<endl;
cout<<\" absoulte value of \"<<lng<<\" = \"<<abslt(lng)<<endl;
cout<<\" absoulte value of \"<<flt<<\" = \"<<abslt(flt)<<endl;
cout<<\" absoulte value of \"<<dbl<<\" = \"<<abslt(dbl)<<endl;
}
int abslt(int num)
{
if(num>=0)
return num;
else
return (-num);
}
long abslt(long num)
{
if(num>=0)
return num;
else return (-num);
}
float abslt(float num)
{
if(num>=0)
return num;
else return (-num);
}
double abslt(double num)
{
if(num>=0)
return num;
else return (-num);
}
38
Output Operator Overloading
absoulte value of -5 = 5
The use of overloading may not have reduced the code complexity /size but has
definitely made it easier to understand and avoided the necessity of remembering
different names for each version function which perform identically the same task.
#include<iostream.h>
// function prototype
int func(int i);
int func(int i, int j);
void main(void)
{
cout<<func(15); //func(int i)is called
#include<iostream.h>
//function prototypes
int func(int i);
double func(double i);
void main(void)
{
cout<<func(15); //func(int i) is called
cout<<func(15, 155); //func(double i) is called
}
int func(int i)
{
return i;
}
double func(double i)
{
return i; 39
}
Inheritance and 2.2.2 How Function Calls are Matched with Overloaded Functions
Polymorphism in C + +
Making a call to an overloaded function results in one of three possible outcomes:
When an overloaded function is called, C++ goes through the following process to
determine which version of the function will be called:
1) First, C++ tries to find an exact match. This is the case where the actual argument
exactly matches the parameter type of one of the overloaded functions. For
example:
2) If no exact match is found, C++ tries to find a match through promotion. In the
lesson on type conversion and casting, we covered how certain types can be
automatically promoted via internal type conversion to other types.
To summarize,
For example:
In this case, because there is no Print(char), the char ‗a‘ is promoted to an integer,
which then matches Print(int).
a) Any numeric type will match any other numeric type, including unsigned (eg.
int to float)
b) Enum will match the formal type of a numeric type (eg. enum to float)
c) Zero will match a pointer type and numeric type (eg. 0 to char*, or 0 to float)
d) A pointer will match a void pointer
40
Operator Overloading
For example:
In this case, because there is no Print(char), and no Print(int), the ‗a‘ is converted to a
float and matched with Print(float).
Note that all standard conversions are considered equal. No standard conversion is
considered better than any of the others.
Although cValue is of type class X, because this particular class has a user-defined
conversion to int, the function call Print(cValue) will resolve to the Print(int) version
of the function.
You can create a situation in which the compiler is unable to choose between two (or
more) overloaded functions. When this happens, the situation is said to be ambiguous.
Ambiguous statements are errors, and programs containing ambiguity will not
compile.
If every overloaded function has to have unique parameters, how is it possible that a
call could result in more than one match? Because all standard conversions are
considered equal, and all user-defined conversions are considered equal, if a function
call matches multiple candidates via standard conversion or user-defined conversion,
an ambiguous match will result.
For example:
Print(10) is similar. 10 is an int, and there is no Print(int). It matches both calls via
standard conversion.
1) Often, the best way is simply to define a new overloaded function that takes
parameters of exactly the type you are trying to call the function with. Then C++
will be able to find an exact match for the function call.
If there are multiple arguments, C++ applies the matching rules to each argument in
turn. The function chosen is the one for which each argument matches at least as well
as all the other functions, with at least one argument matching better than all the other
functions. In other words, the function chosen must provide a better match than all the
other candidate functions for at least one parameter, and no worse for all of the other
parameters.
In the case that such a function is found, it is clearly and unambiguously the best
choice. If no such function can be found, the call will be considered ambiguous.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
42
3) What are the main applications of function overloading? Operator Overloading
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
a) new
b) this
c) malloc( )
d) delete
a) ++
b) ::
c) ( )
d) ~
d) cannot be overloaded
a) ->
b) &
c) *
d) >>
We already know that a function can be overloaded (same function name having
multiple bodies). The concept of overloading a function can be applied to operators as
well. For example, in C++ we can multiply two variables of user-defined data type
with the same syntax that is applied to the basic data type. This means that C++ has
the ability to provide the operators with a special meaning for data type. The
43
Inheritance and mechanism which provides this special meaning to operators is called operator
Polymorphism in C + + overloading. The operator overloading feature of C++ is one of the methods of
realizing polymorphism. Here, poly refers to many or multiple and morphism refers
to actions, i.e. performing many actions with a single operator. Thus operator
overloading enables us to make the standard operators, like +, -, * etc, to work with
the objects of our own data types. So what we do is, write a function which redefines a
The word
particular operator so that it performs a specific operation when it is used with the
polymorphis object of a class. Operator overloading is very exciting feature of C++. The concept of
m is derived operator overloading can also be applied to data conversion. It enhances the power of
from the extensibility of C++. Thus operator overloading concepts are applied to the following
Greek words two principle areas:
poly and
morphism. Extending capability of operators to operate on user defined data, and
Data conversion
This session deals with overloading of operators to make Abstract Data Types
(ADTS) more natural, and closer to fundamental data types.
Most fundamental data types have pre-defined operators associated with them. For
example, the C++ data type float, together with the operators +, -, *, and /, provides an
implementation of the mathematical concepts of an integer. This is purely a
convenience to the user of a class. Operator overloading isn't strictly necessary unless
other classes or functions expect operators to be defined.
To make a user-defined data type as natural as a fundamental data type, the user-
defined data type must be associated with the appropriate set of operators. Operators
are defined as either member functions or friend functions. The purpose of operator
overloading is to make programs clearer by using conventional meanings for ==, [], +,
etc. Operators can be overloaded in any way from those available like globally or on
the basis of class by class. While implementing the operator overloading this can be
achieved by implementing them as functions. Whether it improves program
readability or causes confusion depends on how well you use it. In any case, C++
programmers are expected to be able to use it.
The user can understand the operator notation more easily as compared to a function
call because it is closer to the real-life implementation. Thus, by associating a set of
meaningful operators, manipulation of an ADT can be done in a conventional and
simpler form. Associating operators with an ADT involves overloading them.
Although the semantics of any operator can be extend, we can‘t change its syntax,
associativity, precedence etc.
There are two groups of operators in terms of how they are implemented: member
operators and non-member operators. The distinction between the two is the same as it
is with methods and functions.
44
Some operators are required to be member operators, others must be non-member Operator Overloading
operators, and some can be both.
The following rules constrain how overloaded operators are implemented. However,
they do not apply to the new and delete operators.
45
Inheritance and Table 2.1 shows the operators which can be overloaded
Polymorphism in C + +
Table 2.1: List of Operators that can be overloaded
+ - * / % ^ & | ~ !
= < > += -= *= /= %= ^= &=
new[] delete[]
. .* :: sizeof ?:
Generally the operators that can't be overloaded are like that because overloading
them could and probably would cause serious program errors or it is syntactically not
possible. Following section describe the reason for not overloading some of the
operators defined in C++ language.
For the operators that cannot be overloaded like :: (scope resolution), . (member
selection), and .* (member selection through pointer to function), we are quoting from
Stroustrup's 3rd edition of ‗The C++ Programming Language‘, section 11.2 (page
263), these operators 'take a name, rather than a value, as their second operand and
provide the primary means of referring to members. C++ has no syntax for writing
code that works on names rather than values so syntactically these operators can not
be overload.
b) size of operator
The size of operator returns the size of the object or type passed as an operand. It is
evaluated by the compiler not at runtime so you can not overload it with your own
runtime code. It is syntactically not possible to do.
c) ? : (conditional operator)
All operators that can be overloaded must have at least one argument that is a user-
defined type. That means you can't overload that operator which has no arguments.
46
But it does not suite for ? : (conditional operator) as it does not take name as Operator Overloading
parameter. The reason we cannot overload ? : is that it takes 3 argument rather than 2
or 1. There is no mechanism available by which we can pass 3 parameters during
operator overloading.
You can overload or redefine the most of built-in operators in C++. These operators
can be overloaded globally or on a class-by-class basis. Overloaded operators are
implemented as functions and can be member functions or global functions.
An overloaded operator is called an operator function. You declare an operator
function with the keyword operator preceding the operator. Overloaded operators are
distinct from overloaded functions, but like overloaded functions, they are
distinguished by the number and types of operands used with the operator.
2.6.1 Syntax
Defining an overloaded operator is like defining a function, but the name of that
function is operator #, in which # represents the operator that‘s being overloaded. The
number of arguments in the overloaded operator‘s argument list depends on two
factors:
1. Whether it‘s a unary operator (one argument) or a binary operator (two arguments).
2. Whether the operator is defined as a global function (one argument for unary, two
for binary) or a member function (zero arguments for unary, one for binary – the
object becomes the left-hand argument).
Here return_type is the type of value returned by the specified operation and op is the
operator being overloaded. The op is preceded by the keyword operator. Operator op
is the name of function. They may be also friend functions. Member function has no
argument for unary operator and one argument for binary operator. This is because the
object used to invoke the member function is passed implicitly and so it available to
member function. This case is not with the friend function. Friend function will have
one argument for unary operator and two arguments for binary operator. All the
arguments may be passed either by value or by reference. Following lines define the
steps in overloading the operators
a. Build a class that defines the data type that is going to use in operation of
overloading.
b. Declare the operator function operator op() in public area of class.
c. Now define the operator function to implement the required operations.
To declare a unary operator function as a non static member, you must declare it in the
form:
return_type operator op();
where op is one of the operators listed in the preceding table.
To declare a unary operator function as a global function, you must declare it in the
form:
return_type operator op( arg );
Where op is described for member operator functions and the arg is an argument of
class type on which to operate. An overloaded unary operator may return any type.
#include<iostream.h>
#include<conio.h>
Class complex
{
int real, imaginary;
Public:
complex()
{
}
complex(int a, int b)
{
real = a;
imaginary = b;
}
void operator-();
void display()
{
cout<<‖Real value‖<<real<<endl;
cout<<‖imaginary value‖<<imaginary<<endl;
}
};
void complex::operator-()
{
real = -real;
imaginary = -imaginary;
}
void main()
{
Clrscr();
complex c1(10,12);
cout<< ―real and imaginary value befor operation‖<<endl;
c1.display();
c1; //c1- /*It will give error*/
cout<< ―real and imaginary‘ value after operation‖<<endl;
c1.display();
getch();
48 }
Output Operator Overloading
#include<iostream.h>
#include<conio.h>
class complex
{
int real;
int imaginary;
public:
complex() //default constructor
{
}
complex(int a, int b)
{
real = a;
imaginary = b;
}
friend void operator -(); //operator overloading prototype
void display()
{
cout<<‖real value is‖<<real<<endl;
cout <<‖imaginary value is:‖<<imaginary<<endl;
}
};
//definition of operator overloading function
friend void complex :: operator - (complex &c)
{
c.real = - c.real;
c.imaginary = - c.imaginary;
}
void main()
{
clrscr();
complex c1(50,100);
cout<<‖real and imaginary value before operation‖<<endl;
c1.diaplay(); //calling operator overloading function
-c1;
//c1-; It will give you an error.
cout<<‖real and imaginary value after operator‖<<endl;
c1.display();
getch();
}
49
Inheritance and Output:
Polymorphism in C + +
Real and imaginary value before operation
Example :
#include<iostream.h>
#include<conio.h>
class complex
{
int real, imaginary;
public:
complex()
{
}
complex(int a,int b)
{
real = a;
imaginary = b;
}
void operator +(complex c);
};
void complex::operator+(complex c)
{
complex temp;
temp.real = real + c.real;
temp.imaginary = imaginary + c.imaginary;
cout<<‖real sum is‖<<temp.real<<endl;
}
void main()
{
clrscr();
complex c1(10,20);
complex c2(20,30);
c1+c2;
getch();
}
Output
Real sum is 30
Imaginary sum is 50
50
Explanation: Output is easily predictable, and most of the program is same as above Operator Overloading
program. Difference lies in void complex :: operator +(complex c) if we compare this
statement with our conventional outline statement
We find that return type is void. Class name is complex. Function name is ‗operator+‘
and it takes one argument which is of class complex type object.
When this function is called in main with statement c1+c2, c1 is object that invokes
function ‗Operator+‘ and c2 is passed as argument. Now with in the function real and
imaginary parts are c1 will be directly accessible (as it invokes function) while real
and imaginary of c2 are taken using formal argument ‗complex c‘. Here we can find
that keyword ‗operator‘ is inserted automatically whenever invoking object is user
defined type with operator.
Example
#include<iostream.h>
#include<conio.h>
class complex
{
int real;
int imaginary;
public:
complex(){ } //default constructor
complex(int a, int b)
{
real = a;
imaginary = b;
}
friend complex operator +(comlex c1, complex c2);
void display()
{
cout<<‖real value is‖<<real<<endl;
cout <<‖imaginary value is:‖<<imaginary<<endl;
}
};
complex operator + (comlex c1, complex c2)
{
complex tmp;
tmp.real = c1.real + c2.real
tmp.imaginary = c1.imaginary + c2.imaginary;
return(tmp);
}
void main()
{
clrscr();
complex c1(10,20);
complex c1(30,50);
ccomlex c3 = c1 + c2;
c3.display();
getch();
}
51
Inheritance and Output:
Polymorphism in C + +
real value is : 40
imaginary value is : 70
The overloaded ++ and – – operators present a dilemma because you want to be able
to call different functions depending on whether they appear before (prefix) or after
(postfix) the object they‘re acting upon. The solution is simple, but people sometimes
find it a bit complex and confusing at first. When the compiler sees, for example, ++a
(a pre-increment), it generates a call to operator ++(a); but when it sees a++, it
generates a call to operator ++(a, int.) That is, the compiler differentiates between the
two forms by making calls to different overloaded functions.
Example
#include<iostream>
using namespace std;
//Increment and decrement overloading
class Inc {
private:
int count ;
public:
Inc() {
//Default constructor
count = 0 ; }
Inc(int C) {
// Constructor with Argument
count = C ;
}
Inc operator ++ () {
// Operator Function Definition
return Inc(++count);
}
Inc operator -- () {
// Operator Function Definition
return Inc(--count);
}
void display(void) {
cout << count << endl ;
}
};
52
Operator Overloading
void main(void)
{
Inc a, b(10), c, d, e(5), f(10);
cout << "Before using the operator ++()\n";
cout << "a = ";
a.display();
cout << "b = ";
b.display();
++a;
b++;
cout << "After using the operator ++()\n";
cout << "a = ";
a.display();
cout << "b = ";
b.display();
c = ++a;
d = b++;
cout << "Result prefix (on a) and postfix (on b)\n";
cout << "c = ";
c.display();
cout << "d = ";
d.display();
cout << "Before using the operator --()\n";
cout << "e = ";
e.display();
cout << "f = ";
f.display();
--e;
f--;
cout << "After using the operator --()\n";
cout << "e = ";
e.display();
cout << "f = ";
f.display();
}
Output:
a=0
b = 10
a=1
b = 11
c=2
53
Inheritance and d = 12
Polymorphism in C + +
Before using the operator --()
e=5
f = 10
e=4
f=9
Note :
When specifying an overloaded operator for the postfix form of the increment or
decrement operator, the additional argument must be of type int; specifying any other
type generates an error.
class Complex
{
private:
double real, imag;
public:
Complex(){
real = 0;
imag = 0;
}
Complex(double r, double i) {
real = r;
imag = i;
}
double getReal() const {
return real;
}
double getImag() const {
return imag;
}
Complex & operator=(const Complex &);
};
Complex & Complex::operator=(const Complex& c) {
real = c.real;
imag = c.imag;
return *this;
}
#include <iostream>
int main()
{
using namespace std;
Complex c1(5,10);
Complex c2(50,100);
cout << "c1= " << c1.getReal() << "+" << c1.getImag() << "i" << endl;
54
Operator Overloading
cout << "c2= " << c2.getReal() << "+" << c2.getImag() << "i" << endl;
c2 = c1;
cout << "assign c1 to c2:" << endl;
cout << "c2= " << c2.getReal() << "+" << c2.getImag() << "i" << endl;
}
Output:
c1= 5+10i
c2= 50+100i
assign c1 to c2:
c2= 5+10i
Output streams use the << operator for standard types. We can also overload the <<
operator for our own classes.
Actually, the << is left shift bit manipulation operator. But the ostream class overloads
the operator, converting it into an output tool. The cout is an ostream object and that it
is smart enough to recognize all the basic C++ types. That's because the ostream class
declaration includes an overloaded operator<<() definition for each of the basic types.
Example
#include <iostream>
using namespace std;
class Complex
{
private:
double real, imag;
public:
Complex(){
real = 0;
imag = 0;
}
Complex(double r, double i) {
real = r;
imag = i;
}
double getReal() const {
return real;
}
double getImag() const {
return imag;
}
Complex & operator=(const Complex &);
const Complex operator+(const Complex & );
Complex & operator++(void);
Complex operator++(int);
/*friend const
Complex operator+(const Complex&, const Complex&); */
friend ostream& operator<<(ostream& os, const Complex& c);
};
55
Inheritance and
Polymorphism in C + + Complex & Complex::operator=(const Complex& c) {
real = c.real;
imag = c.imag;
return *this;
}
const Complex Complex::operator+(const Complex& c) {
Complex temp;
temp.real = this->real + c.real;
temp.imag = this->imag + c.imag;
return temp;
}
//pre-increment
Complex & Complex::operator++() {
real++;
imag++;
return *this;
}
//post-increment
Complex Complex::operator++(int) {
Complex temp = *this;
real++;
imag++;
return temp;
}
/* This is not a member function of Complex class */
/*const Complex operator+(const Complex& c1, const Complex& c2) {
Complex temp;
temp.real = c1.real + c2.real;
temp.imag = c1.imag + c2.imag;
return temp;
}*/
ostream& operator<<(ostream &os, const Complex& c) {
os << c.real << '+' << c.imag << 'i' << endl;
return os;
}
int main()
{
Complex c1(5,10);
cout << "c1 = " << c1.getReal() << "+" << c1.getImag() << "i" << endl;
cout << "Using overloaded << " << endl;
cout << "c1 = " << c1 << endl;
}
Output:
c1 = 5+10i
c1 = 5+10i
56
cout << "c1 = " << c1 << endl; Operator Overloading
operator<<(cout, c1);
#include<iostream.h>
#include<string.h>
#include<conio.h>
class string
{
private:
char str[80];
public:
string() { strcpy(str,"ttt"); }
string(char s[]) { strcpy(str,s); }
void display() { cout<<str<<endl; }
string operator+(string );
};
string string::operator+(string ss){
string temp;
if(strlen(str)+strlen(ss.str)<80)
{
strcpy(temp.str,str);
strcat(temp.str,ss.str);
}
else
{
cout<<"string overflow"<<endl;
temp=0;
}
return temp; }
main()
{
clrscr();
string s1(" Operator");
string s2(" Overloading");
string s3;
s1.display();
s2.display();
s3=s1+s2;
s3.display();
getch();
return 0;
}
57
Inheritance and Output:
Polymorphism in C + +
Operator
Overloading
Operator Overloading
#include <iostream.h>
#include <string.h>
#include <conio.h>
class string
{
char *p;
int len;
public:
string()
{}
string(char *a)
{
len=strlen(a);
p=new char[len+1];
strcpy(p,a);
}
operatorchar*()
{
return(p);
}
void display()
{
cout<<p;
}
};
void main()
{
clrscr();
string o1="IGNOU";
cout<<"String of Class type : ";
o1.display();
cout<<endl;
char *str=o1;
cout<<"String of Basic type : "<<str;
getch();
}
Output:
58
Instream and outstream operator overloading Operator Overloading
Example
Class Complex
{
Public:
Friend istream & operator >>(istream &is, Complex &c2);
Friend ostream & operator <<(ostream &os, Complex &c2);
Private:
Int real,imaginary;
};
Istream& operator >>(istream &is, Complex &c2);
{
Cout<<‖enter real and imaginary‖<<endl;
Is>>c2.real>>c2.imaginary;
Return(is);
}
Istream& operator <<(ostream &os, Complex &c2)
{
Os<<‖the complex number is ―<<endl;
Os<<c2.real<<‖I‖<<c2.imaginary;
Return(os);
}
Void main()
{
Complex c1,c2;
Cin>>c1;
Cout<<c1;
Cin>>c2;
Cout<<c2;
}
This operator function have to be declared friends since they have to access the user
class and the objects of stream and ostream classes that are sytem defined. Since these
operators functions are friend functions, the two objects cin and cout are passed as
arguments, along with the objects of the user class. They return the isteam and
ostream objects so that the operator can be chained. That is the above two input
statements can also be written as,
Cin>>c1>>c2;
Cout<<c1<<c2;
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
59
Inheritance and 2) What are the basic rules for operator overloading in C++?
Polymorphism in C + +
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
b) Overloaded operator must have at least one operand of its class type.
c) The overloaded operators follow the syntax rules of the original operator.
iii) Which of the following operator can be overloaded through friend function?
a) ->
b) =
c) ( )
d) *
a) no argument
b) one argument
c) two arguments
d) three arguments
60
Operator Overloading
2.7 SUMMARY
In this unit, we have discussed two important concepts about overloading namely
function overloading and operator overloading. As a part of function overloading, you
learnt that you can create multiple functions of the same name that work differently
depending on parameter type. Function overloading can lower a programs complexity
significantly while introducing very little additional risk. Although this particular
lesson is long and may seem somewhat complex (particularly the matching rules), in
reality function overloading typically works transparently and without any issues. The
compiler will flag all ambiguous cases, and they can generally be easily resolved.
Operator overloading is common-place among many efficient C++ programmers.
Operating overloading allows you to pass different variable types to the same function
and produce different results. Operator overloading permits user-defined operator
implementations to be specified for operations where one or both of the operands are
of a user-defined class or struct type. Operator overloading allows the programmer to
define how operators should interact with various data types. It is so because operators
in C++ are implemented as functions, operator overloading works very analogously to
function overloading. Operator overloading is the ability to tell the compiler how to
perform a certain operation when its corresponding operator is used on one or more
variables.
i) First, C++ tries to find an exact match. This is the case where the actual
argument exactly matches the parameter type of one of the overloaded
functions. For example:
ii) If no exact match is found, C++ tries to find a match through promotion.
In the lesson on type conversion and casting, we covered how certain
types can be automatically promoted via internal type conversion to other
types.
d) can develop more than one function with the same name.
i) (A)
ii) (B)
iii) (C)
iv) (D)
Examples:
a) The operators >> and << may be used for I/O operations because in the
header, they are overloaded.
3) Function overloading is like you have different functions with the same name
but different signatures working differently. So, the compiler can differentiate
and find out which function to call depending on the context. In case of
operator overloading, you try to create your own functions which are called
when the corresponding operator is invoked for the operands.
One important thing to understand is that you can create as many functions as
you want with the same name and different signatures so that they can work
differently but for a particular class, you cannot overload the operator
function based on number of arguments. There is a fundamental reason
behind this.
According to the rules, you can not create your own operators and you have to
use already available operators. Another thing is, since the operators are
already defined for use with built-in types, you can‘t change their
characteristics. For example, the binary operator '+' always takes two
parameters, so for this you cannot create a function that takes three
parameters. But you can always overload them based on the type of the
parameters.
i) (D)
ii) (C)
iii) (D)
iv) (A)
63
Inheritance and
Polymorphism in C + +
5) www.learncpp.com/cpp-tutorial
6) http://www.bogotobogo.com/cplusplus
64
Polymorphism and
UNIT 3 POLYMORPHISM AND VIRTUAL Virtual Function
FUNCTION
Structure Page Nos.
3.0 Introduction 65
3.1 Objectives 65
3.2 Polymorphism 66
3.2.1 Advantages of Polymorphism
3.2.2 Types of Polymorphism
3.3 Dynamic Binding 67
3.4 Virtual Functions 68
3.4.1 Function Overriding
3.4.2 Properties of Virtual Functions
3.4.3 Definition of Virtual Functions
3.4.4 Need of Virtual Functions
3.4.5 Rules for Virtual Function
3.4.6 Limitations for virtual Functions
3.5 Pure Virtual Function 76
3.5.1 Syntax of Pure Virtual Function
3.5.2 Characteristics of Pure Virtual Function
3.5.3 Abstract Classes
3.6 Summary 83
3.7 Answers to Check Your Progress 83
3.8 Further Readings 86
3.0 INTRODUCTION
3.1 OBJECTIVES
3.2 POLYMORPHISM
The same + operator can be also used for floating point addition:
7.15 + 3.78
We saw above that a single operator „+‟ behaves differently in different contexts such as
integer, string or float referring the concept of polymorphism. The above concept leads to
operator overloading. When the exiting operator or function operates on new data type it
is overloaded. C++ also permits the use of different functions with the same name. Such
functions have different argument list. The difference can be in terms of number or type
of arguments or both. It refers as function overloading. So, we conclude that the concept
of operator overloading and function overloading is a branch of polymorphism. Both the
concepts have been discussed in unit 2 in detail.
Polymorphic variables help with memory use, in that a single variable can be used to
store multiple data types (integers, strings, etc.) rather than declaring a different
variable for each data format to be used.
66
Applications are Easily Extendable: Once an application is written using the concept Polymorphism and
of polymorphism, it can easily be extended, providing new objects that conform to the Virtual Function
original interface. It is unnecessary to recompile original programs by adding new
types. Only re-linking is necessary to exhibit the new changes along with the old
application. This is the greatest achievement of C++ object-oriented programming. In
programming language, there has always been a need for adding and customizing. By
utilizing the concept of polymorphism, time and work effort is reduced in addition to
making future maintenance easier.
You know that polymorphism can be implemented using operator and function
overloading, where the same operator and function works differently on different
arguments producing different results. 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, static
binding, static linking or compile time polymorphism.
67
Inheritance and However, ambiguity creeps in when the base class and the derived class both have a
Polymorphism in C + + function with same name. For instance, let us consider the following code snippet.
Class P
{
int a;
public:
void display() {……} //display in base class
};
Class Q : public P
{
int b;
It is also known as public:
dynamic binding void display() {……} //display in derived class
because the
};
selection of the
appropriate
Since, both the display() functions are same but at in different classes, there is no
function is
overloading, and hence early binding does not apply. We have seen earlier that, in such
dynamically at run situations, we may use the class resolution operator to specify the class while invoking the
time. function with the derived class objects.
It would be better if the appropriate function is chosen at the run time. This is known as
run time polymorphism. C++ supports run-time polymorphism by a mechanism called
virtual function. It exhibits late binding.
In the case of a compiled language, the compiler still doesn‟t know the actual object type,
but it inserts code that finds out and calls the correct function body. When a language
implements dynamic binding, there must be some mechanism to determine the type of the
object at runtime and call the appropriate member function.
You know that polymorphism also refers to the ability to call different functions by using
only one type of function call. Suppose a programmer wants to code vehicles of different
shapes such as circles, squares, rectangles, etc. one way to define each of these classes is
to have a member function for each that makes vehicles of each shape. Another
convenient approach the programmer can take is to define a base class named Shape and
68
then create an instance of that class. The programmer can have array that hold pointers to Polymorphism and
all different objects of the vehicle followed by a simple loop structure to make the Virtual Function
vehicle, as per the shape desired, by inserting pointers into the defined array. This
approach leads to different functions executed by the same function call. Polymorphism is
used to give different meanings to the same concept. This is the basis for virtual function
implementation.
1. All different classes must be derived from a single base class. In the above example,
the shapes of vehicles (circle, triangle, rectangle) are from the single base class called
Shape.
2. The member function must be declared virtual in the base class. In the above
example, the member function for making the vehicle should be made as virtual to the
base class.
Conclusion of above discussion is that the form of a member function can be changed at
runtime. Such member functions are called virtual functions and the corresponding class
is called polymorphic class. The objects of the polymorphic class, addressed by pointers,
change at runtime and respond differently for the same message. The word „virtual‟
means something that does not exist in reality, some sort of imaginary thing. The concept
of virtual function is the same as a function, but it does not really exist although it appears
in needed places in a program. The object-oriented programming language C++
implements the concept of virtual function as a simple member function, like all member
functions of the class. The functionality of virtual functions can be overridden in its
derived classes.
To cause late binding to occur for a particular function, C++ requires that you use the
virtual keyword when declaring the function in the base class. Late binding occurs only
with virtual functions, and only when you‟re using an address of the base class where
those virtual functions exist, although they may also be defined in an earlier base class.
To create a member function as virtual, you simply precede the declaration of the
function with the keyword virtual. Only the declaration needs the virtual keyword, not
the definition. If a function is declared as virtual in the base class, it is virtual in all the
derived classes. The redefinition of a virtual function in a derived class is usually called
function overriding. Notice that you are only required to declare a function virtual in the
base class. All derived-class functions that match the signature of the base-class
declaration will be called using the virtual mechanism. You can use the virtual keyword
in the derived-class declarations (it does no harm to do so), but it is redundant and can be
confusing.
Dynamic Binding Property: Virtual Functions are resolved during run-time or dynamic
binding. Virtual functions are also simple member functions. The main difference
between a non-virtual C++ member function and a virtual member function is in the way
69
Inheritance and they are both resolved. A non-virtual C++ member function is resolved during compile
Polymorphism in C + + time or static binding. Virtual Functions are resolved during run-time or dynamic binding.
The general syntax to declare a virtual function uses the following format:
class class_name //This denotes the base class of C++ virtual function
{
public:
virtual return_type member_function_name(arguments) //This denotes the C++
virtual function
{
...
...
}
};
Virtual functions should be define in the public section of a class to realize its full
potential benefits. When such a declaration is made, it allows to decide which function to
be used at runtime, based on the type of object, pointed to by the base pointer rather than
the type of the pointer. The examples of virtual functions provided in this unit illustrate
the use of base pointer to point to different objects for executing different
implementations of the virtual functions.
Note: By default, C++ matches a function call with the correct function definition at
compile time. This is called static binding. You can specify that the compiler match a
function call with the correct function definition at run time; this is called dynamic
binding. You declare a function with the keyword virtual if you want the compiler to use
dynamic binding for that specific function.
The first and foremost question which is arises why do we need virtual function? Suppose
we do have a list of pointer to objects of a super class in an inheritance hierarchy and we
wish to invoke the functions of its derived classes with the help of single list of pointers
provided that the functions in super class and sub classes have the same name and
signature. That in turn means we want to achieve run time polymorphism. So, let we have
brief concept about pointers to derived types.
70
3.4.4.1 Pointers to derived types Polymorphism and
Virtual Function
We know that pointer of one type may not point to an object of another type. You shall
now learn about the one exception to this general rule: a pointer to an object of a base
class can also point to any object derived from that base class. Similarly, a reference to a
base class can also reference any object derived from the original base class. In other
words, a base class reference parameter can receive an object of types derived from the
base class, as well as objects within the base class itself. Let us try to work it out with the
following example:
/*The case when we wish to invoke the child class function with the parent class
pointer, but the output is not the same as we expected*/
#include<iostream.h>
#include<conio.h>
class Faculty
{
int facultyId;
char facultyName[25];
char facultyType;
public:
void calculateSalary() //Parent Class Function
{
cout<<"\n Calculating the salary of a faculty, no matter the faculty is
regular or guest !!";
}
};
71
Inheritance and
Polymorphism in C + + void main()
{
Faculty *pFaculty;
RegularFaculty rFaculty;
GuestFaculty gFaculty;
clrscr();
//Assigning the address of child class object into parent class pointer
pFaculty=&rFaculty;
//Invocation of calculateSalary() function with parent class pointer
pFaculty->calculateSalary();
//Assigning the address of child class object into parent class pointer
pFaculty=&gFaculty;
//Invocation of calculateSalary() function with parent class pointer
pFaculty->calculateSalary();
getch();
}
Output:
Note: But here the output does not come out to be as we expect it to be because here the
super class „Faculty‟ pointer is having reference of child class objects of RegularFaculty
and GuestFaculty classes respectively but when we try to call the derived class function
namely the calculateSalary() with the help of this pointer it does not do so. Both the time
it is calling the function calculateSalary() of super class only!!
72
Polymorphism and
class RegularFaculty : public Faculty Virtual Function
{
public:
void calculateSalary() //Child Class Function
{
cout<<"\n Calculating the salary of a regular faculty !!";
}
};
class GuestFaculty : public Faculty
{
public:
void calculateSalary() //Child Class Function
{
cout<<"\n Calculating the salary of a guest faculty !!";
}
};
void main()
{
Faculty *pFaculty;
RegularFaculty rFaculty;
GuestFaculty gFaculty;
clrscr();
//Assigning the address of child class object into parent class pointer
pFaculty=&rFaculty;
//Invocation of calculateSalary() function with parent class pointer
pFaculty->calculateSalary();
//Assigning the address of child class object into parent class pointer
pFaculty=&gFaculty;
//Invocation of calculateSalary() function with parent class pointer
pFaculty->calculateSalary();
getch();
}
Output:
Explanation
See the magic of virtual function. There is a slight change in the above program the
function calculateSalary() in super class is declared to be virtual and the output is turned
to be as per our expectations, we are having the pointer „pFaculty‟ to super class but when
the references of child class objects namely the rFaculty and gFaculty to this pointer we
see that with the pointer having the reference of rFaculty the function of child class
regularFaculty is called where as when it contains the referenc of gFaculty then the
function of child class GuestFaculty is called.
73
Inheritance and Let we have one more example to clarify the concept:
Polymorphism in C + +
The vital reason for having a virtual function is to implement a different functionality in
the derived class.
For example: a Make function in a class Vehicle may have to make a Vehicle with red
color. A class called FourWheeler, derived or inherited from Vehicle, may have to use a
blue background and 4 tires as wheels. For this scenario, the Make function for
FourWheeler should now have a different functionality from the one at the class called
Vehicle. This concept is called Virtual Function.
Example 3.
class Vehicle //This denotes the base class of C++ virtual function
{
public:
virtual void Make() //This denotes the C++ virtual function
{
cout << "Member function of Base Class Vehicle Accessed" << endl;
}
};
After the virtual function is declared, the derived class is defined. In this derived class, the
new definition of the virtual function takes place. When the class FourWheeler is derived
or inherited from Vehicle and defined by the virtual function in the class FourWheeler, it
is written as:
#include <iostream>
using namespace std;
class Vehicle //This denotes the base class of C++ virtual function
{
public:
virtual void Make() //This denotes the C++ virtual function
{
cout << "Member function of Base Class Vehicle Accessed" << endl;
}
};
class FourWheeler : public Vehicle
{
public:
void Make()
{
cout << "Virtual Member function of Derived class FourWheeler Accessed"
<< endl;
}
};
void main()
{
Vehicle *a, *b;
a = new Vehicle();
a->Make();
b = new FourWheeler();
74 b->Make();
}
Explanation Polymorphism and
Virtual Function
In the above example, it is evident that after declaring the member functions Make() as
virtual inside the base class Vehicle, class FourWheeler is derived from the base class
Vehicle. In this derived class, the new implementation for virtual function Make() is
placed.
In this example, the member function is declared virtual and the address is bounded only
during run time, making it dynamic binding and thus the derived class member function is
called.
To achieve the concept of dynamic binding in C++, the compiler creates a v-table each
time a virtual function is declared. This v-table contains classes and pointers to the
functions from each of the objects of the derived class. This is used by the compiler
whenever a virtual function is needed.
The function call takes slightly longer due to the virtual mechanism, and it also makes
it more difficult for the compiler to optimize because it doesn't know exactly which
function is going to be called at compile time.
In a complex system, virtual functions can make it a little more difficult to figure out
where a function is being called from.
Virtual functions will usually not be inlined.
Size of object increases due to virtual pointer.
75
Inheritance and
Polymorphism in C + + 3.5 PURE VIRTUAL FUNCTIONS
Remember that a Pure Virtual Functions are the specific type of virtual functions. A virtual function with
class containing pure no function body is called pure virtual function i.e. a pure virtual function is a function
virtual functions declared in a base class that has no definition relative to base class. A pure virtual
can‟t be used to function purely exists in base class only to be overridden by the derived class functions. A
declare any objects base class only specifies that there is a function with this name and signature which will
be implemented by any of derived class or by some other derived class in the same
of its own.
inheritance hierarchy. Such classes are also called abstract base class.
#include<iostream.h>
#include<conio.h>
class Faculty
{
int facultyId;
char facultyName[25];
char facultyType;
public:
virtual void calculateSalary()=0; //Pure Virtual Function in parent class
};
class RegularFaculty:public Faculty
{
public:
void calculateSalary() //Child Class Function
{
cout<<"\n Calculating the salary of a regular faculty !!";
}
};
class GuestFaculty:public Faculty
{
public:
void calculateSalary() //Child Class Function
{
cout<<"\n Calculating the salary of a guest faculty !!";
}
};
void main()
{
Faculty *pFaculty;
RegularFaculty rFaculty;
GuestFaculty gFaculty;
clrscr();
76
Polymorphism and
Virtual Function
//Assigning the address of child class object into parent class pointer
pFaculty=&rFaculty;
pFaculty->calculateSalary(); //Invocation of calculateSalary() function with
parent class pointer
//Assigning the address of child class object into parent class pointer
pFaculty=&gFaculty;
pFaculty->calculateSalary(); //Invocation of calculateSalary() function with
parent class pointer
getch();
}
Output:
This is the same faculty salary calculation program that is introduced in the discussion of
virtual functions but there is a change here, the function calculateSalary() in base class
„Faculty‟ is declared to be pure virtual with no function definition. This function is
implemented by two concrete children of Faculty class namely the „ReguarFaculty‟ and
„GuestFaculty‟.
Then in main, we have pointer to base class Faculty namely the „pFaculty‟ that is assigned
by the references of the child class objects „rFaculty‟ and „gFaculty‟ one by one and is
used to call the calculateSalary() function and it is clear from the output that one time it
calls up the function in RegularFaculty and the function in GuestFaculty the other time.
A class member function can be declared to be pure virtual by just specifying the
keyword „virtual‟ in front and putting „=0‟ at the end of the function declaration.
Pure virtual function itself do nothing but acts as a prototype in the base class and
gives the responsibility to a derived class to define this function.
As pure virtual functions are not defined in the base class thus a base class can not
have its direct instances or objects that means a class with pure virtual function acts as
an abstract class that cannot be instantiated but its concrete derived classes can be.
We cannot have objects of the class having pure virtual function but we can have
pointers to it that can in turn hold the reference of its concrete derived classes.
Pure virtual functions also implements run time polymorphism as the normal virtual
functions do as binding of functions to the appropriate objects here is also delayed up
to the run time, that means which function is to invoke is decided at the run time.
Pure virtual functions are meant to be overridden.
Only the functions that are members of some class can be declared as pure virtual that
means we cannot declare regular functions or friend functions as pure virtual.
77
Inheritance and The corresponding functions in the derived class must agree be compatible with the
Polymorphism in C + + pure virtual function‟s name and signature that means both must have same name and
signature.
For abstract class, pure virtual function is must.
The pure virtual functions in an abstract base class are never implemented. Because
no objects of that type are ever created, there is no reason to provide
implementations, and the ADT (Abstract Data Type) works purely as the definition
of an interface to objects which derive from it.
It is possible, however, to provide an implementation to a pure virtual function.
The function can then be called by objects derived from the ADT, perhaps to
provide common functionality to all the overridden functions.
Abstract classes act as a container of general concepts from which more specific classes
can be inherited. Thus an abstract class is one that is not used to create any object of its
own but it solely exists to act as a base class for the other classes that means the abstract
class must be a part of some inheritance hierarchy.
An abstract class can not be instantiated that means abstract classes can not have their
own instances but their child or derived classes may have their own instances
provided the child class itself is not an abstract class.
Though objects of an abstract class cannot be created, however, one can use pointers
and references to abstract class types.
A class should contain at least one pure virtual function to be called as abstract. Pure
virtual functions can be declared with the keyword virtual and =0 syntax at the end of
function declaration statement.
If a class is made abstract by giving a pure virtual function then it must be inherited
by a child class of it that provides the implementation of the pure virtual function.
If a class inherits an abstract class and does not provide the implementation of the
pure virtual function then the child class itself should declare the function as pure
virtual that means the child class will be an abstract class as well.
The signature of the function declared as pure virtual in base class must strictly agree
with the signature of the function in child class that implements the pure virtual
function.
78
Example Polymorphism and
Virtual Function
void showDetails()
{
cout<<"\n Id:"<<facultyId;
cout<<"\n Name:"<<facultyName;
cout<<"\n FacultyType: Regular";
}
};
class GuestFaculty:public Faculty
{
79
Inheritance and
Polymorphism in C + +
int noOfLectures;
float perLectureRemuneration;
public:
GuestFaculty(int id,char name[])
{
facultyId=id;
strcpy(facultyName,name);
facultyType='G';
}
setSalaryParameters(int nol,float plr)
{
noOfLectures=nol;
perLectureRemuneration=plr;
}
float calculateSalary() //Child Class Function
{
return(noOfLectures*perLectureRemuneration);
}
void showDetails()
{
cout<<"\n Id:"<<facultyId;
cout<<"\n Name:"<<facultyName;
cout<<"\n FacultyType: Guest";
}
};
void main()
{
float sal;
Faculty *pFaculty;
RegularFaculty rFaculty(1,"Ram");
GuestFaculty gFaculty(2,"Shyam");
clrscr();
rFaculty.setSalaryParameters(1500,550.65,250.5,120);
//Assigning the address of child class object into parent class pointer
pFaculty=&rFaculty;
//Invocation of calculateSalary() function with parent class pointer
sal=pFaculty->calculateSalary();
//Invocation of showDetails() function with parent class pointer
pFaculty->showDetails();
cout<<"\n Salary:"<<sal<<endl;
gFaculty.setSalaryParameters(20,150.50);
//Assigning the address of child class object into parent class pointer
pFaculty=&gFaculty;
//Invocation of calculateSalary() function with parent class pointer
sal=pFaculty->calculateSalary();
//Invocation of showDetails() function with parent class pointer
pFaculty->showDetails();
cout<<"\n Salary:"<<sal;
getch();
}
80
Output: Polymorphism and
Virtual Function
Id:1
Name:Ram
FacultyType: Regular
Salary:2181.149902
Id:2
Name:Shyam
FacultyType: Guest
Salary:3010
Explanation
Here in this example the class „Faculty‟ is an abstract class as it is having two pure virtual
functions named calculateSalary and showDetails. The implementation of these pure
virtual functions is provided by the concrete subclasses of the class Faculty namely the
RegularFaculty and GuestFaculty.
In the main function we do have objects of the two concrete subclasses and we assign the
address of these objects in the pointer variable of super class type i.e. Faculty (as we
cannot have direct objects of base class but we can have pointer to the abstract class type
that can contain the references to the objects of its concrete child class objects) and when
the functions are invoked by this pointer variable, the invocation or calling of function is
bound with the exact function definition with the help of the type of reference that the
pointer variable is containing. When it contains the reference of object of RegularFaculty
class then the calcuateSalary and showDetails of RegularFaculty class are invoked and
when it contains the reference of object of GuestFaculty class then the calcuateSalary and
showDetails of GuestFaculty class are invoked and this binding is delayed upto the run
time that‟s why it is termed as late binding or dynamic binding.
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
81
Inheritance and 3) Explain the pointers to object with the help of an example.
Polymorphism in C + +
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………………
5) Explain briefly the importance of pure virtual function in the software development
paradigm.
…………………………………………………………………………………………
…………………………………………………………………………………………
…………………………………………………………………………………
a) friend function
b) virtual function
c) operator overloading
d) function overloading
a) overloading.
b) overriding.
c) static binding.
d) dynamic binding.
82
iv) A virtual class is the same as Polymorphism and
Virtual Function
a) an abstract class
c) a base class
a) has no body
b) returns nothing
3.6 SUMMARY
Polymorphism simply defines the concept of one name having more than multiple forms.
It has two types of time compile time and run time. In compile time, an object is bound to
its function call at compile time. In run time polymorphism, an appropriate member
function is selected while the program is running. C++ supports the run time
polymorphism with the help of virtual function by using the concept of dynamic binding.
Dynamic binding requires use of pointers to objects. Pointers to objects of a base class
type are compatible with pointers to objects of a derived class. Run time polymorphism is
achieved only when a virtual function is accessed through a pointer to the base class. If a
virtual function is defined in the base class, it need not be necessarily redefined in the
derived class. Such virtual functions (equated to zero) are called pure virtual functions. A
class containing such pure function is called an abstract class.
83
Inheritance and Polymorphism is the ability to use an operator or function in different ways. Poly
Polymorphism in C + + implies multiple that signify the many uses of these operators and methods. A
single function usage or an operator functioning in many ways can be called
polymorphism. Polymorphism refers to codes, operations or objects that behave
differently in different contexts. Polymorphism plays an important role in
allowing objects having different internal structures to share the same external
interface. Polymorphism is two type, compile time polymorphism (operator &
function overloading) and run-time polymorphism (virtual function)
3) By pointers you can access the class members. Pointer can also point to object
created by a class. Consider the following statement:
element el;
Where element is a class and el is an object of that class. IN similar way
we can define a pointer el_pointer of type element as follows:
Element *el_pointer;
Pointers to objects are useful in crteating objects at run time. Let we explain it
more broadly with the help of an example.
#include <iostream.h>
Class element
{
int id;
float price;
public:
void input(int p, int q)
{
id=p;
price=q;
}
Void display(void)
{
Cout<< “ID :” << id<< “\n”;
Cout<< “PRICE :” << price<< “\n”;
}
};
{
int *a = new element[limit];
int *b = a;
int m, i;
float n;
for(i=0; i<limit; i++)
{
cout<< “Input ID and price of element” <<i+1;
cin >> m >> n;
a->input(m, n);
a++;
}
for(i=0; i<limit; i++)
{
cout<< “ELEMENT” << i+1<< “\n”;
b-> display();
b++;
}
}
Output:
ELEMENT 1
ID : 40
PRICE : 342.25
ELEMENT 2
ID : 11
PRICE : 250.50
ELEMENT 3
ID : 101
PRICE : 500
85
Inheritance and Explanation
Polymorphism in C + +
In above program we created space dynamically for three objects of equal size.
The statement
4) Through Look up tables added by the compiler to every class image. This also
leads to performance penalty.
5) Its 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 seldom used for
performing any task. It only serve as a placeholder. Such functions are called „do-
nothing‟ functions.
I-(B)
II-(A)
III-(D)
IV-(D)
V-(C)
VI-(D)
1) The C++ Programming Language, Bjarne Stroustroup, 3rd edition, Addison Wesley,
1997
2) C++: The Complete Reference, H. Shildt, 4th edition, TMH, New Delhi, 2004
3) Mastering C++, K. R. Venugopal, Rajkumar and T. Ravishankar, TMH, New Delhi,
2004
4) Object-Oriented Programming with C++, E. Balagurusamy, 2nd edition, TMH, New
Delhi, 2001
5) www.learncpp.com/cpp-tutorial
6) http://www.bogotobogo.com/cplusplus
7) http://www.gamespp.com/c/introductionToCppMetrowerksLesson11.html
86
Streams and Files
UNIT 1 STREAMS AND FILES
Structure Page Nos.
1.0 Introduction 5
1.1 Objectives 5
1.2 C++ Streams and Stream Classes 6
1.3 Unformatted I/O 8
1.4 Formatting Outputs 12
1.5 File Stream Operations 19
1.6 File Pointers and Operations 23
1.7 Summary 26
1.8 Answers to Check Your Progress 26
1.9 Further Readings 27
1.0 INTRODUCTION
In the previous blocks, we have discussed about the basic approach of object oriented
programming and its important themes such as classes, inheritance, overloading,
polymorphism and virtual functions. You might have seen a number of programming
examples where you used cin and cout with operators >> and << for the input and
output operations. We have, however, not taken up the issue of input and output to
C++ programs formally. This was deliberately deferred to this point since I/O
functions in C++ makes use of features like classes, derived classes and virtual
functions. As we have already covered these topics, this unit builds further upon the
preliminary introduction of I/O statements in C++ programs.
Through this unit, we aim to present a systematic and formal description of input and
output mechanisms employed by C++ programs. C++ provides a rich set I/O functions
and operations through the concept of streams and stream classes to implement I/O
operations: both console and disk. The C++ I/O system contains a hierarchy of classes
(known as stream classes) that are used for reading and writing by programs. Like
many popular high level languages C++ supports two types of I/O: unformatted and
formatted. While unformatted I/O uses functions like put(), get(), getline(), write();
formatted I/O makes use of manipulators and user-defined functions in addition to ios
class functions and flags. We have also described the file stream operations and use of
buffer and pointers for manipulating files.
1.1 OBJECTIVES
5
Advanced Features of C ++
1.2 C++ STREAMS AND STREAM CLASSES
In C++ I/O occurs in streams, which are sequence of bytes. A stream acts as an
interface between the program and the I/O device and can acts either as a source from
which the input data can be obtained or as a destination to which the output data may
be sent. In input operations, thy bytes flow from a device (e.g. a keyboard, a disk
drive, a network connection, etc.) to main memory. In output operations bytes flow
from main memory to a device (e.g., display monitor, a printer, a disk drive, a network
connection, etc.). The stream that acts as a source is called input stream whereas the
stream acting as destination is called output stream. The figure below illustrates the
flow of data while using streams”
Input stream
Input Extraction
device from input
stream
Program
Insertion
Output stream into
Output output
Device stream
Though a program can take input and write output to a variety of devices (each of
which may be quite different), the C++ streams provides a common interface for input
and output operations irrespective of the device used. The bytes in the stream could
represent characters, raw data, an image, video, speech or any other information that
an application may require. It is the application (user program) that associates
meaning with bytes.
In the past, the C++ used streams (often termed as classic streams) to enable input and
output of characters. Since a character usually occupies one byte, it can represent only
a limited set of characters (such as those in ASCII character set). Many languages
however use alphabets that contain more alphabets than a single-byte character can
represent. Hence C++ now includes the standard stream library that allows performing
I/O operations with new character encoding systems such as Unicode. As we will
shortly see, C++ now contains several pre-defined streams (e.g., cin, cout, cerr, etc.)
that are automatically opened when a program begins its execution.
The C++ I/O system contains a hierarchy of classes which are used to define various
streams to manage both console and disk I/O operations. These classes are called
stream classes. The figure 1.2 given below shows the hierarchy of the stream classes
used for input and output operations with the console. The stream class hierarchy for
disk I/O is described in section 1.5
6
Streams and Files
ios
pointer
istream streambuf ostream
input output
iostream
The ios class is the base class for iostream (input stream) and ostream (output stream) The standard
which are in turn base classes for iostream class (input/ output stream). The ios class streams- cin,
is declared as the virtual base class so that only one copy of its member are inherited cou, cerr and
by the iostream. The ios class thus provides the basic support for formatted and clog- are also
unformatted I/O operations. The class istream provides facilities for formatted and defined in
unformatted input while the class ostream provides facilities for formatted output. The <iostream>
class iostream provides facilities for handling both input and output operations. All header file.
these classes are declared in the header file iostream. Most of the C++ programs
include the <iostream> header file, which declares all the basic services required for
all stream-I/O operations. Relevant classes for formatted I/O and disk I/O are declared
in <iomanip> and <fstream> header files respectively (discussed in later part of the
chapter).
The cin, cout, cerr and clog objects correspond to the standard input stream, the
standard output stream, the unbuffered standard error stream and the buffered standard
error stream, respectively. These are predefined objects which are by default
connected to certain devices. The extraction (>>) and insertion (<<) operators define
the direction of data flow. For example, the first statement below is used to read a
value from keyboard and pass it to the variable „num‟; whereas the second statement
the value of variable „avg‟ is written to the monitor (the standard output device).
cin >> num; // reading the value of num from keyboard, data flow denotes input
cout << avg; // displaying the value of avg on monitor, data flow denotes output
The number of characters read is determined by the type of variable. For example, if
we type 3456X as the value for number, only „3456‟ is assigned to the variable „num‟
and „X‟ remains in the stream. Hence the operator >> reads the data character by
character and assigns it to the indicated variable, unless a whitespace or a character
that does not match with the destination variable type is encountered. At this point,
extraction from stream is terminated and the remaining characters are consumed by
subsequent cin statements. The nature of extraction (>>) and insertion (<<) operators
therefore allows use of following kinds of cin and cout statements.
cin >> var1 >> var2 >> var3 >> ….>> varN
cout << var1 << var2 << var3 <<….<< varN
The variables in first statement may be variables of any type. The variables in second
statement may be variables or constants of any type.
7
Advanced Features of C ++ The predefined object cerr is an ostream instance and is connected by default to the
standard error device (usually the monitor). Outputs to object cerr are unbuffered,
implying that each stream insertion to cerr causes its output to appear immediately.
(This is appropriate since it allows notifying a user promptly about errors). The
predefined object clog is an instance of the ostream class also connected to the
standard error device. However, outputs to clog are buffered. This means that each
insertion to clog causes its ouput to be held in a buffer until the buffer is filled or it is
flushed.
The ios class provides the basic support for two kinds of input and output: formatted
and unformatted. The class istream provides the facilities for formatted and
unformatted input operations whereas the ostream class provides the facilities for
formatted and unformatted output. The istream class declares input functions such as
get(), getline(), read() etc., in addition to inheriting the properties of ios class. It also
contains overloaded extraction operator >>. The ostream class declares output
functions such as put() and write(), in addition to inheriting properties of ios class. It
also contains overloaded insertion operator <<. The iostream class inherits the
properties of ios, istream and ostream classes through multiple inheritance and hence
contains all input and output functions. This is the reason why we include the
iostream class only in our programs.
We have already seen use of cin and cout objects along with overloaded operators >>
and << for input and output operations, in previous blocks. C++ provides many other
functions for input and output operations. We will therefore briefly review their use
through some examples. Functions put(), get(), getline(), putline(), read() and write()
are other commonly used functions for unformatted I/O. The following sections
describe, with appropriate examples, the use of these functions for unformatted I/O
operations.
As stated in section 1.2.2 earlier, the overloaded extraction (>>) and insertion (<<)
operators are used with cin and cout objects for stream input and output operations,
respectively. The general syntax of its usage is as:
where, variable 1 to N are any valid variable types in C++ and items 1 to N are any
valid variable or constants in C++. C++ takes care of reading only appropriate number
and type of variables (corresponding to the type of input variable) from the stream.
The insertion operator puts the unformatted output into the output stream which is
then displayed on the monitor. The use of these operators with cin and cout is further
illustrated through following programming example:
# include <iostream.h>
int main()
{
float num1, num2, num3, sum, avg;
cout << “Enter the three numbers:”;
cin >> num1 >> num2 >> num3;
8
sum = num1 + num2 +num3; Streams and Files
avg = sum / 3;
cout << “Sum of the numbers =” << sum;
cout << “Average of the numbers =” << avg;
return (0);
}
This program first displays a prompt for entering three numbers by using cout and
then reads three numbers entered from the keyboard by using cin. The program then
computes sum and average of the numbers and their values are displayed on the
monitor through cout statements.
1.3.2 Using member functions get (), put (), getline (), ignore (), putback
() and peek ()
Unformatted input and output operations can also be carried out using various
member functions of cin and cout objects provided by the istream and ostream classes.
The functions get() and put() can be used to handle single character input and output
operations, respectively. The general usage syntax of get is as follows:
get (char *)
get (void)
The get (char *) function assigns the character read from the keyboard to its argument.
Unlike extraction operator >>, it can read blanks spaces and newline characters. [Note
that >> operator simply skips the blank spaces and newline character while extracting
characters from the input stream.] The get (void) simply returns the character read
from the keyboard without assigning it to any variable.
The put () member function can be used to write one character to the monitor. It may
take a character constant or variable as argument. The put () function can also take an
integer value as input (for ex. 65), however rather than displaying the integer value it
displays its ASCII equivalent character, “A” for 65. It can be put in a loop to output a
line of text character by character.
The program below illustrates use of get () and put () functions. The program reads an
input text and displays it on the output screen. It also counts the number of characters
and displays it on output screen. For example, if the user enters “I love
Programming”, the output screen displays the entered text “I love Programming” and
“Number of characters = 18” on separate lines on the output screen.
# include <iostream.h>
int main()
{
int count = 0;
char c;
cout << “Enter some text:” ;
cin.get(c);
while (c!= „\n‟)
{
cout.put(c);
count++;
cin.get(c);
9
Advanced Features of C ++ }
cout << “\n Number of characters = ” << count << “\n”;
return (0);
}
The functions get() and put() can handle a single character at a time. Many practical
situations however require us to read and display more than a single character, for
example a line of text. The getline () member function can be used for this purpose.
The general syntax of getline () function is as follows:
This function reads the character input into the variable. The reading is terminated as
soon as size-1 characters are read or „\n‟ is encountered. The delimiter character „\n‟
however is discarded and not saved in the variable. For example, for the code
segment:
char name [20];
cin.getline (name, 20)
if the text entered from the keyboard is “IGNOU <press RETURN>”, it stores the line
as “IGNOU” in the variable name. However, if we enter “Object Oriented
Programming <press RETURN>”, it stores only first 19 characters in the variable
name as “Object Oriented Pro”. Similar to get (), getline () can also read blank spaces.
The ignore () member function reads and discards a designated number of characters
(default = 1) or terminates upon encountering delimiter EOF. The putback () member
function places the character just read by get () back into the stream. The peek ()
member function returns the next character from an input stream but does not remove
the character from the stream.
The other member functions used to perform unformatted I/O include read (), write ()
and gcount (). The member function read () inputs bytes to a character array in
memory; member function write () write output bytes from character array; and
member function gcount () reports the number of characters read by the last input
operation. The general syntax of read () and write () functions are as follows:
The member function read () inputs a designated number of characters (max. = size)
into a character array variable. It is different from getline () in terms of usage of array
variable. The member function write () outputs the characters in the character array
variable on the output screen. It however does not stops at delimiter (null char)
boundary and continues to display characters even beyond the line (when size > length
of array). The gcount () member function is used to report the number of characters
actually read by the last read () operation. The program below demonstrates the use of
read () and write () member functions. If the string entered from the keyboard is “I
love Programming”, it stores only “I love” in the input array variable. Function gcount
() returns the value as 6.
# include <iostream.h>
int main()
{
char buffer [80];
cout << “Enter a line of text \n” ;
10
cin.read(buffer, 20); Streams and Files
cout.write (buffer, cin.gcount());
return (0);
}
3) For each of the following, write a single statement that performs the indicated task:
a) Output the string “Enter your name”.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
b) Use istream member function read to input 50 characters into char array line.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
c) Get the value of next character to input without extracting it from the stream.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
11
Advanced Features of C ++ d) Use the istream member function gcount to determine the number of
characters input into character array line by the last call to read and output
that number of characters using write.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
C++ provides a number of features that can be used display the outputs in a specified
manner (formatted output). These features can be broadly categorized into following
three types:
The ios class contains a large number of member functions that are used to format
outputs in variety of ways. Most of the stream manipulators provide roughly the same
features as that of ios class formatting functions, though they are at times convenient
to use than their counterpart ios class functions. C++ allows users to design their own
stream manipulators as well.
The ios class contains functions for defining field width, setting precision, filling and
padding, displaying sign of numerical values etc. The Table 1.1 shows the lists of
important ios class functions for formatting I/O:
Function Purpose
width () To specify field size for displaying an output value
To specify the number of digits to be displayed after the
precision ()
decimal sign
To specify a character that fills the unused portion of an
fill ()
output data filed
To specify format flags such as left-justify, right-justify
setf()
etc.
unsetf () To clear/ reset defined flags
The width () function is used to define the width of a field required for displaying an
output item. It is invoked by cout object as follows:
cout.width (w)
where w is the number of columns (field width). The output value is printed in a field
of w characters wide at right end. This can specify field width for displaying only one
12
output value (the one that immediately follows it). The following statements Streams and Files
demonstrate the use of width ():
cout.width (5);
cout << 123 << “\n”;
cout.width (5);
cout << 35;
However, C++ never truncates the display value if the specified width is smaller than
required. In turn it expands field width to accommodate the output value. This feature
can be used to print large number of numerical values in a predetermined manner (a
situation that is often encountered in accounting and other commercial applications).
Setting Precision
In C++ the floating point numbers are by default printed with six digits after the
decimal point. We can however change the number of digits to be displayed after the
decimal sign by using precision () function. The syntax is as follows:
cout.precision (d)
where d is the number of digits to be displayed to the right of decimal point. For
example, the statements:
cout.precision (3);
cout << sqrt (2) << “\n”;
cout << 3.14159 << “\n”;
cout << 1.50009 << “\n”;
1.141 (truncated)
3.142 (rounded to nearest cent)
1.5 (no trailing zeros)
The precision () function is different from width () in its effect, as the effect of
precision once set continues in all subsequent statements until it is reset. The
precision () function can be used with width () function as illustrated in following
example:
cout.precision(2);
cout.width(5);
cout << 5.6705;
5 6 7
The statements print the output value with a precision of 2 digits after the decimal
place within a field width of 5.
13
Advanced Features of C ++ Filling and Padding
The fill () function is used to fill unused portion of a display field with a desired
character rather than the blank spaces printed by default. The syntax is:
cout.fill (ch);
where, ch is the character to be used to fill the unused portions of a display field. For
example, the following statement:
cout.fill („*‟);
cout.width(10);
cout << 1234 << “\n”;
* * * * * * 1 2 3 4
This kind of padding is very useful for institutions like banks which use it in their
financial instruments (demand drafts etc) so that no one can change the figures. The
fill () function also stays in effect till it is reset.
The setf () is another important ios class function that is commonly used for
formatting outputs. The general syntax of setf () is as follows:
or
cout.setf (arg)
Here the arg1 is one of the formatting flags defined in ios class and arg2 is an ios
constant that specifies the group to which the formatting flag belongs. These flags and
bit-fields can be used for changing the alignment of display (left, right and center
justify), displaying numbers in desired notation (scientific or fixed point), displaying
numbers in different base systems (decimal, octal and hexadecimal). The setf ()
function can be used with single argument as well. In that case only flags are used
without bit-fields.
The flags, bit-fields and their format actions are described in Table 1.2
14
The ios flags that do not have bit-fields are described in Table 1.3: Streams and Files
Flag Purpose
ios::showbase Use base indicator on output
ios::showpos Print „+‟ before positive numbers
ios::showpoint Show trailing decimal point and zeros
ios::uppercase Use uppercase letters for hex output
ios::skipus Skip blank space on input
ios::unitbuf Flush all streams after insertion
ios::stdio Flush stdout and stderr after insertion
These flags are used with setf () to produce desired outputs. The following example
code segments demonstrate use of some of these flags:
cout.fill („*‟);
cout.setf (ios::left, ios::adjustfield);
cout.width (10);
cout << “OUTPUT 1” << “\n”;
O U T P U T 1 * *
cout.fill („#‟);
cout.precision (2);
cout.setf (ios::internal, ios::adjustfield);
cout.setf (ios::scientific, ios::floatfield);
cout.width (12);
cout << -32.234 << “\n”;
will produce the following output: (Sign is left justified and value is right-justified)
- # # 3 2 . 2 3 e + 0 1
cout.setf (ios::showpoint);
cout.setf (ios::showpos);
cout.precision (3);
cout.setf (ios::fixed, ios::floatfield);
cout.setf (ios::internal, ios::adjustfield);
cout.width (10);
cout << 123.4 << “\n”;
will produce the following output: (output with sign and trailing zeros)
+ 1 2 3 . 4 0 0
15
Advanced Features of C ++ 1.4.2 Stream Manipulators
C++ defines a number of functions called manipulators in header file iomanip that
can be used to manipulate the output formats. Most of these manipulators are quite
similar in function to the ios class functions and flags, though at times they are more
convenient to use. The best thing is that two or more manipulators can be used in a
single statement as:
cout << manip1 << manip2 << manip3 << manip4 << item;
Some of the commonly used stream manipulators and their effect is listed in
Table 1.4.
Table1.4: List of Used Stream Manipulators
Manipulator Purpose
setw (int w) Set the field width to w.
setprecision (int d) Set the floating point precision to d.
setfill (int c) Set the fill character to c.
setiosflags (long f) Set the format flag f.
resetiosflags (long f) Clear the format flag f.
endif Insert a new line and flush stream.
You can easily notice that in terms of functionality, setw () has similar effect to ios
function width (), setprecision () to ios function precision (), setfill () to ios function
fill (), setiosflag () to ios function setf (), resetiosflags () to ios function unsetf () and
endif to “\n”. There is however a major difference between implementation of ios
functions and stream manipulators. The ios member functions return the previous
format state which can be used later but the manipulator does not return to previous
format state.
Some example code segments illustrating use of various stream manipulators and their
outputs are given below:
will produce the following output: (12345 is displayed right-justified in a field width
of 10)
1 2 3 4 5
will produce the following output: (Sign is left justified and value is right-justified)
1 . 2 3
3 . 1 4 1 5
16
1.4.3 User Defined Stream Manipulators Streams and Files
C++ allows users to design their own customized stream manipulators. These user-
defined manipulators may be non-parameterized or parameterized ones. The general
syntax for creating a user-defined stream manipulator without any argument is as
follows:
# include <iostream.h>
#include <iomanip.h>
ostream & currency(ostream & output)
{
output << “INR”;
return (output);
}
ostream & form(ostream & output)
{
output.setf (ios::showpos);
output.setf (ios::showpoint);
output.fill („*‟);
output.precision (2);
output << setiosflags (ios::fixed) << setw (10);
return (output);
}
17
Advanced Features of C ++ int main()
{
cout << currency << form << 5465.4;
return (0);
}
Another example code which makes use of stream manipulators and other formatting
techniques is given below. This program creates two user-defined manipulators area
and volume, which are used to display output values in a specific manner. The value
of area is displayed with SQ.MTS unit and the volume is displayed with CUBIC MTS
unit.
# include <iostream.h>
#include <iomanip.h>
ostream & area(ostream & output)
{
output << “SQ.MTS”;
return (output);
}
ostream & volume(ostream & output)
{
output.precision (4);
output << setiosflags (ios::fixed) << setw (15);
output << “CUBIC MTS”
return (output);
}
int main()
{
cout << area << 3000;
cout<< volume << 9000;
return (0);
}
18
Streams and Files
3) For each of the following, show the output:
a) cout << setw (10) << setfill („$‟) << 10000;
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
b) cout << showbase << oct << 99 << endl << hex << 99;
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
4) For each of the following, write a single C++ statement that performs the desired
task.
a) Use a stream manipulator such that, when integer values are output, the integer
base for octal and hexadecimal values is displayed.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
b) Print the current precision setting, using a member function of object cout.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
d) Print 1.92, 1.925 and 1.9258 separated by tabs and with 3 digits of precision,
using a stream manipulator.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
19
Advanced Features of C ++ 5) Create a user-defined manipulator showcurr that prints „#‟ sign before every
numerical value displayed.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
Many real world applications require reading and writing large number of data items.
Usually large volumes of data are stored as files on disk. Like many high level
programming languages, C++ also provides mechanism to read and write data items
from files. A C++ program can thus take input from a disk file and also write data to
it. C++ file handling mechanism is quite similar to console input-output operations. It
uses streams (called file streams) as an interface between programs and files. The
Figure 1.3 illustrates the use of file streams for input and output:
Disk
Output stream
The stream that supplies results
data to the program is file
called input stream and outfile
the one receiving data
from program for Program
writing to file is called
output stream. Input stream
data
file
infile
The Figure 1.3 shows a C++ program that reads data from one file and writes the
output to another file (named results). The input stream is connected to data file used
for input and output stream is connected to results file used for output. Programs can
do reading and writing on the same file as well.
The I/O system of C++ contains a set of classes that provide methods for reading and
writing from files. These classes are ifstream, ofstream and fstream. All these classes
are derived from fstream base class and also inherits features from iostream class. The
stream classes and their inheritance is shown in the Figure 1.4:
20
Streams and Files
ios
iostream
fstream base
All these classes are declared in fstream and that is why this header file is included in
all programs doing file processing. The fstream base class provides operations
common to the file streams and contains open() and close() functions. It also serves as
base class for the other three file stream classes. The ifstream class provides functions
for input operations. This includes functions like get(), getline(), read(), seekg() etc.
The ofstream class provides functions for output operations and include functions like
put(), write() etc. The fstream class provides support for simultaneous input and
output operations. It also inherits all functions from istream and ostream classes
through iostream. The filebuf is used for setting the file buffers for read and write
operations. This is required since volume of data is read and written to files.
Every disk file has a name (usually a string of valid characters). In order to read data
from a file or to write data into it, we first need to open the file. This opened file has
to be then connected to input-output stream so that the corresponding program
becomes able read and write from it. A file stream can be defined using any of the
three classes ifstream, ofstream or fstream, depending upon the purpose of the file.
A file can be opened either by using the constructor function of the class or by
invoking member function open () of the class. In order to open file using constructor
function, we may use statements of the form:
Here, first statement opens a file called data and attaches it to the stream infile. This
file can then be used for input operations. The second statement opens a file called
results and attaches it to stream outfile. This file can only be used for output
operations. Once the infile and outfile streams are created and connected to
corresponding files, statements of the form:
21
Advanced Features of C ++ outfile << “Sum”;
outfile << “avg”;
infile >> num;
infile >> name;
can be used to write data items to the output file results and to read data from input
file data. After completing the input-output operations, the file may be closed by
closing the corresponding stream. For example:
outfile.close();
infile.close();
Even if we fail to explicitly close a file, it gets closed automatically when the program
terminates (and hence the corresponding stream expires). Nevertheless it is a good
practice to close the open files once they are no longer required.
A file can also be opened using open (). The general syntax of open () is as follows:
For example, to open a file data for input, we may use the statements:
ifstream infile;
infile.open(“data”);
Now, the stream infile can be used for reading data form the file “data” in a similar
manner as that of console I/O. After the file‟s use is complete, it should be closed by
closing the corresponding (by invoking close() function).
C++ allows the files to be opened in different modes. Hence, the open() function can
specify the mode of opening as well. The statement invoking open can be written as:
stream-object.open(“filename”, mode);
The mode argument specifies the purpose for which the file is opened. The file mode
parameter is defined in ios class and can take any of the following values:
The function open() contains default values for these modes and hence even if the
mode is not specified, the file is opened with default mode.
One must also be careful in reading from an input file so as to ensure that no read
attempt is made once the file end is reached. We will see the use of EOF() member
function of ios class for this purpose in next section.
An example program demonstrating how we can read from a disk file and write the
results to the disk file is given below:
22
Streams and Files
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
int main()
{
const int SIZE = 80;
char line [SIZE];
ifstream infile;
ofstream outfile;
infile.open(“namelist”);
outfile.open(“results”);
while(infile.eof()!=0)
{
infile.getline(line, SIZE);
outfile << line;
}
return (0);
}
This program opens a file “namelist” for reading and “results” for writing. Then it
continues to read the entire contents of file “namelist” and copies it to the file
“results”. The getline() stream member function is used for reading and the output
content is simply directed to the stream “outfile” for writing it to the file “results”.
The reading (and subsequent copying) continues till the end of file “namelist” is
reached. If one needs to display the contents while copying, a statement cout << line;
may be added. This program can be made meaningful, if we copy the sorted namelist
to the “results” file. This can be done by first sorting the contents of “namelist” file
(temporarily storing it in an array of strings) and then writing the sorted values.
We can manipulate these file pointers by invoking member functions of the file stream
class. The commonly used functions for this purpose include seekg(), seekp(), tellg(),
tellp() etc. The seekg() function moves the input (get) pointer to a specified location.
The seekp() function moves to output (put) pointer to a specified location. The tellg()
and tellp() functions tell the current position of get and put pointers, respectively. The
general syntax for using seekg() and seekp() is given below:
seekg(offset, refposition);
seekp(offset, refposition);
Where, offset represents the number of bytes, the file pointer is to be moved from the
location specified by the parameter refposition. The refposition may take one of the
three positions defined in the ios class:
23
Advanced Features of C ++ ios::beg – start of the file
ios::cur – current position of the pointer
ios::end – end of file.
The seekg() function moves the get pointer whereas the seekp() function moves the
put pointer as per the parameters specified in the statement.
Reading and writing operations in files are made simpler by C++ by providing some
member functions in the file stream class. The functions put() and get() are used for
handling a single character at a time. Functions read() and write() are designed to
handle blocks of binary data. We also have functions like getline().
Two programming examples demonstrating use of put() – get() and read() - write()
are given below:
#include <iostream.h>
#include <fstream.h>
#include <string.h>
int main()
{
char name [80];
cin >> name;
int len = strlen(name);
fstream file;
file.open(“text”, ios::in I ios:out);
for (int i =0; I < len; i++)
file.put(name[i]);
file.seekg(0);
char c;
while (file)
{
file.get(ch);
cout << ch;
}
return (0);
}
The program above reads a string and puts it character by character in a file called
“text”. This file is opened for both reading and writing. Then the program goes to read
the contents written in the file one character at a time by using get() function. Before
doing that, the file pointer is set to the beginning of the file.
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
const char * filename = “BINARY”;
int main()
{
int num[5] = {12, 23, 34, 45, 56};
ofstream outfile;
outfile.open(filename);
outfile.write((char *) & num, sizeof(num));
outfile.close();
for (int i=0; i<5; i++)
24
num[i]= 0; Streams and Files
ifstream infile;
infile.open(filename);
infile.read((char *) & num, sizeof(num));
for (i=0; i<5; i++)
{
cout.setf(ios::showpos);
cout << setw(5) << name[i];
}
infile.close();
return (0);
}
The program above reads an integer array and then writes its contents to a binary file
using write(). The file is then opened again this time for reading and the contents
written in the file are read and displayed on the monitor. The read() function is used
for reading.
a) The file opening mode ios::ate positions the file pointer at end-of-file on
opening.
b) The function tellp() can be used to detect end of a file.
c) A C++ program can do reading and writing on the same file.
3) For each of the following, write a single statement that performs the desired task:
a) To open a file “text” in append mode and connect a stream infile to it.
…………………………………………………………………………………
…………………………………………………………………………………
…………………………………………………………………………………
25
Advanced Features of C ++ c) To read an entire line of text of size characters from a file connected to f1 file
stream into a variable line.
…………………………………………………………………………………
…………………………………………………………………………………
…………………………………………………………………………………
1.7 SUMMARY
This unit has introduced you to the concept of streams and how they are used for
console and disk I/O operations by a C++ program. The stream concept provides in
C++ the flexibility of using the same mechanism for input-output operations from
different devices. A stream is a sequence of bytes and it serves as both source and
destination for an I/O data. C++ provides a hierarchy of stream classes that support
different functions for managing I/O devices from console and disk. There are certain
streams which are by default connected to standard devices. The console I/O
operations may be unformatted or formatted. We use separate functions for both
purposes. Output can be produced in a desired manner (formatted) by using one of the
three mechanisms: ios class functions and flags, stream manipulators and user-defined
stream manipulator functions. C++ also provides a large number of functions that can
be used to read and write data from disk files. Files need to be opened and closed for
I/O operations. Files may be opened in different modes depending upon the kind of
operation to be performed. C++ provide different functions for manipulating file
pointers and hence deciding where to read and write the data.
3. a) $$$$$10000
b) o143
oX63
c) 10000
+10000
5.
ostream & showcurr (ostream & output)
{
output << “#”;
return output;
}
2. a) True
b) False, It is actually eof() function.
c) True
3. a) ifstream infile; infile.open(“text”, “ios::app”);
b) file.get(ch);
c) f1.getline(line, size);
d) file.eof()
27
Advanced Features of C ++
UNIT 2 TEMPLATES AND STANDARD
TEMPLATE LIBRARY
Structure Page Nos.
2.0 Introduction 28
2.1 Objectives 28
2.2 Class Templates 29
2.3 Function Templates 31
2.4 Use of Templates 34
2.5 The Standard Template Library 35
2.6 Summary 43
2.7 Answers to Check Your Progress 44
2.8 Further Readings 45
2.0 INTRODUCTION
In the previous units, we have discussed about different features and functionalities of
C++ programming language for object oriented programming. C++ being an object
oriented language also supports reuse. Templates are one of the most prominent
examples of reuse concept in action. This feature has been added to the C++ design
recently. It supports the idea of generic programming by providing facility for
defining generic classes and functions. Thus a template class provides a broad
architecture which can be used to create a number of new classes. Similarly, a
template function can be used to write various versions of the function. This chapter
describes the template mechanism in C++ based on the paper titled „Parameterized
types for C++‟ by Bjarne Stroustup (creator of C++) published in Proceedings of the
USENIX C++ Conference held in Denver, Colorado in October 1988.
This unit aims to explain the basic idea and motivation for templates. The unit
explains in detail (with appropriate examples) the design and use of both Class and
Function Templates. It then proceeds further to explain the use of templates and how
they are related to the concepts of overloading and inheritance. We then discuss the
structure and utility of the Standard Template Library in C++. Further, the unit
describes the three core components of the Standard Template Library: containers,
algorithms and iterators. These features are used in many real world application
designs. The unit concludes with a summary of the Template and Standard template
Library framework followed by model answers to assist you in check your progress
exercises.
2.1 OBJECTIVES
28
appreciate the use of the Standard template Library in real world application Templates and Standard
designs. Template Library
You might have got at least an idea from the introduction that templates are like
stencils out of which we trace shapes. Function-template specializations and class-
template specializations are like the separate tracings that all have the same shape, but
could, for example, be drawn in different colours. In other words, a template may be
considered as a kind of macro. When the actual object of that type is to be defined, the
template definition is substituted with required data type. For example, if we define a
template Array of elements, then this same generic definition may be used to create
Array of integers or of characters or float quantities. We need not make a new class
definition every time. We define a generic class with a parameter that s replaced by a
particular data type at the time of actual use of that class. This is the reason template
classes are also known as parameterized classes.
Designing a template class thus involves a simple process of creating a generic class
with an anonymous type. The general syntax for defining a class template is:
For example, consider the following template definition for a Vector class:
template<class T>
class vector
{
T * v; // the vector is of type T
int size;
Public:
vector(int m)
{
v = new T [size = m];
for (int i=0; i<size; i++)
v[i]=0;
}
vector (T * a)
{
for(int i=0; i<size; i++)
v[i] = a[i];
}
T operator * (vector &x)
{
T sum = 0;
for(int i=0; i<size; i++)
sum += this->v[i] *x- v[i];
return (sum);
}
};
29
Advanced Features of C ++ This definition creates a template class vector of type T with variables, constructors
and „*‟ operator. This class definition is similar to an ordinary class definition except
that of the use of template<class T> and use of type T inside the class definition. The
template<class T> tells the compiler that it is a template class with parameter T
instead of a normal class definition. The declaration thus creates a parameterized class
with T as the parameter, which can be substituted with any valid data type. This can
be done by a statement of the following form:
For example, following statements create classes of 20 element integer and float
vectors, respectively.
This task of creating an actual object from a template class is instantiation. Here we
have written only one class definition for class vector but we have been able to create
more than one actual instantiations of the template class vector.
A class template can also be created by using multiple generic data types as
arguments. The general syntax for such definition would be as below:
A simple program demonstrating the declaration and use of class templates is given
below. Please note that this program instantiates two objects from the class template
Example. The program first declares a template class Example with two arguments
and then declares a constructor to instantiate the class. The main function creates two
objects test1 and test2 of different types and their values are then displayed using the
function show.
#include <iostream>
30
Templates and Standard
int main() Template Library
{
Example <float, int> test1 (3.45, 345);
Example <int, char> test2 (100, „m‟);
test1.show();
test2.show();
return(0);
};
The program creates two template classes test1 and test2 using the template class
Example. The test1 class has two parameter values “3.45” and “345”, whereas test2
class has two parameter values “100” and character “m”. For creating test1 object,
arguments are float and integer respectively, whereas in case of test2 object they are
integer and character. The values displayed in invocation of show() function from
main will be “3.45 and 345” for test1 and “100 and m” for test2 object.
Function templates are similar to class templates in the sense that they create a generic
function type. This generic function can then be used to create a family of functions
that may take different arguments. A function template can be defined as follows:
The swap() function can now be invoked like any ordinary function. Any call to
swap() with input arguments will exchange the values contained in those arguments.
Hence if a and b are integer variables and p and q are float variables; we may invoke
swap() function as swap(a,b) and swap(p,q), respectively. The same function
definition can be used to swap values of two variables of different types.
As we have discussed earlier, we can define class templates with multiple arguments,
we can also define function templates with multiple arguments. This can be done
through a declaration of the form:
31
Advanced Features of C ++ template <class T1, class T2, ……..>
return_type function_name (arguments of type T1, T2,….)
{
………..
……….body of function
………..
};
The function and class templates can be used to write programs which work correctly
on different types of data. For example, we can write the following program to sort a
list in desired order using function templates swap() and bsort() as shown in the
program below:
#include <iostream>
template<class T>
void bsort(T a[], int n)
{
for (int i=0; i<n-1; i++)
for (int j=n-1; i<j; j--)
if (a[j] < a[j-1])
swap(a[j], a[j-1]);
}
template <class X>
void swap( X &a, X &b)
{
X temp =a;
a = b;
b = temp;
}
int main()
{
int x[5] = {10,50,30,60,40};
float y[5] = {3.2, 71.5, 17.3, 45.9, 92.7};
bsort(x,5);
bsort(y,5);
This program uses two function templates swap() and bsort(). The function template
swap() is invoked within the bsort() function and is hence said to be nested in it. This
program can be used to sort different types of lists without the need of modifying the
program. The program will produce following output:
Sorted X-Array: 10 30 40 50 60
32
Sorted Y-Array: 3.2 17.3 45.9 71.5 92.7 Templates and Standard
Template Library
A template function may also be overloaded in a manner similar to other functions. In
fact, function templates and overloading are intimately related. All the function-
template specializations generated from a function template have the same name, so
the compiler uses overloading resolution to invoke the proper function. A function
template can be overloaded in several ways:
Whenever, the compiler has to perform the matching process to determine what
function to call, it achieves the overloading resolution as follows:
In case no match is found, the compiler generates an error. In case there are multiple
matches for the function call, the compiler considers the call to be ambiguous and the
compiler generates an error message. It would also be worth mentioning that no
automatic conversions are applied to arguments on the template functions.
33
Advanced Features of C ++ 4) Write appropriate statements to create a template class item that can instantiate
objects of at least following types: item name: shirt, measure: size (expressed as
characters „S‟, „M‟, „L‟ and „X‟) and item name: trouser, measure: size (expressed
as waist size of integers). The template class must also have a template function to
display the details of the items.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
The concept of class templates and function templates derives its motivation from the
principle of reuse. We have seen in earlier sections how templates allow us to create
generic data types and functions that can fit into various situations. Rather than
defining multiple classes and functions, we define a generic type and depending on
the kind of input data it may customize itself. Templates in this sense serve as a
blueprint for defining classes and functions. This not only eliminates code duplication
for handling different data types but also makes the program development easier and
more manageable. In the previous section, we saw an example of program for sorting
that can a sort lists of various types. We present below another example demonstrating
use of templates for solving a quadratic equation:
#include <iostream>
#include <iomanip>
#include <cmath>
template<class T>
void roots(T a, T b, T c)
{
T d = b*b - 4*a*c;
if (d==0)
{
cout << “R1 = R2 =” << -b/(2*a) << endl;
}
else if (d > 0)
{
cout << “Roots are real \n”;
float R = sqrt (d);
float R1 = (-b + R) / (2*a);
float R2 = (-b - R) / (2*a);
cout << “R1 =” << R1 << “and” ;
cout << “R2 =” << R2 << endl;
}
else
{
cout << “Roots are complex \n”;
float R1 = -b /(2*a);
float R2 = sqrt (-d) / (2*a);
cout << “Real part =” << R1 << endl;
cout << “Imaginary part =” <<R2 <<endl;
}
}
int main()
34
{ Templates and Standard
cout << “Integer coefficients \n”; Template Library
roots (1, -5, 6);
cout << “\n Float coefficients \n”;
roots (1.5, 3.6, 5.0);
return(0);
};
Integer coefficients
Roots are real
R1 = 3 and R2 = 2
Float coefficients
Roots are complex
Real part = -1.2
Imaginary part = 1.375985
As we can see, the program above can be used to compute roots of a quadratic
equation having different kinds of coefficients. It calculates roots for an equation
having integer coefficient and for another equation having float coefficients. The
templates have become so popular that now we have a rich library of predefined
templates in C++, known as the Standard Template Library. We will discuss the
contents and use of the standard template library in next section.
Object 2
Object 3
Iterator 3
Algorithm 3
Containers
Containers are objects that hold data. These container classes are defined as class
templates that can be customized to hold different kinds of data. The Figure 2.2
illustrates the three main types of container classes. The container classes contain
definitions for commonly used data structures such as vector, list, queue, stack, set,
map etc. Each container class also defines a set of functions that can be used to
manipulate its contents. The STL defines a number of containers which can be
grouped into mainly three types: sequence containers, associative containers and
derived containers. The derived containers are sometime also referred to as container
adapters.
Containers
The Table 2.1 lists some commonly used container classes available in the STL.
36
insertions and deletions at both access Templates and Standard
ends. Template Library
An associative container for storing
set <set> Bidirectional
unique sets. Allows fast lookup.
An associative container for storing
multiset <set> Bidirectional
non-unique sets.
An associative container for storing
map <map> Bidirectional
unique key-value pairs.
An associative container for storing
multimap key-value pairs that may use one-to- <map> Bidirectional
many mapping.
The sequence containers represent linear data structures such as vectors and linked
lists. The associative containers are non-linear container that typically store elements
in a key-value pair fashion and support fast lookup. The sequence containers and
associative containers are collectively referred to as First Class containers. Stacks and
Queues are actually constrained versions of these first class containers and that is why
often referred to as derived containers or container adapters. They enable a program to
view a sequential container in a constrained manner. Sometimes we also hear about
“near conatiners”, which are similar to first class containers but do not support all
functionalities of first class containers. Bitsets is one such example.
Hence, out of the various container classes listed in the table, vector, list and deque
are sequential containers. Set, multiset, map and multimap are associative containers.
Stack, queue and priority queue are derived containers.
Most STL containers provide similar functionality. Many generic operations, such as
member function size, therefore apply to all containers. A good number of operations
apply on subsets of container classes. Some of the common member functions that
apply to most of container classes are listed in the Table 2.2:
Member Functions
default constructor, copy constructor, destructor, empty, insert, size, operator=,
operator>, operator<, operator<=, operator>=, operator==, operator!=, swap
Functions found only in First class containers
max_size, begin, end, rbegin, rend, erase, clear.
Algorithms
Algorithms are functions that are used across a variety of container classes for
processing their contents. As we have just learnt that each container class provides
member functions for its basic operations, but STL further extends this by providing
some standard algorithms for manipulating different containers. The STL contains
approximately seventy standard algorithms to support more extended or complex
operations. Standard algorithms have another advantage that they allow working with
two different types of containers at the same time, unlike container member functions.
The STL implement these algorithms as standalone function templates that can be
customized to work with different kind of containers. Inserting, deleting, searching
and sorting are some of the examples.
Unlike member functions, the algorithms operate on containers indirectly through the
use of iterators. Many algorithms operate on sequences of elements defined by pair of
iterators- one pointing to the first element of the sequence and other pointing to one
37
Advanced Features of C ++ element past the last element. It is also possible to create new algorithms that operate
in a similar fashion to that of STL algorithms. Algorithms often return iterators that
indicate the results of algorithms (for example algorithm find). STL algorithms, based
on the nature of operations they perform, may be categorized into following groups:
A list of some of these algorithms along with a description of their purpose is given in
the Table 2.3:
Table 2.3: Mutating sequence Algorithm
Mutating-sequence algorithms
copy() Copies a sequence
copy_backward() Copies a sequence from the end
fill() Fills a sequence with a specified value
fill_n() Fills first n elements with a specified value
generate() Replaces all elements with the result of an operation
generate_n() Replaces first n elements with the result of an
operation
iter_swap() Swaps elements pointed to by iterators
random_shuffle() Places elements in random order
Remove() Deletes elements of a specified value
remove_copy() Copies a sequence after removing a specified value
remove_copy_if() Copies a sequence after removing elements
matching a predicate
remove_if() Deletes elements matching matching a predicate
replace() Replaces elements with a specified value
replace_copy() Copies a sequence replacing elements with a given
value
replace_copy_if() Copies a sequence replacing elements matching a
predicate
38
Templates and Standard
Template Library
Sorting algorithms
binary_search() Conducts a binary search on an ordered sequence
equal_range() Finds a sub range of elements with a given value
inplace_merge() Merges two consecutive sorted sequences
lower_bound() Finds the first occurrence of a specified value
make_heap() Makes a heap from a sequence
merge() Merges two sorted sequences
nth_element() Puts a specified element in its proper place
partial_sort() Sorts a part of a sequence
partial_sort_copy() Sorts a part of a sequence and then copies
partition() Places elements matching a predicate first
pop_heap() Deletes the top element
push_heap() Adds an element to heap
sort() Sorts a sequence
sort_heap() Sorts a heap
stable_partition() Places elements matching a predicate first matching relative
order
stable_sort() Sorts maintaining order of equal elements
upper_bound() Finds the last occurrence of a specified value
Set algorithms
includes() Finds whether a sequence is a subsequence of another
set_difference() Constructs a sequence that is the difference of two
ordered sets
set_intersection() Constructs a sequence that contains the intersection
of ordered sets
set_symmetric_difference() Produces a set which is the symmetric difference
between two ordered sets
set_union Produces sorted union of two ordered sets
Relational algorithms
equal() Finds whether two sequences are the same
lexicographical_compare() Compares alphabetically one sequence with other
max() Gives minimum of two values
max_element() Finds the maximum element within a sequence
min() Gives minimum of two values
min_element() Finds the minimum element within a sequence
Mismatch() Finds the first mismatch between the elements in two
sequence
Iterators
Iterators are used to access container class elements. They are called iterators because
of their use in traversing the elements (from one to another) of a container class. In
this sense they are quite similar to pointers. Iterators hold state information sensitive
to the particular containers on which they operate, thus, iterators are implemented
appropriately for each type of container. Certain iterator operations are uniform across
containers. For example, ++ operation on an iterator moves it to the next element of
the container. If iterator i points to a particular element, then, i++ points to the “next”
element and *I refers to the element pointed by i.
39
Advanced Features of C ++ There are five broad types of iterators supported by the STL. These are listed in Table
2.4:
Table 2.4: Types of Iterators
Each type of iterator is used for performing a particular set of functions. The input and
output iterators are used to traverse a container and have functionality limited to this
use. The forward operator also supports input and output and at the same time
retaining its position in the container. The bidirectional iterator provides ability to
move backwards in addition to forward movements. The random access iterator
allows random jumps to a particular location in addition to bidirectional operations.
Now that we had a look at the organization and different components of the STL, we
will go through some illustrative examples of use of the STL components. Since the
STL is quite big and we can not cover examples on the entire STL, we will see here
one example each of the use of List and Map container classes.
#include <iostream>
#include <list>
#include <cstdlib>
using namespace std;
int main()
{
list<int> list1; // empty list of zero length
list<int> list2(5); //empty list of 5 elements
list<int> :: iterator p;
for (p=list2.begin(); p!=list2.end(); ++p)
*p=rand()/100;
cout << “list1 \n”;
display(list1);
40
cout << “list2 \n”; Templates and Standard
display(list2); Template Library
return(0);
};
The program above creates various lists and performs different operations on them. It
uses member functions like begin(), end(), push_back(), push_front() etc. It also sorts
and merges two lists. The user-defined function display() makes use of iterator to
display the elements of the lists.
Here, phone is a map object and the statement associates number 123456 with the key
value “ashok”. The map entries can be manipulated using various member functions
and algorithms. The key operations in a map include operations like add, delete,
modify, sort the entries in map etc. We will have a look at an example of use of map
in the program below:
#include <iostream>
#include <map>
#include <string>
using namespace std;
41
Advanced Features of C ++ typedef map<string, int> phonemap;
int main()
{
string name;
int number;
phonemap phone;
return(0);
};
This program first creates a map (phone) with three entries read from the keyboard.
Then it moves to insert two new entries using two ways. It then prints the entire map
using iterator. Finally it looks up the value of a given key stored in the map.
Similar to list and map container classes, the other container classes can also be used
as the situation desires. We can use vector container class to create and manipulate
various arrays; stack for handling LIFO memory operations; queue and priority
queues for managing queue operations etc. We can manipulate these data structures
not only by the member functions they contain, but also by using various algorithms
that apply to them. Iterators help and guide the processing of elements contained in
the class. The STL provides a rich set of template declarations along with different
algorithms that are very useful in designing and implementing programming solutions
for different real world problems. It supports and promotes reuse, a key theme of
object oriented programming.
42
Check Your Progress 2 Templates and Standard
Template Library
1) Fill in the blanks:
a) The two types of first-class STL containers are sequence containers and
……………………….. containers.
b) The five main iterator types are …………………, ………………..,
………………., …………………., and …………………. .
c) The three STL container adapters are ……………, …………….., and
………………. .
d) STL algorithms operate on container elements indirectly, using
…………………… .
e) The sort algorithm requires a (n) …………………… iterator.
3) For each of the following, write a single statement that performs the indicated
task:
a) Name the member functions that are used to refer to beginning and end of the
list class.
…………………………………………………………………………………
…………………………….……………………..……………………………
…………………………………………………………………………………
2.6 SUMMARY
This unit has introduced the basic idea of template classes and functions. Templates
are mechanisms supported by C++ for generic programming. Templates allow us to
generate a family of classes or a family of functions to handle different data types.
Template classes and functions promote reuse and avoid code duplication. The
member functions of a class template are also defined using the parameters of the
class templates.
43
Advanced Features of C ++ C++ now contains a rich set of template classes and functions packaged as a library,
known as the standard template library. The STL consists of three main components:
containers, algorithms, and iterators. Containers are objects that hold data of some
type and are usually grouped into three types: sequential, associative and derived.
Container classes contain a large number of member functions that make manipulating
them simple. In addition to member functions, we also have a large number of
algorithms (such as sorting, searching, copying, and merging) that are used to
manipulate the container classes and perform various operations on them. Iterators,
which are similar to pointers allow manipulation of elements of container classes
indirectly by algorithms.
2. (a) True
(b) False, it need not be unique.
(c) True
(d) False, This also allows for a type parameter of a fundamental type
3.
template<typename T>
void printarray(T a[], int n)
{
for (int i=0; i<n-1; i++)
cout << a[i] << “ ”;
}
4.
template<class T1, class T2>
class item
{
T1 x;
T2 y;
Public:
item(T1 a, T2 b)
{
x = a;
y = b;
}
template<typename T>
void display(T a, T b)
{
cout << “item name” << a;
cout << “item measure” << b ;
}
44
Check Your Progress 2 Templates and Standard
Template Library
1. (a) Associative
(b) input, output, forward, bidirectional and random access
(c) stack, queue, priority queue
(d) iterators
(e) random access
45
Advanced Features of C ++
UNIT 3 EXCEPTION HANDLING
Structure Page Nos.
3.0 Introduction 46
3.1 Objectives 46
3.2 Exceptions in C++ Programs 46
3.3 Try, Throw and Catch Expressions 48
3.4 Specifying Exception Types 53
3.5 Summary 58
3.6 Answers to Check Your Progress 58
3.7 Further Readings 58
3.0 INTRODUCTION
In the units covered so far, we have talked about various features provided by C++ to
design different programs. The programs which are written correctly produce the
desired output when input data is supplied to them. However, in some cases programs
may behave in an unexpected manner. One of the reasons that may lead to this
situation is when we provide inappropriate input data (something that the programmer
never expected or anticipated). These situations are unexpected and that is why they
are termed exceptions. Exceptions are different from syntactical and logical errors but
they also cause the program to misbehave. Exceptions are usually encountered at run
time. In order to ensure that programs work correctly under all conditions, we have to
incorporate mechanisms to identify and handle different exceptions that may occur in
a program.
This unit introduces the nature and type of exceptions that may occur in a C++
program. It then describes the steps in exception handling. Then the syntax and use of
try, throw and catch expressions are explained with appropriate examples. This unit
tries to present a comprehensive picture of the exception handling mechanisms in C++
and their use in designing correct and robust programs.
3.1 OBJECTIVES
46
typical exceptions may include conditions like divide by zero, access to an array Exception Handling
outside its range, running out of memory etc.
# include <iostream>
int main()
{
int x,y;
cout << “enter values of x & y \n”;
cin >> x;
cin >> y;
cout << “result of x divided by y is:” <<
x/y;
}
This program reads values of variables x and y from standard input and produces
output of x divided by y, which is then displayed on the standard output. However,
please note that if the value of y read from the keyboard is „0‟, then the program
witnesses a divide by zero situation. In this case, the result will be infinite and
program terminates.
Exceptions can be of two kinds: asynchronous and synchronous. The exceptions that
are caused by events beyond the control of the program (such as keyboard interrupts)
are called asynchronous exceptions. The other unusual conditions (such as overflow,
out of range array index) that are part of the program are called synchronous
exceptions. The C++ exception handling mechanism is designed to handle
synchronous type of exceptions only. It provides a means to detect, report and act on
an unusual condition. The exception handling mechanism C++ deals with exceptions
by performing following tasks:
These tasks are incorporated in C++ exception handling mechanism in two segments,
one to detect (try) and inform (throw) about the exception, and the other to catch the
exception and take appropriate actions to handle it.
As indicated earlier, the C++ exception handling mechanism is built upon following
three expressions:
Try
Throw
Catch
47
Advanced Features of C ++ The expression try is used to preface (enclose in braces) that block which may
generate exceptions. This block is often termed as try block. The throw expression is
invoked when an exception is detected. It informs the catch block that an exception
has occurred. The exception handling code is enclosed in catch block. The catch
block catches the exception thrown by the throw expression and handles it in a
predefined manner. The Figure 3.1 further shows the use of these three expressions
and their relationship:
Try block
Exception
object
catch block
The keyword „try‟ is used to enclose the statements that may generate an exception.
These statements begin with a try keyword and are enclosed in braces. When the try
block encounters an exception, it uses the throw keyword to pass the information to
the exception handling block. The exception handling block is enclosed within a block
preceding the catch keyword. This catch block should immediately follow the try
block that throws the exception. The general syntax of these statements and blocks is
as follows:
………………..
………………..
try
{
………………
………………
throw exception;
……………….
……………….
}
catch (type arg)
{
………………..
………………..
………………..
}
…………………
…………………
As some statement within the try block of the program generates an exception, it is
thrown using the throw statement. At this time, the program control transfers to the
48
catch block. The throw contains an argument named exception which is passed to the Exception Handling
catch block as an argument. However, the catch block handles this exception only if
the arguments passed from throw matches with the argument specified in the catch
block. In case the exceptions that may be generated could be of different types, then
multiple catch blocks will be required. This can be done by writing these catch blocks
one after another. When an exception is thrown, the exception object is compared with
the argument in the catch blocks written in succession. The first catch block matching
the exception object is executed. We will see use of multiple catch blocks in the next
part of the chapter. If the exception object thrown does not match with the argument
specified in catch block, then the program gets terminated by automatic invocation of
abort() function. Sometimes exceptions are thrown from functions that are invoked
within the try block. The point at which this throw is executed is called throw point.
After an exception is thrown to the catch block, control cannot return back to the
throw point. The Figure 3.2 demonstrates this situation when a function invoked from
within the try block throws an exception.
Throw point
Try block
Throw
exception Invokes a function that
contains an exception
catch block
Catches and handles
the exception
Figure 3.2 Throw, try and catch blocks for exception handling
We present following two code segments that demonstrate use of try, throw and catch
expressions for exception handling. The first program presents a simple example of
use of a single try and catch block. The second program presents an example where
the exception is thrown from a function invoked from within the try block.
# include <iostream>
int main()
{
int x,y;
cout << “enter values of x & y \n”;
cin >> x;
cin >> y;
int a = x-y;
try
{
if (a!=0)
{
cout << “Result (x/a) =” << x/a;
}
else
{
throw (a);
}
}
49
Advanced Features of C ++ catch (int i)
{
cout << “Exception caught a=” << a;
}
return(0);
}
# include <iostream>
void divide (int x, int y, int z)
{
cout << “inside function \n”;
if (x-y)!=0)
{
int r = z/ (x-y);
cout << “result =” << r << “\n”;
}
else
{
throw (x-y);
}
}
int main()
{
Try
{
cout << inside try block \n”;
divide (10,20,30);
divide(10,10,20);
}
catch (int i)
{
cout << “Caught the exception”;
}
return(0);
}
You would see that in the first program, if input values are 20 and 15 then the
program runs correctly without any exception with result being 4. On the other hand,
if input given is 10 and 10, the program would detect an exception and display it as
“0” value. Similarly, in the second program for the first invocation of divide (), the
result will be -3, whereas the second invocation will result into an exception.
throw (exception);
throw exception;
throw;
The first two throw statements pass the exception object to the catch handler, whereas
the third throw statement without any exception object is used to rethrow an exception
from within a catch block.
A catch handler may rethrow the exception, without handling it, to the next catch
block. This is equivalent to passing the exception to the next enclosing catch block
within the scope of try/catch sequence. Please note that a rethrown exception is not
50
caught by the same catch handler or any other catch handler in that group, but by an Exception Handling
appropriate catch handler in the outer try/catch sequence only. This also applies to
those exceptions that may be detected within a catch handler block itself.
We have seen earlier that a catch block looks like a function definition. It has a type
argument which specifies the type of exception that this catch block may handle
followed by statements (enclosed within braces) to process the exception. After
executing these statements, the control goes to the statement immediately following
the catch block. It is also possible that a program may have more than one exception
condition. In such cases multiple catch statements are needed to handle the different
types of exceptions. Now when an exception is thrown, the exception handlers are
searched in order for an appropriate match. The first handler that matches the thrown
exception object type is executed. Rest of the catch blocks are then skipped and the
control goes to first statement following the last catch block. This indicates that in
case of multiple catch blocks matching the thrown exception, only the first matching
catch block is executed. The following program demonstrates the use of multiple
catch blocks:
#include<iostream>
void test(int x)
{
try
{
if (x==1) throw x;
else
if (x==0) throw „x‟;
else
if(x==-1) throw 1.0;
}
catch (char c)
{
cout << “caught a character \n”;
}
catch(int m)
{
cout << “caught an integer \n”;
}
catch(double d)
{
cout << “caught a double \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);
51
Advanced Features of C ++
return(0);
}
As you can see this program has multiple catch blocks, each handling exception
objects of different types. One integer, other character and the third one a double
exception argument. The last invocation of test with argument 2 does not throw any
exception and hence no catch block is invoked.
There are many situations where it may be very difficult to anticipate in advance all
possible types of exceptions that may occur in a program. C++ provides with a
mechanism to cope with this problem in form of a catch (…) expression. This type of
catch statement catches all exceptions, unlike only one exception being caught. The
general syntax of use of this kind of catch expression is as follows:
catch(…)
{
//statements for processing
//all exceptions
}
The following example presents a case of use of this kind of catch expression:
# include <iostream>
void test (int x)
{
try
{
if (x==0) throw x;
if (x==-1) throw „x‟;
if (x==1) throw 1.0;
}
catch (…)
{
cout << “caught an exception \n”;
}
}
int main()
{
cout << “testing generic catch \n”;
test (-1);
test (0);
test(1);
return(0);
}
You may see that this program prints the line “caught an exception” three times as
follows:
Output:
caught an exception
caught an exception
caught an exception
52
This is because all the exceptions (x getting values -1, 0 and 1) are caught by the same Exception Handling
catch handler block. This is the reason why this kind of catch block is termed as catch
all expression. This property can make this kind of catch all expression to be placed as
default catch handler. This default handler may then be used to catch all those
exceptions which are not handled explicitly. However, one must be careful to place
this catch all expression in the last place of catch handlers.
#include <iostream>
void test(int x) throw (int, double)
{
if (x==0) throw „x‟;
else
if (x==1) throw x;
else
if (x==-1) throw 1.0;
}
int main()
{
try
{
cout << :testing throw specifications \n”;
cout << “x==0 \n”;
test(0);
cout << “x==1 \n”;
test(1);
cout << “x==-1 \n”;
test(-1);
cout << “x==2 \n”;
test(2);
}
catch(cahr c)
{
cout << “caught a character \n”;
}
catch (int m)
{
cout << “caught an integer \n”;
}
catch (double d)
{
cout << caught a double \n”;
}
return (0);
}
You may note that this program tries to throw a char exception object in the very first
invocation of test(). This results in an abnormal termination of the program, since the
test can throw only exceptions of type int and double.
Program Output:
54
Throwing an exception that has not been declared in a function‟s exception Exception Handling
specification causes a call to function unexpected. The compiler will not generate a
compilation error if a function contains a throw expression for an exception not listed
in the function‟s specification. An error occurs only when that function attempts to
throw that exception at execution time. To avoid surprises at execution time, its better
to carefully check the code to ensure that functions do not throw exceptions not listed
in their specifications.
The function unexpected calls, the function registered with the function
set_unexpected (defined in header file <exception>). If no function has been
registered in this manner, function terminate is called by default. The function
set_terminate can specify the function to invoke when terminate is called. Otherwise,
terminate calls abort, which terminates the program without calling the destructors of
any remaining objects of automatic or static storage class. This could lead to resource
leaks when a program terminates prematurely.
When an exception is thrown but not caught in a particular scope, the function call
stack is “unwound” and an attempt is made to catch the exception in the next outer
try….catch block. Unwinding the function call stack means that the function in which
the exception was not caught terminates, all local variables in that function are
destroyed and control returns to the statement that originally invoked that function. If
a try block encloses that statement, an attempt is made to catch the exception. If a try
block does not enclose the statement, stack unwinding occurs again. If no catch
handler ever catches this exception, function terminate is called to terminate the
program. The following programming example demonstrates stack unwinding:
#include <iostream>
#include <stdexcept>
using namespace std;
int main()
{
//invoke function1
55
Advanced Features of C ++ try
{
cout << “function1 is called inside main” << endl;
function1();
}
catch (runtime_error & error)
{
cout << “exception occurred:” << error.what() << endl;
cout << “ exception handled in main” << endl;
}
}
The program will produce the following output:
function1 is called inside main
function2 is called inside function1
function3 is called inside function2
in function3
exception occurred: runtime_error in function3
exception handled in main
Exception handling and Constructors and Destructors
It is worth discussing that what happens if an exception is thrown while executing a
constructor? Since the object is not yet fully constructed, its destructor would not be
called once the program control goes out of the object‟s context. And, if the
constructor had reserved some memory before the exception was raised, then there
would be no mechanism to prevent such memory leak. Hence. Appropriate exception
handling mechanism must be implemented pertaining to the constructor routine to
handle exceptions that occur during object construction.
Where to catch the exception is another important issue here. Whether it should be
done inside the constructor block or inside the main. If we allow the exception to be
handled inside main then we would not be able to prevent the memory leak situation.
Therefore, we must catch the exception within the constructor block so that we get
chance to free up any reserved memory spaces. However, we must simultaneously
rethhrow the exception to be appropriately handled inside the main block.
runtime_error logic_error
4) How do you restrict the exception type that a function can throw?
………………………………………………………………………………
………………………………………………………………………………
………………………………………………………………………………
57
Advanced Features of C ++
3.5 SUMMARY
Exceptions are a kind of problem that may occur when a program is executed. C++
provides an exception handling mechanism to handle synchronous exceptions. An
exception is handled by a group of try, throw and catch expressions. The block that
may cause a possible exception is enclosed within a try block. The exceptional
situation occurring in the try block is reported by throw expression to an exception
handling block, called catch block. When an exception is not caught the program is
terminated. The throw expression passes the exception object to an appropriate catch
block. A program may have more than one catch block to handle different kinds of
exceptions. We can also have a catch all expression that can be used as a default
handler. A catch block may also rethrow an exception without processing it. We may
also restrict the type of exception objects that a function may throw. The try-throw-
catch mechanism in C++ is quite useful to provide for dealing with unexpected
situations that may occur at runtime in a program.
1) This causes the search for a match to continue in the next enclosing try block if
there is one. As this process continues, it might eventually be determined that
there is no handler in the program that matches the type of thrown object. In this
case, program is aborted.
2) No, but it does terminate the block in which the exception is thrown.
3) The exception will be processed by a catch handler (if one exists) associated with
the try block (if one exists) enclosing the catch handler that caused the exception.
4) Provide an exception specification listing the exception type that the function can
throw.
5) Function unexpected is called to terminate the program.
58
A Case Study
UNIT 4 A CASE STUDY
Structure Page Nos.
4.0 Introduction 59
4.1 Objectives 59
4.2 Designing a Transaction-processing System 60
4.3 Summary 74
4.4 Further Readings 74
4.0 INTRODUCTION
In the units covered so far, we have discussed various features of C++ language that
help in designing and implementing useful programs to solve various real world
problems. The bottom up approach adopted by C++ language provides a better way to
capture the details of real world problems and design efficient and adaptable solutions.
Whether it is the mechanism of constructors and destructors, inheritance, or
polymorphism; all taken collectively provide suitable design methodology and tool for
solving various real world problems through C++ programming formulations. In order
to solve a real world problem, the first and foremost requirement is to identify the
various objects in the system along with their general attributes. This is then followed
by the more involved process of identifying the methods/ functions that can be applied
on the different objects. Once this is done, the effort gets more focused towards
design, which involves designing various classes and implementing different
functions.
4.1 OBJECTIVES
59
Advanced Features of C ++
4.2 DESIGNING A TRANSACTION-PROCESSING
SYSTEM
A transaction processing system is one where certain activities are carried out as part
of some bigger goal. The kind of transactions performed in a system depends on the
domain of the problem. For example, in a ticket reservation domain the key
transactions may be booking a ticket, realizing payment for a ticket, cancelling a
ticket, modifying or amending a ticket, refund of a cancelled ticket etc. Similarly in a
banking domain, the transactions could be opening a customer account, updating the
account records, processing withdrawal from an account, deposit into an account,
printing summary of accounts etc. Every transaction processing system, irrespective
of the domain, has to complete certain activities (referred to as transactions).
Nowadays when a large number of transaction processing activities are automated to
be performed on a computer system, it is very important to know and understand how
can we design such a system. Moreover, with the increased use of Internet and web-
based services many of these transactions are initiated and realized at different
physical machines. The data related to transactions is sent over communication lines.
One common thing however in all kind of transaction processing systems is the need
to store and manipulate associated data. The data of the system may be stored either in
a database format or in terms of a collection of various files. The general practice in
most of the real world transaction processing systems is to go for a database design
approach. However, in the example described below we have used a file processing
approach.
Most of the transaction processing systems are quite big and result into large
programs. The large programs often comprise of various modules. In order to have
better understanding and design convenience, these transaction processing systems are
designed as a collection of multiple programs. In the previous units we have largely
seen example programs consisting of a single program file. Whenever we have to
design programming solution for a larger problem, it is often required to organize the
large code into multiple files. Using a multiple file organization not only helps in
clarity of the design but also in appropriate use of class libraries and better
coordination of programmers working on the large project. In fact, large programs are
usually divided into separate files, where different files have code for different
functionalities, such as one file for mathematical analysis, another for graphics display
and a separate one for I/O etc. Large applications sometimes also involve multiple
designers who coordinate their effort to design the final solution. Most of the C++
IDEs provide a feature called PROJECT which helps in designing and organizing
larger programs comprising multiple files.
We will now see how we can use the various features and capabilities of C++ that we
have learned so far to design a transaction-processing system. The proposed system
involves some fixed-length account records for a company having certain number of
customers. Each record consists of an account number that acts as the record key, a
last name, a first name and a balance. The transaction-processing program is to be
designed in such a manner that it can provide overall management functions for the
accounts and transactions. It should be able to perform functions like update an
account, insert a new account, delete an account and insert all the account records into
a formatted text file for printing.
The key components in this application design can be understood through following
abstract diagram representation.
60
A Case Study
Entering
data and
updating
records
Accounts and Customer related
information stored in credit.dat
file
Retrieving
data from the
file and
displaying
results
As we can see, the entire data corresponding to accounts and customer information is
stored in credit.dat file. We will design program to enter, add and update the data in
this file. The data entered may also be retrieved and displayed as a formatted text
output through the use of various stream manipulators. We first create a ClientData
class header file that defines the format of the data and then define the constructor and
certain basic methods. The following two program segments (Program 4.1 and 4.2)
are written for this purpose.
1 #ifndef CLIENTDATA_H
2 #define CLIENTDATA_H
3 #include <string>
4 using namespace std;
5 class ClientData
6 {
7 public:
8 ClientData(int =0, string = “ “, string = “ “, double =
0.0);
9
10 void setAccountNumber (int);
11 int getAccountNumber() const;
12 void setLastname(string);
13 string getLastName() const;
14 void setFirstName(string);
15 string getFirstName() const;
16 void setBalance(double);
17 double getBalance() const;
18
19 private:
20 int accountNumber;
21 char lastName[15];
22 char firstName[10];
23 double balance;
24 };
25 #endif
The program 4.1 above defines client data header file which specifies the data format
to be used in the application. The main data items are account number (an integer
61
Advanced Features of C ++ value), last name of customer (a string), first name of customer (a string) and balance
(a float value denoting the account balance). These data items are declared as private.
The methods to access and modify this data are setAccountNumber(),
getAccountNumber(), setLastName(), getLastName(), setFirstName(),
getFirstName(), setBalance() and getBalance(). All these functions are used to define
and retrieve values for various fields, and are defined in next program (Program 4.2).
The client data represent a customer’s credit information and the methods described in
program 4.2 provide the code for manipulating the data. The exact code is described
in in the program 4.2 given below:
1 #include <string>
2 #include “ClientData.h”
3 using namespace std;
4
5 // default ClientData constructor
6 ClientData::ClientData(int accountNumberValue, string
lastNameValue,
7 string firstNameValue, double balanceValue)
8 {
9 setAccountNumber(accountNumberValue);
10 setLastName(lastNameValue);
11 setFirstName(firstNameValue);
12 setBalance(balanceValue);
13 } // end ClientData constructor
14 //get account number value
15 int ClientData::getAccountNumber() const
16 {
17 return accountNumber;
18 }
19 //set account number value
20 void ClientData::setAccountNumber(int accountNumberValue)
21 {
22 accountNumber=accountNumberValue;
23 }
24 // get last name value
25 string ClientData::getLastName() const
26 {
27 return lastName;
28 }
29 // set last name value
30 void ClientData::setLastName(string lastnameString)
31 {
32 int length=lastNameString.size();
33 length = (length<15? length:14); \\for copying at most 15
chars
34 lastNameString.copy(lastName, length);
35 lastName[length]=’\0’; \\appending null character
36 }
37
38 //get first-name value
39 string ClientData::getfirstName() const
40 {
41 return firstName;
42 }
43
44 // set first-name value
45 void ClientData::setfirstName(string firstNameString)
46 {
47 // copy at most 10 chars
48 int length =firstNameString.size();
49 length = (length < 10? length:9);
62
50 firstNameString.copy(firstName, length); A Case Study
51 firstName[length]=’\0’; \\ appending null char
52 }
53
54 // get balance value
55 double ClientData::getBalance() const
56 {
57 return balance;
58 }
59
60 //set balance value
61 void ClientData::setBalance(double lalanceValue)
62 {
63 balance=balanceValue;
64 }
65
As you may easily notice, the program defines the ClientData constructor comprising
of various functions, each of which have a specified code. The functions
setLastName() and setFirstName() limit the number of characters read from input that
are finally written to actual data.
We now look at the code (Program 4.3) for creating a file credit.dat with some data
entries to be used in our transaction processing system. The program creates a binary
file credit.dat for output. It then writes 100 blank records into the credit.dat data file.
The next program (program 4.4) then uses various functions to actually write data into
this file.
Program 4.3: Creating the credit.dat file with 100 blank records
Once the file credit.dat is created we can use this file to store the desired data
corresponding to the accounts and customers. After entering the basic data, actual
63
Advanced Features of C ++ transaction-processing may be performed. The program below reads the data from
user entered values through keyboard and then uses fstream functions to store data at
desired locations in the file credit.dat. Note that the file is opened in out mode for
writing. An example run of the program 4.4 is presented after the program code. The
run shows how different data values can be entered into the data file. Note that line 19
includes the header file ClientData.h defined in Program 4.1 so the program can use
ClientData objects.
1
2 // Writing to a random-access file.
3 #include <iostream>
4 using std::cerr;
5 using std::cin;
6 using std::cout;
7 using std::endl;
8 using std::ios;
9
10 #include <iomanip>
11 using std::setw;
12
13 #include <fstream>
14 using std::fstream;
15
16 #include <cstdlib>
17 using std::exit; // exit function prototype
18
19 #include "ClientData.h" // ClientData class definition
20
21 int main()
22 {
23 int accountNumber;
24 char lastName[ 15 ];
25 char firstName[ 10 ];
26 double balance;
27
28 fstream outCredit( "credit.dat", ios::in | ios::out |
ios::binary );
29
30 // exit program if fstream cannot open file
31 if ( !outCredit )
32 {
33 cerr << "File could not be opened." << endl;
34 exit( 1 );
35 } // end if
36
37 cout << "Enter account number (1 to 100, 0 to end
input)\n? ";
38
39 // require user to specify account number
40 ClientData client;
41 cin >> accountNumber;
42
43 // user enters information, which is copied into file
44 while ( accountNumber > 0 && accountNumber <= 100 )
45 {
46 // user enters last name, first name and balance
47 cout << "Enter lastname, firstname, balance\n? ";
48 cin >> setw( 15 ) >> lastName;
49 cin >> setw( 10 ) >> firstName;
50 cin >> balance;
51
64
52 // set record accountNumber, lastName, firstName and A Case Study
balance values
53 client.setAccountNumber( accountNumber );
54 client.setLastName( lastName );
55 client.setFirstName( firstName );
56 client.setBalance( balance );
57
58 // seek position in file of user-specified record
59 outCredit.seekp( ( client.getAccountNumber() - 1 ) *
60 sizeof( ClientData ) );
61
62 // write user-specified information in file
63 outCredit.write( reinterpret_cast< const char * >(
&client ),
64 sizeof( ClientData ) );
65
66 // enable user to enter another account
67 cout << "Enter account number\n? ";
68 cin >> accountNumber;
69 } // end while
70
71 return 0;
72 } // end main
65
Advanced Features of C ++ The transaction processing system that we are designing can now be visualized
in figure 4.2:
ClientData Class
(Members and Main
Constructor) Transaction
Processing
program
credit.dat file
We now present our main transaction-processing program (Program 4.5) which uses
the ClientData.h and credit.dat files to achieve “instant” -access processing. As we
discussed earlier, the program manages a bank’s account information. The program
can perform all functions of accounts processing. It can update existing accounts, adds
new accounts, deletes accounts and stores a formatted listing of all current accounts in
a text file. We assume that the program 4.3 has been executed to create the file
credit.dat and that the program of Program 4.4 has been executed to insert the initial
data, before this program can be used for transaction-processing operations.
1
2 // This program reads a random-access file sequentially,
updates
3 // data previously written to the file, creates data to be
placed
4 // in the file, and deletes data previously stored in the
file.
5 #include <iostream>
6 using std::cerr;
7 using std::cin;
8 using std::cout;
9 using std::endl;
10 using std::fixed;
11 using std::ios;
12 using std::left;
13 using std::right;
14 using std::showpoint;
15
16 #include <fstream>
17 using std::ofstream;
18 using std::ostream;
19 using std::fstream;
20
21 #include <iomanip>
22 using std::setw;
66
23 using std::setprecision; A Case Study
24
25 #include <cstdlib>
26 using std::exit; // exit function prototype
27
28 #include "ClientData.h" // ClientData class definition
29
30 int enterChoice();
31 void createTextFile( fstream& );
32 void updateRecord( fstream& );
33 void newRecord( fstream& );
34 void deleteRecord( fstream& );
35 void outputLine( ostream&, const ClientData & );
36 int getAccount( const char * const );
37
38 enum Choices { PRINT = 1, UPDATE, NEW, DELETE, END };
39
40 int main()
41 {
42 // open file for reading and writing
43 fstream inOutCredit( "credit.dat", ios::in | ios::out |
ios::binary );
44
45 // exit program if fstream cannot open file
46 if ( !inOutCredit )
47 {
48 cerr << "File could not be opened." << endl;
49 exit ( 1 );
50 } // end if
51
52 int choice; // store user choice
53
54 // enable user to specify action
55 while ( ( choice = enterChoice() ) != END )
56 {
57 switch ( choice )
58 {
59 case PRINT: // create text file from record file
60 createTextFile( inOutCredit );
61 break;
62 case UPDATE: // update record
63 updateRecord( inOutCredit );
64 break;
65 case NEW: // create record
66 newRecord( inOutCredit );
67 break;
68 case DELETE: // delete existing record
69 deleteRecord( inOutCredit );
70 break;
71 default: // display error if user does not select
valid choice
72 cerr << "Incorrect choice" << endl;
73 break;
74 } // end switch
75
76 inOutCredit.clear(); // reset end-of-file indicator
77 } // end while
78
79 return 0;
80 } // end main
81
82 // enable user to input menu choice
83 int enterChoice()
67
Advanced Features of C ++ 84 {
85 // display available options
86 cout << "\nEnter your choice" << endl
87 << "1 - store a formatted text file of accounts" <<
endl
88 << " called \"print.txt\" for printing" << endl
89 << "2 - update an account" << endl
90 << "3 - add a new account" << endl
91 << "4 - delete an account" << endl
92 << "5 - end program\n? ";
93
94 int menuChoice;
95 cin >> menuChoice; // input menu selection from user
96 return menuChoice;
97 } // end function enterChoice
98
99 // create formatted text file for printing
100 void createTextFile( fstream &readFromFile )
101 {
102 // create text file
103 ofstream outPrintFile( "print.txt", ios::out );
104
105 // exit program if ofstream cannot create file
106 if ( !outPrintFile )
107 {
108 cerr << "File could not be created." << endl;
109 exit( 1 );
110 } // end if
111
112 outPrintFile << left << setw( 10 ) << "Account" <<
setw( 16 )
113 << "Last Name" << setw( 11 ) << "First Name" <<
right
114 << setw( 10 ) << "Balance" << endl;
115
116 // set file-position pointer to beginning of
readFromFile
117 readFromFile.seekg( 0 );
118
119 // read first record from record file
120 ClientData client;
121 readFromFile.read( reinterpret_cast< char * >( &client
),
122 sizeof( ClientData ) );
123
124 // copy all records from record file into text file
125 while ( !readFromFile.eof() )
126 {
127 // write single record to text file
128 if ( client.getAccountNumber() != 0 ) // skip empty records
129 outputLine( outPrintFile, client );
130
131 // read next record from record file
132 readFromFile.read( reinterpret_cast< char * >( &client ),
133 sizeof( ClientData ) );
134 } // end while
135 } // end function createTextFile
136
137 // update balance in record
138 void updateRecord( fstream &updateFile )
139 {
140 // obtain number of account to update
141 int accountNumber = getAccount( "Enter account to
68
update" ); A Case Study
142
143 // move file-position pointer to correct record in file
144 updateFile.seekg( ( accountNumber - 1 ) * sizeof(
ClientData ) );
145
146 // read first record from file
147 ClientData client;
148 updateFile.read( reinterpret_cast< char * >( &client ),
149 sizeof( ClientData ) );
150
151 // update record
152 if ( client.getAccountNumber() != 0 )
153 {
154 outputLine( cout, client ); // display the record
155
156 // request user to specify transaction
157 cout << "\nEnter charge (+) or payment (-): ";
158 double transaction; // charge or payment
159 cin >> transaction;
160
161 // update record balance
162 double oldBalance = client.getBalance();
163 client.setBalance( oldBalance + transaction );
164 outputLine( cout, client ); // display the record
165
166 // move file-position pointer to correct record in
file
167 updateFile.seekp( ( accountNumber - 1 ) * sizeof(
ClientData ) );
168
169 // write updated record over old record in file
170 updateFile.write( reinterpret_cast< const char * >(
&client ),
171 sizeof( ClientData ) );
172 } // end if
173 else // display error if account does not exist
174 cerr << "Account #" << accountNumber
175 << " has no information." << endl;
176 } // end function updateRecord
177
178 // create and insert record
179 void newRecord( fstream &insertInFile )
180 {
181 // obtain number of account to create
182 int accountNumber = getAccount( "Enter new account
number" );
183
184 // move file-position pointer to correct record in file
185 insertInFile.seekg( ( accountNumber - 1 ) * sizeof(
ClientData ) );
186
187 // read record from file
188 ClientData client;
189 insertInFile.read( reinterpret_cast< char * >( &client
),
190 sizeof( ClientData ) );
191
192 // create record, if record does not previously exist
193 if ( client.getAccountNumber() == 0 )
194 {
195 char lastName[ 15 ];
196 char firstName[ 10 ];
69
Advanced Features of C ++ 197 double balance;
198
199 // user enters last name, first name and balance
200 cout << "Enter lastname, firstname, balance\n? ";
201 cin >> setw( 15 ) >> lastName;
202 cin >> setw( 10 ) >> firstName;
203 cin >> balance;
204
205 // use values to populate account values
206 client.setLastName( lastName );
207 client.setFirstName( firstName );
208 client.setBalance( balance );
209 client.setAccountNumber( accountNumber );
210
211 // move file-position pointer to correct record in
file
212 insertInFile.seekp( ( accountNumber - 1 ) * sizeof(
ClientData ) );
213
214 // insert record in file
215 insertInFile.write( reinterpret_cast< const char *
>( &client ),
216 sizeof( ClientData ) );
217 } // end if
218 else // display error if account already exists
219 cerr << "Account #" << accountNumber
220 << " already contains information." << endl;
221 } // end function newRecord
222
223 // delete an existing record
224 void deleteRecord( fstream &deleteFromFile )
225 {
226 // obtain number of account to delete
227 int accountNumber = getAccount( "Enter account to
delete" );
228
229 // move file-position pointer to correct record in file
230 deleteFromFile.seekg( ( accountNumber - 1 ) * sizeof(
ClientData ) );
231
232 // read record from file
233 ClientData client;
234 deleteFromFile.read( reinterpret_cast< char * >(
&client ),
235 sizeof( ClientData ) );
236
237 // delete record, if record exists in file
238 if ( client.getAccountNumber() != 0 )
239 {
240 ClientData blankClient; // create blank record
241
242 // move file-position pointer to correct record in
file
243 deleteFromFile.seekp( ( accountNumber - 1 ) *
244 sizeof( ClientData ) );
245
246 // replace existing record with blank record
247 deleteFromFile.write(
248 reinterpret_cast< const char * >( &blankClient ),
249 sizeof( ClientData ) );
250
251 cout << "Account #" << accountNumber << "
deleted.\n";
70
252 } // end if A Case Study
253 else // display error if record does not exist
254 cerr << "Account #" << accountNumber << " is
empty.\n";
255 } // end deleteRecord
256
257 // display single record
258 void outputLine( ostream &output, const ClientData &record
)
259 {
260 output << left << setw( 10 ) <<
record.getAccountNumber()
261 << setw( 16 ) << record.getLastName()
262 << setw( 11 ) << record.getFirstName()
263 << setw( 10 ) << setprecision( 2 ) << right << fixed
264 << showpoint << record.getBalance() << endl;
265 } // end function outputLine
266
267 // obtain account-number value from user
268 int getAccount( const char * const prompt )
269 {
270 int accountNumber;
271
272 // obtain account-number value
273 do
274 {
275 cout << prompt << " (1 - 100): ";
276 cin >> accountNumber;
277 } while ( accountNumber < 1 || accountNumber > 100 );
278
279 return accountNumber;
280 } // end function getAccount
The program presents a menu driven interface to the user. The choices available to the
user are 1-Print, 2-Update, 3-New account, 4- Delete account and 5-End processing.
These menu choices are realized through following five options:
71
Advanced Features of C ++
Option3 calls function newrecord (lines 159-201) to add a new account to the file. If
the user enters an account number for an existing account, newRecord displays an
error message indicating that the account exists (lines 199-200). A typical output for
option 3 is:
72
A Case Study
Option4 calls function deleteRecord (lines 204-235) to delete a record from the file.
Line 207 prompts the user to enter the account number. Only an existing record may
be deleted, so if the specified account is empty, line 234 displays an error message. If
the account exists, lines 227-229 reinitialize that account by copying an empty record
(blank-Client) to the file. Line 231 displays a message to inform the user that the
record has been deleted. A typical output for option 4 is:
4
Enter account to delete (1 – 100) : 29
Account #29 deleted.
73
Advanced Features of C ++ It would also be in order to discuss here the fact that the sequential files are
inappropriate for instant-access applications, in which a particular record must be
located immediately. Common instant-access applications are airline reservation
systems, banking systems, point-of-sale systems, automated teller machines and other
kinds of transaction-processing systems that require rapid access to specific data. A
bank might have hundreds of thousands (or even millions) of other customers, yet,
when a customer uses an automated teller machine, the program checks that
customer’s account in a few seconds or less for sufficient funds. This kind of instant
access is made possible with random-access files. Individual records of a random-
access file can be accessed directly (and quickly) without having to search other
records. As we have said, C++ does not impose structure on a file. So the application
that wants to use random-access files must create them. A variety of techniques can be
used. Perhaps the easiest method is to require that all records in a file be of the same
fixed length. Using same-size, fixed-length records makes it easy for a program to
calculate (as a function of the record size and the record key) the exact location of any
record relative to the beginning of the file. Using a database based approach is a
common choice for many of these applications.
C++ provides rich set of features for designing various applications to solve various
real world problems. A number of useful applications in different domain cab be
designed using C++. Applications like passenger reservation systems, automated plant
control, restaurant management, library management are some possible applications
which can be implemented using C++ features.
4.5 SUMMARY
In the previous chapters, we have discussed various features of C++. C++ provides a
rich set of features and capabilities that can be used to write useful programs to solve
a number of real world problems. This unit presents a case study of designing and
implementing a transaction- processing system in banking domain. The design
involves creating necessary data files to store accounts and customer information and
then accessing them through suitable code for writing data, appending data,
performing credit operations and displaying the results. The program design makes
use of various features of C++, including its capability to design multi-file programs.
The file processing capability of C++ coupled with the rich I/O capability through
stream classes can be used to design many interesting applications. This unit
demonstrated use and application of various C++ features for solving one real world
large scale problem. C++ can be used to solve many other simple and sophisticated
real world problems.
74