MINNAL INFOTECH
Software and Hardware Solutions
Thursday, 7 March 2013
Saturday, 23 February 2013
c++ files notes
UNIT
I
EVOLUTION OF C++
C++ is an
object-oriented programming language and is considered to be an extension of C.
Bjarne Stroustrup at
AT&T Bell Laboratories, Murray Hill, New Jersey (USA) developed it in the
early eighties of twentieth century.
Stroustrup,
a master of Simula67 and C, wanted to combine the features of both the
languages into a more powerful language that could support object-oriented
programming with features of C.
The
outcome was C++ as per in the following figure.
Various
ideas were derived from SIMULA67 and ALGOL68. Stroustrup called the new
language ‘C with classes’. However, in 1983, the name was changed to C++. The
thought of C++ came from the C increment operator ++. Rick Mascitti coined the
term C++ in 1983. Therefore, C++ is an extended version of C. C++ is a superset
of C. All the concepts of C are applicable to C++ also.
For
developing complicated applications object-oriented languages are most
convenient and easy. Hence, a programmer must be aware of the new concepts of
object-oriented techniques.
ANSI
STANDARD
The
recognized council working under the procedure of the American National
Standard Institute (ANSI) has made an international standard for C++. The C++
standard is also referred to as ISO (International Standard Organization)
standard. The process of standardization is gradual and the first draft of the
planned ANSI standard was made on 25 January 1994. This book will continue to
refer to ANSI standard code, which is more commonly used. The ANSI standard is
an attempt to ensure that C++ is portable.
PROGRAMMING PARADIGMS
(1)
Monolithic
Programming
(2)
Procedural
Programming
(3)
Structured
Programming
(1)
Monolithic
Programming
In
monolithic programming languages such as BASIC and ASSEMBLY, the data variables
declared are global and the statements are written in sequence.
The
program contains jump statements such as goto, that transfer control to any
statement as specified in it. Figure shows a program of monolithic type. The
global data can be accessed from any portion of the program. Due to this reason
the data is not fully protected.
The
concept of subprograms does not exist and hence useful for smaller programs.
(2)
Procedural Programming
In
procedural programming languages such as FORTRAN and COBOL, programs are
divided into a number of segments known as subprograms. Thus it focuses on
functions apart from data. Following figure
describes a program of procedural type. It shows different subprograms
having access to the same global data. Here also, the data is not fully protected.
The
control of program is transferred using unsafe goto statement.
Data
is global and all the subprograms share the same data.
These
languages are used for developing medium size applications.
(3)
Structured Programming
In structured programming languages such as
PASCAL and C larger programs are developed. These programs are divided into
multiple submodules and procedures.
Each
procedure has to perform different tasks.
Each
module has its own set of local variables and program code as shown in following
figure. Here, the different modules are
shown accessing the global data.
User-defined
data types are introduced.
KEY
CONCEPTS OF OBJECT-ORIENTED PROGRAMMING
There
are several fundamental or key concepts in object-oriented programming. Some of
these are as bellow.
(1)
Object
(2)
Class
(3)
Method
(4)
Data
Abstraction
(5)
Encapsulation
(6)
Inheritance
(7)
Polymorphism
(8)
Dynamic
Binding
(9)
)
Reusability
(10)
Message
Passing
(11)
Genericity
(12)
Delegation
1. OBJECT
Objects
are primary run-time entities in an object-oriented programming. They may stand
for a thing that has specific application for example, a spot, a person, any
data item related to program, including user-defined data types. Programming
issues are analyzed in terms of object and the type of transmission between
them. The following Figure describes various objects.
The
selected program objects must be similar to actual world objects. Objects
occupy space in memory. Every object has its own properties or features. An
object is a specimen of a class. It can be singly recognized by its name. It
declares the state shown by the data values of its characteristic at a specific
time. The state of the object varies according to procedure used. It is known
as the action of the object. The action of the object depends upon the member
function defined within its class.
2. CLASS
A
class is grouping of objects having identical properties, common behavior, and
shared relationship. A class is the accomplishment of abstract data type. It
defines the nature and methods that act on the data structure and abstract data
type respectively.
The
entire group of data and code of an object can be built as a user-defined data
type using class. Objects are nothing but variables of type class. Once a class
has been declared, the programmer can create a number of objects associated
with that class. The syntax used to create an object is similar to the syntax
used to create an integer variable in C. A class is a model of the object.
Every object has its own value for each of its member variables. However, it
shares the property names or operations with other instances of the class.
Thus, classes define the characteristics and actions of different objects.
In
following Figure some common objects, their properties, and the actions they
perform have been described. A car can be distinguished from another car on the
basis of its properties, for example, company, model, color, capacity etc. and
also on the basis of its actions for example, speed, average, break etc.
3. METHOD
An
operation required for an object or entity when coded in a class is called a
method. The operations that are required for an object are to be defined in a
class. All objects in a class perform certain common actions or operations.
Each action needs an object that becomes a function of the class that defines
it and is referred to as a method.
In
following Figure, the class, its associated data members, and functions are
shown in different styles. This style is frequently used while writing a class
in the program.
The
class A contains private data members and public methods or member functions.
Generally, the data members are declared private, and member functions are
declared public. We can also define public data members and private member
functions. The data member of any class uses its member functions or methods to
perform operations.
4. DATA ABSTRACTION
Abstraction
directs to the procedure of representing essential features without including
the background details. Classes use the theory of abstraction and are defined
as a list of abstract properties such as size, cost, height, and few functions
to operate on these properties. Data abstraction is the procedure of
identifying properties and methods related to a specific entity as applicable
to the application.
A
powerful method to achieve abstraction is by the manipulation of hierarchical
classifications. It permits us to break the semantics of multiple systems into
layers, by separating them into multiple controllable parts. For example, a
computer is made of various parts such as cpu, keyboard, and so on. We think it
as a single unit, but it has several sub units. These units when combined
together perform the required task. By assembling subparts we can make a single
system.
Hierarchical
abstraction of complicated systems can also be used in computer software. The
data from conventional procedure oriented programs can be converted by
abstraction mechanism into its partial objects. A series of operation steps may
develop a set of messages between these objects. Each object shows its own
attributes.
5.
ENCAPSULATION
The
packing of data and functions into a single component is known as
encapsulation. C++ supports the features of encapsulation using classes. The
data is not accessible by outside functions. Only those functions that are able
to access the data are defined within the class. These functions prepare the
interface between the object's data and the program. With encapsulation data
hiding can be accomplished. Data hiding is an important feature. By data hiding
an object can be used by the user without knowing how it works internally.
In
C++, the fundamental of encapsulation is class. A class defines the structure
of data and member functions. It is common to all its objects. Class is a
logical structure whereas an object is a physical quantity. The goal of the
class is to encapsulate complication. The class also has mechanism for hiding
the data. Each member in the class may be private or public. Any non-member
function cannot access the data of the class. The public section of the class
must be carefully coded not to expose the inner details of the class. Following
Figure explains different sections of encapsulation.
6. INHERITANCE
Inheritance
is the method by which objects of one class get the properties of objects of
another class. In object-oriented programming, inheritance provides the thought
of reusability. The programmer can add new properties to the existing class
without changing it. This can be achieved by deriving a new class from the
existing one. The new class will possess features of both the classes. The
actual power of inheritance is that it permits the programmer to reuse a class
that is close to what he wants, and to tailor the class in such a manner that
it does not bring any unwanted incidental result into the rest of the class.
Thus, inheritance is the feature that permits the reuse of an existing class to
make a new class. The Figure shows an example of inheritance.
In
Figure red, yellow and blue are the main colours. Orange colour is created from
the combination of red and yellow, green is created from yellow and blue, and
violet is created from red and blue. Orange colour has attributes of both red
and yellow, which produces a new effect. Thus, many combinations are possible.
7.
POLYMORPHISM
Polymorphism
makes possible the same functions to act differently on different classes as
shown in following Figure. It is an important feature of OOP concept and has
the ability to take more than one form. Polymorphism accomplishes an important
part in allowing objects of different classes to share the same external
interface. It is possible to code a non-specific (generic) interface to a set
of associated actions.
8.
DYNAMIC
BINDING
Binding
means connecting one program to another program that is to be executed in reply
to the call. Dynamic binding is also known as late binding. The code present in
the specified program is unknown till it is executed. It is analogous to
inheritance and polymorphism.
In
above figure, polymorphism allows single object to invoke similar function from
different classes. The program action is different in all the classes. During
execution time, the code analogous to the object under present reference will
be executed.
9.
Message Passing
Object-oriented
programming includes objects which communicate with each other. Programming
with these objects should be followed in steps shown below:
(1)
Declaring classes that define objects and their actions.
(2)
Declaring objects from classes.
(3)
Implementing relation between objects.
Data
is transferred from one object to another. A message for an object is the
demand for implementation of the process. Message passing as shown in Figure
contains indicating the name of the object, function, and required data
elements.
Objects
can be created, released, and interacted with each other. An object is
workable, as long as it is active. In object-oriented programming, there is a
panorama of independent objects that communicate with each other by swapping
messages. Objects invoke member functions. They also negate if the calling
object is not a member of the same class. Thus a message is a solicitation to
an object to call one of its member functions. A message contains name of the
member function and parameters of the function. Execution of member function is
just a response generated due to receipt of a message. It is possible when the
function and the object are of the same class.
10.
REUSABILITY
Object-oriented
technology allows reusability of classes by extending them to other classes
using inheritance. Once a class is defined, the other programmer can also use
it in their programs and add new features to the derived classes. Once verified
the qualities of base classes need not be redefined. Thus, reusability saves
time.
In
following figure class A is reused and class B is created. Again class B is
reused and class C is created.
11.
Delegation
In
OOP, two classes can be joined either by - inheritance or delegation, which
provide reusability of the class.
In
inheritance, one class can be derived from other class and relationship between
them is known as kind of relationship. For example, if class Y is derived from
class X, then class Y is known as kind of X, as shown in figure (a).
The
second type of relationship is has a relationship. When object of one class is
used as data member in other class, such composition of objects is known as
delegation. As shown in Figure (b) class C has two data members that are
objects of class A and B. Such a relationship between two classes is known as
has a relationship.
12.
Genericity
The
software components of a program have more than one version depending on the
data types of arguments. This feature allows declaration of variables without
specifying exact data type. The compiler identifies the data type at run-time.
The programmer can create a function that can be used for any type of data. The
template feature in C++ allows generic programming.
ADVANTAGES OF OOP
Object-oriented
programming provides many advantages to the programmer and the user. This
technology solves many problems related to software development, provides
improved quality, and low cost software. OOP has the following advantages:
(1)
Object-oriented programs can be comfortably upgraded.
(2)
Using inheritance, redundant program codes can be eliminated and the use of
previously defined classes may be continued.
(3)
The technology of data hiding facilitates the programmer to design and develop
safe programs that do not disturb code in other parts of the program.
(4)
The encapsulation feature provided by OOP languages allows programmer to define
the class with many functions and characteristics and only few functions are
exposed to the user.
(5)
All object-oriented programming languages can create extended and reusable
parts of programs.
(6)
Object-oriented programming enhances the thought process of a programmer
leading to rapid development of new software in short span of time.
USAGE OF OOP
Object-oriented
technology is changing the style of software engineers to think, analyze, plan,
and implement the software. The software developed using OOP technology is more
efficient and easy to update. OOP languages have standard class library. The
users can reuse the standard class library in their program. Thus, it saves lot
of time and coding work.
The
most popular application of object-oriented programming is windows. There are
several windowing software based on OOP technology. Following are the areas for
which OOP is considered:
(1)
Object-Oriented DBMS
(2)
Office automation software
(3)
AI and expert systems
(4)
CAD/CAM software
(5)
Network programming
(6)
System software
USAGE OF C++
C++
is a flexible language. Lengthy programs can be easily controlled by the use of
C++. It creates hierarchy -associated objects and libraries that can be useful
to other programmers. C++ helps the programmer to write bug-free program, which
are easy to maintain.
Input and Output in
C++
Applications
generally involve reading a large amount of data from input devices and sending
them to the output devices. Hence to control such operations every language
provides a set of in-built functions. C++ supports all Input /Output functions
of C. C++ also has library functions. A library is a set of .obj files, which
is linked to the program and gives additional support to its functions. A
programmer can use the library functions in the programs. The library is also
called as iostream library. The difference between C and C++ I/O functions is
that C functions do not support object-oriented platform whereas C++ supports
it.
STREAMS IN C++
C++
supports a number of Input/Output (I/O) operations to read and write
operations. These C++ I/O functions make it possible for the user to work with
different types of devices such as keyboard, disk, tape drivers etc. The stream
is an intermediator between I/O devices and the user. The standard C++ library
contains the I/O stream functions. The I/O functions are part of the standard
library that provides portability to the language itself. A library is nothing
but a set of .obj files. It is connected to the user's program.
Stream
is flow of data in bytes in sequence. If data is received from input devices in
sequence then it is called as source stream and when the data is passed to
output devices then it is called as destination stream. It is also referred as
encapsulation through streams. The data is received from keyboard or disk and
can be passed on to monitor or to the disk. Figure describes the concept of
stream with input and output devices.
STREAM
CLASSES
C++
streams are based on class and object theory. C++ has a number of stream
classes that are used to work with console and file operations. These classes
are known as stream classes. Following figure indicates the stream classes. All
these classes are declared in the header file iostream.h. The file iostream.h
must be included in the program if we are using functions of these classes.
As
described in following figure the classes istream and ostream are derived
classes of base class ios. The ios class contains member variable object
streambuf.v The streambuf places the buffer. The member function of streambuf class
handles the buffer by providing the facilities to flush clear and pour the
buffer. The class iostream is derived from the classes istream and ostream by
using multiple inheritance. The ios class is a virtual class and this is to
avoid ambiguity that frequently appears in multiple inheritance. The chapter on
Inheritance describes multiple inheritance and virtual classes.
UNFORMATTED CONSOLE
I/O OPERATIONS
Input
and Output Streams
The input stream uses
cin object to read data and the output stream uses cout object to display data
on the screen. The cin and cout are predefined streams for input and output of
data. The data type is identified by these functions using operator overloading
of the operators << (insertion operator) and >> (extraction
operator). The operator << is overloaded in the ostream class and the
operator >> is overloaded in istream class.
INPUT STREAM The input stream
does read operation through keyboard. It uses cin as object. The cin statement
uses >> (extraction operator) before variable name. The cin statement is
used to read data through the input device. Its syntax and example are as
follows.
Cin>>variable
Example:
Int
v1;
Float
v2;
Char
v3;
Cin>>v1
>>v2>>v3…>>vn;
OUTPUT STREAM
The output stream manages output of
the stream i.e., displays content of variables on the screen. It uses <<
insertion operator before variable name. It uses the cout object to perform
console write operation. The syntax and example of cout statements are as
follows.
Syntax:
cout<<variable
Example:
cout << v1 << v2
<< v3 … << vn
Where
v1,v2 and v are variables.
MEMBER FUNCTIONS OF
ISTREAM CLASS
The
istream contains following functions that can be called using cin object.
peek( )
It returns the succeeding characters without
extraction.
Example:
cin.peek( )==‘#’;
where
cin is an object and ‘#’ is a symbol to be caught in the stream.
ignore( )
The member function ignore( ) has two
arguments, maximum number of characters to avoid, and the termination
character.
Example:
cin.ignore(1,‘#’);
The
statement ignores 1 character till ‘#’ character is found.
program
to demonstrate the use of peek( ) and ignore( ) functions.
#
include <iostream.h>
#
include <conio.h>
main(
)
{
char c;
clrscr( );
cout <<"enter text (press F6 to
end:) ";
while(cin.get(c))
{
cout<<c;
while(cin.peek( )==‘#’)
{
cin.ignore(1,‘#’);
}
}
return 0;
}
MANIPULATORS
The
output formats can be controlled using manipulators. The header file iomanip.h
has a set of functions. Effect of these manipulators is the same as ios class
member functions. Every ios member function has two formats. One is used for
setting and second format is used to know the previous setting. But the
manipulator does not return to the previous setting. The manipulator can be
used with cout( ) statement as given below.
cout
<<m1 <<m2 <<v1;
Here
m1 and m2 are two manipulators and v1 is any valid C++ variable.
Following
table describes the most useful manipulators. The manipulator hex, dec, oct,
ws, endl, and flush are defined in iostream.h. The manipulator setbase, width(
), fill( ) etc. that requires an argument are defined in iomanip.h.
Manipulator
|
Function
|
Setw(int
n)
|
The
field width is fixed to n
|
Setbase
|
Sets
the base of the number system
|
Setprecision(int
p)
|
The
precision point is set to p
|
Setfill(char
f)
|
The
fill character is set to character stored in variable f
|
Setiosglags(long
l)
|
Format
flag is set to 1
|
Resetiosflags(long
l)
|
Removes
the flagsindicated by 1
|
Endl
|
Splits
a new line
|
Skipws
|
Omit
white space on input
|
Noskipws
|
Does
not omit white space on input
|
Ends
|
Adds
null character to close an output string
|
Flush
|
Flushes
the buffer stream
|
Lock
|
Locks
the file associated with the file handle
|
Ws
|
Used
to omot leading white spaces present before the first field
|
Hex,
oct, dec
|
Display
the number in hexadecimal, octal, and decimal format
|
USER-DEFINED
MANIPULATORS
The
programmer can also define their own manipulator according to the requirements
of the program. The syntax for defining manipulator is given below:
ostream
& m_name( ostream & o )
{
statement1;
statement2;
return o;
}
The
m_name is the name of the manipulator.
program
to create manipulator equivalent to ‘\t’. Use it in the program and format the
output.
#
include <iostream.h>
#
include <iomanip.h>
#
include <conio.h>
ostream
& tab (ostream & o)
{
o <<"\t";
return o;
}
void
main( )
{
clrscr( );
cout <<1<<tab<<2
<<tab<<3;
}
OUTPUT
1
2 3
Following
figure illustrates working of the program.
In
the above program, tab named manipulator is defined. The definition of tab
manipulator contains the escape sequence ‘\t’. Whenever we call the tab
manipulator, the ‘\t’ is executed and we get the effect of tab.
MANIPULATOR
WITH ONE PARAMETER
The
prototype declared in the iomanip.h as described earlier allows us to define
individual set of macros. The manipulator can be created without the use of int
or long arguments.
Program
with one parameter to display the string in the middle of the line.
#
include <iostream.h>
#
include <iomanip.h>
#
include <string.h>
#
include <conio.h>
ostream&
fc (ostream& ost, int iw)
{
for (int k=0;k<((75-iw)/2);k++)
ost <<" ";
return (ost);
}
OMANIP
(int) middle (int iw)
{
return OMANIP (int) (fc,iw);
}
int main( )
{
clrscr( );
char *m=" * Well come *";
cout <<middle (strlen(m)) <<m;
return 0;
}
OUTPUT
** WEL COME **
In
the above program, middle is a user-defined parameterized manipulator. It
receives a value strlen(m) i.e., string length. The header file IOMANIO.H
defines a macro, OMANIO (int). It is expanded to class_OMANIP_int. Due to this
the definition consists of a constructor and an overloaded ostream insertion
operator. When middle( ) function is added into the stream, it invokes the
constructor which generates and returns an OMANIP_int object. The fc( )
function is called by the object constructor.
MANIPULATORS
WITH MULTIPLE PARAMETERS
In
this type of manipulator, multiple arguments are passed on to the manipulator.
The following program explains it.
program
to create manipulator with two arguments.
#
include <iostream.h>
#
include <conio.h>
#
include <iomanip.h>
#
include <math.h>
struct
w_p
{
int w;
int p;
};
IOMANIPdeclare
(w_p);
static
ostream& ff(ostream& os, w_p w_p)
{
os.width (w_p.w);
os.precision(w_p.p);
os.setf(ios::fixed);
return os;
}
OMANIP
(w_p) column (int w, int p)
{
w_p w_p;
w_p.w=w;
w_p.p=p;
return OMANIP (w_p) (ff,w_p);
}
int
main ( )
{
clrscr( );
double n,sq,sqr;
cout <<"number\t"
<<"square\t" <<"\tsquare root\n";
cout <<"===================================\n";
n=1.0;
for
(int j=1;j<16;j++)
{
sq=n*n;
sqr=sqrt(n);
cout.fill(‘0’);
cout <<column(3,0)<<n
<<"\t";
cout <<column(7,1) <<sq
<<"\t\t";
cout <<column(7,6) <<sqr
<<endl;
n=n+1.0;
}
return 0;
}
UNIT II
INTRODUCTION
Before writing any
program it is necessary to know the rules of syntaxes of the language. This
enables a programmer to write error-free programs. The user makes many mistakes
if he/she does not know the rules of the language even though the logic is
clear. Thus the user fails to write programs due to poor knowledge of basic
concepts.
PARTS
OF C++ PROGRAM
A Program consists of
different sections as shown infFigure. Some of them are optional and can be
excluded from the program if not required. For example, every C and C++ program
starts with function main( ), and if the user writes a program without main( ),
it won't be executed. Hence, it is compulsory to write the main( ) function. In
C, the structure allows to combine only variables of different data types. In
addition, C++ allows combining variable and functions in structures and
classes. The structure and classes are same and used for the same purpose.
Functions can be defined inside or outside the class.
(1) Include
Files Section
Like C, C++ program
also depends upon some header files for function definition. Each header file
has an extension.h. The file should be included using # include directive as
per the format given below
#include
<iostream.h>
Or
#incluide “iostream.h”
(2)
Class declaration or
Definition
Declaration
of a class is done in this section. It is also possible to declare class after
the function main(), but it is better to declare it before main() function.
A class
contains data variables, function prototypes or function definitions. The class
always terminated by a semicolon.
Function
prototype declaration reports to the compiler it’s name, return type and
required argument list of the function. The function definition tells the
compiler how the function works.
(3)
Class function
definitions.
This parts contains
definition of functions. The function definition can be done outside or inside
the class. The function defined inside the class are implemented as inline
functions. When a function is large, it is defined outside the class. In this
case, prototype of a function is declared inside the class.
(4)
The Main function
Like c, c++ programs
always start execution from main() function. Thus execution of every program in
c++ starts with main() function.
C++
tokens
The C++ programs contain various
components. The compiler identifies them as tokens. Tokens are classified in
the following types. Figure also indicates types of tokens.
1. Keywords
2. Identifiers
3. Constants
4. Special character(Punctuators)
5. Operators
1.
Keywords
These are some reserved words in C++ which
have predefined meaning to compiler called keywords. Some commonly used Keyword
are given below:
asm auto break case catch
char class const continue default
delete do double else enum
extern inline int float for
friend goto if long new
operator private protected public register
return short signed sizeof static
struct switch template this Try
typedef union unsigned virtual void
volatile while
2.
Identifiers
Symbolic names can be
used in C++ for various data items used by a programmer in his program. A
symbolic name is generally known as an
identifier. The identifier is a sequence of characters taken from C++ character
set. The rule for the formation of an identifier are:
·
An
identifier can consist of alphabets, digits and/or underscores.
·
It
must not start with a digit
·
C++
is case sensitive that is upper case and lower case letters are considered
different from each other.
·
It
should not be a reserved word.
·
Any
other special symbols are not allowed
3.
Literals (Constants)
Literals (often
referred to as constants) are data items that never change their value during
the execution of the program. The following types of literals are available in
C++.
Constant
Decimal Octal
Hexadecimal Floating point Exponent
Integer-Constants
Floating-constants
Character-constants
Strings-constants
Integer
Constants
Integer constants are whole number without any
fractional part. C++ allows three types of integer constants.
Decimal integer
constants : It consists of sequence of digits and should not begin with 0
(zero). For example 124, - 179, +108.
Octal integer constants:
It consists of sequence of digits starting with 0 (zero). For example. 014,
012.
Hexadecimal integer
constant: It consists of sequence of digits preceded by ox or OX.
Floating
constants
They are also called
real constants. They are numbers having fractional parts. They may be written
in fractional form or exponent form. A real constant in fractional form
consists of signed or unsigned digits including a decimal point between digits.
For example 3.0, -17.0, -0.627 etc.
Character
constants
A character constant
in C++ must contain one or more characters and must be enclosed in single
quotation marks. For example 'A', '9', etc. C++ allows nongraphic characters
which cannot be typed directly from keyboard, e.g., backspace, tab, carriage
return etc. These characters can be represented by using an escape sequence. An escape sequence
represents a single character. The following table gives a listing of common
escape sequences.Escape Sequence Nongraphic
Character
\a Bell (beep)
\n Newline
\r Carriage Return
\t Horizontal tab
\0 Null Character
String
Literals
A sequence of
character enclosed within double quotes is called a string literal. String
literal is by default (automatically) added with a special character ‘\0' which
denotes the end of the string. Therefore the size of the string is increased by
one character. For example "COMPUTER" will re represented as
"COMPUTER\0" in the memory and its size is 9 characters.
4.
Punctuators
The following
characters are used as punctuators in C++.
Brackets [ ] Opening
and closing brackets indicate single and multidimensional array subscript.
Parentheses ( ) Opening
and closing brackets indicate functions calls,; function parameters for
grouping expressions etc.
Braces { } Opening
and closing braces indicate the start and end of a compound statement.
Comma , It is used as a separator in a function
argument list.
Semicolon ; It is used as a statement terminator.
Colon : It indicates a labeled statement or
conditional operator symbol.
Asterisk * It is used in pointer declaration or as
multiplication operator.
Equal sign = It is used as an assignment
operator.
Pound sign # It is used as pre-processor
directive.
5.
Operators
Arithmetic Operators
C++ provides five basic arithmetic
operators. These are summarized in Table.
Operator Name Example
+ Addition
12 + 4.9 // gives 16.9
- Subtraction
3.98 - 4 // gives -0.02
* Multiplication
2 * 3.4 // gives 6.8
/ Division
9 / 2.0 // gives 4.5
% Remainder
13 % 3 // gives 1
Except for remainder (%) all other
arithmetic operators can accept a mix of
integer and real operands. Generally,
if both operands are integers then the result
will be an integer. However, if one or
both of the operands are reals then the result
will be a real (or double to be
exact).
When both operands of the division
operator (/) are integers then the division
is performed as an integer division
and not the normal division we are used to.
Integer division always results in an
integer outcome (i.e., the result is always
rounded down).
For example:
9 / 2 //
gives 4, not 4.5!
-9 / 2 // gives -5, not -4!
Unintended integer divisions are a
common source of programming errors. To
obtain a real division when both
operands are integers, you should cast one of the
operands to be real:
int cost = 100;
int volume = 80;
double unitPrice = cost / (double)
volume; // gives 1.25
The remainder operator (%) expects
integers for both of its operands. It returns the remainder of integer-dividing
the operands. For example 13%3 is calculated by integer dividing 13 by 3 to
give an outcome of 4 and a remainder of 1; the result is therefore 1.
It is possible for the outcome of an
arithmetic operation to be too large for
storing in a designated variable. This
situation is called an overflow. The outcome
of an overflow is machine-dependent
and therefore undefined. For example:
unsigned char k = 10 * 92; //
overflow: 920 > 255
It is illegal to divide a number by
zero. This results in a run-time division-byzero
failure which typically causes the
program to terminate. ¨
www.pragsoft.com
Chapter 2: Expressions 19
Relational Operators
C++ provides six relational operators
for comparing numeric quantities. These are
summarized in Table. Relational
operators evaluate to 1 (representing the true
outcome) or 0 (representing the false
outcome).
Operator Name Example
== Equality
5 == 5 //
gives 1 (true)
!= Inequality
5 != 5 //
gives 0(false)
< Less
Than 5 <
5.5 // gives 1(true)
<= Less
Than or Equal 5
<= 5 // gives 1(true)
> Greater
Than 5 > 5.5 //
gives 0(false)
>= Greater
Than or Equal 6.3 >= 5 // gives
1(true)
The
operands of a relational operator must evaluate to a number. Characters are
valid operands since they are represented by numeric values. For example (assuming
ASCII coding):
'A' < 'F' // gives 1 (is like 65
< 70)
The
relational operators should not be used for comparing strings, because this will
result in the string addresses being compared, not the string contents.
For example,
the expression
"HELLO" < "BYE"
causes
the address of "HELLO" to be compared to the address of
"BYE". As these addresses are determined by the compiler (in a
machine-dependent manner), the outcome may be 0 or may be 1, and is therefore
undefined. C++ provides library functions (e.g., strcmp) for the lexicographic
Logical Operators
C++ provides three logical operators
for combining logical expression. These are summarized in following table. Like
the relational operators, logical operators evaluate to 1 or 0.
Operator Name Example
! Logical
Negation !(5 == 5) //
gives 0 (false)
&& Logical And 5 < 6 && 6 < 6 // gives 1
(true)
|| Logical
Or 5 < 6
|| 6 < 5 // gives 1 (true)
Logical negation is a unary operator,
which negates the logical value of its single operand. If its operand is
nonzero it produce 0, and if it is 0 it produces 1.
Logical
and
produces
0 if one or both of its operands evaluate to 0. Otherwise, it produces 1.
Logical
or
produces
0 if both of its operands evaluate to 0. Otherwise, it produces 1.
Note that here we talk of zero and
nonzero operands (not zero and 1). In general, any nonzero value can be used to
represent the logical true, whereas only zero represents the logical false.
The following are all valid logical expressions:
!20 //
gives 0 (false)
10 && 5 // gives 1 (true)
10 || 5.5 // gives 1 (true)
10 && 0 // gives 0 (false)
C++ does not have a built-in boolean
type. It is customary to use the type int
for this purpose instead.
For example:
int sorted = 0; // false
int balanced = 1; // true
Bitwise Operators
C++ provides six bitwise operators for
manipulating the individual bits in an integer
quantity. These are summarized in following
table.
Operator Name Example
~ Bitwise
Negation ~'\011' // gives '\366'
& Bitwise
And '\011' &
'\027' // gives '\001'
| Bitwise
Or '\011' |
'\027' // gives '\037'
^ Bitwise
Exclusive Or '\011' ^ '\027' // gives '\036'
<< Bitwise Left Shift '\011' << 2 // gives '\044'
>> Bitwise Right Shift '\011' >> 2 // gives '\002'
Bitwise operators expect their
operands to be integer quantities and treat them as bit sequences.
Bitwise negation is a unary operator
which reverses the bits in its operands.
Bitwise
and
compares
the corresponding bits of its operands and produces a 1 when both bits are 1,
and 0 otherwise.
Bitwise or compares the corresponding
bits of its operands and produces a 0 when both bits are 0, and 1 otherwise.
Bitwise exclusive
or
compares
the corresponding bits of its operands and produces a 0 when both bits are 1 or
both bits are 0, and 1 otherwise.
Bitwise
left shift
operator
and bitwise right shift operator
both take a bit sequence as their left operand and a positive integer quantity n
as their right operand. The former produces a bit sequence equal to the
left operand but which has been shifted n bit positions to the left. The
latter produces a bit sequence equal to the left operand but which has been
shifted n bit positions to the right. Vacated
bits at either end are set to 0.
The following table illustrates bit
sequences for the sample operands.
unsigned char x = '\011';
unsigned char y = '\027';
Example Octal Value Bit Sequence
x 011
0
0 0 0 1 0 0 1
y 027
0
0 0 1 0 1 1 1
~x 366
1
1 1 1 0 1 1 0
x & y 001 0
0 0 0 0 0 0 1
x | y 037
0
0 0 1 1 1 1 1
x ^ y 036
0
0 0 1 1 1 1 0
x << 2 044 0
0 1 0 0 1 0 0
x >> 2 002 0
0 0 0 0 0 1 0
¨
Increment/Decrement
Operators
The auto increment (++) and auto
decrement (--) operators provide a convenient way of, respectively, adding
and subtracting 1 from a numeric variable. These are summarized in following
table. The examples assume the following variable definition:
int k = 5;
Operator Name Example
++ Auto
Increment (prefix) ++k +
10 // gives 16
++ Auto
Increment (postfix) k++ +
10 // gives 15
-- Auto
Decrement (prefix) --k +
10 // gives 14
-- Auto
Decrement (postfix) k-- + 10
// gives 15
Both operators can be used in prefix
and postfix form. The difference is significant. When used in prefix form, the
operator is first applied and the outcome is then used in the expression. When
used in the postfix form, the expression is evaluated first and then the
operator applied.
Both operators may be applied to
integer as well as real variables, although in
practice real variables are rarely
useful in this form. ¨
Assignment Operator
The
assignment operator is used for storing a value at some memory location (typically
denoted by a variable). Its left operand should be an variable, and its right operand
may be an arbitrary expression. The latter is evaluated and the outcome is stored
in the location denoted by the variable.
The
assignment operator has a number of variants, obtained by combining it with the
arithmetic and bitwise operators. These are summarized in following table. The examples
assume that n is an integer variable.
Operator Example Equivalent To
= n
= 25
+= n
+= 25 n
= n + 25
-= n
-= 25 n
= n - 25
*= n*=
25 n
= n * 25
/= n
/= 25 n
= n / 25
%= n
%= 25 n
= n % 25
&= n &= 0xF2F2 n = n & 0xF2F2
|= n
|= 0xF2F2 n
= n | 0xF2F2
^= n
^= 0xF2F2 n
= n ^ 0xF2F2
<<= n <<= 4 n = n << 4
>>= n >>= 4 n = n >> 4
An
assignment operation is itself an expression whose value is the value stored in
its left operand. An assignment operation can therefore be used as the right operand
of another assignment operation. Any number of assignments can be concatenated
in this fashion to form one expression. It is called multiple assignment.
For example:
int m, n, p;
m = n = p = 100; // means: n = (m = (p = 100));
m = (n = p = 100) + 2; // means: m =
(n = (p = 100)) + 2;
This is equally applicable to other
forms of assignment.
For example:
m = 100;
m += n = p = 10; // means: m = m + (n = p = 10);
¨
Conditional Operator
The conditional operator takes three
operands. It has the general form:
operand1 ? operand2 : operand3
First operand1 is evaluated,
which is treated as a logical condition. If the result is nonzero then operand2
is evaluated and its value is the final result. Otherwise, operand3 is
evaluated and its value is the final result.
For example:
int m = 1, n = 2;
int min = (m < n ? m : n); // min receives 1
Note that of the second and the third
operands of the conditional operator only one is evaluated. This may be
significant when one or both contain side-effects (i.e., their evaluation
causes a change to the value of a variable).
For example,
In int min = (m < n ? m++ : n++);
m is incremented because m++ is
evaluated but n is not incremented because n++
is not evaluated. Because a
conditional operation is itself an expression, it may be used as an
operand of another conditional
operation, that is, conditional expressions may be nested.
For example:
int m = 1, n = 2, p =3;
int min = (m < n ? (m < p ? m :
p) : (n < p ? n : p));
¨
Comma Operator
Multiple expressions can be combined
into one expression using the comma operator. The comma operator takes two
operands. It first evaluates the left operand and then the right operand, and
returns the value of the latter as the final outcome.
For example:
int m, n, min;
int mCount = 0, nCount = 0;
//...
min = (m < n ? mCount++, m :
nCount++, n);
Here when m is less than n, mCount++
is evaluated and the value of m is stored in
min. Otherwise, nCount++ is evaluated
and the value of n is stored in min.
¨
The sizeof Operator
C++ provides a useful operator, sizeof, for calculating the size of any
data item or type. It takes a single operand which may be a type name (e.g.,
int) or an expression (e.g., 100) and returns the size of the specified entity
in bytes. The outcome is totally machine-dependent.
#include <iostream.h>
int main (void)
{
cout << "char size = "
<< sizeof(char) << " bytes\n";
cout << "char* size =
" << sizeof(char*) << " bytes\n";
cout << "short size =
" << sizeof(short) << " bytes\n";
cout << "int size = "
<< sizeof(int) << " bytes\n";
cout << "long size = "
<< sizeof(long) << " bytes\n";
cout << "float size =
" << sizeof(float) << " bytes\n";
cout << "double size =
" << sizeof(double) << " bytes\n";
cout << "1.55 size = "
<< sizeof(1.55) << " bytes\n";
cout << "1.55L size =
" << sizeof(1.55L) << " bytes\n";
cout << "HELLO size =
" << sizeof("HELLO") << " bytes\n";
}
When run, the program will produce the
following output (note: depends machine):
char size = 1 bytes
char* size = 2 bytes
short size = 2 bytes
int size = 2 bytes
long size = 4 bytes
float size = 4 bytes
double size = 8 bytes
1.55 size = 8 bytes
1.55L size = 10 bytes
HELLO size = 6 bytes
¨
Operator Precedence
The
order in which operators are evaluated in an expression is significant and is determined
by precedence rules. These rules divide the C++ operators into a number of
precedence levels. Operators in higher levels take precedence over operators in
lower levels.
Level Operator Kind Order
Highest :: Unary Both
() [] -> . Binary
Left to Right
+ - ++ -- ! ~ * &
new delete sizeof() Unary Right to Left
->* .* Binary Left to Right
* / % Binary Left to Right
+ - Binary Left to Right
<< >> Binary Left to Right
< <= > >= Binary Left to Right
== != Binary Left to Right
& Binary Left to Right
^ Binary Left to Right
| Binary Left to Right
&& Binary Left to Right
|| Binary Left to Right
? : Ternary Left to Right
= += -= *= /= ^= %= &=
|= <<= >>= Binary Right to Left
Lowest , Binary Left to Right
For example,
In
a == b + c * d
c * d is evaluated first because * has
a higher precedence than + and ==. The
result is then added to b because +
has a higher precedence than ==, and then ==
is evaluated. Precedence rules can be overridden using brackets. For example,
rewriting the above expression as
a == (b + c) * d
causes + to be evaluated before *.
Operators with the same precedence
level are evaluated in the order specified
In the table.
For example, in
a = b += c
the evaluation order is right to left,
so first b += c is evaluated, followed by a =b. ¨
Simple Type
Conversion
A value in any of the built-in types
we have see so far can be converted (type-cast)
to any of the other types. For
example:
(int) 3.14 // converts 3.14 to an int
to give 3
(long) 3.14 // converts 3.14 to a long
to give 3L
(double) 2 // converts 2 to a double
to give 2.0
(char) 122 // converts 122 to a char
whose code is 122
(unsigned short) 3.14 // gives 3 as an
unsigned short
As shown by these examples, the
built-in type identifiers can be used as type operators. Type operators
are unary (i.e., take one operand) and appear inside brackets to the left of
their operand. This is called explicit type conversion.
When the type name is just one word,
an alternate notation may be used in which
the brackets appear around the
operand:
int(3.14) // same as: (int) 3.14
In some cases, C++ also performs implicit
type conversion. This happens
when values of different types are
mixed in an expression. For example:
double d = 1; // d receives 1.0
int i = 10.5; // i receives 10
i = i + d; // means: i = int(double(i)
+ d)
In the last example, i + d involves
mismatching types, so i is first converted to
double (promoted) and then
added to d. The result is a double which does not
match the type of i on the left side
of the assignment, so it is converted to int
(demoted) before being assigned
to i.
The above rules represent some simple
but common cases for type
conversion.
Structure
of c++ statement
C++ statement can be categorized
by three types.
1. Sequential
structure
2. Control structure
3. Repetitive
structure
Sequential structure:
The
statements are executed one by one as they appear in the program sequence. It
may be specified by single statement or statement block. More than one
statements are enclosed with braces { } is called statement block.
Example:
Int x=10;
si=p*n*r/100;
total =m1+m2+m3;
{
Statement1;
Statement2;
Statement3;
}
Control structure :
It can
be divided into two types.
i.
Conditional
control
ii.
Unconditional control
Conditional control
In this
conditional control structure the statements are executed based on the
condition. The following are the conditional control statements available in
C++.
1.
Simple
if statement
2.
If..else
statement
3.
Nested
if statement
4.
If
..else ladder statement
5.
Switch
…case statement
Simple if statement
Syntax
:
if
(expression)
statement1;
next_statement;
note : statement1
may be either single or block statement. And expression may be of arithmetic, relational
or logical expression.
when if
statement encountered first the expression will be evaluated.
If the
expression gives non-zero (True) value then the statement1 will be gets
executed and then control goes to next_statement.
If the
expression gives zero (False) value then statement1 will not be executed,
control directly goes to next_statement.
The
following flowchart illustrates the execution of simple if statement.
Example
program(1):
void main()
{
float
BP,NP,HRA=0;
BP=6000;
if(BP>5000)
HRA=BP*10/100;
// single statement
NP=BP+HRA;
cout<<”NP=”<<NP;
}
Output: NP=6600
Example
program (2) :
void main()
{
float BP,NP,HRA=0,TA=0;
BP=6000;
if(BP>5000)
{
HRA=BP*10/100;
//statement block
TA=BP*5/100;
}
NP=BP+HRA+TA;
cout<<”NP=”<<NP;
}
Output
: NP=6900
Example
program (3) :
void
main()
{
float
BP,NP,HRA=0;
BP=5000;
if(BP+1000)
HRA=BP*10/100;
// single statement
NP=BP+HRA;
cout<<”NP=”<<NP;
}
Output
: NP=6600
if…else
statement
Syntax :
if (expression)
statement1;
else
statement2;
next_statement;
note :
statement1 and statement2 may be either single or block statement. And
expression may be of arithmetic, relational or logical expression.
when if
statement encountered first the expression will be evaluated.
If the
expression gives non-zero (True) value then the statement1 will be gets
executed and then control goes to next_statement.
If the
expression gives zero (False) value then statement2 will be executed, and
control goes to next_statement.
The
following flowchart illustrates the execution of if…else statement.
Example
program(1):
void main()
{
float
BP,NP,HRA;
BP=6000;
if(BP>5000)
HRA=BP*10/100;
// single statement
Else
HRA=BP*8/100;
NP=BP+HRA;
cout<<”NP=”<<NP;
}
Output: NP=6600
Example
program (2) :
void main()
{
float
BP,NP,HRA,TA;
BP=6000;
if(BP>5000)
{
HRA=BP*10/100;
//statement block
TA=BP*5/100;
}
Else
{
HRA=BP*8/100;
//statement block
TA=BP*3/100;
}
NP=BP+HRA+TA;
cout<<”NP=”<<NP;
}
Output
: NP=6900
Example
program (3) :
void
main()
{
float
BP,NP,HRA=0;
BP=5000;
if(BP+1000)
HRA=BP*10/100;
// single statement
Else
HRA=BP*8/100;
// single statement
NP=BP+HRA;
cout<<”NP=”<<NP;
}
Output
: NP=6600
Nested
if statement
An if
statement can nested. The if or else block may itself have another if statement
is called nested if.
Syntax
1:
If(expression1)
If expression2)
…
…
If(expression_N)
Statement1;
Next_statement;
Note :
statement1 may be either single or block statement. And expression may be of
arithmetic, relational or logical expression.
Statement1
will be executed only if all the conditions(1 to N) becomes true, otherwise
control directly goes to Next_statement.
Syntax
2:
If(expression1)
{
If(expression2)
Statement1;
else
Statement2;
Next_statement1;
}
else
{
If(expression3)
Statement3;
else
Statement4;
Next_statement2;
}
Next_statement3;
Note :
All statements(1 to 4) are may be either single or block statement. And
expressions(1 to 3) may be of
arithmetic, relational or logical expression.
Both of
the expressions 1 & 2 gets non_zero(true) values then the statement1,
Next_statement1 will be executed and then control goes to Next_Statement3.
If
expression1 becomes true but expression2 is false then the
statement2,Next_statement1 are executed and then control goes to
Next_statement3.
If
expression1 becomes false but expression3 is true then the
statement3,Next_statement2 are gets executed and then control goes to
Next_statement3.
Both of
the expressions 1 & 3 gets zero(false) values then the statement4,
Next_statement2 will be executed and then control goes to Next_Statement3.
Example Program 1:
void main()
{
float BP,HRA=0;
int cc=1
BP=6000;
if(BP>5000)
If(CC==1)
HRA=BP*10/100;
NP=BP+HRA;
Cout<<”NP =
“<<NP;
}
Output :
NP = 6600.00
Example program 2 :
void
main()
{
float
BP,NP,HRA,TA;
int
cc=1;
BP=6000;
if(BP>5000)
{ if(CC==1)
{
HRA=BP*10/100;
//statement block
TA=BP*5/100;
}
else
{
HRA=BP*8/100;
//statement block
TA=BP*3/100;
}
cout<<”Basic
Pay is greater than 5000”<<endl;
}
else
{
if(CC==1)
{
HRA=BP*6/100;
//statement block
TA=BP*2/100;
}
else
{
HRA=BP*4/100;
//statement block
TA=BP*2/100;
}
cout<<”Basic
Pay is less than 5000”<<endl;
}
NP=BP+HRA+TA;
cout<<”NP=”<<NP;
}
Output :
Basic Pay is
greater than 5000
6900.00
If…else
Ladder
Syntax :
if(expression1)
Statement1;
else if(expession2)
statement2;
else
if(expression3)
statement3;
……
……
else
if(expression_N)
Statement_N;
else
Default_Statement;
Next_Statement;
Note : All
statements(1 to N and Default_Statement) are may be either single or block
statement. And expressions(1 to N) may
be of arithmetic, relational or logical expression.
When this statement
encountered first the expression1 is exercised, if it gets non_zero(True) value
then the statement1 will be executed and then control goes to Next_Statement.
If expression1 become
zero(false) then the expression2 is exercised, it gets non_zero(true) value
then the statement2 will be executed and then control goes to Next_Statement.
In this way all the
expressions are exercised, when ever expression gets non_zero(true) value then
the corresponding statement will be gets executed and immediately control goes
to Next_Statement.
If no expressions
gets non_zero(true) value then the Default_Statement will be executed and then
control goes to Next_Statement.
The following
flowchart illustrates the execution of if …else ladder statement.
…………………………………………………
…………………………………………………
Example Program 1:
void
main()
{
float
BP,NP,HRA,TA;
BP=6000;
if(BP<5000)
{
HRA=BP*4/100;
TA=BP*2/100;
}
else if(BP<10000)
{
HRA=BP*6/100;
TA=BP*4/100;
}
else if(BP<15000)
{
HRA=BP*8/100;
TA=BP*6/100;
}
else
if(BP<20000)
{
HRA=BP*8/100;
TA=BP*6/100;
}
else
{
HRA=BP*6/100; TA=BP*2/100;
}
NP=BP+HRA+TA;
cout<<”NP=”<<NP;
}
Output :
NP=6600.00
Switch…case
statement
Syntax :
switch(Arithmetic_expression)
{
case value1:
statement sequence1;
…..
……
break;
case
value2:
statement
sequence2;
…..
…..
break;
case value3:
statement
sequence3;
…..
…..
break;
………………………………
………………………………
……………………………..
case valueN:
statement
sequenceN;
…..
…..
break;
default:
default
statement sequence;
…..
…..
}
Next_Statement;
When switch statement
encountered first the arithmetic expression to be evaluated, the value of
arithmetic expression is equal to value1 then the statement sequence1 will be
executed and then sequence control transferred to Next_statement by break statement. If the
value of arithmetic expression is equal to value2 then the statement sequence2
will be gets executed.
In this way the value
of arithmetic expression is compared with all the case values from value1 to
valueN. whenever the value of expression is matched with the case value then
the subsequent statements are gets executed.
If there is no value
matched case value, the default statement sequence will be gets executed.
The following
flowchart illustrates the execution of switch ..case statement.
fd
……………………………………………………
…………………………………………………....
……………………………………………………
Example program1:
void main()
{
int x;
cout<<”Enter the
value for x<<endl;
top:
cin>>x;
switch(x)
{
case 1:
cout<<
“ONE”;
break;
case 2:
cout<<”ONE”<<endl;
cout<<”TWO”<<endl;
break;
case 3:
cout<<”ONE”<<endl;
cout<<”TWO”<<endl; cout<<”THREE”<<endl;
break;
default:
cout<<”Please
enter from 1 to 3”;
goto
top;
}
}
Output:
Enter the value for x
3
ONE
TWO
THREE
Example program2:
void main()
{
int x,y,z;
char op;
cout<<”Enter the values for x
and y<<endl;
cin>>x>>y;
cout<<”Enter the arithmetic
operator”<<endl;
cin>>op;
switch(op)
{
case ‘+’ :
cout<<”Arithmetic
Addition”<<endl;
z=x+y;
break;
case ‘-’ :
cout<<”Arithmetic
Subtraction”<<endl;
z=x-y;
break;
case ‘*’ :
cout<<”Arithmetic
Multiplication”<<endl;
z=x*y;
break;
case
‘/’ :
cout<<”Arithmetic
Division”<<endl;
z=x/y;
break;
case ‘%’ :
cout<<”Arithmetic
Modulo division”<<endl;
z=x%y;
break;
default:
cout<<”Please
enter the valid arithmetic operator”<<endl;
goto
first;
}
cout<<z;
}
Output :
Enter the values for
x and y
10
3
Enter the arithmetic
operator
%
Arithmetic modulo
division
1
Example program3:
void main()
{
char ch;
cout<<”Enter the character”;
cin>>ch;
switch(ch)
{
case ‘a’:
case ‘A’:
case ‘e’:
case ‘E’:
case ‘i’:
case ‘I’:
case ‘o’:
case ‘O’:
case ‘u’:
case ‘U’:
cout<<”Entered
character is vowel”<<endl;
break;
default:
cout<<”Entered
character is consonant”<<endl;
}
}
Output:
Enter the character
K
Entered character is
consonant
Repetitive
structure (Looping structure)
These repetitive
structure statements are used to execute a block of statement as more than one
time. There are three types of repetitive structure used in c++. In any looping
statement we should maintain the following four things as properly.
1.
Proper
Loop control variable
2.
The
loop control variable must be initialized before starting of loop
3.
The
loop must have proper termination condition
4.
The
loop control variable properly incremented or decremented in right place.
If any one
of thing is fail, we get infinite loop.
The following are the
repetitive structures used in c++
1.
while
statement
2.
do
while statement
3.
for
statement
while statement
Syntax :
while(expression)
{
// Body-of- loop
………
………
……..
}
Next-Statement;
note : expression may
be of arithmetic, relational or logical expression.
When while statement
encountered first the expression to be evaluated. If the value of expression is
non zero(true) value then the body of the loop will be executed. Again the
expression is exercised it gets true again the body-of-loop gets executed.
This process is
repeated again and again until the expression gets zero (false) value. Whenever
expression gets zero(false) value the body-of-loop will be skipped and control
goes to Next- statement.
It is noted that, if
the expression gets zero (false) value at the first time the body-of-loop does
not executed at least one time. Here the loop is controlled at entry level.
Since it is called Entry Control Loop.
The following
flowchart illustrate the execution of while statement.
Example program 1:
void main()
{
int i; // loop control variable
declared
i=1;// loop control variable
initialized
while(i<=5) // termination
condition
{
cout<<i<<endl;
i++; // control variable
incremented
}
}
Output :
1
2
3
4
5
Example program 2:
void main()
{
int i; // loop control variable
declared
i=10;// loop control variable
initialized
while(i<=5) // termination
condition
{
cout<<i<<endl;
i++; // control variable
incremented
}
}
Output :
No output displayed
Because the
expression gets false value in first attempt.
Example program 3:
void main()
{
int i; // loop control variable
declared
i=1;// loop control variable
initialized
while(i<=5) // termination
condition
{
cout<<i<<endl;
}
}
Output :
1
1
1
…
…
…
The number 1 will be
displayed repetitively, Because the expression gets always true value due to
not increment of control variable i. It forms infinite loop.
Example program 4
(Amstrong number):
void main()
{
int N;
cout<<”Enter the value for
N”<<endl;
cin>>N; // N=153
Temp=N;
while(N) // termination condition
{
R=N%10;
S=S+R*R*R;
Q=N/10;
N=Q;
}
If (Temp==S)
cout<<”Givin
number is amstrong”;
else
cout<<”Givin
number is not amstrong”;
}
Output :
Enter the value for N
153
Given number is
amstrong
do…while
statement
Syntax :
do
{
Body-of-loop;
…..
…..
…..
}while(expression);
Next-statement;
When do…while
statement encountered first the body-of-loop will be executed and finally the
expression becomes evaluated. If expression gets non zero (true) value again
the body-of-loop will gets executed.
This repetitive
process will occur again and again until the expression gets zero (false)
value. Whenever expression gets zero (false) value the body-of-loop will be
skipped and control goes to Next- statement.
It is noted that, the
expression is evaluated at end. Even though expression gets zero (false) value,
The body-of-loop is executed at least one time.
Here the loop is controlled at exit level. Since it is called Exit Control Loop.
The following flowchart
illustrate the execution of do…while statement.
Example program 1:
void main()
{
int i; // loop control variable
declared
i=1;// loop control variable
initialized
do
{
cout<<i<<endl;
i++; // control variable
incremented
} while(i<=5) //
termination condition
}
Output :
1
2
3
4
5
Example program 2:
void main()
{
int i; // loop control variable
declared
i=10;// loop control variable
initialized
do
{
cout<<i<<endl;
i++; // control variable
incremented
} while(i<=5) //
termination condition
}
Output :
10
Because the
expression gets false value in first attempt.
Example program 3:
void main()
{
int i; // loop control variable
declared
i=1;// loop control variable
initialized
do
{
cout<<i<<endl;
} while(i<=5) //
termination condition
}
Output :
1
1
1
…
…
…
The number 1 will be
displayed repetitively, Because the expression gets always true value due to
not increment of control variable i. It forms infinite loop.
Example program 4
(Amstrong number):
void main()
{
int N;
cout<<”Enter the value for
N”<<endl;
cin>>N; // N=153
Temp=N;
do
{
R=N%10;
S=S+R*R*R;
Q=N/10;
N=Q;
} while(N) // termination condition
If (Temp==S)
cout<<”Givin
number is amstrong”;
else
cout<<”Givin
number is not amstrong”;
}
Output :
Enter the value for N
153
Given number is
amstrong
for
statement
In the case of while
and do…while statements, initialization, termination condition and increment of
control variable are done by different statement sequence position. In for
statement these things may encapsulate in single statement. The syntax of the
for statement is as bellow.
for(initialization ;
test-expression ; increment/decrement)
{
Body-of-loop;
………
……...
……..
}
Next-statement;
When for statement encountered first
the initialization of control variable is done, and then exercise the
test-expression, if it gets non zero (true) value the body-of-loop will gets
executed. After that the control variable is incremented / decremented by
increment/decrement part. Again the test-expression becomes exercised, it gets
true value the body-of-loop is executed again.
This process will occur again and
again until the test-expression gets zero (false) value. whenever
test-expression gets zero (false) value the body-of-loop will be skipped and
control goes to next-statement.
It is noted that, if
the test-expression gets zero (false) value at the first time the body-of-loop
does not executed at least one time. Here the loop is controlled at entry
level. Since it is called Entry Control
Loop.
The following
flowchart illustrates the execution of for loop.
Example program 1:
void main()
{
int i; // loop control variable
declared
for(i=1;i<=5:i++)
{
cout<<i<<endl;
}
}
We can also rewrite
the above program as follow
void main()
{
int i; // loop control variable
declared
i=1;
for( ;i<=5: )
{
cout<<i<<endl;
i++;
}
}
Both program gives
following output
Output :
1
2
3
4
5
Example program 2:
void main()
{
int i; // loop control variable
declared
for(i=10;i<=5:i++)
{
cout<<i<<endl;
}
}
Output :
No output displayed
Because the
expression gets false value in first attempt.
Example program 3:
void main()
{
int i; // loop control variable
declared
for(i=1;i<=5:)
{
cout<<i<<endl;
}
}
Output :
1
1
1
…
…
…
The number 1 will be
displayed repetitively, Because the expression gets always true value due to
not increment of control variable i. It forms infinite loop.
Pointers
and arrays
INTRODUCTION
In C++ variables are
used to hold data values during program execution. Every variable when declared
occupies certain memory locations. It is possible to access and display the
address of memory location of variables using ‘&’ operator. Memory is arranged
in series of bytes. These series of bytes are numbered from zero onwards. The
number specified to a cell is known as memory address. Pointer variable
stores the memory address of any type of variable. The pointer variable and
normal variable should be of the same type. The pointer is denoted by (*)
asterisk symbol.
Definition:
A
pointer is a memory variable that stores a memory address. Pointers can have
any name that is legal for other variables and it is declared in the same
fashion like other variables but it is always denoted by * operator.
Features of Pointers
1.
Pointes save the memory
space.
2.
Execution time with
pointer is faster because data is manipulated with the address i.e., direct
access to memory location.
3.
The memory is accessed
efficiently with the pointers. The pointer assigns the memory space dynamically
that leads you to reserve a specific bytes in the memory.
4.
Pointers are used with
data structures. They are useful for representing two-dimensional and
multi-dimensional arrays.
5.
In C++,a pointer declared to a base class could access the
objects of derived class. Whereas a pointer to derived class cannot access the
objects of base. The compiler will generate an error message “cannot covert
‘A*’ to ‘B *’ “ where A is the base class and B is the derived class.
POINTER DECLARATION
Pointer variables can be
declared as below:
Example
int *x;
float *f;
char *y;
(1) In the first statement
‘x’ is an integer pointer and it informs to the
compiler that it holds the address of any integer variable. In the same way, ‘f’ is afloat pointer that stores the address of any
float variable and ‘y’ is acharacter pointer
that stores the address of any character variable.
(2) The indirection operator (*) is also called the deference operator.When a
pointer is dereferenced, the value at that address stored by the pointer is
retrieved.
(3) Normal variable
provides direct access to their own values whereas a pointer indirectly
accesses the value of a variable to which it points.
(4) The indirection operator (*) is used in two distinct ways with
pointers, declaration and deference.
(5) when pointer is
declared, the star indicates that it is a pointer, not a normal variable.
(6) when the pointer is
dereferenced, the indirection operator indicates that the value at that memory
location stored in the pointer in the pointer is to be accessed rather than the
address itself.
(7) Also note that * is
the same operator that can be used as the multiplication operator. The compiler
knows which operator to call, based on context.
(8) The ‘&’ is the
address operator and it represents the address of the variable. The address of
any variable is a whole number. The operator ‘&’ immediately preceding the
variable returns the address of the variable. In the example given bellow
‘&’ is immediately preceding the variable ‘num’ which provides address of
the variable.
Example program 1:
//Program for displaying
the address of the vaiable
#include
<iostream.h>
#include<conio.h>
main()
{
int n;
clrscr()
cout<<”Enter a Number = “;
cin>>n;
cout<<”Value of n = “ <<n<<endl;
cout<<”Address of n = “ << (unsigned) &n;
getch();
}
Output :
Enter a Number = 10
Value of n= 10
Address of n = 4068
Example program 2 :
// Program using pointer
variable
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
void main()
{
int *p;
int x=10;
p=&x;
clrscr();
cout<<”\n x= “<<x <<”&x=”<<
&x<<endl;
cout<<”\n value of x using pointer *p=”<<
*p<<endl;
cout<<Address of x using pointer p=”<<p;
}
Output :
X= 10 &x= 4096
Value of x using pointer
*p = 10
Address of x using pointer
p = 4096
VOID POINTERS
Pointers can
also be declared as void type. Void pointers cannot be dereferenced without
explicit type conversion. This is because being void the compiler cannot
determine the size of the object that the pointer points to. Though void
pointer declaration is possible, void variable declaration is not allowed.
Thus, the declaration void p will
display an error message “Size of ‘p’ is unknown or zero” after compilation.
It is not
possible to declare void variables like pointers. Pointers point to an existing
entity. A void pointer can point to any type of variable with proper
typecasting. The size of void pointer displayed will be two. When pointer is
declared as void, two bytes are allocated to it. Later using typecasting,
number of bytes can be allocated or de-allocated. Void variables cannot be
declared because memory is not allocated to them and there is no place to store
the address. Therefore, void variables cannot actually serve the job they are
made for.
Example poogam :
//Program for usage of
void pointer
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
int p;
float d;
char c;
void *pt=&p; //pointer to p
void main()
{
clrscr();
*(int *)pt=12;
cout<<”\n p=”<<p;
pt=&d; //pointer
to d
*(float *)pt=5.4;
cout<<”\n d= “<<d;
pt=&c; //pointer
to c
*(char *)pt=’S’;
cout<<”\n c=”<<c;
}
Output :
P=12
R=5.4
C=S
WILD POINTERS
Pointers are
used to store memory addresses. An improper use of pointers creates many errors
in the program. Hence, pointers should be handled cautiously. When pointer
points to an unallocated memory location or to data value whose memory is
deallocated, such a pointer is called as wild pointer. The wild pointer
generates garbage memory location and pendent reference.
When a
pointer pointing to a memory location gets vanished, the memory turns into
garbage memory. It indicates that memory location exists but pointer is
destroyed. This happens when memory is not de-allocated explicitly.
The pointer
becomes wild pointer due to the following reasons:
(1)
Pointer declared but not initialized
(2)
Pointer alteration
(3)
Accessing destroyed data
Example program :
#include<iostream.h>
#include<conio.h>
int main()
{
clrscr();
int
*x;
for(int
k=0;k<10;k++)
cout<x[k]<<” “;
return
0;
}
Output :
28005
27760 29793 29541
29728 8303 25954 28704
25205 26988
POINTER TO CLASS
We know that pointer is a variable that holds
the address of another data variable. The variable may be of any data type
i.e., int, float or double. In the same way, we can also
define pointer to class. Here, starting address of the member variables can be
accessed. Such pointers are called class pointers.
Example:
class book
{
char name [25];
char
author [25];
int
pages;
};
a) class book *ptr;
or
a) struct book *ptr;
In the above example, *ptr is pointer
to class book. Both the statements (a) and (b) are valid. The syntax for using
pointer with member is given below.
1) ptr->name 2)
ptr->author 3) ptr->pages.
By executing these three
statements, starting address of each member can be estimated.
Example pogram:
//Program for pointer to class
#include<iostream.h>
#include<conio.h>
void main()
{
class man
class man
{
public:
char name[10];
int
age;
};
man m={”Akash”, 15};
man *ptr;
ptr=&(man)m;
// *ptr=(man) m;
// *ptr=man(m);
// *ptr=m;
// ptr=&m;
clrscr();
cout<<”\n”<<m.name<<” “<<m.age;
cout<<”\n”<<ptr->name<<” “<<ptr->age;
}
Output :
Akash 15
Akash 15
POINTER TO
OBJECT
Like variables, objects also have an address. A pointer can point
to specified object. The following program illustrates this.
//program to declare an object and pointer to the class. Invoke
member functions using pointer.
# include <iostream.h>
# include <conio.h>
class Bill
{ int qty;
float price;
float amount;
public :
void getdata (int a, float b, float c)
{
qty=a;
price=b;
amount=c;
}
void show( )
{
cout <<"Quantity : " <<qty <<"\n";
cout <<"Price : " <<price <<"\n";
cout <<"Amount : " <<amount <<"\n";
}
};
int main( )
{
clrscr( );
Bill s;
Bill *ptr =&s;
ptr->getdata(45,10.25,45*10.25);
(*ptr).show( );
return 0;
}
Output :
Quantity : 45
Price : 10.25
Amount : 461.25
The this Pointer
Use of this pointer is now
outdated. The objects are used to invoke the non-static member functions of the
class. For example, if p is an
object of class P and get( ) is a member function of P, the statement p.get( ) is used to call the function. The
statement p.get( ) operates
on p. In the same way if ptr is a pointer to P object,
the function called ptr->get( ) operates
on *ptr.
However, the question is,
how does the member function get( ) understand
which p it is functioning on? C++ compiler
provides get(
) with a pointer to p called this. The pointer this is transferred as an unseen parameter
in all calls to non-static member functions. The keyword this is a local variable that is always
present in the body of any non-static member function.
Example program :
// Program to demonstrate
the this pointer
#include<iostream.h>
#include<conio.h>
class number
{
Int num;
public:
void input()
{
cout<<”\n Enter a Number :”;
cin>>num;
}
void show()
{
cout<<”\n
The Minimum Number : “ <<num;
}
number min(number t)
{
If(t.num<num)
return
t;
else
return
*this;
}
};
void main()
{
clrscr();
number n,n1,n2;
n1.input();
n2.input();
n=n1.min(n2);
n.show();
}
Output :
Enter a Number : 152
Enter a Number : 458
The Minimum Number : 152
POINTER TO DERIVED CLASSES AND BASE CLASSES
It is possible to declare
a pointer which points to the base class as well as the derived class. One
pointer can point to different classes. For example, X is a base class and Y is a derived class. The pointer
pointing to X can
also point to Y.
/* program to declare a pointer to the base class and access the
member variable of base and derived class. */
// Pointer to base object //
# include <iostream.h>
# include <conio.h>
class A
{
public :
int b;
void display( )
{
cout <<"b = " <<b <<"\n";
}
};
class B : public A
{
public :
int d;
void display( )
{
cout <<"b= " <<b <<"\n" <<" d="<<d <<"\n";
}
};
main( )
{
clrscr( );
A *cp;
A base;
cp=&base;
cp->b=100;
// cp->d=200; Not Accessible
cout <<"\n cp points to the base object \n";
cp->display( );
B b;
cout <<"\n cp points to the derived class \n";
cp=&b;
cp->b=150;
// cp->d=300; Not accessible
cp->display( );
return 0;
}
Output :
cp points to base object
b=100
cp points to the derived class
b=150
POINTER
TO MEMBERS
It is possible to obtain
address of member variables and store it to a pointer. The following program
explain how to obtain address and accessing member variables with pointers.
/* program to initialize and display the contents of the structure
using dot (.) and
arrow (->) operator. */
# include <iostream.h>
# include <conio.h>
int main ( )
{
clrscr( );
struct c
{
char *name;
};
c b, *bp;
bp->name=" CPP";
b.name="C &";
cout<<b.name;
cout<<bp->name;
return 0;
}
ACCESSING
PRIVATE MEMBERS WITH POINTERS
The public and private
member variables are stored in successive memory locations. The following
program explains how private members can also be accessed using pointer.
// program to access private members like public members of the
class using pointers.
# include <iostream.h>
# include <conio.h>
class A
{
private:
int j;
public :
int x;
int y;
int z;
A ( )
{
j=20;
}
};
void main( )
{
clrscr( );
A a;
int *p;
a.x=11;
a.y=10;
a.z=15;
p=&a.x;
p--;
cout<<endl<<"j ="<<*p;
p++;
cout<<endl<<"x= "<<*p;
p++;
cout<<endl<<"y= "<<*p;
p++;
cout<<endl<<"z= "<<*p;
}
OUTPUT
j =20
DIRECT ACCESS TO PRIVATE MEMBERS
we have initialized private
members of the class using constructor or member function of the same class. In
the same way, we can initialize private members and display them. Obtaining the
address of any public member variable and using address of the object one can
do this. The address of the object contains address of the first element.
Programs concerning this are explained below:
/* program to initialize the private members and display them
without the use of member functions. */
# include <iostream.h>
# include <conio.h>
class A
{
private :
int x;
int y;
};
void main( )
{
clrscr( );
A a;
int *p=(int*)&a;
*p=3;
p++;
*p=9;
p--;
cout <<endl <<"x= "<<*p;
p++;
cout <<endl<<"y= "<<*p;
}
Output :
x=3
y=9
ADDRESS
OF OBJECT AND VOID POINTERS
The size of object is
equal to number of total member variables declared inside the class. The size
of member function is not considered in object. The object itself contains
address of first member variable. By obtaining the address we can access the
member variables directly, no matter whether they are private or public. The
address of object cannot be assigned to the pointer of the same type. This is
because increase operation on pointers will set the address of object according
to its size (size of object=size of total member variables). The address of
object should be increased according to the basic data type. To overcome this
situation a void pointer is useful. The type of void pointer can be changed at
run-time using typecasting syntax. Thus, all the member variables can be
accessed directly.
// Program to declare void pointers and access member variables
using void pointers.
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
class A
{
protected :
int
x;
int
y;
};
class B : public A
{
public :
int
z;
B()
{
x=10;
y=20;
z=30;
}
};
void main()
{
clrscr();
B b;
int j;
void *p=&b;
for(j=0;j<3;j++)
printf(“\n
member variable [%d]= %d”,j+1,*((int *)p+j);
}
Output :
member
variable[1]=10
member variable[2]=20
member
variable[3]=30
ARRAYS
Array is a collection of elements of similar data types in which
each element is unique and located in separate memory locations.
(1) Array
Declaration and Initialization
Declaration of an array is shown below:
Declaration
int
a [5];
It tells to the compiler
that ‘a’ is an integer type of array and it must
store five
integers. The compiler reserves two bytes of memory for each integer
array element. In the same way array of different data types are declared as
below:
Array
Declaration
char
ch [10];
float
real [10];
long
num [5];
The array initialization
is done as given below:
Array
Initialization
int
a [5]={1,2,3,4,5};
Here, five elements are stored in an array ‘a’. The array elements are stored sequentially in
separate locations. Then question arises how to call individually to each
element from this bunch of integer elements. Reading of array elements begins
from zero.
CHARACTERISTICS
OF ARRAYS
(1) The declaration int a[5] is nothing but creation of five variables
of integer type in memory. Instead of declaring five variables for five values,
the programmer can define them in an array.
(2) All the elements of an array share the
same name, and they are distinguished from one another with the help of element
number.
(3) The element number in an array plays
major role in calling each element.
(4) Any
particular element of an array can be modified separately without disturbing
other elements.
int a [5]={1,2,3,4,8};
If the programmer needs to replace 8 with 10, he/she is not required to change all other numbers except 8. To carry out this task the statement a[4]=10 can be used. Here the other three elements are not disturbed.
int a [5]={1,2,3,4,8};
If the programmer needs to replace 8 with 10, he/she is not required to change all other numbers except 8. To carry out this task the statement a[4]=10 can be used. Here the other three elements are not disturbed.
(5) Any
element of an array a[] can be assigned/equated to another ordinary variable or
array variable of its type.
INITIALIZATION
OF ARRAYS USING FUNCTIONS
The programmers always
initialize the array using statement like int d[ ]={1,2,3,4,5}. Instead of this the function can
also be directly called to initialize the array. The program given below
illustrates this point.
//program to initialize an array using functions.
# include <stdio.h>
# include <conio.h>
main( )
{
int k,c( ),d[]={c( ),c( ),c( ),c( ),c( )};
clrscr( );
printf ("\n Array d[] elements are :");
for (k=0;k<5;k++)
printf ("%2d",d[k]);
return (NULL);
}
c( )
{
static int m,n;
m++;
printf ("\nEnter Number d[%d] : ",m);
scanf ("%d",&n);
return(n);
}
OUTPUT:
Enter Number d[1] : 4
Enter Number d[2] : 5
Enter Number d[3] : 6
Enter Number d[4] : 7
Enter Number d[5] : 8
Array d[] elements are : 4 5 6 7
8
ARRAYS OF
CLASSES
We know that array is a
collection of similar data types. In the same way, we can also define array of
classes. In such type of array, every element is of class type. Array of class
objects can be declared as shown below:
class stud
{
public:
char name [12]; // class declaration
int rollno;
char grade[2];
};
class stud st[3]; // declaration of array of class objects
In the above example, st[3] is an array of three elements containing
three objects of class stud. Each element of st[3] has
its own set class member variables i.e., char name[12], int rollno and char grade[2].
A program is explained as given below:
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
void main()
{ int k=0;
class stud
{
char
name[12];
int
rollno;
char
grade[2];
};
class stud st[3];
while(k<3)
{
clrscr();
gotoxy(2,4);
cout<<”Name
:”;
gotoxy(17,4);
cin>>st[k].name;
gotoxy(2,5);
cout<<”Roll No. : “;
gotoxy(17,5);
cin>>st[k].rollno;
gotoxy(2,6);
cout<<”Grade
:”;
gotoxy(17,6);
cin>>st[k].grade;
st[k].grade[1]=’\0’;
puts(“ press any key…”);
getch();
K++;
}
K=0;
clrscr();
cout<<”\n Name\t Rollno Grade \n”;
while(k<3)
{
Cout<<st[k].name<<”\t”<<st[k].rollno<<”\t”<<st[k].gade<<”\n”;
K++;
}
}
Output :
Name Rollno Grade
Balaji 50 A
Manoj 51 B
Sanjay 55 C
Unit III
C++
Functions
When the concept of
function or sub-program was not introduced, the programs were large in size and
code got repeated. It was very difficult to debug and update these large
programs because many bugs were encountered. When the functions and
sub-programs are introduced, the programs are divided into a number of segments
and code duplication is avoided. Bugs in small programs can be searched easily
and this step leads to the development of complex programs with functions.
One of the features
of C/C++ language is that a large sized program can be divided into smaller
ones. The smaller programs can be written in the form of functions. The process
of dividing a large program into tiny and handy sub-programs and manipulating
them independently is known as modular programming. This technique is similar
to divide-and-conquer technique. Dividing a large program into smaller
functions provides advantages to the programmer. The testing and debugging of a
program with functions becomes easier. A function can be called repeatedly
based on the application and thus the size of the program can be reduced. The message
passing between a caller (calling function) and callee (called function) takes
places using arguments. The concept of modular approach of C++ is obtained from
function.
THE main( ) FUNCTION
IN C AND C++
In C++, the function
main( ) always returns integer value to operating system by default. The return
value of the function main( ) is used by the operating system to check whether
the program is executed successfully or not. If the returned value is zero (0),
it means that the program is executed successfully. A non-zero value indicates
that the program execution was unsuccessful. The statement return 0 indicates
that the program execution is successful. The prototype of main( ) function in
C++ follows below:
int main( );
int main(int argc,
char *argv[]);
The return statement
is used to return value. If there is no return statement, compiler displays a
warning message “Function should return a value”. The main( ) function in C++
is explained with example as below.
main() in c++
int main()
{
statement1;
statement2;
return 0;
}
Return type is
specified
The return statement
is used
Can be declared as
void. If declared void no need of return statement.
Parts
of function
A function has the
following parts
1.
Function
prototype declaration
2.
Definition
of a function(function declarator)
3.
Function call
4.
Actual
and formal arguments
5.
The
return statement
Function prototype
declaration
A function prototype declaration
consists of the function return type, name, and arguments list. It tells the
compiler (a) the name of the function, (b) the type of value returned, and (c)
the type and number of arguments.
PASSING
ARGUMENTS
The main objective of
passing argument to function is message passing. The message passing is also
known as communication between two functions i.e., between caller and callee
functions. There are three methods by which we can pass values to the function.
These methods are.
(a) Call by value
(pass by value),
(b) Call by address
(pass by address), and
(c) Call by reference
(pass by reference).
C++ supports all
these three types of passing values to the function whereas C supports only the
first two types. The arguments used to send values to function are known as
input-arguments. The arguments used to return results are known as output
arguments. The arguments used to send as well as return results are known as
input-output arguments. While passing values the following conditions should be
fulfilled.
RETURN BY REFERENCE
We have studied the reference variable and it's
functioning. A reference allows creating alias for the preexisting variable. A
reference can also be returned by the function. A function that returns
reference variable is in fact an alias for referred variable. This technique of
returning reference is used to establish cascade of member functions calls in
operator overloading. Consider the following example:
The program given below illustrates return by
reference.
//Write a program to return a value by reference.
# include <iostream.h>
# include <constream.h>
void main( )
{
clrscr(
);
int
& min ( int &j, int &k);
int
a=18,b=11,c;
c=min
(a,b);
cout
<<"Minimum Value = "<<c;
}
int
& min(int &j, int &k)
{
if (k<j )
return k;
else
return
j;
}
RETURNING MORE VALUES BY REFERENCE
The return( ) statement has one big
limitation that it can return only one value at a time. The return(
) statement is only used when values are passed by value to functions.
Call by address and call by reference, accesses memory location directly. When
the user wants to return more than one value from function, he/she should pass
values by address or by reference method. In C, for returning more values, call
by address is used. In C++ we have one additional method i.e., call by
reference. Consider the following program:
Write a program to return
more than one value from function by reference.
# include <iostream.h>
# include <constream.h>
void main( )
{
int
sq,cb,n;
void
more(int &, int &, int);
cout
<<"\n Enter a Number : ";
cin>>n;
more(sq,cb,n);
cout
<<"\n Square ="<<sq;
cout
<<"\n Cube
="<<cb;
}
void more(int & s, int & c,int j)
{
s=j*j;
c=j*j*j;
}
INTRODUCTION
Functions are
the building blocks of C++ programs where all the program activity occurs.
Function is a collection of declarations and statements.
Need for a Function
Monolethic
program (a large single list of instructions) becomes difficult to understand.
For this reason functions are used. A function has a clearly defined objective
(purpose) and a clearly defined interface with other functions in the program.
Reduction in program size is another reason for using functions. The functions
code is stored in only one place in memory, even though it may be executed as
many times as a user needs.
The following program illustrates the use of a function :
//to display general message using function
#include<iostream.h>
include<conio.h>
void main()
{
void disp(); //function prototype
clrscr(); //clears the screen
disp(); //function call
getch(); //freeze the monitor
}
//function definition
void disp()
{
cout<<”Welcome to the GJU of S&T\n”;
cout<<”Programming is nothing but logic implementation”;
}
FUNCTION DEFINITION AND DECLARATION
In C++, a function must be defined
prior to it’s use in the program. The function definition contains the code for
the function. The general syntax of a function definition in C++ is shown
below:
Type name_of_the_function (argument
list)
{
//body of the function
}
Here, the type specifies the type of the value to be returned
by the function. It may be any valid C++ data type. When no type is
given, then the compiler returns an integer value from the function.
Name_of_the_function is a valid C++ identifier (no reserved
word allowed) defined by the user and it can be used by other functions for
calling this function.
Argument list is a comma separated list of variables of a
function through which the function may receive data or send data when called
from other function. When no parameters,
The following function illustrates the concept of function
definition :
//function definition add()
void add()
{
int a,b,sum;
cout<<”Enter two integers”<<endl;
cin>>a>>b;
sum=a+b;
cout<<”\nThe sum of two numbers is
“<<sum<<endl;
}
The above function add ( ) can also be coded with the help of
arguments of parameters as shown below:
//function definition add()
void add(int a, int b) //variable names are must in definition
{
int sum;
sum=a+b;
cout<<”\nThe sum of two numbers is
“<<sum<<endl;
}
ARGUMENTS TO A FUNCTION
Arguments of a function is the data that the function receives
when called/invoked from another function.
PASSING ARGUMENTS TO A FUNCTION
It is not always necessary for a function to have arguments or
parameters. The functions add ( ) and divide ( ) in above program not contain
any arguments. The following example illustrates the concept of passing
arguments to function SUMFUN ( ):
// demonstration of passing arguments to a function
#include<iostream.h>
void main ()
{
float x,result; //local variables
int N;
formal parameters
Semicolon here
float SUMFUN(float x, int N); //function declaration
return type
………………………….
………………………….
result = SUMFUN(X,N); //function declaration
}
//function SUMFUN() definition
No semicolon here
float SUMFUN(float x,int N) //function declaration
{
………………………….
…………………………. Body of the function
………………………….
}
No semicolon here
DEFAULT ARGUMENTS
C++ allows a function
to assign a parameter the default value in case no argument for that parameter
is specified in the function call. For example.
// demonstrate default
arguments function
#include<iostream.h>
int calc(int U)
{
If (U % 2 == 0)
return U+10;
Else
return U+2
}
Void pattern (char M, int B=2)
{
for (int CNT=0;CNT<B; CNT++)
cout<calc(CNT) <<M;
cout<<endl;
}
Void main ()
{
Pattern(‘*’);
Pattern (‘#’,4)’
Pattern (;@;,3);
}
CONSTANT ARGUMENTS
A C++ function may have constant
arguments(s). These arguments(s) is/are treated as constant(s). These values
cannot be modified by the function.
For making the arguments(s) constant
to a function, we should use the keyword const as given below in the function
prototype :
Void max(const float x, const float y, const float z);
Here, the qualifier const informs the compiler that the
arguments(s) having const should not be modified by the function max ().
These are quite useful when call by reference method is used for passing
arguments.
CALLING FUNCTIONS
In C++ programs, functions with arguments can be invoked by :
(a) Value
(b) Reference
Call by Value: - In this method the values of the
actual parameters (appearing in the function call) are copied into the formal
parameters (appearing in the function definition), i.e., the function creates
its own copy of argument values and operates on them. The following program
illustrates this concept :
//calculation of compound interest
using a function
#include<iostream.h>
#include<conio.h>
#include<math.h> //for
pow()function
Void main()
{
Float principal, rate, time;
//local variables
Void calculate (float, float,
float); //function prototype clrscr();
Cout<<”\nEnter the following
values:\n”;
Cout<<”\nPrincipal:”;
Cin>>principal;
Cout<<”\nRate of interest:”;
Cin>>rate;
Cout<<”\nTime period (in
yeaers) :”;
cin>>time;
Calculate (principal, rate, time);
//function call
Getch ();
}
//function definition calculate()
Void calculate (float p, float r,
float t)
{
Float interest; //local variable
Interest = p*
(pow((1+r/100.0),t))-p;
Cout<<”\nCompound interest is
: “<<interest;
}
Call by Reference: - A reference provides an alias – an
alternate name – for the variable, i.e., the same variable’s value can be used
by two different names : the original name and the alias name.
In call by reference method, a reference to the actual
arguments(s) in the calling program is passed (only variables). So the called
function does not create its own copy of original value(s) but works with the
original value(s) with different name. Any change in the original data in the
called function gets reflected back to the calling function. It is useful when
you want to change the original variables in the calling function by the called
function.
//Swapping of two numbers using
function call by reference
#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
int num1,num2;
void swap (int &, int &);
//function prototype
cin>>num1>>num2;
cout<<”\nBefore swapping:\nNum1:
“<<num1;
cout<<endl<<”num2:
“<<num2;
swap(num1,num2); //function call
cout<<”\n\nAfter swapping :
\Num1: “<<num1;
cout<<endl<<”num2:
“<<num2;
getch();
}
//function fefinition swap()
void swap (int & a, int &
b)
{
Int temp=a;
a=b;
b=temp;
}
INLINE FUNCTIONS
These are the functions designed to
speed up program execution. An inline function is expanded (i.e. the function
code is replaced when a call to the inline function is made) in the line where
it is invoked. You are familiar with the fact that in case of normal functions,
the compiler have to jump to another location for the execution of the function
and then the control is returned back to the instruction immediately after the
function call statement. So execution time taken is more in case of normal
functions. There is a memory penalty in the case of an inline function.
The system of inline function is as follows :
inline function_header
{
body of the function
}
For example,
//function definition min()
inline void min (int x, int y)
cout<< (x < Y? x : y);
}
Void main()
{
int num1, num2;
cout<<”\Enter the two intergers\n”;
cin>>num1>>num2;
min (num1,num2; //function code inserted here
------------------
------------------
}
An inline function definition must be defined before being
invoked as shown in the above example. Here min ( ) being inline will not be
called during execution, but its code would be inserted into main ( ) as shown
and then it would be compiled.
If the size of the inline function is large then heavy memory
pentaly makes it not so useful and in that case normal function use is more
useful.
The inlining does not work for the following situations :
1. For
functions returning values and having a loop or a switch or a
goto statement.
2. For
functions that do not return value and having a return statement.
3. For
functions having static variable(s).
4. If the
inline functions are recursive (i.e. a function defined in terms of itself).
The benefits of inline functions are as follows :
1. Better than
a macro.
2. Function
call overheads are eliminated.
3. Program
becomes more readable.
4. Program
executes more efficiently.
SCOPE RULES OF FUNCTIONS AND VARIABLES
The scope of an identifier is that part of the C++ program in
which it is accessible. Generally, users understand that the name of an
identifier must be unique. It does not mean that a name can’t be reused. We can
reuse the name in a program provided that there is some scope by which it can
be distinguished between different cases or instances.
In C++ there are four kinds of scope as given below :
1. Local Scope
2. Function
Scope
3. File Scope
4. Class Scope
Local Scope:- A block in C++
is enclosed by a pair of curly braces i.e., ‘{‘ and ‘}’. The variables declared
within the body of the block are called local variables and can be used
only within the block. These come into existence when the control enters the
block and get destroyed when the control leaves the closing brace. You should
note the variable(s) is/are available to all the enclosed blocks within a
block.
For example,
int x=100;
{ cout<<x<<endl;
Int x=200;
{
cout<<x<<endl;
int x=300;
{
cout<<x<<endl;
}
}
cout<<x<<endl;
}
Function Scope : It pertains
to the labels declared in a function i.e., a label can be used inside the
function in which it is declared. So we can use the same name labels in
different functions.
For example,
//function definition add1()
void add1(int x,int y,int z)
{
int sum = 0;
sum = x+y+z;
cout<<sum;
}
//function definition add2()
coid add2(float x,float y,float z)
{
Float sum = 0.0;
sum = x+y+z;
cout<<sum;
}
Here the labels x, y, z and sum in
two different functions add1 ( ) and add2 ( ) are declared and used locally.
File Scope : If the declaration of an identifier
appears outside all functions, it is available to all the functions in the
program and its scope becomes file scope. For Example,
int x;
void square (int n)
{
cout<<n*n;
}
void main ()
{
int num;
…………...........
cout<<x<<endl;
cin>>num;
squaer(num);
…………...........
}
Here the declarations of variable x and function square
( ) are outside all the functions so these can be accessed from any place
inside the program. Such variables/functions are called global.
Class
Scope : In C++, every class maintains its won associated scope. The class
members are said to have local scope within the class. If the name of a
variable is reused by a class member, which already has a file scope, then the
variable will be hidden inside the class. Member functions also have class
scope.
DEFINITION AND DECLARATION OF A CLASS
A Class is the backbone of Object-Oriented Computing. It is
an abstract data type. We can declare and define data as well as functions in a
class. An object is a replica of the class to the exception that it has its own
name. A class is a data type and an object is a variable of that type. Classes
and objects are the most important features of C++. The class implements OOP
features and ties them together.
A class in C++ combines related data
and functions together. It makes a data type which is used for creating objects
of this type.
Classes represent real world entities
that have both data type properties (characteristics) and associated operations
(behavior).
The syntax of a class definition is shown below :
Class name_of _class
{
private :
variable declaration; // data member
Function
declaration; // Member Function (Method)
protected:
Variable
declaration;
Function
declaration;
public :
variable
declaration;
Function
declaration;
};
Here, the keyword
class specifies that we are using a new data type and is followed by the class
name.
The body of the class has two keywords namely :
(i) private (ii) public
In C++, the keywords private and public are
called access specifiers. The data hiding concept in C++ is achieved by using
the keyword private. Private data and functions can only be accessed
from within the class itself. Public data and functions are accessible outside
the class also.
Data hiding not mean the security
technique used for protecting computer databases. The security measure is used
to protect unauthorized users from performing any operation (read/write or
modify) on the data.
The data declared under Private section
are hidden and safe from accidental manipulation. Though the user can use the
private data but not by accident.
The functions that operate on the
data are generally public so that they can be accessed from outside the
class but this is not a rule that we must follow.
MEMBER FUNCTION DEFINITION
The class specification can be done in two part :
(i) Class
definition. It describes both data members and member functions.
(ii) Class
method definitions. It describes how certain class member functions are
coded.
We have already seen the class definition syntax as well as an
example.
In C++, the member functions can be coded in two ways :
(a) Inside
class definition
(b) Outside
class definition using scope resolution operator (::)
The code of the function is same in both the cases, but the
function header is different as explained below :
MEMBER FUNCTION Inside Class Definition:
When a member function is defined inside a class, we do not
require to place a membership label along with the function name. We use only
small functions inside the class definition and such functions are known as inline
functions.
In case of inline function the compiler inserts the code of
the body of the function at the place where it is invoked (called) and in doing
so the program execution is faster but memory penalty is there.
MEMBER FUNCTION Outside Class Definition Using Scope
Resolution Operator (::) :
In this case the function’s full name
(qualified_name) is written as shown:
Name_of_the_class :: function_name
The syntax for a member function definition outside the class
definition is :
return_type name_of_the_class::function_name (argument list)
{
body of function
}
Here the operator :: known as scope resolution operator helps
in defining the member function outside the class.
DECLARATION OF OBJECTS AS INSTANCES OF A CLASS
The objects of a class are declared after the class
definition. One must remember that a class definition does not define any
objects of its type, but it defines the properties of a class. For utilizing
the defined class, we need variables of the class type. For example,
Largest ob1,ob2; //object declaration
will create two objects ob1 and ob2 of largest class
type. As mentioned earlier, in C++ the variables of a class are known as
objects. These are declared like a simple variable i.e., like fundamental data
types.
In C++, all the member functions of a class are created and
stored when the class is defined and this memory space can be accessed by all
the objects related to that class.
Memory space is allocated separately to each object for their
data members. Member variables store different values for different objects of
a class.
The figure shows this concept
ACCESSING
MEMBERS FROM OBJECT(S)
After defining a class and creating a class
variable i.e., object we can access the data members and member functions of
the class. Because the data members and member functions are parts of the
class, we must access these using the variables we created. For functions are
parts of the class, we must access these using the variable we created. For
Example,
Class student
{
private:
char reg_no[10];
char name[30];
int age;
char address[25];
public :
void init_data()
{
- - - - - //body of
function
- - - - -
}
void display_data()
{
- - - - - //body of function
- - - - -
}
};
student ob; //class variable (object) created
- - - - -
- - - - -
Ob.init_data(); //Access the member function
ob.display_data(); //Access the member function
- - - - -
- - - - -
Here, the data members can be
accessed in the member functions as these have private scope, and
the member functions can be accessed outside the class i.e., before or after
the main() function.
STATIC CLASS MEMBERS
Data members and member functions of
a class in C++, may be qualified as static. We can have static data members and
static member function in a class.
Static Data Member: It is generally used to store value
common to the whole class. The static data member differs from an
ordinary data member in the following ways :
(i) Only a single
copy of the static data member is used by all the objects.
(ii) It can be
used within the class but its lifetime is the whole program.
For making a data member static, we require :
(a) Declare it
within the class.
(b) Define it
outside the class.
For example
Class student
{
Static int count; //declaration within class
-----------------
-----------------
-----------------
};
The static data member is defined outside the class as :
int student :: count; //definition outside class
The definition outside the class is a must.
We can also initialize the static data member at the time of
its definition as:
int student :: count = 0;
If we define three objects as : sudent obj1, obj2, obj3;
Static Member Function: A static member function can
access only the static members of a class. We can do so by putting the keyword
static before the name of the function while declaring it for example,
Class student
{
Static int count;
-----------------
public :
-----------------
-----------------
static void showcount (void) //static member function
{
Cout<<”count=”<<count<<”\n”;
}
};
int student ::count=0;
Here we have put the keyword static before the name of the
function shwocount ().
In C++, a static member function fifers from the other member
functions in the following ways:
(i) Only static
members (functions or variables) of the same class can be accessed by a static
member function.
(ii) It is called
by using the name of the class rather than an object as given below:
Name_of_the_class :: function_name
For example,
student::showcount();
FRIEND CLASSES
In C++ , a class can be made a friend to another class. For
example,
class TWO; // forward declaration of the class TWO
class ONE
{
………………………
…………….
public:
……………..
……………..
friend class TWO; // class TWO declared as friend of class ONE
};
Now from class TWO ,
all the member of class ONE can be accessed.
Constructor
A constructor (having the same
name as that of the class) is a member function which is automatically used to
initialize the objects of the class type with legal initial values.
Declaration and Definition of a Constructor:-
It is defined like other member
functions of the class, i.e., either inside the class definition or outside the
class definition.
For example, the following program illustrates the concept of
a constructor :
//To demonstrate a constructor
#include <iostram.h>
#include <conio.h>
Class rectangle
{
private :
float length, breadth;
public:
rectangle ()//constructor definition
{
//displayed whenever an object is created
cout<<”I am in the constructor”;
length-10.0;
breadth=20.5;
}
float area()
{
return (length*breadth);
}
};
void main()
{
clrscr();
rectangle rect; //object declared
cout<<”\nThe area of the rectangle with default
parameters is:”<<rect.area()<<”sq.units\n”;
getch();
}
Type Of Constructor
There are different type of constructors in C++.
Overloaded Constructors
Besides performing the role of member data initialization,
constructors are no different from other functions. This included overloading
also. In fact, it is very common to find overloaded constructors. For example,
consider the following program with overloaded constructors for the figure
class :
//Illustration of overloaded constructors
//construct a class for storage of dimensions of circles.
//triangle and rectangle and calculate their area
#include<iostream.h>
#include<conio.h>
#include<math.h>
#include<string.h> //for strcpy()
Class figure
{
Private:
Float radius, side1,side2,side3; //data members
Char shape[10];
Public:
figure(float r) //constructor for circle
{
radius=r;
strcpy (shape, “circle”);
}
figure (float s1,float s2) //constructor for rectangle
strcpy
{
Side1=s1;
Side2=s2;
Side3=radius=0.0; //has no significance in rectangle
strcpy(shape,”rectangle”);
}
Figure (float s1, floats2, float s3) //constructor for
triangle
{
side1=s1;
side2=s2;
side3=s3;
radius=0.0;
strcpy(shape,”triangle”);
}
void area() //calculate area
{
float ar,s;
if(radius==0.0)
{
if (side3==0.0)
ar=side1*side2;
else
ar=3.14*radius*radius;
cout<<”\n\nArea of the “<<shape<<”is
:”<<ar<<”sq.units\n”;
}
};
Void main()
{
Clrscr();
Figure circle(10.0); //objrct initialized using constructor
Figure rectangle(15.0,20.6);//objrct initialized using
onstructor
Figure Triangle(3.0, 4.0, 5.0); //objrct initialized using
constructor
Rectangle.area();
Triangle.area();
Getch();//freeze the monitror
}
Copy Constructor
It is of the form classname (classname &) and used for the
initialization of an object form another object of same type. For example,
Class fun
{
Float x,y;
Public:
Fun (floata,float b)//constructor
{
x = a;
y = b;
}
Fun (fun &f) //copy constructor
{cout<<”\ncopy constructor at work\n”;
X = f.x;
Y = f.y;
}
Void display (void)
{
{
Cout<<””<<y<<end1;
}
};
Here we have two constructors, one copy constructor for
copying data value of a fun object to another and other one a parameterized
constructor for assignment of initial values given.
Dynamic Initialization of Objects
In C++, the class objects can be initialized at run time
(dynamically). We have the flexibility of providing initial values at execution
time. The following program illustrates this concept:
//Illustration of dynamic initialization of objects
#include <iostream.h>
#include <conio.h>
Class employee
{
Int empl_no;
Float salary;
Public:
Employee() //default constructor
{}
Employee(int empno,float s)//constructor with arguments
{
Empl_no=empno;
Salary=s;
}
Employee (employee &emp)//copy constructor
{
Cout<<”\ncopy constructor working\n”;
Empl_no=emp.empl_no;
Salary=emp.salary;
}
Void display (void)
{
Cout<<”\nEmp.No:”<<empl_no<<”salary:”<<salary<<end1;
}
};
Void main()
{
int eno;
float sal;
clrscr();
cout<<”Enter the employee number and salary\n”;
cin>>eno>>sal;
employee obj1(eno,sal);//dynamic initialization of object
cout<<”\nEnter the employee number and salary\n”;
cin>eno>>sal;
employee obj2(eno,sal); //dynamic initialization of object
obj1.display(); //function called
employee obj3=obj2; //copy constructor called
obj3.display();
getch();
}
Constructors and Primitive Types
In C++, like derived type, i.e. class, primitive types
(fundamental types) also have their constructors. Default constructor is used
when no values are given but when we given initial values, the initialization
take place for newly created instance. For example,
float x,y; //default constructor used
int a(10), b(20); //a,b initialized with values 10 and 20
float i(2.5), j(7.8); //I,j, initialized with valurs 2.5 and
7.8
Constructor with Default Arguments
In C++, we can define constructor s with default arguments.
For example,
The following code segment shows a constructor with default
arguments:
Class add
{
Private:
Int num1, num2,num3;
Public:
Add(int=0,int=0); //Default argument constructor
//to reduce the number of constructors
Void enter (int,int);
Void sum();
Void display();
};
//Default constructor definition
add::add(int n1, int n2)
{
num1=n1;
num2=n2;
num3=n0;
}
Void add ::sum()
{
Num3=num1+num2;
}
Void add::display ()
{
Cout<<”\nThe sum of two numbers
is “<<num3<<end1;
}
Now using the above code objects of
type add can be created with no initial values, one initial values or two
initial values. For Example,
Add obj1, obj2(5), obj3(10,20);
Here, obj1 will have values of data
members num1=0, num2=0 and num3=0
Obj2 will have values of data members
num1=5, num2=0 and num3=0
Obj3 will have values of data members
num1=10, num2=20 and num3=0
If two constructors for the above
class add are
Add::add() {} //default constructor
and add::add(int=0);//default argument constructor
Then the default argument constructor can be invoked with
either two or one or no parameter(s).
Without argument, it is treated as a default constructor-using
these two forms together causes ambiguity. For example,
The declaration add obj;
is ambiguous i.e., which one constructor to invoke i.e.,
add :: add()
or add :: add(int=0,int=0)
so be careful in such cases and avoid such mistakes.
SPECIAL CHARACTERISTICS OF CONSTRUCTORS
These have some special characteristics. These are given
below:
(i) These are called automatically
when the objects are created.
(ii) All objects of the class having
a constructor are initialized before some use.
(iii) These should be declared in
the public section for availability to all the functions.
(iv) Return type (not even void)
cannot be specified for constructors.
(v) These cannot be inherited, but a
derived class can call the base class constructor.
(vi) These cannot be static.
(vii) Default and copy constructors
are generated by the compiler wherever required. Generated constructors are
public.
(viii) These can have default
arguments as other C++ functions.
(ix) A constructor can call member
functions of its class.
(x) An object of a class with a
constructor cannot be used as a member of a union.
(xi) A constructor can call member
functions of its class.
(xii) We can use a constructor to
create new objects of its class type by using the syntax.
Name_of_the_class (expresson_list)
For example,
Employee obj3 = obj2; // see program 10.5
Or even
Employee obj3 = employee (1002, 35000); //explicit call
(xiii) The make implicit calls
to the memory allocation and deallocation operators new and delete.
(xiv) These cannot be virtual.
Destructors
Destructors are the functions that
are complimentary to constructors. These are used to de-initialize objects when
they are destroyed. A destructor is called when an object of the class goes out
of scope, or when the memory space used by it is de allocated with the help of delete
operator.
Declaration and Definition of a Destructor
The syntax for declaring a destructor
is :
~name_of_the_class()
{
}
So the name of the class and
destructor is same but it is prefixed with a ~
(tilde). It does not take any
parameter nor does it return any value. Overloading a destructor is not
possible and can be explicitly invoked. In other words, a class can have only
one destructor. A destructor can be defined outside the class. The following
program illustrates this concept :
//Illustration of the working of
Destructor function
#include<iostream.h>
#include<conio.h>
class add
{
private :
int num1,num2,num3;
public :
add(int=0, int=0); //default argument
constructor
//to reduce the number of
constructors
void sum();
void display();
~ add(void); //Destructor
};
//Destructor definition ~add()
Add:: ~add(void) //destructor called
automatically at end of program
{
Num1=num2=num3=0;
Cout<<”\nAfter the final
execution, me, the object has entered in the”
<<”\ndestructor to destroy
myself\n”;
}
//Constructor definition add()
Add::add(int n1,int n2)
{
num1=n1;
num2=n2;
num3=0;
}
//function definition sum ()
Void add::sum()
{
num3=num1+num2;
}
//function definition display ()
Void add::display ()
{
Cout<<”\nThe sum of two numbers
is “<<num3<<end1;
}
void main()
{
Add obj1,obj2(5),obj3(10,20):
//objects created and initialized clrscr();
Obj1.sum(); //function call
Obj2.sum();
Obj3.sum();
cout<<”\nUsing obj1 \n”;
obj1.display(); //function call
cout<<”\nUsing obj2 \n”;
obj2.display();
cout<<”\nUsing obj3 \n”;
obj3.display();
}
Special Characteristics of Destructors
Some of the characteristics associated with destructors are :
(i) These are called automatically
when the objects are destroyed.
(ii) Destructor functions follow
the usual access rules as other member functions.
(iii) These de-initialize each
object before the object goes out of scope.
(iv) No argument and return type
(even void) permitted with destructors.
(v) These cannot be inherited.
(vi) Static destructors are
not allowed.
(vii) Address of a destructor
cannot be taken.
(viii) A destructor can call member
functions of its class.
(ix) An object of a class having a
destructor cannot be a member of a union.
Operator
overloading
Operator overloading is one of
the most exciting features of C++. It is helpful in enhancement of the power of
extensibility of C++ language. Operator overloading redefines the C++ language.
User defined data types are made to behave like built-in data types in C++.
Operators +, *. <=, += etc. can be given additional meanings when applied on
user defined data types using operator overloading. The mechanism of providing
such an additional meaning to an operator is known as operator overloading in
C++.
DECLARATION AND DEFINITION OF A OVERLOADING
For defining an additional task to an operator, we must
mention what is means in relation to the class to which it (the operator) is
applied. The operator function helps us in doing so.
The Syntax of declaration of an Operator function is as
follows:
Operator Operator_name
For example, suppose that we want to declare an Operator
function for ‘=’. We can
do it as follows:
operator =
A Binary Operator can be defined either a member function
taking one argument or a
global function taking one arguments. For a Binary Operator X,
a X b can be interpreted as either an operator X (b) or operator X (a, b).
For a Prefix unary operator Y, Ya can be interpreted as either
a.operator Y ( ) or Operator Y (a). For a Postfix unary operator Z, aZ can be
interpreted as either a.operator Z(int) or Operator (Z(a),int).
The operator functions namely operator=, operator [ ],
operator ( ) and operator? must be non-static member functions. Due to this,
their first operands will be lvalues.
An operator function should be either a member or take at
least one class object argument. The operators new and delete need not follow
the rule. Also, an operator function, which needs to accept a basic type as its
first argument, cannot be a member function. Some examples of declarations of
operator functions are given below:
class P
{
P operator ++ (int);//Postfix increment
P operator ++ ( ); //Prefix increment
P operator || (P); //Binary OR
}
Some examples of Global Operator Functions are given below:
P operator – (P); // Prefix Unary minus
P operator – (P, P); // Binary “minus”
P operator - - (P &, int); // Postfix Decrement
We can declare these Global Operator Functions as being
friends of any other class.
Examples of operator overloading:
Operator overloading using friend.
Class time
{
int r;
int i;
public:
friend time operator + (const time &x, const time &y
);
// operator overloading using friend
time ( ) { r = i = 0;}
time (int x, int y) {r = x; i = y;}
};
time operator + (const time &x, const time &y)
{
time z;
z.r = x.r +y.r;
z.i = x.i + y.i;
return z;
}
main ( )
{
time x,y,z;
x = time (5,6);
y = time (7,8);
z = time (9, 10);
z = x+y; // addition using friend function +
}
Operator overloading using member function:
Class abc
{
char * str;
int len ; // Present length of the string
int max_length; // (maximum space allocated to string)
public:
abc ( ); // black string of length 0 of maximum allowed length
of size 10.
abc (const abc &s ) ;// copy constructor
~ abc ( ) {delete str;}
int operator = = (const abc &s ) const; // check for
equality
abc & operator = (const abc &s );
// overloaded assignment operator
friend abc operator + (const abc &s1, const abc &s2);
} // string concatenation
abc:: abc ()
{
max_length = 10;
str = new char [ max_length];
len = 0;
str [0] = ‘\0’;
}
abc :: abc (const abc &s )
{
len = s. len;
max_length = s.max_length;
str = new char [max_length];
strcpy (str, s.str); // physical copying in the new location.
}
[ Note: Please note the need of explicit copy
constructor as we are using
pointers. For example, if a string object containing string
“first” is to be used to
initialise a new string and if we do not use copy constructor
then will cause:
Str1
F I R S T ‘\
Str2
That is two pointers pointing to one
instance of allocated memory, this will create
problem if we just want to modify the current value of one of
the string only. Even destruction of one string will create problem. That is
why we need to create separate
space for the pointed string as:
Str2 F I R S T ‘\
Str1 F I R S T ‘\
Thus, we have explicitly written the copy constructor. We have
also written the explicit destructor for the class. This will not be a problem
if we do not use pointers.
abc :: ~ abc ( )
{
delete str;
}
abc & abc :: operator = (const abc &s )
{
if (this ! = &s) // if the left and right hand variables
are different
{
len = s.len;
max_length = s.max-length;
delete str; // get rid of old memory space allocated to this
string
str = new char [max_length]; // create new locations
strcpy (str, s.str); // copy the content using string copy
function
}
return *this;
}
// Please note the use of this operator which is a pointer to
object that invokes the call to this assignment operator function.
inline int abc :: operator == (const abc &s ) const
{
// uses string comparison function
return strcmp (str,s.str);
}
abc abc:: operator + (const abc &s )
abc s3;
s3.len = len + s.len;
s3.max_length = s3.len;
char * newstr = new char [length + 1];
strcpy (newstr, s.str);
strcat (newstr,str);
s3.str = newstr;
return (s3);
}
Overloading << operator:
To overload << operator, the following function may be
used:
Ostream & operator << (ostream &s, const abc
&x )
{
s<< “The String is:” <<x; }
return s;
}
You can write appropriate main function and use the above
overloaded operators as shown in the complex number example.
ASSIGNMENT AND INITIALISATION
Consider the following class:
class student
{
char name;
int rollno;
public:
student ( ) {name = new char [20];}
~ student ( ) {delete [ ] name;}
};
int f ( )
{ student S1, S2;
cin >> S1;
cin >> S2;
S1 = S2;
}
Now, the problem is that after the execution of f ( ),
destructors for S1& S2 will be
executed. Since both S1 & S2 point to the same storage,
execution of destructor twice
will lead to error as the storage being pointed by S1 & S2
were disposed off during
the execution of destructor for S1 itself.
Defining assignment of strings as follows can solve this
problem,
class student
{
Public:
char name;
int rollno;
student ( ) {name = new char [20];}
~ student ( ) {delete [ ] name ;}
student & operator = (const student & )
}
student & student :: Operator = (const student &e)
{
if (this ! =&e)
delete [] name;
name = new char [20];
strcpy(name, name);
}
return *this;
}
TYPE CONVERSIONS
We have overloaded several kinds of operators but we haven’t
considered the assignment operator (=). It is a very special operator having
complex properties. We know that = operator assigns values form one variable to
another or assigns the value of user defined object to another of the same
type. For example,
int x, y ;
x = 100;
y = x;
Here, first 100 is assigned to x and
then x to y.
Consider another statement, 13 = t1 + t2;
This statement used in program 11.2 earlier, assigns the
result of addition, which is of type time to object t3 also of type time. So
the assignments between basic types or user defined types are taken care by the
compiler provided the data type on both sides of = are of same type.
But what to do in case the variables are of different types on
both sides of the = operator? In this case we need to tell to the compiler for
the solution.
Three types of situations might arise for data conversion
between different types :
(i) Conversion form basic type to class type.
(ii) Conversion from class type to basic type.
(iii) Conversion from one class type to another class type.
Now let us discuss the above three cases :
(i) Basic Type to Class Type
This type of conversion is very easy. For example, the
following code segment converts an int type to a class type.
class distance
{
int feet;
int inches;
public:
.....
.....
distance (int dist) //constructor
{
feet = dist/12;
inches = dist%12;
}
};
The following conversion statements can be coded in a function
:
distance dist1; //object dist1 created
int length = 20; dist1=length; //int to class type
After the execution of above statements, the feet member
of dist1 will have a value of 1 and inches member a value of 8,
meaning 1 feet and 8 inches.
A class object has been used as the
left hand operand of = operator, so the type conversion can also be done by
using an overloaded = operator in C++.
(ii) Class Type to Basic Type
For conversion from a basic type to
class type, the constructors can be used. But for conversion from a class type
to basic type constructors do not help at all. In C++, we have to define an
overloaded casting operator that helps in converting a class type to a
basic type. The syntax of the conversion function is given below:
Operator typename()
{
.......
....... //statements
}
Here, the function converts a class type data to typename. For
example, the operator float ( ) converts a class type to type float,
the operator int ( ) converts a class type object to type int. For example,
matrix :: operator float ()
{
float sum = 0.0;
for(int i=0;i<m;i++)
{
for (int j=0; j<n; j++)
sum=sum+a[i][j]*a[i][j];
}
Return sqrt(sum); //norm of the matrix
}
Here, the function finds the norm of the matrix (Norm is the
square root of the sum of the squares of the matrix elements). We can use the
operator float ( ) as given below :
float norm = float (arr);
or
float norm = arr;
where arr is an object of type matrix. When a class
type to a basic type conversion is required, the compiler will call the casting
operator function for performing this task.
The following conditions should be satisfied by the casting
operator function :
(a) It must not have any argument
(b) It must be a class member
(c) It must not specify a return
type.
(i) One Class Type to Another
Class Type
There may be some situations when we
want to convert one class type data to another class type data. For example,
Obj2 = obj1; //different type of
objects
Suppose obj1 is an object of
class studdata and obj2 is that of class result. We are
converting the class studdata data type to class result type data
and the value is assigned to obj2. Here studdata is known as source
class and result is known as the destination class.
The above conversion can be performed in two ways :
(a) Using a constructor.
(b) Using a conversion function.
When we need to convert a class, a
casting operator function can be used i.e. source class. The source class
performs the conversion and result is given to the object of destination class.
If we take a single-argument
constructor function for converting the argument’s type to the class type
(whose member it is). So the argument is of the source class and being passed
to the destination class for the purpose of conversion. Therefore it is
compulsory that the conversion constructor be kept in the destination class.
Inheritance allows a class to include the members of other
classes without repetition of members. There were three ways to inheritance
means, “public parts of super class remain public and protected parts of super
class remain protected.” Private Inheritance means “Public and Protected Parts
of Super Class remain Private in Sub-Class”. Protected Inheritance means
“Public and Protected Parts of Superclass remain protected in Subclass.
A pointer is a variable which holds a memory address. Any
variable declared in a program has two components:
(i) Address of the variable
(ii) Value stored in the variable.
For example,
int x = 386;
The above declaration tells the C++ compiler for :
(a) Reservation of space in memory for storing the value.
(b) Associating the name x with his memory location.
(c) Storing the value 386 at this location.
It can be represented with the following figure :
location name x
value at location 386
location number 3313
Here, the address 3313 is assumed one, it may be some other
address also.
The pointers are one of the most useful and strongest features
of C++. There are three useful reason for proper utilization of pointer :
(i) The memory location can be
directly accessed and manipulated.
(ii) Dynamic memory allocation is
possible.
(iii) Efficiency of some particular
routines can be improved.
Unit IV
CONCEPT OF INHERITANCE
Inheritance is one of the most useful and essential
characteristics of object-oriented programming. The existing classes are main
components of inheritance. The new classes are created from existing one. The
properties of existing classes are simply extended to the new classes. The new
classes created using such
methods are known as derived classes and the existing classes are known as base
classes as shown in Figure.
The
relationship between the base and derived class is known as kind of
relationship. The
programmer can define new member variables and functions in the derived class.
The base class remains unchanged. The object of derived class can access
members of base as well as derived class. On the other hand, the object of base
class cannot access members of derived classes. The base classes do not know
about their subclasses.
BASE CLASS AND DERIVED CLASS
Let us take the classes, Employee and
Manager. A Manager is an Employee with some additional information. when we are
declaring the classes Employee and Manager without applying the concept of inheritance,
they will look as follows:
class Employee
{
public:
char* name;
int age;
char* address;
int salary;
char *department;
int id;
};
Now, the class Manager is as follows:
Class Manager
{
public:
char* name;
int age;
char* address;
int salary;
char*department;
int id;
employee* team_members; //He heads a
group of employees
int level; // his position in
hierarchy of the organisation
.
.
.
.
};
Now, without repeating the entire information of class
Employee in class Manager,
we can declare the Manager class as follows:
class Manager: Public Employee
{
public:
Employee*Team_members;
int level;
.
.
.
.
};
The latest declaration of class
Manager is the same as that of its previous one, with the exception that we did
not repeat the information of class Employee explicitly. This is what is meant
by the Application of inheritance mechanism. Please note that in the above
example, Employee is called Base Class and Manager is called Derived Class.
Private Inheritance
Consider the following classes:
class A { /*......*/);
class C: private A
{ /*
.
.
.
*/
}
All the public parts of class A and
all the protected parts of class A, become private members/parts of the derived
class C in class C. No private member of class A can be accessed by class C. To
do so, you need to write public or private functions in the Base class. A
public function can be accessed by any object, however, private function can be
used only within the class hierarchy that is class A and class C and friends of
these classes in the above cases.
Public Inheritance
Consider the following classes:
class A{/*........*/};
class E: public A
{ /*
:
:
:
};
Now, all the public parts of class A become public in class E
and protected part of
A become protected in E
Protected Inheritance
Consider the following classes:
class E: protected A
{ /*
.
.
.
*/
};
Now, all the public and protected parts of class A become
protected in class E.
No private member of class A can be accessed by class E. Let
us take a single
example to demonstrate the inheritance of public and private
type in more details. Let
us assume a class close_shape as follows:
class closed_shape
{
public:
.
.
.
}
class circle: public closed_shape
// circle is derived in public access mode from class
// closed-shape
{
float x, y; // Co-ordinates of the centre of the circle
float radius;
public:
.
.
.
.
}
class semi-circle : public circle
{ private:
.
.
.
public:
-
-
-
}
class rectangle: private
closed_shape
{
float x y ;
1, 1
float x ,y ;
2 2
public:
.
.
.
.
};
class rounded_rectangle :
public rectangle
{
private:
public :
.
.
.
}
TYPES OF INHERITANCES
Inheritance is classified
as follows:
• Single
Inheritance
• Multiple
Inheritance
• Hierarchical
Inheritance
• Multilevel
Inheritance
• Hybrid
Inheritance
• Multi-path
Inheritance
The base
classes are at the top level and derived classes at the bottom. The arrow
pointed from top to bottom indicates that properties of base classes are
inherited by the derived class and the reverse is not applicable.
SINGLE INHERITANCE
When only one
class is derived from a single base class such derivation of a class is known
assingle inheritance, further,
the derived class is not used as a base class. This type of inheritance uses
one base and one derived class.
The new class
is termed as derived class and the old class is called as base class as shown in Figure.
A derived class inherits data member variables
and functions of base class. However, constructors and destructors of base
class are not inherited in derived class.
The newly
created class receives entire characteristics from its base class. In single
inheritance, there are only one base class and derived class. The single
inheritance is not as complicated as compared to other types of inheritances.
// Single inheritance //
# include <iostream.h>
# include <constream.h>
class A1 // Base class
{
protected :
char name[15];
int age;
};
class A2 : public A1 // Derivation first level
{
protected :
float height;
float weight;
};
MULTILEVEL INHERITANCE
The procedure of deriving a class from derived
class is named as multilevel inheritance.
In the Figure class A3 is derived from class A2. The
class A2 is derived from class A1. The
class A3 is
derived class. The class A2 is a
derived class as well as base class for class A3. The class A2 is called as intermediate base class. The class A1 is a base class of classes A2 and A3. The series of classes A1, A2, and A3 is called as inheritance pathway as
shown in Figure.
//program to create multilevel inheritance. Create classes A1, A2,
and A3.
// Multilevel inheritance //
# include <iostream.h>
# include <constream.h>
class A1 // Base class
{
protected :
char name[15];
int age;
};
class A2 : public A1 // Derivation first level
{
protected :
float height;
float weight;
};
class A3 : public A2 // Derivation second level
{
protected :
char sex;
public :
void get( ) // Reads data
{
cout <<"Name : "; cin >>name;
cout <<"Age : "; cin >>age;
cout <<"Sex : "; cin >>sex;
cout <<"Height : "; cin >>height;
cout <<"Weight : "; cin >>weight;
}
void show( ) // Displays data
{
cout <<"\nName : " <<name;
cout <<"\nAge : " <<age <<" Years";
cout <<"\nSex : " <<sex;
cout <<"\nHeight : " <<height <<" Feets";
cout <<"\nWeight : " <<weight <<" Kg.";
}
};
void main( )
{
clrscr( );
A3 x; // Object Declaration
x.get( ); // Reads data
x.show( ); // Displays data
}
MULTIPLE INHERITANCE
Multiple
inheritance is the latest addition to the C++ language.
When a class is derived from more than one class then this type of inheritance
is called as multiple
inheritance. A class can be
derived by inheriting properties of more than one class. Properties of various
pre-defined classes are transferred to single derived class. Figure shows multiple
inheritance.
A class can have more than one
direct base classes.
Consider the following classes:
Class A {/* .....*/};
Class B {/* .....*/};
Class C : public A, public B
{ /*
.
.
.
.
*/
};
This is called Multiple
Inheritance. If a class is having only one base class, then it is
known as single inheritance. In
the case of Class C, other than the operations specified in it, the union of operations
of classes A and B can also be applied.
//program to derive a class from multiple
base classes.
// Multiple Inheritance //
# include <iostream.h>
# include <constream.h>
class A { protected : int a; }; // class A declaration
class B { protected : int b; }; // class B declaration
class C { protected : int c; }; // class C declaration
class D { protected : int d; }; // class D declaration
// class E : public A, public B, public C, public D
class E : public A,B,C,D // Multiple derivation
{
int e;
public :
void getdata( )
{
cout <<"\n Enter values of a,b,c & d & e : ";
cin >>a>>b>>c>>d>>e;
}
void showdata( )
{
cout <<"\n a="<<a <<" b = "<<b <<" c = "<<c <<" d= "<<d <<" e= "<<e;
}
};
void main ( )
{
clrscr( );
E x;
x.getdata( ); // Reads data
x.showdata( ); // Displays data
}
HIERARCHICAL INHERITANCE
We know that in
inheritance, one class could be inherited from one or more classes. In
addition, new members are added to the derived class. Inheritance also supports
hierarchical arrangement of programs. Several programs require hierarchical
arrangement of classes, in which derived classes share the properties of base
class. Hierarchical unit shows top down style through splitting a compound
class into several simple sub classes. Figure shows perfect example of
hierarchy of classes.
The program based on hierarchical inheritance
is illustrated below.
//program to show hierarchical inheritance.
# include <constream.h>
# include <iostream.h>
class red
{
public:
red ( )
{cout<<" Red ";};
};
class yellow
{
public :
yellow(
) { cout <<" Yellow "; }
};
class blue
{
public:
blue ( )
{ cout <<" Blue "; }
};
class orange : public red, public yellow
{
public :
orange(
) { cout <<" = Orange "; }
};
class green : public blue, public yellow
{
public:
green( )
{ cout <<" = Green "; }
};
class violet : public red, public blue
{
public:
violet(
) { cout <<" = Violet
"; }
};
class reddishbrown : public orange, public
violet
{
public:
reddishbrown( ) { cout <<" = Reddishbrown "; }
};
class yellowishbrown : public green, public
orange
{
public:
yellowishbrown( ) { cout<<" = Yellowishbrown "; }
};
class bluishbrown : public violet, public green
{
public:
bluishbrown( ) { cout<<"
= Bluishbrown "; }
};
void main( )
{
clrscr(
);
reddishbrown r;
endl(cout);
bluishbrown b;
endl(cout);
yellowishbrown y;
endl(cout);
}
HYBRID INHERITANCE
The
combination of one or more types of inheritance is known as hybrid inheritance. Sometimes,
it is essential to derive a class using more types of inheritances. Figure shows hybrid inheritance.
In the
diagram given below the class GAME is derived from two base classes i.e., LOCATION and PHYSIQUE. The classPHYSIQUE is also derived from class player.
//program to create a derived class from multiple base classes.
// Hybrid Inheritance //
# include <iostream.h>
# include <constream.h>
class PLAYER
{
protected :
char name[15];
char gender;
int age;
};
class PHYSIQUE : public PLAYER
{
protected :
float height;
float weight;
};
class LOCATION
{
protected :
char city[10];
char pin[7];
};
class GAME : public PHYSIQUE, LOCATION
{
protected :
char game[15];
public :
void getdata( )
{
cout <<" Enter Following Information\n";
cout <<"Name : "; cin>> name;
cout <<"Gender : "; cin>>gender;
cout <<"Age : "; cin>>age;
cout <<"Height : "; cin>>height;
cout <<"Weight : "; cin>>weight;
cout <<"City : "; cin>>city;
cout <<"Pincode : "; cin>>pin;
cout <<"Game : "; cin>>game;
}
void show( )
{
cout <<"\n Entered Information";
cout <<"\nName : "; cout<<name;
cout <<"\nGender : "; cout<<gender;
cout <<"\nAge : "; cout<<age;
cout <<"\nHeight : "; cout<<height;
cout <<"\nWeight : "; cout<<weight;
cout <<"\nCity : "; cout<<city;
cout <<"\nPincode : "; cout<<pin;
cout <<"\nGame :”;cout<<game;
}
};
int main()
{
clrscr();
GAME G;
G.getdata();
G.show();
return 0;
}
MULTIPATH INHERITANCE
When a class
is derived from two or more classes, which are derived from the same base class
such type of inheritance is known as multipath
inheritance. Multipath
inheritance consists of many types of inheritances such as multiple, multilevel
and hierarchical as shown in Figure.
Consider the following
example:
class A1
{
protected:
int a1;
};
class A2 : public A1
{
protected:
int a2;
};
class A3: public A1
{
protected: int a3;
};
class A4: public A2,A3
{int a4; };
In the given example, class A2 and A3 are derived from the same base class i.e., class A1(hierarchical inheritance). The classes A2 and A3 both can access variable a1 of class A1. The class A4 is derived from class A2 and class A3 by multiple inheritances. If we try to access the variable a1 of class A, the compiler shows error messages as given below.
(a) Member is ambiguous: ‘A1::a1 and ‘A1::a1’
(b) Member is ambiguous: ‘A1::a1 and ‘A1::a1’
VIRTUAL BASE CLASSES
To overcome the
ambiguity occurred due to multipath inheritance, C++ provides the key word virtual.
The keyword virtual declares the specified classes virtual. The
example given below illustrates the virtual classes.
class A1
{
protected:
int
a1;
};
class A2 : virtual
public A1 // virtual class declaration
{
protected:
int
a2;
};
class A3: virtual
public A1 // virtual class declaration
{
protected:
int
a3;
};
class A4: public A2,A3
{
int a4;
};
When classes are
declared as virtual, the compiler takes necessary precaution to avoid
duplication of member variables. Thus, we make a class virtual if it
is a base class that has been used by more than one derived class as their base
class.
Nestesd Classes
A class may be declared as a
member of another class. Consider the following:
Class M1
{
int n;
public:
int m;
};
class M2
{
int n;
public:
int m;
};
class M3
{ M1 N1;
public:
M2 N2;
};
Now, N1 and N2 are nested
classes of M3. M3 can access only public members of N1
and N2. A nested class is
hidden in the lexically enclosing class.
Dynamic Memory Allocation/
Deallocation Operators Using
New, Delete:-
New Operator
In C++, the pointer support
dynamic memory allocation (allocation of memory during runtime). While studying
arrays we declared the array size approximately. In this case if the array is
less than the amount of data we cannot increase it at runtime. So, if we wish
to allocate memory as and when required new operator helps in this
context.
The syntax of the new operator
is given below :
pinter_variable = new data_type;
Where the data type is any
allowed C++ data type and the pointer_variable is a pointer of the same data
type. For example,
char * cptr
cptr = new char;
The above statements allocate 1
byte and assigns the address to cptr.
The following statement
allocates 21 bytes of memory and assigns the starting address to cptr :
char * cptr;
cptro = new char [21];
We can also allocate and
initialize the memory in the following way :
Pointer_variable = new data_type
(value);
Where value is the value to be
stored in the newly allocated memory space and it must also be of the type of
specified data_type. For example,
Char *cptr = new char (‘j’];
Int *empno = new int [size];
//size must be specified
Delete Operator
It is used to release or
deallocate memory. The syntax of delete operator is :
delete_pointer_variable;
For example,
delete cptr;
delete [ ] empno; //some
versions of C++ may require size
The This Pointer
We know that while defining a
class the space is allocated for member functions only once and separate memory
space is allocated for each object, as shown in figure With the above shown
allocation there exists a serious problem that is which object’s data member is
to be manipulated by any member function. For example, if memberfunc2( ) is
responsible for modifying the value of datamember1 and we are interested in
modifying the value of datamember1 of object3. In the situation
like it, how to decide the manipulation of which object’s datamember1?
The this pointer is an answer to this problem. The this is a
pointer that points to that object using which the function is called. The This
pointer is automatically passed to a member function when it is called. The
following program illustrates the above mentioned concept :
#include<iostream.h>
#include<string.h>
class per
{
char name[20];
float saralry;
public :
Fig. Allocation of memory for
functions and class objects
Member func
Member func
Member func 3()
Object 1 object 2
Datamember 1
Datamember 2
Datamember 1
Datamember 2
Datamember 1
Datamember 2
per (char *s,float a)
{strcpy(name,s); salaru =a’}
per GR(per & x)
{ if (x.salary> =salary)
return &x;
else
return this;
}
void display()
{
cout<<”name :
“<<name<<’\n’;
cout<<”salar
:”<<salary<<’\n’;
}
};
Void main ()
{
Per
p1(“REEMA:, 10000), p2(“KRISHANAN”,20000), p3 (“GEORGE”, 50000);
The output of the Program would
be :
Name : REEMA
Salary : 10000
Name : KRISHANAN
Salary : 20000
Here, the first call to the
function GR returns reference to the object P1 and the second
call returns reference to the object P2.
VIRTUAL FUNCTIONS
Polymorphism
is a mechanism that enables same interface functions to work with the whole
class hierarchy. Polymorphism mechanism is supported in C++ by the use of
virtual functions. The concept of virtual function is related to the concept of
dynamic binding. The term Binding refers to binding of actual code to a
function call. Dynamic binding also called late binding is a binding mechanism
in which the actual function call is bound at run-time and it is dependent on
the contents of function pointer at run time. It meant that by altering the
content of function pointers, we may be able to call different functions having
a same name but different code, that is demonstrating polymorphic behaviour.
Let us look into an example for
the above concept:
#include <iostream.h>
class employee
{
public:
char *name;
char *department;
employee (char *n, char *d)
{
name = n;
department = d;
}
virtual void print ( );
};
void employee:: print ( )
{
cout <<
“name:”<<name;
cout << “department:”
<< department;
}
class manager : public employee
{
public:
short position;
manager (char *n, char *d,
short p) : employee (n, d)
{
name = n;
department = d;
position = p;
}
void print ( )
{
cout << name <<
“\n” << department << “\n” << position;
}
};
void main ( )
{
employee* e (“john”, “sales”);
manager* m (“james”,
“marketing”, 3);
e print ( )
m print ( ) ;
}
The output will be:
John
Sales
James
marketing
3
Polymorphim
Polymorphism means ‘one name
multiple forms’. Runtime polymorphism can be achieved by using virtual
functions. The polymorphism implementation in C++ can be shown as in figure.
Compile time polymorphism
STATIC POLYMORPHISM OR
COMPILE TIME POLYMORPHISM
It
means existence of an entity in various physical forms simultaneously. Static
polymorphism refers to the binding of functions on the basis of their signature
(number, type and sequence of parameters). It is also called early
binding because the calls are type and sequence of parameters). It is also
called early binding because the calls are already bound to the proper
type of functions during the compilation of the program. For example,
Void volume (int); //prototype Fig.
Implementation of polymorphism. Void volume (int,int,int); //prototype
When the function volume ( ) is
invoked, the passed parameters determine which one to be executed. This
resolution takes place at compile time.
DYNAMIC POLYMORPHISM
It
means change of form by entity depending on the situation. A function is said
to exhibit dynamic polymorphism if it exists in various forms, and the
resolution to different function calls are made dyanamically during execution
time. This feature makes the program more flexible as a function can be
called, depending on the context.
STATIC AND DYNAMIC BINDING
As
stated earlier the dynamic binding is more flexible, and the static binding is
more efficient in certain cases. Statically bound functions do not require
run-time search, while the dynamic function calls need it. But in case of
dynamic binding, the function calls are resolved at execution time and the user
has the flexibility to alter the call without modifying the source code.
For a
programmer, efficiency and performance are more important, but to the user,
flexibility and maintainability are of primary concern. So a trade-off between
the efficiency and flexibility can be made.
POINTERS AND INHERITANCE
The private and public member
variables of a class are stored in successive memory locations. A pointer to
public member variable gives us access to private member variables.
The same is true for
derived class. The member variables of base class and derived class are also
stored in successive memory locations. The following program explains the
mechanism of accessing private data members of the base class using the address
of public member variable of derived class using pointer. Here, no member
functions are used.
// program to access private member variables of
base class using pointers.
# include <iostream.h>
# include <conio.h>
class A
{
private:
int x;
int y;
public:
A( ) {
x=1;
y=2;
}
};
class B : private A
{
public:
int z;
B( ) { z=3; }
};
void main( )
{
clrscr(
);
B b; //
object declaration
int *p;// pointer declaration
p=&b.z; // address of public member variabe
is stored in pointer
cout<<endl<<" Address of z :
"<<(unsigned)p <<" "<<"Value of z
:"<<*p;
p--; //
points to previous location
cout<<endl<<" Address of y :
"<<(unsigned)p <<" "<<"Value of y
:"<<*p;
p--;
cout<<endl<<" Address of x :
"<<(unsigned)p <<" "<<"Value of x
:"<<*p;
}
Unit V
FILES
With the advancement of
information technology a great amount of information is available on Internet.
Huge amount of data is processed in computer networking. The information can be
uploaded or downloaded from the desktop computer. The information transfer in
computer networking in day-to-day life is in the form of files. The files can
be written, read, or updated depending upon the applications. The data is saved
in the file on the disk. The file is an accumulation of data stored on the
disk. The stored data can be retrieved or updated. The console I/O function
reads data through input devices and displays on the screen. The data read
through these functions are temporarily stored in variables or in arrays. The
data stored vanishes when the
program ends. In order to store the data permanently, we need to apply disk I/O
function. The disk I/O functions are associated with disk files. These
functions perform read and write operations with the file. Like other
languages, C++ also provides function that allows a programmer to perform
read/write operation with the file. The disk I/O functions in C++ are very
different as compared to C, though the entire disk I/O functions of C can be
used in C++. However, these functions are not appropriate with the
object-oriented conditions.
FILE STREAM CLASSES
Stream is nothing but
flow of data. In object-oriented programming the streams are controlled using
the classes. The operations with the files are mainly of two types. They are
read and write. C++ provides various classes as shown in Figure to perform these operations.
The ios class is the base class. All other classes are derived from
the ios class. These classes contain several member functions that
perform input and output operations. The streambuf class has
low-level routines for controlling data buffer.

The istream and ostream classes
control input and output functions respectively. The ios is the base
class of these two classes. The member functions of these classes handle
formatted and unformatted operations (for more details about formatted and
unformatted functions please refer to Chapter “INPUT and OUTPUT in
C++”). The functions get( ), getline( ), read( )and overloaded
extraction operators (>>) are defined in the istream class. The
functions put( ), write( ) and overloaded insertion operators
(<<) are defined in the ostream class.
STEPS OF FILE OPERATIONS
Before performing file operations, it is necessary
to create a file. Operation of a file involves the following basic activities:
■ File name
■ Opening file
■ Reading or writing the file (File processing)
■ Detecting errors
■ Closing the file
The file name can be a
sequence of characters, called as a string. Strings are always declared with
character array. Using file name a file is recognized. The length of file name
depends on the operating system, for example, WINDOWS-98 supports long file
names whereas MS-DOS supports only eight characters. A file name also contains
extension of three characters. The file name should not be device name such as
LPT1, CON etc. You might have observed the .cpp extension to
the C++ program file name separated by dot (.). The extension is optional. The
following file names are valid in MS-DOS and WINDOWS-98 operating systems.
CHECKING FOR ERRORS
Until now, we carried
out the file operations without thinking whether it is performed successfully
or not. If any fault occurs during file operation, fault cannot be detected.
Various errors can be made by the user while performing file operation. Such
errors must be reported in the program to avoid further program failure. When
the user attempts to read file that does not exist or opens a read-only file
for writing purpose, in such situations operation fails. Such errors must be
reported and proper actions have to be taken before further operations.
The ! (Logical negation
operator) overloaded operator is useful for detecting the errors. It is a unary
operator and in short it is called as not operator. The ( ! ) not
operator can be used with object of stream classes. This operator returns
non-zero value if stream error is found during operation. Consider the
following program.
FINDING END OF A FILE
While reading a data from a file, it is
necessary to find where the file ends i.e., end of file. The programmer cannot
predict the end of file. In a program while reading the file, if the program
does not detect end of file, the program drops in an infinite loop. To avoid
this, it is necessary to provide correct instruction to the program that
detects the end of file. Thus, when end of file is detected, the process of
reading data can be easily terminated. The eof( ) member function is
used for this purpose. The eof ( ) stands for end of file. It is an instruction
given to the program by the operating system that end of file is reached. It
checks the ios::eofbit in the ios::state. The eof(
) function returns non-zero value when end of file is detected, otherwise
zero.
FILE OPENING MODES
In previous examples we have learnt how to open
files using constructor and open( ) function by using the objects
of ifstream and ofstream classes. The opening of file also
involves several modes depending upon operation to be carried out with the file.
The open( ) function has two arguments as given below:
Syntax of open( ) function
object.open ( “file_
name”, mode);
Here object is a stream
object, followed by open( ) function. The bracket of open function
contains two parameters. The first parameter is name of the file and second is
mode in which file is to be opened. In the absence of mode parameter default
parameter is considered. The file mode parameters are given in Table
13.1.
FILE POINTERS AND MANIPULATORS
All file objects hold two file pointers
associated with the file. These two file pointers provide two integer values.
These integer values indicate exact position of file pointers in number of
bytes in the file. The read or write operations are carried out at the location
pointed by these file pointers .One of them is called as get pointer
(input pointer) and the second one is called as putpointer (output
pointer). During reading and writing operations with files, these file pointers
are shifted from one location to another location in the file. The
(input) get pointer helps in reading the file from the given location
and the output pointer helps for writing data in the file at specified
location. When read and write operations are carried out, respective pointer is
moved.
MANIPULATORS WITH ARGUMENTS
The seekp( ) and seekg(
) functions can be used with two arguments. Their formats with two
arguments follows below:
seekg ( offset,
pre_position);
seekp ( offset,pre_position);
The first
argument offset specifies the number of bytes the file pointer is to
be shifted from the argument pre_position of the pointer.
The offset must be a positive or negative number. The positive number
moves the pointer in forward direction whereas negative number moves the
pointer in backward direction. The pre_position argument may have one
of the following values.
• ios::beg Beginning of
the file
• ios::cur Current
position of the file pointer
• ios::end End of the
file
Figure
13.11 shows status
of pre_position arguments.
SEQUENTIAL READ AND WRITE OPERATIONS
C++ allows file manipulation command to access
file sequentially or randomly. The data of sequential file must be accessed
sequentially i.e., one character at a time. In order to access nth number of
bytes, all previous characters are read and ignored. There are number of
functions to perform read and write operations with the files. Some function
read /write single character and some function read/write block of binary data.
The put( ) and get( ) functions are used to read or write a
single character whereas write( ) and read( ) are used to
read or write block of binary data.
The put( ) and get(
) Functions
The function get( ) is a member
function of the class fstream. This function reads a single character from
the file pointed by the get pointer i.e., the character at current get pointer
position is caught by the get( ) function.
BINARY AND ASCII FILES
The insertion and extraction operators, known as
stream operator, handles formatted data. The programmer needs to format data in
order to represent it in a suitable fashion. The description of formatted and
unformatted data is given in Chapter “INPUT and OUTPUT IN C++”. ASCII
codes are used by the I/O devices to share or pass data to the computer
system, but central processing unit (CPU) manipulates the data using binary
numbers i.e., 0 and 1. For this reason, it is essential to convert the data
while accepting data from input devices and displaying the data on output
devices. Consider the following statements:
cout<<k; //
Displays value of k on screen
cin>>k; //
Reads value for k from keyboard
Here, k is an
integer variable. The operator << converts value of integer
variable k into stream of ASCII characters. In the same fashion, the
<< operator converts the ASCII characters entered by the user to binary.
The data is entered through the keyboard, a standard input device. For example,
you enter 21. The stream operator >> gets ASCII codes of the individual
digits of the entered number 21 i.e., 50 and 49. ASCII code of 2 and 1 are 50
and 49 respectively. The stream operator >> converts the ASCII value to
equivalent binary format and assigns it to the variable k. The stream
operator << converts the value of k (21) that is stored in
binary format into equivalent ASCII codes i.e., 50 and 49. Figure
13.9 shows
representation of integer number in ASCII and binary format.
RANDOM ACCESS OPERATION
Data files always contain large information and
the information always changes. The changed information should be updated
otherwise the data files are not useful. Thus to update data in the file we
need to update the data files with latest information. To update a particular
record of data file it may be stored anywhere in the file but it is necessary
to obtain at which location (in terms of byte number) the data object is
stored.
The sizeof(
) operator determines the size of object. Consider the following
statements.
(a) int size=sizeof(o);
Where, o is an
object and size is an integer variable. The sizeof(
) operator returns the size of object o in bytes and it is stored
in the variable size. Here, one object is equal to one record.
ERROR HANDLING FUNCTIONS
Until now, we have performed the file operation
without any knowledge of failure or success of the function open(
) that opens the file. There are many reasons and they may result in error
during read/write operation of the program.
(1) An attempt to read a file which does not
exist.
(2) The file name specified for opening a new
file may already exist.
(3) An attempt to read contents of file when
file pointer is at the end of file.
(4) Insufficient disk space.
(5) Invalid file name specified by the
programmer.
(6) An effort to write data to the file that is
opened in read only mode.
(7) A file opened may already be opened by
another program.
(8) An attempt to open read only file for
writing operation.
(9) Device error.
COMMAND LINE ARGUMENTS
An executable program that performs a specific
task for operating system is called as command. The commands are issued from
the command prompt of operating system. Some arguments are to be associated
with the commands hence these arguments are called as command line arguments.
These associated arguments are passed to program.
Like C, in C++ every
program starts with a main( ) function and it marks the beginning of
the program. We have not provided any arguments so far in the main(
) function. Here, we can make arguments in the main( ) like
other functions. The main( ) function can receive two arguments and
they are argc (argument counter) and argv (argument
vector). The first argument contains the number of arguments and
the second argument is an array of char pointers. The *argv points to the
command line arguments. The size of array is equal to value counted by
the argc. The information contained in the command line is passed on to
the program through these arguments when the main( ) is called up by
the system.
STRSTREAMS
(1) ostrstream
The strstream class is derived
from istrstream and ostrstream classes.
The strstream class works with memory. Using objects
of ostrstream class different type of data values can be stored in an
array.
13.23 Write a program to demonstrate use of
ostrstream objects.
# include
<strstream.h>
# include
<iomanip.h>
# include
<conio.h>
main ( )
{
clrscr( );
char h='C';
int j=451;
float PI=3.14152;
char txt[]="applications";
char buff[70];
ostrstream o (buff,70);
o<<endl <<setw(9)<<"h="<<h<<endl <<setw(9) <<"j="<<oct<<j<<endl
<<setw(10)<<"PI="<<setiosflags(ios::fixed)<<PI<<endl <<setw(11)
<<"txt="<<txt <<ends;
cout<<o.rdbuf(
);
return 0;
}
OUTPUT
h=C
j=703
PI=3.14152
txt= applications
h=C
j=703
PI=3.14152
txt= applications
SENDING OUTPUT TO DEVICES
It is also possible to send information of file
directly to devices like printer or monitor. Table
13.6describes various
devices with their names and descriptions. The program given next illustrates
the use of such devices.
Table 13.6 Standard devices
Device Name
|
Description
|
CON
|
Console (monitor
screen)
|
COM1 or AUX
|
Serial port – I
|
COM2
|
Serial port – II
|
LPT1 OR PRN
|
Parallel printer – I
|
LPT2
|
Parallel printer – II
|
LPT3
|
Parallel printer – III
|
NUL
|
Dummy device
|
13.25 Write a program to read a file and send data
to the printer.
# include
<fstream.h>
# include
<iostream.h>
# include
<conio.h>
# include
<process.h>
# define eject out.put('\x0C');
void main ( )
{clrscr( );
char h;
char name[20];
cout <<"Enter file name : ";
cin>> name;
ifstream in (name);
if (!in)
{
cerr <<endl<<"File opening error";
_cexit( );
}
ofstream out ("LPT1");
if(!out)
{
cerr <<endl<<"device opening error";
_cexit( );
}
while (in.get(h)!=0)
out.put(h);
eject;
}
Subscribe to:
Posts (Atom)