0% found this document useful (0 votes)
96 views

CS-235 0bject Oriented Programming With C++ Complete Lecture Notes

C++ is an extension of C that was created in 1979 at Bell Labs to address increasing complexity in programs. It incorporates object-oriented programming principles like encapsulation, inheritance, and polymorphism to organize programs around data and objects rather than just functions. Key concepts in C++ include classes, which define objects and member functions, and objects as instances of classes that encapsulate data and methods.

Uploaded by

Yogesh Katre
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
96 views

CS-235 0bject Oriented Programming With C++ Complete Lecture Notes

C++ is an extension of C that was created in 1979 at Bell Labs to address increasing complexity in programs. It incorporates object-oriented programming principles like encapsulation, inheritance, and polymorphism to organize programs around data and objects rather than just functions. Key concepts in C++ include classes, which define objects and member functions, and objects as instances of classes that encapsulate data and methods.

Uploaded by

Yogesh Katre
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 242

CS213 1

Programming in C++ / Session 1 / 1 of 45


C++
C++ is an extension of C . In other words C++ is a superset of C
C++ was invented by Bjarne stroustrup in 1979 at Bell laboratories, New Jersey
Initially it was called “C with classes”. However in 1983 the name was changed to
C++
The invention of C++ was necessitated by one major programming factor ::
increasing complexity. In C , once a program exceeds from 25000 to 100000 lines
of code, it becomes complex & difficult to grasp
In structured programming language, data types are processed in many functions,
and when changes occur in data types, modification must be made at every
location that acts on these data types within the program. This is a complex task
for large sized programs
Reference books ::
 The complete reference C++ by Herbert schildt (Tata McGraw Hill)
 Let us C++ by yashavant Kanetkar (BPB publications)
 Object oriented programming in C++ by Robert Lafore (Galgotia publications)

**
CS213 2
Programming in C++ / Session 1 / 2 of 45
The Object-Oriented approach

Accounts
Personnel

Sales

People in each department control and operate on that department's


data.

**
CS213 3
Programming in C++ / Session 1 / 3 of 45
Drawbacks of Traditional Programming
Fortran : not structured (uses goto)
Pascal/ C : Structured (less use of goto),
subroutines/function to add modularity or more
structure, but modularity only at functional level
C++ : modularity at both functional and data level
In C programs are organized around the code  what
is happening
In C++ programs are organized around the data 
who is being affected.

**
CS213 4
Programming in C++ / Session 1 / 4 of 45
Introduction to OOP
OOP allows for analysis and design of an application
in terms of entities or objects.

Code and data are merged into a single indivisible


entity -- an object.

**
CS213 5
Programming in C++ / Session 1 / 5 of 45
Data and Functions of an Object
Accounts
Data: Functions:

Number of employees Calculate salary


Salary statements Pay salary
Bills Pay bills
Vouchers Tally accounts
Receipts Transact with banks
Petty cash records
Banking data

**
CS213 6
Programming in C++ / Session 1 / 6 of 45
Objects
Incorporate a combination of a set of data values as data
members, and the set of operations as member function.

Analogues to how things are in the real world.

Each object has its own properties or characteristics that


describe what it is or does.

**
CS213 7
Programming in C++ / Session 1 / 7 of 45
Different Objects

Name: Jack Model: Ferrari


Age: 28 Colour: Red
Weight: 65 kgs Year: 1995

Actions:
Walk Actions:
Talk Start
Sleep Stop
Accelerate

**
CS213 8
Programming in C++ / Session 1 / 8 of 45
Classes
Class is a logical abstraction for representing various objects
having similar attributes/properties.

Each object is said to be an instance of its class.

**
CS213 9
Programming in C++ / Session 1 / 9 of 45
Objects and Classes
Polygon class
Polygon objects
Properties:
Vertices
Border color
Abstract Fill color

into Methods:
Draw
Erase
Move

**
CS213 10
Programming in C++ / Session 1 / 10 of 45
Property/Attribute
• Each object ie instance of the class has its own value
for each of its properties but it shares the property
names or operations with other instances of the class
(object).

**
CS213 11
Programming in C++ / Session 1 / 11 of 45
Method
What is the salary  The black box actually contains
of Jack code
Sales
 The communication between
objects is done using
messages.

Jack’s salary is  These messages can be


$2000 translated to function calls in a
program.
Accounts

An action required of an object or entity


represented in a class is known as a method

**
CS213 12
Programming in C++ / Session 1 / 12 of 45
Abstraction
Process of examining certain aspects of a problem.
An abstract specification tells us what an object does
independent of how it works.
In C++ an abstraction indicates what data can an object
hold and what functions can it perform on the data. How
these functions are performed is abstracted away

**
CS213 13
Programming in C++ / Session 1 / 13 of 45
Inheritance
The property that allows the reuse of an existing class to
build a new class. The derived class inherits all the
capabilities of the base class and can either refine some
of its features or add totally new features of its own
Superclass - The class from which another class
inherits its behaviour.
Subclass - The class that inherits the properties and
methods of another class.
Inheritance works the same way as in real life. Children inherit
features from their parents, refine some of them and add a few of
their own
**
CS213 14
Programming in C++ / Session 1 / 14 of 45
Class Animals and its subclasses

Animals

Insects Mammals Reptiles Amphibians

**
CS213 15
Programming in C++ / Session 1 / 15 of 45
Encapsulation

Encapsulation is the mechanism that binds together the


code & data it manipulates, and keep both safe from outside
interference & misuse.
In C++ the basis of encapsulation is a class. The purpose of a
class is to encapsulate complexity and C++ provides
mechanisms for hiding the complexity of implementation inside
the class

**
CS213 16
Programming in C++ / Session 1 / 16 of 45
Polymorphism
Polymorphism means the ability to assume several
forms. In object oriented programming context this
refers to the ability of an entity to refer to objects of
various classes at run time
Three types in C++
 Function overloading Compile time polymorphism

 Operator overloading

Run time polymorphism


 Virtual functions

**
CS213 17
Programming in C++ / Session 1 / 17 of 45
C++ Program Structure
C++ is a structured programming language

# include <iostream.h>
void main()
{
cout << “ Hello there !!! “ ;
}

Output:

**
CS213 19
Programming in C++ / Session 1 / 19 of 45
Standard I/O streams
Input Stream
The following object, in combination with its corresponding
insertion operator performs input in C++. >> operator stops reading after
seeing the first white space

Output Stream
The following object, in combination with its corresponding
extraction operator performs output in C++.

**
CS213 21
Programming in C++ / Session 1 / 21 of 45
Cascading I / O Operators
The input and output streams can be used in combination.

**
CS213 22
Programming in C++ / Session 1 / 22 of 45
Certain Essentials
The essential components of a program construct are:

Functions are defined to break up large tasks into


smaller tasks.

Delimiters { … } are used to delimit blocks of code


in loops and functions.

Each code instruction in C++ must be terminated


with a semi-colon (;).

In C++ Comments can be single line comments (//) or


multiple line comments (/* …… */).
**
CS213 25
Programming in C++ / Session 1 / 25 of 45
Defining Objects

exampleclass object1,object2;

When we define an object, space is set aside for it in


memory.

**
CS213 31
Programming in C++ / Session 1 / 31 of 45
Two objects with different values
object_data
object_data object1
200

Specifications for
Objects of the class
exampleclass objects
exampleclass

object_data

350
object2
exampleclass
class specifier
**
CS213 34
Programming in C++ / Session 1 / 34 of 45
CS213 35
Programming in C++ / Session 1 / 35 of 45
Introduction

Identifier
**
CS213 36
Programming in C++ / Session 1 / 36 of 45
Special characters
[] () . -> ++ -- &
* + - ~ ! \ /
% << >> < > <= >=

== != ^ && | || ?:
= *= /= %= += -= <<=

>>= &= ^= |= , # ##
CS213 37
Programming in C++ / Session 1 / 37 of 45
Escape sequences
Back space
New line
Tab
Carriage return
Form feed
Single quote
CS213 38
Programming in C++ / Session 1 / 38 of 45
Escape sequences (1)
Back slash
Bell
Octal number
given by ooo
Hexadecimal number
given by hh
CS213 39
Programming in C++ / Session 1 / 39 of 45
Identifiers

The part of the program where the identifier is recognized

CS213 41
Programming in C++ / Session 1 / 41 of 45
Keywords
Keywords, inherited from the C language

New in C++

CS213 42
Programming in C++ / Session 1 / 42 of 45
Data Types and Variables

CS213 43
Programming in C++ / Session 1 / 43 of 45
Another predefined data type of C++ :: bool
bool data type : can store true and false
 true or false are the keywords defined in C++

Automatic conversion takes place which allow bool values to be converted to


integers & vice versa
Any non zero integer value is converted to true & integer value zero is converted
to false
bool True is converted to integer 1 and bool false is converted to integer 0
#include<iostream.h>
Void main() {
bool b = 32;
int i = false;
count << endl <<b <<endl << i; // prints 1 & then 0
int j = b + b;
bool k = b + b;
cout <<endl << j <<endl << k; // prints 2 & then 1
CS213 45
Programming in C++ / Session 1 / 45 of 45
Declaring variables
data_type variable name = initial value

int num ;
int num1 = 3; optional
char alpha = ‘G’ ; C requires that all variables be
declared before the first executable
float float_no ; statement. Whereas C++ allows
declaration of variables anywhere in
float floa = 33.33; the program. So you can declare
double d_no ; variables at the point where they
are used
double doub = 1234.121212121
; CS213 46
Programming in C++ / Session 1 / 46 of 45
Access modifiers

const float pi = 3.146 ;


const char three = ‘3’;
const int number = 5 ;
const double d_number = 8738478.9898 ;
CS213 50
Programming in C++ / Session 1 / 50 of 45
Constants

The value of the variable defined as constant will not be allowed to change through
out the program. So in purpose const is similar to #define
const is a better idea as compared to #define because its scope of operation can be
controlled by placing it appropriately either inside a function or outside all functions

CS213 51
Programming in C++ / Session 1 / 51 of 45
const pointers
const char *q = “Hello”; //string is constant but pointer q is not constant
*q = ‘M’; // error
q = “bye” //ok

char const *q = “Hello”; //string is constant but pointer q is not constant


*q = ‘M’; // error
q = “bye” //ok

char *const t = “Hello”; //string is not constant but pointer t is constant


*t = ‘M’; // ok
t = “bye” //error

const char * const u = “Hello”; //string is constant as well as pointer u is constant


*u = ‘M’; // error
u = “bye” //error

 The above is similarly also applicable to integer pointer, floating point pointers etc

CS213 58
Programming in C++ / Session 1 / 58 of 45
Returning const value
 A function can return a pointer to a constant string as shown below

#include <iostream.h>
void main() {
const char *fun();
const char *p;
p = fun(); // since fun() is returning a const value so in main() we are not allowed to assign the
//return value to a pointer to a non const value . Ie p must be a pointer to const string.
*p = ‘a’; // error as p is a pointer to constant string whose contents can not be changed
cout << p;
}

const char *fun() {


return “ Rain”;
}
Note : In this case main() will also be not allowed to pass the return value to a function that is
expecting a pointer to a non const string

CS213 59
Programming in C++ / Session 1 / 59 of 45
Precedence and Order of Evaluation

CS213 70
Programming in C++ / Session 1 / 70 of 45
Conversion table

CS213 72
Programming in C++ / Session 1 / 72 of 45
Type casting

Often leads to
Use explicit type conversions
in mixed mode expressions
N = (y-1) * (long) j ; // C style of typecasting ; also supported by C++
float a ;
(int) a ; N = (y-1) * long(j); // new C++ style of typecasting

CS213 74
Programming in C++ / Session 1 / 74 of 45
The :: operator
:: is a scope resolution operator
#include < iostream.h>
Int a=10; // global a
Void main() {
Int a = 15; // local a
cout << “\n local a =“ << a << “global a = “ << ::a;
}

CS213 79
Programming in C++ / Session 1 / 79 of 45
The break Statement

The break statement used within a loop causes the


loop to be terminated and forces the execution to
proceed with the statements following that loop.

CS213 109
Programming in C++ / Session 1 / 109 of 45
The continue Statement

When continue statement is encountered in a loop,


the rest of the statements in the loop are skipped
and the control passes to the condition, which is
evaluated and if TRUE the loop is entered again.

CS213 112
Programming in C++ / Session 1 / 112 of 45
The exit() Construct

The function exit() is used to terminate a program


immediately. An exit() is used to check if a
mandatory condition for a program execution is
satisfied or not. The general form of an exit() is:

exit(int return_code)

CS213 114
Programming in C++ / Session 1 / 114 of 45
Return from functions

CS213 123
Programming in C++ / Session 1 / 123 of 45
Return from functions

 No default to int in C++


funC(int i) {
Return i*i;
/* valid in C because by default a function () is expected to return int, but this is
not the case in C++ (but some C++ compilers still support C default to int
function(). But it is not advisable for new codes as per standard C++
recommendations */
CS213 124
} Programming in C++ / Session 1 / 124 of 45
Scope of Variables

CS213 125
Programming in C++ / Session 1 / 125 of 45
Scope of Variables

CS213 126
Programming in C++ / Session 1 / 126 of 45
Scope of Variables
int gi_area; // Declaring a global variable

void main(void)
{ void using_globalvar(void);
void g_func(void) ;
int li_len, li_wid; //Declaring local variables
:
:
using_globalvar() ; //Function call
}
void using_globalvar(void)
{
cout << "\nArea = " << gi_area; // Global variable
getch() ;
return ;
}

CS213 128
Programming in C++ / Session 1 / 128 of 45
Actual and Formal parameters
The parameter specified during a function call

Actual parameter ( argument )


The corresponding parameter in the called function

Formal parameter ( argument )

CS213 131
Programming in C++ / Session 1 / 131 of 45
The sizeof() operator

CS213 135
Programming in C++ / Session 1 / 135 of 45
Storage classes

 auto
 static
 extern
 register

CS213 139
Programming in C++ / Session 1 / 139 of 45
Auto storage class
Automatic variables do not retain the
value over a number of function calls

Local variables are by default auto variables

To declare an automatic variable the keyword auto,


which is optional for local variables, is used

CS213 140
Programming in C++ / Session 1 / 140 of 45
Static storage class
Static variables retain their values
over a number of function calls

To declare a static variable the keyword static


is placed at the head of the declaration

CS213 141
Programming in C++ / Session 1 / 141 of 45
Static storage class
void print_auto(void)
{
static int i = 0 ;
auto j = 0;
cout << "\nValue of i before incrementing = " << i ;
cout << "\nValue of j before incrementing = " << j ;
i += 10 ;
j += 10 ;
cout << "\nValue of i after incrementing = " << i ;
cout << "\nValue of i after incrementing = " << j ;
}

CS213 142
Programming in C++ / Session 1 / 142 of 45
Static storage class
void main(void)
{
clrscr() ;
print_auto() ;
cout<<”\n”;
print_auto() ;
cout<<”\n”;
print_auto() ;
}

CS213 143
Programming in C++ / Session 1 / 143 of 45
Extern storage class

A global variable located in file A


can be accessed by a function in file B
using the keyword extern

CS213 144
Programming in C++ / Session 1 / 144 of 45
Extern storage class

CS213 145
Programming in C++ / Session 1 / 145 of 45
Register storage class
Register memory is a part of
microprocessor itself

Register storage class can be specified


only for local variables

For faster execution of programs


register storage class can be specified

Address operator ‘&’ cannot


be applied to register variables

register int number ;


CS213 146
Programming in C++ / Session 1 / 146 of 45
Functions in multiple files
Programs can be composed of multiple files
Functions of the same program can be defined
in different files
As with variables in multifile programs,
functions can also be defined as static or external
static fn_type ( argument list ) Can not be used outside the file

extern fn_type ( argument list ) Functions declaration by


default are extern

CS213 147
Programming in C++ / Session 1 / 147 of 45
Pointers
A pointer is a variable that we can use to store a memory address.

Defined using the ‘ * ‘ operator

CS213 148
Programming in C++ / Session 1 / 148 of 45
Pointers

char v, *pv
v = 'A' ;
pv = &v ;

CS213 149
Programming in C++ / Session 1 / 149 of 45
Pointer operation
int *p1, *p2;
 p1 + 4, p2 – 2, p1++, --p2 are valid operation
 p2 - p1 is valid and gives the no. of elements between p1 &
p2 if p1 & p2 both are pointers to the same array
 Pointers can be compared  p1 > p2, p1 ==p2, p1 != p2
are all valid operation
 p1 + p2, p1/p2 , p1 * p2, p1/3. p2 * 5  invalid operations

CS213 151
Programming in C++ / Session 1 / 151 of 45
void pointers
In C++ special care has to be taken to handle the assignment of
void pointers to other pointer types
void *p;
Char *s;
p = s; // valid
s = p; // invalid assignment should be s = (char *) p ;

While you can assign a pointer of any type to a void pointer, the
reverse is not true unless you specifically typecast it

CS213 152
Programming in C++ / Session 1 / 152 of 45
Call by value
When data is passed between functions using variable names
void main(void)
{
int data ;
:
:
call_function(data) ;
}
void call_function(int data)
{
cout << data ;
}
CS213 153
Programming in C++ / Session 1 / 153 of 45
Call by reference
When data is passed between functions using address of variables
void main(void)
1000
{ 1001 (data) 12 50
1002
int data ; 1003
1004
data =12; 1005 (p_data) 1001
1006
:
1007
: 1008
1009
call_function(&data) ;
}
1001
void call_function(int *p_data)
{
*p_data = 50
cout << *p_data ;
}
CS213 154
Programming in C++ / Session 1 / 154 of 45
Value modification
void funct1(int u, int v)
{
u = 0; v = 0;
}
void funct2(int *pu, int *pv)
{
*pu = 0 ; *pv = 0 ;
}
CS213 156
Programming in C++ / Session 1 / 156 of 45
Character Arrays
# include <iostream.h>
void main(void)
{
char name[10];

cout << "\nEnter your first name: " ;


cin >> name ;
cout << endl ;

cout << “\nHello " << name << ". Welcome to Arrays!” ;
}

Enter your first name: SARAH


Hello SARAH Welcome to Arrays!

CS213 163
Programming in C++ / Session 1 / 163 of 45
Pointers and Arrays
An array of pointers can be created
(Int (*pt)[7] :: pointer to an
int *pt[7] ; array of 7 integers)

An array called pt compromising of seven pointers

pt[0], pt[1], ……………..pt[6]

CS213 170
Programming in C++ / Session 1 / 170 of 45
Pointers and Arrays
Initializing array of character pointers
void main(void)
{
char *song[]= { “ Humpty dumpty sat on a wall\n”,
“ Humpty dumpty had a great fall\n”,
“ Not all the kings horses and men\n”
};
cout<<song[2];
}
Not all the kings horses and men

CS213 171
Programming in C++ / Session 1 / 171 of 45
Basic Introduction to Classes & Objects
// Example showing use of class and objects
#include <iostream>
using namespace std; // explained in next slide
#define SIZE 100
// This creates the class stack.
class stack {
int stck[SIZE]; // default scope is private
int tos;
int main()
public: // scope : discussed later
{
void init(); // Function declaration
stack stack1, stack2; // create two stack objects
void push(int i);
stack1.init(); // we access the class members
int pop();
// with the help of . operator
}; // we can declare an object here also but then it
stack2.init();
// will be a global object
stack1.push(1);
void stack::init() // function defination
stack2.push(2);
{
stack1.push(3);
tos = 0;
stack2.push(4);
}
cout << stack1.pop() << " ";
void stack::push(int i)
cout << stack1.pop() << " ";
{
cout << stack2.pop() << " ";
if(tos==SIZE) {
cout << stack2.pop() << "\n";
cout << "Stack is full.\n";
return 0;
return;
}
}
stck[tos] = i;
tos++;
}
int stack::pop()
{
if(tos==0) {
cout << "Stack underflow.\n";
return 0;
}
tos--;
return stck[tos];
}
Prepared by Dr. Naveen Choudhary 1
Prepared by Dr. Naveen Choudhary 2
Prepared by Dr. Naveen Choudhary 3
Defined in iostream
Prepared by Dr. Naveen Choudhary 4
Prepared by Dr. Naveen Choudhary 5
Prepared by Dr. Naveen Choudhary 6
Prepared by Dr. Naveen Choudhary 7
Prepared by Dr. Naveen Choudhary 8
Prepared by Dr. Naveen Choudhary 9
Constructors & Destructors
 How to initialize data members (specially private members) of an object  use
constructors
 A constructor is a special function that is a member of a class and has the same name
as that of the class
 Constructor do not return values & so constructor function has no return type
 How constructor is called :: called when the object is declared. An object’s
constructor is called once for global or static local objects. For non static local
objects, the constructor is called each time the object declaration is encountered.

 DESTRUCTORS
 Syntax :: ~Class_name
 Purpose : In many circumstances an object will need to perform some actions when it
is destroyed.
 An object may need to de-allocate memory that it had previously allocated or it may
need to close a file that it had opened. So in C++, it is destructor’s function that
handles deactivation events.
 when destructor is called :: when an object is destroyed, it’s destructor is
automatically called.
 when an object is destroyed :: local objects are created when their block is
entered & destroyed when the block is left
 Global objects are destroyed when program terminates
 like constructor, destructors also do not have return values

Prepared by Dr. Naveen Choudhary 10


Example constructor & destructor
// Using a constructor and destructor. int stack::pop()
#include <iostream> {
using namespace std; if(tos==0) {
#define SIZE 100 cout << "Stack underflow.\n";
// This creates the class stack. return 0;
class stack { }
int stck[SIZE]; tos--;
int tos; return stck[tos];
public: }
stack(); // constructor declared
~stack(); // destructor declared
void push(int i); int main()
int pop(); {
}; stack a, b; // create two stack objects
a.push(1);
// stack’s constructor function b.push(2);
stack::stack() // no return value a.push(3);
{ b.push(4);
tos = 0; cout << a.pop() << " ";
cout << "Stack Initialized\n"; cout << a.pop() << " ";
} cout << b.pop() << " ";
cout << b.pop() << "\n";
// stack’s destructor function return 0;
stack::~stack() // no return value }
{
cout << "Stack Destroyed\n";
} output :
stack initialized
void stack::push(int i)
{ stack initialized
if(tos==SIZE) { 3142
cout << "Stack is full.\n"; stack destroyed
return; stack destroyed
}
stck[tos] = i;
tos++;
} Prepared by Dr. Naveen Choudhary 11
Classes & Objects

Prepared by Dr. Naveen Choudhary 12


Classes
 Class is a logical abstraction whereas Object
has physical existence
 Object is an instance of a class
Class class_name { There are few restriction that apply to
Data members & member functions // by default private data members
int a; a non static member variable cannot have an
int b; initializer
access_specifier : Class ABC {
int A = 2; // not allowed
/ * public, private or protected, once an access specifier has been used, it }
remains in effect until either another access specifier is encountered or  No member can be object of the class that is
the end of the class declaration is reached data members & member being declared. Although a member can be a
functions */ pointer to the class that is being declared.
. Class ABC {
. . ABC BOX; //not allowed
. ABC *next_box; // allowed
access_specifier : }
 No member can be declared as auto, extern or
data members & member functions register (but can be static )
.
. .
.
} object_list ; Access Specifiers :
 private :: private to class only
 Public:: access specifier allows functions or data to be
accessible to other parts of your program.
 protected :: will be discussed later
Prepared by Dr. Naveen Choudhary 13
Structures & Classes
 Structure in C++ can have member functions
 Only difference b/w structure & Classes is that data members are
public by default in structure. Whereas in class, data members are
private by default.

struct mystr {
int a; // public by default
int b;
void showa();
void showb(char *s);
};
void mystr :: showa() {
.
.
}

 C-like structure (without member functions) are generally referred as


POD (plain old data)
 General rule is to use classes where necessary & use structure only in
the POD style.
Prepared by Dr. Naveen Choudhary 14
Union & Classes
 Like in C, the C++ union data members share the same location in memory
 like structure, union members are public by default
 like in C++ structure, Union can have their own constructors or destructors
#include <iostream>
using namespace std; note : what is POD union : : C like union without the
union swap_byte { member functions
void swap();
void set_byte(unsigned short i);
void show_word();
unsigned short u; Restriction in C++ on Unions
unsigned char c[2];  union cannot inherit any other class
};  Union can not be a base class
void swap_byte::swap() Union can not have virtual functions
{
Union can not have static member variables
unsigned char t;
t = c[0]; Union can not use a reference member variables
c[0] = c[1];  A union cannot have as a member any object that
c[1] = t; overloads the = operator.
}  no object can be a member of a union if the object
void swap_byte::show_word()
has an explicit constructor or destructor.
{
cout << u;
}
void swap_byte::set_byte(unsigned short i)
{
u = i;
} Note : In c we need to declare a variable of union
int main() as
{
swap_byte b; union swap_byte b;
b.set_byte(49034);
But in C++ we need not use union keyword. Same
b.swap();
b.show_word(); is the case with structures, enum & classes
return 0; Prepared by Dr. Naveen Choudhary 15
}
Anonymous Union
 It is a special type of Union
 Anonymous Union does not include a type name and thus no objects
of the anonymous Union can be declared
 The variables of Anonymous Union can be directly referred with out
the normal dot operator.
 The scope of Anonymous Union Variable will be same as other local
variables and thus anonymous Union variable name should not
collide/conflict with the local variable names
#include <iostream> RESTRICTIONS ON ANONYMOUS
#include <cstring>
using namespace std; UNIONS
int main()
{  All restriction involving unions
// define anonymous union
union {
apply to anonymous Unions also
long l;
double d;
no member function allowed
char s[4]; Anonymous Unions can not
};
// now, reference union elements directly contain private or protected
l = 100000;
cout << l << " "; elements
d = 123.2342;
cout << d << " ";
Global Anonymous unions must
strcpy(s, "hi");
cout << s;
be specified as static
return 0;
} Prepared by Dr. Naveen Choudhary 16
Friend Function
 A friend function has access to all private and protected members of
the class for which it is a friend
class B{
int b1,b2,b3;
public:
void func (int a1, int a2);
friend int funcglobal (int x1);
}

void B::func (int a1, int a2){


-------
-------
}

int funcglobal(int x1){


B ob;
ob.b1 = x1; // here you can access the private(or protected ) members of B, like b1,b2,b3

ob.b2 = x1; }

 USE OF FRIEND FUNCTION


 Useful for overloading certain types of operators
 Friend functions make the creation of some types of I/O function easier.
 Friend function may also be desirable where two or more classes may
contain members that are interrelated relative to other parts of the
program.
Prepared by Dr. Naveen Choudhary 17
Example Friend Function
#include <iostream>
using namespace std;
const int IDLE = 0; int main()
const int INUSE = 1; {
class C2; C1 x;
/* forward declaration (required here since a class C2 y;
can’t be referred to until it has been declared ) */ x.set_status(IDLE);
class C1 { y.set_status(IDLE);
int status; // IDLE if off, INUSE if on screen if(idle(x, y)) cout << "Screen can be used.\n";
// ... else cout << "In use.\n";
public: x.set_status(INUSE);
void set_status(int state); if(idle(x, y)) cout << "Screen can be used.\n";
friend int idle(C1 a, C2 b); else cout << "In use.\n";
/* or friend int C2 :: idle(C1 a)  if idle happened return 0;
to be defined in class C2 */ }
};
class C2 {
int status; // IDLE if off, INUSE if on screen
// ...
public:
void set_status(int state);
friend int idle(C1 a, C2 b); C1
};
void C1::set_status(int state) Share data (especially)
{ through friend finction C2
status = state;
Ie int idle() in this case
}
void C2::set_status(int state)
{
status = state;
}
int idle(C1 a, C2 b)
{ C1 & C2 are unrelated classes
if(a.status || b.status) return 0;
else return 1;
} Prepared by Dr. Naveen Choudhary 18
Friend Classes
 One class can be friend of another class. When this is the case,
the friend class and all of its member function have access to
the private members defined within the class.
Class C1 {
int a, b;
public:
friend class min;
};
class min {
func1(); // all these can access the private members of C1
func2(); // ---------do----------------------------
func3(); // -----------do------------------------
}

 Note: It is critical to understand that when one class is a friend of


another, it only has access to names defined within the other class. It
does not inherit the other class. Specifically, the members of the first
class do not become members of the friend class

Prepared by Dr. Naveen Choudhary 19


Inline Function
 Normal function call  push arguments in stack, save various registers,
transfer control and do vice versa on return  so more time consuming
process
 Inline function  code is expanded inline so efficient (faster) but will result in
larger code size  so generally very small functions are inlined.
 Note :: inline is actually is just a request, not a command to the compiler. The
compiler can choose to ignore it. It is common for a compiler not to inline a
recursive function. If a function cannot be inlined, it will simply be called as a
normal function
// note  inline function may be class member
#include <iostream>
//functions
using namespace std;
Class myclass {
inline int max(int a, int b)
_
{
_
return a>b ? a : b;
public :
}
void xyz()
int main()
int show ()
{
}
cout << max(10, 20); // == cout << (10>20 ? 10 : 20)
cout << " " << max(99, 88); // == cout << " " << (99>88 ? 99 : 88)
inline void myclass :: xyz() {
return 0;
_
}
note : when a function is defined inside a class declaration it is automatically made into an inline
_
function (if possible). It is not necessary (but not an error) to precede its declaration
} with the inline
keyword
class myclass { inline int myclass :: show()
- {
- _
_
void xyz(int i, int j) { a = i ; b = j; } // automatic inline as defined within the
_ class
void show () { cout << a << “ “ << b << “\n” // automatic inline as defined within the class
}; }
Prepared by Dr. Naveen Choudhary 20
Constructors - inlined
 constructors and destructors functions may also be inlined, ( by default), If
defined within their class or explicitly
Parameterized constructors
Class myclass { call to constructor ::
_
_ myclass ob(3,4);  this is generally used
_ or
int a, b;
myclass ob = myclass(3,4);
public :
myclass(int i, int j) {a = i ; b = j ; } // this will be inline
};
Constructor with one parameter
Class myclass {
int a ;
- call to constructor with single argument
- myclass ob = 99 actually for compiler it is equivalent to
-
public :
myclass(int i) { a = i; } // this is inline myclass ob = myclass(99);
}
we can also use  myclass ob(99); //generally this is used

myclass ob = 99  is possible b/s whenever you create a


constructor that takes one argument, you are also
implicitly creating a conversion from the type of that
argument to the type of the class.

Prepared by Dr. Naveen Choudhary 21


Static Data Members /* Another use of static member variable is to keep track
Class shared {
of the//one
no.useof objects
of staticofvariable
a particular
is to class
provide
type
access
that are in
Static int a ; // only a declaration so no space is
existence
//control */ to some shared resource used by all
//allocated as such
listing
//objects
26//static
of a class
-
#include
#include <iostream>
<iostream>
-
using using
namespace
namespace std;std;
};
class class
Counter
cl { {
public: static int resource;
int shared :: a; // definition, so now space is allocated
static
public:
int count;
Counter()
int get_resource();
{ count++; }
/* note : static  means you are telling the compiler that only
~Counter()
void free_resource()
{ count--; } {resource = 0;}
one copy of that variable will exist & that all objects of the class
}; };
will share that variable. All static variables (by default) are
int Counter::count;
int cl::resource; // define resource
initialized to 0 before the first object is created.*/
voidint f();cl::get_resource()
int main(void)
{
int main()
{ if(resource) return 0; // resource already in use
{
Counter
else {o1;
shared :: a = 99 // we have not created any object, still
cout resource
<< "Objects = 1;in existence: ";
// we can use static variable a
cout return
<< Counter::count
1; // resource
<< "\n";allocated to this object
Counter
} o2;
count << shared :: a ; // prints 99
cout} << "Objects in existence: ";
shared x;
cout << Counter::count << "\n";
count << x.a; // prints 99, use of static variable a
f();int main()
//with object
cout{ << "Objects in existence: ";
return 0;
coutcl<< ob1,
Counter::count
ob2; << "\n";
}
returnif(ob1.get_resource())
0; cout << "ob1 has
} resource\n";
void f()if(!ob2.get_resource()) cout << "ob2 denied
{ resource\n";
Counter
ob1.free_resource();
temp; // let someone else use it
coutif(ob2.get_resource())
<< "Objects in existence: ";
cout cout
<< Counter::count
<< "ob2 can now << "\n";
use resource\n";
// temp
returnis destroyed
0; when f() returns
} }

Prepared by Dr. Naveen Choudhary 22



Static Member function
Static member function can be called with class name or with object name
Restrictions on static member functions
#include <iostream> They can only directly refer to other static
using namespace std;
class cl {
member of the class ( but they can use non static
static int resource; global functions and data)
public: A static member function can not use this
static int get_resource(); pointer
void free_resource() { resource = 0; } There cannot be a static and non static versions
};
int cl::resource; // define resource
of the same function
int cl::get_resource() A static member function may not be virtual
{ Static member functions cannot be declared as
if(resource) return 0; // resource already in use constant or volatile
else {
resource = 1;
return 1; // resource allocated to this object /* Static member functions have limited application,
} but one good use of them is to “preinitialize” private
}
int main()
static data before any object is actually created. */
{ #include <iostream>
cl ob1, ob2; using namespace std;
/* get_resource() is static so may be called independent class static_type {
of any object. */ static int i;
if(cl::get_resource()) cout << "ob1 has resource\n"; public:
if(!cl::get_resource()) cout << "ob2 denied resource\n"; static void init(int x) { i = x; }
ob1.free_resource(); void show() { cout << i; }
};
/* we can also call static member function getr_resource int static_type::i; // define i
using object syntax also */ int main()
if(ob2.get_resource()) {
cout << "ob2 can now use resource\n"; // init static data before object creation
return 0; static_type::init(100);
} static_type x;
x.show(); // displays 100
return 0;
Prepared by Dr. Naveen Choudhary 23
}
WHEN CONSTRUCTORS AND DESTRUCTORS
ARE EXECUTED
 A local object constructor function is executed when the objects declaration statement
is encountered. Objects destructor is called when the life time of the object is about to
end.
 Global objects have their constructor function execute before main() begins execution.
Global constructors are executed in order of their declaration, within the same file. You
cannot know the order of execution of global constructors spread among several files.
Global destructors execute in reverse order after main() has terminated
#include <iostream>
using namespace std;
class myclass {
public:
int who;
myclass(int id); o/p :
~myclass();
} glob_ob1(1), glob_ob2(2); Initializing 1
myclass::myclass(int id) Initializing 2
{
cout << "Initializing " << id << "\n";
Initializing 3
who = id; This will not be the first line displayed
} Initializing 4
myclass::~myclass()
{ Destructing 4
cout << "Destructing " << who << "\n"; Destructing 3
}
int main()
Destructing 2
{ Destructing 1
myclass local_ob1(3);
cout << "This will not be first line displayed.\n";
myclass local_ob2(4);
return 0;
}
Prepared by Dr. Naveen Choudhary 24
THE SCOPE RESOLUTION OPERATOR ::

int i; // global i
void f()
{
int i; // local i
::i = 10; // now refers to global i
.
.
.
}

Prepared by Dr. Naveen Choudhary 25


Local Classes
#include <iostream.h>
using namespace std;
void f();
int main() { Restriction on local classes
f();  Member functions must be defined
return 0; within the class declaration in local classes
} (i.e. they are inline)
void f() { The local class may not use or access
class myclass local variables of the function in which it is
{ declared but can use the static local
int i; variable of the function.
public: Local class may access type names &
void put_i (int x) { enumerators defined by the enclosing
i = x; function.
} No static variable may be declared inside
int get_i (){ a local class.
return i; Because of these problems local classes
} are not common in C++
}ob;
ob.put_i (10);
cout<<ob.get_i();
}

Prepared by Dr. Naveen Choudhary 26


Passing Objects to functions
 Objects are passed by value // Passing an object to a function.
 So new object needs to be created #include <iostream>
when passing objects as parameter using namespace std;
class myclass {
 So whether constructor is called  int i;
no rather it will be a bitwise copy { public:
myclass(int n);
if constructor is called then it is as ~myclass();
good as creating a new object but we void set_i(int n) { i=n; }
want to actually pass the old object  int get_i() { return i; }
};
so no constructor should be called myclass::myclass(int n)
 Although destructor for the object {
i = n;
(parameter) will be called when the cout << "Constructing " << i << "\n";
function ends  necessary  as }
separate memory is occupied by the myclass::~myclass()
{
parameter object (object’s copy ) & it cout << "Destroying " << i << "\n";
need to be freed }
void f(myclass ob);
 Bit wise copy : Exact bit by bit copy int main()
but will lead to problem of side {
effect in case like  if an object used myclass o(1);
f(o);
as an argument allocates memory & cout << "This is i in main: ";
frees that memory when it is cout << o.get_i() << "\n";
return 0;
destroyed, then its local copy }
(parameter object ) inside the function void f(myclass ob)
will free the same memory when its {
destructor is called & this will leave the ob.set_i(2);
cout << "This is local i: " << ob.get_i();
original object damaged & effectively cout << "\n";
useless  what is the solution  use copy }
constructor (to be discussed later)Prepared by Dr. Naveen Choudhary 27
RETURNING OBJECTS
// Returning objects from a function.
 When an object is returned by a #include <iostream>
function (object local to function), a using namespace std;
temporary object is automatically class myclass {
int i;
created that holds the return value
public:
 It is this object that is actually void set_i(int n) { i=n; }
returned by the function. int get_i() { return i; }
 After the value has been returned, };
this object is destroyed. myclass f(); // return object of type myclass
 The destructor of temporary object int main()
{
may cause side effects
myclass o;
Side effects like  if the object o = f();
returned by the function has a cout << o.get_i() << "\n";
destructor that free dynamically return 0;
allocated memory, that memory will }
be freed even though the object that myclass f()
{
is receiving the return value is still
myclass x;
using it. x.set_i(1);
return x;
soln: overloading the assignment operator }
using copy constructor

Prepared by Dr. Naveen Choudhary 28


Object Assignment
// Assigning objects.
#include <iostream>
using namespace std;
class myclass {
01 02
int i;
public:
void set_i(int n) { i=n; }
ptr ptr
int get_i() { return i; }
}; (5000) (2000)
int main()
{
myclass ob1, ob2;
ob1.set_i(99); o1=o2 // o1.ptr =2000
ob2 = ob1; // assign data from ob1 to ob2 (bitwise copy)
cout << "This is ob2's i: " << ob2.get_i();
return 0;
}

Note : We can avoid bit – by – bit copy by overloading the assignment


operator & define some other assignment procedure

Prepared by Dr. Naveen Choudhary 29


Const member functions & constant object
Const member function : member function that guarantees
that it will never modify any of its class member data
void constfunc () const //the const will come in both member
Const function arguments
//function declaration & definition
If we want that argument passed by
reference should not be changed then we
distance add_dist(const distance &d2) const //***
should define these argument in function
{
declaration & definition as const.
distance temp;
feet = 0; //error as feet is class data member of invoking
void func (int &a, const int &b); //declaration
//object
void func (int &a, const int &b)
d2.feet = 0; //error, as d2 is passed as constant
{
temp.feet = temp.feet + d2.feet; // allowed
---------
return temp;
}
//definition
---------
*** if you want that the argument passed by reference to
}
this function should not be modified then it should be
No problem in passing a const argument by
declared as const reference argument in the member
value, because the function can’t modify the
function.
original value anyway.

Prepared by Dr. Naveen Choudhary 30


constant objects
 when an object is declared as const then you can’t modify it. It also means that you can
only use those member function with this object which are declared as const as they are
the only one that guarantees not to modify it.

Class Distance {
.
.
Public :

Distance(…, …) { ……. }

Void getlist() { …. }

Void showdist() const

{...... }
};
int main(){

const Distance ft(300, 0)

// ft.getlist();  not allowed

ft.showdist(); // allowed
}

Prepared by Dr. Naveen Choudhary 31


Containership & Nested Classes
Nested Class ::
Containership ::
A class has an object of it is possible to define one
different class as its data member class within another class.
class A {
Class A{ class B // Nested
- //class
- {
};
class B{
}
A obA; // define obA as an object of
//class A }
};
A nested class is only valid
member function of B can access the within the scope of the enclosing
public members of A with the help of dot class.
( . ) operator. Nested classes are rarely used &
are not generally required.

Prepared by Dr. Naveen Choudhary 32


Arrays, Pointers, References &
Dynamic Memory Allocation

Prepared by Dr. Naveen Choudhary 33


Array of Objects
// In case of classes with no constructor function
//In case of constructor with two arguments and no constructor
Class C1 { //with single argument
. Class C1 {
int h;
.
int i;
}; public :
C1(int j, int k) { h = j; i=k; }
int main() };
{ int main() {
C1 ob[3] = { C1(1, 2), C1(3, 4), C1(5, 6) };
C1 ob[3]; // array of 3 objects
C1 ob[3] // invalid  can’t have uninitialized array here
. }
.
}
//Creating initialized & uninitialized array
//In case of class with constructor of single argument //  if we want to create uninitialized array along with
//initialized array then along with other constructor, we
Class C1 { //have to explicitly create a parameter less constructor
int i;
//also.
public :
C1(int j) { i = j; } Class C1 {
. int i;
. public :
}; C1() {i = 0;}// parameter less constructor
int main()
C1(int j) { i = j;}
{
C1 ob[3] = { 1, 2, 3 }; };
// the above statement is equivalent to C1 ob[3] = { C1(1), C1(2), C1(3) } int main() {
// and C1 ob[3];  will be an error here because we don’t have a zero C1 a1[3] = {3, 5, 6 }; // initialized array  valid statement
// argument constructor C1 a2[4]; // un initialized array  valid statement
.
}
.
}
Prepared by Dr. Naveen Choudhary 34
Pointers to objects
 When accessing members of a class, given a pointer to an object, use the
arrow () operator instead of the dot operator.
// we can assign the address of a public member of an
class C1 {
//object to a pointer and then access that member by using
int i;
//the pointer
public:
C1 (int j) { i=j; }
#include <iostream>
int get_i() { return i; }
using namespace std;
};
class cl {
int main() {
public:
C1 ob(88), *p;
int i;
p = &ob;
cl(int j) { i=j; }
cout << pget_i();
};
return 0;
int main() {
}
cl ob(1);
int *p;
OR
p = &ob.i; // get address of ob.i
cout << *p; // access ob.i via p
int main() {
return 0;
C1 ob[3] = {1,2,3};
}
C1 *p;
int i;
p = ob; // get start of array
//Type checking C++ pointer
for (i=0; i<3;i++) {
//you may assign one pointer to another only if the two pointer
cout << pget_i() << "\n";
// types are compatible
p++; //point to the next element of array
// in this case p++ then the pointer points to the next
int *pi;
//object in the array
float *pf;
}
pi = pf; //error - type mismatch
return 0;
// Note:- Of course, you can override any type in compatibilities using a cast
}
pi = (int *) pf; //Ok
Prepared by Dr. Naveen Choudhary 35
this pointer
 When a member function is called, it is automatically passed an implicit
argument that is pointer to the invoking object (that is, the object on which the
function is called)
Class C1{ Usefulness of this
int i;
public:  any member function can find
get_i() {
return this.->i; // if we say return i then also it out the address of the object
means
//the same
of which it is a member
};
} this is actually useful when
int main() { operators are overloaded and
C1 ob1;
cout<<ob1.get_i(); whenever a member function
}
must utilize a pointer to the
class alpha {
int data;
object that invoked it
public:
-------
Note:- friend function are not
------- member of a class and
alpha &operator = (alpha &a) {
data=a.data therefore are not passed a this
return *this;
} pointer
};
int main() {
Note: static member function
alpha a1(37);
alpha a2,a3;
do not have a this pointer
a3 = a2 = a1; // cascading of = was possible b/s
//this pointer was returned
} Prepared by Dr. Naveen Choudhary 36
Pointers to a derived type
 let B is base class & D be the derived class
 A pointer of type B* (ie say B*ptr) may also point to an object of the type D
 A pointer of type *D (ie say D *ptr1) may not be able to point to an object of type
B
 Although we can use a base pointer to point to a derived object, we can access
only the members of the derived type that were imported/inherited from the
base. that is, we won't be able to access any members added by the derived
class {although we can cast a base pointer into derived pointer & gain full
access to the entire derived class}
int main() {
class base { base *bp;
int i; derived d;
public: bp = &d; // base pointer points to derived object
void set_i(int num) { i=num; } // access derived object using base pointer
int get_i() { return i; } bp->set_i(10);
}; cout << bp->get_i() << " ";
class derived: public base { /* The following won't work. You can't access element of a
int j; derived class using a base class pointer. */
public:
void set_j(int num) { j=num; } bp->set_j(88); // error --- ((derived *)bp)->set_j(88);//ok
int get_j() { return j; } cout << bp->get_j(); //error--cout << ((derived *)bp) >get_j();//ok
}; return 0;
}

Prepared by Dr. Naveen Choudhary 37


Pointers to a derived type
 It is important to remember that pointer arithmetic is relative to the base type of
the pointer. for this reason, when a base pointer is pointing to a derived object,
incrementing the pointer does not cause it to point to the next object of the
derived type. instead it will point to what it thinks is the next object of the base
type.
// This program contains an error.
#include <iostream>
using namespace std;
class base {
int i; The use of base pointer to
public:
void set_i(int num) { i=num; } derived type is most useful when
int get_i() { return i; }
}; creating run-time polymorphism
class derived: public base {
int j;
(through the mechanism of virtual
public:
void set_j(int num) {j=num;}
functions)
int get_j() {return j;}
};
int main()
{
base *bp;
derived d[2];
bp = d;
d[0].set_i(1);
d[1].set_i(2);
cout << bp->get_i() << " ";
bp++; // relative to base, not derived
cout << bp->get_i(); // garbage value displayed
return 0; Prepared by Dr. Naveen Choudhary 38
}
References
 it is basically an implicit pointer or in other words it is an alias (different
name) for a variable
 Independent references
 An independent reference must be initialized when they are created (you
need something to point to)

#include <iostream>
using namespace std; int i=4; int n[10];
int main() { int &x = n[10]; // x is alias for n[10]
int a;
int &ref = a;
int &j; //error char &a = '\n'; // initialised reference
/* independent reference must be initialized at the time of declaration */ //to a literal
a = 10; Int &j=4;//ok
cout << a << " " << ref << "\n"; int x;
/* a & ref both refer to the same value a=10, ref=10 */
ref = 100; J=i; int *p = &x;
cout << a << " " << ref << "\n"; // a=100, ref=100 int &m = *p; // so new m refers to x
int b = 19;
ref = b; // this puts b's value into a //(which is pointed to by
cout << a << " " << ref << "\n"; // a=19, ref = 19 // pointer P)
ref--; // this decrements a it does not affect what ref refers to
cout << a << " " << ref << "\n"; // a=18,ref=18 int &n = 50;
return 0;
}
// creates a int object with value 50
//and name n

Prepared by Dr. Naveen Choudhary 39


Reference
// Manually create a call-by-reference using a pointer.
#include <iostream>
using namespace std; #include <iostream>
void neg(int *i); using namespace std;
int main() {
int x;
void swap(int &i, int &j);
x = 10; int main()
cout << x << " negated is "; {
neg(&x); int a, b, c, d;
cout << x << "\n"; a = 1;
return 0;
}
b = 2;
void neg(int *i) c = 3;
{ d = 4;
*i = -*i; cout << "a and b: " << a << " " << b << "\n";
} swap(a, b); // no & operator needed
// Call by reference using reference variable
cout << "a and b: " << a << " " << b << "\n";
// Use a reference parameter. cout << "c and d: " << c << " " << d << "\n";
#include <iostream> swap(c, d);
using namespace std; cout << "c and d: " << c << " " << d << "\n";
void neg(int &i); // i now a reference return 0;
int main()
{
}
int x; void swap(int &i, int &j)
x = 10; {
cout << x << " negated is "; int t;
neg(x); // no longer need the & operator t = i; // no * operator needed
cout << x << "\n";
return 0;
i = j;
} j = t;
void neg(int &i)// at the time of call  int &i = x }
{
i = -i; // i is now a reference, don't need *
}

Prepared by Dr. Naveen Choudhary 40


Reference
 Passing reference to object
 when we pass an object by reference, no bit-wise copy of the object is
made. this means that no object used as a parameter is destroyed when
the function terminates, and so the parameter’s destructor is not called.

#include <iostream>
using namespace std;
class cl {
int id; Output:- constructing 1
public:
int i; -10
cl(int i);
~cl(); destruction 1
void neg(cl &o) { o.i = -o.i; } note:- destructor is called only once
// no temporary object is created
}; ie when main() terminates
cl::cl(int num) {
cout << "Constructing " << num << "\n";
id = num;
 Passing object by reference is faster
} than passing object by value. as there
cl::~cl() { is no need of making any copy &
cout << "Destructing " << id << "\n";
} putting on to the stack
int main() {
cl o(1);
o.i = 10;
o.neg(o);
cout << o.i << "\n";
return 0;
} Prepared by Dr. Naveen Choudhary 41
Reference
Function returning reference can be used on the left side (as well as on right side) of an
assignment statement. In other words when a function returns a reference, the function
call can exist in any context where a reference can exist

//the program replaces hello there with helloxthere  Reference is an implicit constant
#include <iostream> pointer ie once a reference variable
using namespace std;
has been defined to refer to a
char &replace(int i); // return a reference
char s[80] = "Hello There"; particular variable, it can not refer to
int main() any other variable. that is, once the
{ variable and the reference are linked
replace(5) = 'X'; // assign X to space after Hello they are tied together inseparably.
cout << s;
return 0;
 We can create reference to a
}
char &replace(int i) pointer
{ char *p = “Hello”;
return s[i]; char * &q = p;
}
 A variable can have multiple
Note :: One thing to be careful about when returning
reference. changing the value of one
reference is that the object being referenced to
should not go out of scope after the function of them effects a change in all
terminates. That is do not try to return local variable others.
by reference

Prepared by Dr. Naveen Choudhary 42


Restriction on Reference
 You can't reference another reference (ie you can't
obtain the address of a reference)
 You can not create array of references
 You can not create a pointer to a reference
 You can not reference a bit- field
 You can not have a null reference
 A reference variable must be initialized when it is
declared unless it is a member of a class, a function
parameter or a return value.

Prepared by Dr. Naveen Choudhary 43


References --- Q & A
 Q 1. When should we make a call by reference?
 Hint:- A call by pointer or a call by reference is useful in two situations:
 When we intend to change the values of actual arguments through the called function.
 When we want to save memory by preventing the creation of large structure variable that are
being passed to the function
To achieve these purpose reference offer a cleaner and more elegant way as compared to pointers, as
with references, we are not required to use the *and  operators.

 Q 2. Is reference a pointer?
 Hint:- A reference is a const pointer . hence once initialized a reference cannot be made to refer
to another variable. Unlike a pointer a reference gets automatically de-referenced.

 Q3. Is reference to a reference like shown below allowed?


int i;
int &j = i;
int &k = j; // reference to a reference.
 Hint : no, because when we try to assign a reference to a reference the new reference starts
referring to the same variable the first reference is referring to

 Q 4. Can we create a pointer to a reference?


 Hint:- No. This can be explained with the help of following code:
int i;
int &p = i;
int *j = &p; // not a pointer to a reference
 Here it seems that j is a pointer to the reference p, but actually it is pointing to the variable i. this
is because a reference is automatically de-referenced, i.e., &p internally becomes &*p. Thus in j
what gets stored is address of i.

Prepared by Dr. Naveen Choudhary 44


References --- Q & A
 Q 5. How would the compiler interpret the
following statements?
int i = 9;
int &p = i;
int &q = p;
 Hint:- The compiler would interpret statement as shown
below.
int i = 9;
int *const p = &i; // address of 9
int *const q = &*p; // address of 9
 As a reference is nothing but a const pointer the address
of the variable gets stored in a reference. Hence in the
second statement address of i gets stored in const
pointer p. And as reference are automatically de-
referenced p becomes &*p in the third statement.

Prepared by Dr. Naveen Choudhary 45


References --- Q & A
 Q 7 What are the advantages of pointer over reference?
 Hint:- Reference being a const pointer cannot be reassigned. On the other hand pointers can be reassigned. This is
shown in the following example:
main () {
int i,j;
int *p = &i;
p = &j;
}

 Also, arithmetic operation cannot be performed on a reference.This is shown in the following example:
main () {
int i;
int &r = i;
r++; // will not increment r but will increment the value of i
int *p = &i;
p++;
}
 Here r++ would not increment the value of r. But it will increment value of i. This means that when an arithmetic
operation is performed on a reference, it gets performed on a referent. But when p++ is done, the value of p is
incremented.
 Q 8 . Why should we not return a reference or an address of a local variable.
 Hint:- When we return a reference of a local variable, the variable would die once control returns to the calling
function. Hence, calling function would be referencing to a variable that no longer exists.
 Q 9. Can we create a reference to an array?
 Hint:- Yes, a reference to an array is allowed. For example: Note: int (*pt)[7] :: pointer to an array of
int a[] = {3,7,6,9,5}; 7 integers
int(&p)[5] = a; // reference to an array int *pt[7] ; Array of 7 pointers

 Q 10 Why is it so that when we print the address of a reference the address of a referent gets printed?

int i; When we write &r it is actually treated as &*r which is


nothing but address of the values stored in r, that is address
int &r = i; of i.
cout << &r; Prepared by Dr. Naveen Choudhary 46
References --- Q & A
 State whether the following statements are True or False:
 It is possible to create an array of reference.
 ANS: False, A reference is not an object. Hence we cannot find address of a reference, nor can
we create an array of references. And for the same reason we can not have pointer to the
reference also.

 Once a reference is tied with a variable it cannot be tied with another variable
 ANS: True. A reference being a const pointer, once initialized its value cannot be changed.

 A variable can be tied with several references.


 ANS: True. This is because there is no limitation on storing the address of a variable in multiple
pointers. Since references are const pointer this works. For example:
int a = 10;
int &b = a;
int &c = a;
 In c++ a function call can occur even on the left-hand side of an assignment operator.
 ANS: True. If a function returns a reference its call can exist on the left-hand side of an
assignment operator. This is shown in the following code:
# include <iostream.h>
int i;
void main() {
int &fun(); int &fun() {
fun() = 10; i = 2;
return i;
} }
Here, the function fun() returns a reference to a integer variable i. the
returned reference replace the functions calls. Hence the statement becomes (reference
of i) = 10. hence i would be assigned a value 10, as can be verified by output of cout.

 It is unsafe to return a local variable by reference.


 ANS: True. As soon as the function returns, local variables die. If a reference (or address)of a
local variable is returned, it means
Prepared bywe
Dr.would beChoudhary
Naveen referring to the dead variable. 47
Dynamic memory allocation in C
1000 1009(p)
main()
{
double x=100, y;
int *p, *p1; 1003
p =&x; 1009(p1)
p1=p;
printf(“%d”, x);100
printf(“%d”, *p); 100
printf(“%d”, *p1); 100
printf(“%u”, p); 1009
printf(“%u”, p1); 1009

} 1009
100 (x)

Pointer arithmetic
We can add or subtract integer to or from pointers (p1 = p1 + 3)
We can subtract same type of pointer from another same type of pointer (to find the
no. of elements separating the two pointers in the array)
 Pointers can be compared (<, <=, >, >=, ==, !=)
Pointes can not be multiplied or divided (p1/3, p*3, p1/p2, p1*p2  all these are
illegal operations on the pointer )
Can not add two pointers (p1 + p2 illegal)
We can not add or subtract type float or double to or from pointers (p + 2.14, p -
2.14 illegal)
Prepared by Dr. Naveen Choudhary 48
Dynamic memory allocation in C
Arrays & Pointers
Name of the array is actually the address of the first
element of the array
int num[] = { 24, 34, 12, 44, 56, 77 }; Address Array elements
//num == &num[0] == 1000 (&num[0]) 1000 24 (num[0])
num[i] ==*(num + i) == *( i + num) == i[num]
(&num[1])  1004 34 (num[1])

(&num[2]) 1008 12 (num[2])

(&num[3]) 1012 44 (num[3])


2 –D Array (&num[4]) 1016 56 (num[4])
main() {
int num[3][2]; (&num[5]) 1020 77 (num[5])
int i,j;
for(i=0; i <= 2; i++) Address Array elements
{
for(j =0; j <= 1; j++)
{ (&num[0][0]) 1000 24 (num[0][0])
scanf(“%d”, &num[i][j]); (&num[0][1])  1004 34 (num[0][1])
}
} (&num[1][0]) 1008 12 (num[1][0])
} (&num[1][1]) 1012 44 (num[1][1])
(&num[2][0]) 1016 56 (num[2][0])
(&num[2][1]) 1020 77 (num[2][1])
Prepared by Dr. Naveen Choudhary 49
Dynamic memory allocation in C

num[2][1] == *(num[2] + 1) == * (*(num + 2) + 1)


Num *(Num + 0 ) 
 num + i == pointer to the ith row
*(Num +1)
*(num + i)  pointer to the 1st element in the ith row
*(Num +2) 
*(num + i) + j  pointer to the jth element in the ith row

*(*(num + i) + j)  value stored in num[i][j]

*(Num+0)
Num 

*(Num +1)

*(Num +2)  Num is the address of first element . now


first element here is a pointer to array of int

int num[3][3]  int(*num)[3] == int ptr[][3]

Prepared by Dr. Naveen Choudhary 50


Dynamic memory allocation in C
main() {
int num[3][2];
call_func(num);
}

call_func(int ptr [][3]) or call_func(int (*ptr)[3])


{
.
.
.
}

NULL  defined in stdio.h and stddef.h


basically means that NULL assigned pointer can not point to any
object by mistake
 NULL pointer is a predefined position in memory. If this memory
location contents are tried to be changed or some pointer try to access
this area then NULL pointer assignment error is generated.
Prepared by Dr. Naveen Choudhary 51
Dynamic memory allocation in C
Malloc
 To allocate memory dynamically

#include <stdlib.h> / #include <alloc.h>


void *malloc(unsigned int no_of_bytes)
Q. How to allocate a 1-D array of int
main() {
char *p; int *p,i;
p = (char *)malloc(1000); // allocate space for 1000 bytes p = (int *)malloc(10*sizeof(int));
// & returns the pointer the first element of the block
for(i=0;i<10;i++) {
int *p; p[i] = i; //*(p+i)
p = (int *)malloc(50 * sizeof(int)); // 50*2 if size of int = 2 bytes printf(“%d”, p[i]);
}
void free(void *p) // p is a pointer to a memory that was }
//previously allocated using malloc()
main() {
char *s; P
char *fun(); (say 1000 )
s = fun(); }
char *fun() {
char buffer[30];
strcpy(buffer, “hello”);
return(buffer); }
 The scope & life time of buffer ends as the fun() returns . so
problem
soln.
 static char buffer[30];
 or buffer is a global pointer
 or
char *ptr
ptr = (char *)malloc(30);
strcpy(ptr, “. . . . . . .. . . .”);
return(ptr); Prepared by Dr. Naveen Choudhary 52
Dynamic memory allocation in C
Q. how to do proper 2 – D dynamic array allocation so that
we can use arr[i][j]
main() {
int **p, i, j;
p = (int **) malloc(3*sizeof(int *)); // 3 = no. of rows
Q. how to dynamically allocate a 2-D array of int for(i = 0; i < 3; i++ )
p[i] = (int * )malloc(4 * sizeof(int));// 4 = no. of columns
main() {
for(i = 0; i < 3 ; i++ )
int *p, i, j; {
p = (int *) malloc(3*4*sizeof(int)) for(j=0; j < 4; j++)
for(i=0; i < 3; i++ ) { {
for(j =0; j < 4; j++) p[i][j] = i;// *(*(p+i) + j)
printf(“%d”, p[i][j]);
{
}
p[i*4 + j] = i; printf(“\n”);
printf(“%d”, p[i*4 + j]); }
} }
pintf(“\n”);
//to free memory free each p[i] first free(p[i])
}
// then free(p);
}

P

int *
P 0 0 /1002 0/1004 0/1006
(1000) /1000 int *
1/1008 1/1010 1/1012 1/1014 Int *

2/1016 2/1018 2/1020 2/1022

Prepared by Dr. Naveen Choudhary 53


C++'s Dynamic memory allocation operators

new & delete #include <iostream>


malloc () & free () of C for dynamic #include <new>
allocation of memory are also available in using namespace std;
C++ for compatibility with C but is not int main() {
recommended to be used in C++ int *p;
try {
programs. p = new int; // allocate space for an int
} catch (bad_alloc xa) {
new :- The new operator allocates memory & cout << "Allocation Failure\n";
returns a pointer to the start of it. return 1;
delete :- The delete operator frees memory }
previously allocated using new. *p = 100;
cout << "At " << p << " ";
cout << "is the value " << *p << "\n";
p_var = new type; delete p;
delete p_var; return 0;
}
new - If no memory is available for allocation
(from the heap) a bad-alloc exception is raised,
which your program should catch & handle
otherwise the program will be terminated
abnormally.

Older compilers (some still do) return Null on


failing to allocated memory.
Prepared by Dr. Naveen Choudhary 55
C++'s Dynamic memory allocation operators
Allocating array
Advantages of new & delete over malloc &
free p_var = new array_type[size];
 new automatically allocates enough delete[] p_var; // [] inform that array
memory to hold an object of the //is being released
specified type & so no need of sizeof int *p
operator p = new int[10]; // allocate 10 integer
// array
delete[] p; // release the array
 new automatically returns a pointer to
the specified type & we don't need to do Note: when arrays are allocated
explict type cast as in malloc () using news, we can not give them
any initial value
 Both new & delete can be overloaded,
allowing you to create customized
allocation system

Initializing allocated memory


p_var = new var_type (initializer)
int *p;
p = new int (87); // initialize to 87

Prepared by Dr. Naveen Choudhary 56


C++'s Dynamic memory allocation operators
class c1{
Allocating objects:
--------
--------
We can allocate objects dynamically by using new.
public:
when we do this, an object is created & a pointer is
c1(double n, char *s) {
returned to it. when object is created dynamically
using new, its constructor function (if it has one )
----------
is called. when the object is freed, its destructor
function is executed. }
~c1() {
class c1{
-----------
--------
}
--------
int main()
fun(int,int)
c1 *p;
}
p= new c1 (123.7,"good work");
int main() {
-----
c1 *p;
-----
---------
delete p;
---------
p= new c1; // parameter less constructor if any will }
//be called

p-> fun (23,78);


delete p; // destructor if any is called
}

Prepared by Dr. Naveen Choudhary 57


C++'s Dynamic memory allocation operators
void set(double n, char *s) {
Array of objects
cur_bal = n;
strcpy(name, s);
Allocation using new, we can allocate array of object
}
but no array allocated by new can have an initializer.
void get_bal(double &n, char *s) {
so we should make sure that if the class contains n = cur_bal;
strcpy(s, name);
constructor function, one will be parameter less (if
}
you don't c++ compiler will not find a matching
};
constructor when you attempt to allocate the array
int main() {
& will not compile your program)
balance *p;
char s[80];
double n;
#include <iostream>
int i;
#include <new>
try {
#include <cstring>
p = new balance [3]; // allocate entire array
using namespace std;
class balance { } catch (bad_alloc xa) {
cout << "Allocation Failure\n";
double cur_bal;
return 1;
char name[80];
}
public:
// note use of dot, not arrow operators
balance(double n, char *s) {
p[0].set(12387.87, "Ralph Wilson");
cur_bal = n;
p[1].set(144.00, "A. C. Conners");
strcpy(name, s);
} p[2].set(-11.23, "I. M. Overdrawn");
for(i=0; i<3; i++) {
balance() { } // parameterless constructor
p[i].get_bal(n, s);
~balance() {
cout << s << "'s balance is: " << n;
cout << "Destructing ";
cout << name << "\n"; cout << "\n";
}
}
delete [] p;
Prepared by Dr. Naveen Choudhary 58
return 0;
C++'s Dynamic memory allocation operators
// Demonstrate nothrow version of new.
#include <iostream>
#include <new>
using namespace std;
int main() {
int *p, i;
p = new(nothrow) int[32]; // use nothrow option
if(!p) {
cout << "Allocation failure.\n";
return 1;
}

Few end notes to remember


1D dynamic array in C++
int* ary = new int[Size]

2D dynamic array in C++


int** ary = new int*[rowCount];

for(int i = 0; i < rowCount; ++i)


ary[i] = new int[colCount];

Prepared by Dr. Naveen Choudhary 59


Function overloading
int myfunc (int i); Oveloading Constructor function
double myfunc (double i);

functions are overloaded beside they have Constructor functions can also be overloaded
different type of arguments.
Dynamically allocated Array (of objects) can not be
initialized so a parameter less constructor is a
int myfunc (int i) must in such cases
int myfunc (int i, int j) but if you need initialized version of objects also
then you should have (with parameters)
overloaded as they differ in number of constructor also
parameters
Note : example on next slide
int myfunc (int i)
float myfunc (int i)

 Error : differing returns types are insufficient


when overloading

void f (int *p);


void f (int p[]);

int *p & int p[] basically same so can not be


overloaded

Prepared by Dr. Naveen Choudhary 60


Constructor Overloading
cout << "\n\n";
#include <iostream>
// set powers of three
#include <new>
ofThree[0].setx(1);
using namespace std;
ofThree[1].setx(3);
ofThree[2].setx(9);
class powers {
ofThree[3].setx(27);
ofThree[4].setx(81);
int x;
// show powers of three
public:
cout << "Powers of three: ";
// overload constructor two ways
for(i=0; i<5; i++) {
powers() { x = 0; } // no initializer
cout << ofThree[i].getx() << " ";
// parameter less constructor
}
powers(int n) { x = n; } // initializer
cout << "\n\n";
//with parameter const.
// dynamically allocate an array
int getx() { return x; }
try {
void setx(int i) { x = i; }
p = new powers[5]; // no initialization
};
} catch (bad_alloc xa) {
cout << "Allocation Failure\n";
int main()
return 1;
{
}
powers ofTwo[] = {1, 2, 4, 8, 16};// initialized
// initialize dynamic array with powers of two
/* statically allocated arrays */
for(i=0; i<5; i++) {
p[i].setx(ofTwo[i].getx());
powers ofThree[5]; // uninitialized
}
powers *p;
// show powers of two
int i;
cout << "Powers of two: ";
// show powers of two
for(i=0; i<5; i++) {
cout << "Powers of two: ";
cout << p[i].getx() << " ";
for(i=0; i<5; i++) {
}
cout << ofTwo[i].getx() << " ";
cout << "\n\n";
}
delete [] p;
return 0;
}

Prepared by Dr. Naveen Choudhary 61


Copy constructor
Copy constructor applies only to initialization
 By default when one object is used to initialize
another, C++ performs a bitwise copy. initialization occour in three different ways
When one object explicity initializes another,
 There are situations in which a bitwise copy such as in a declaration
should not be used. One of the most common is
when an object allocates memory when it is  myclass x = y; // y explicitly initializes x
created
When a copy of an objectis made to be
 Solution of the above problem -> Copy passed to a function
constructor { when copy constructor exists,
the default copy is bypassed. func(y) // y passed as a parameter.

class name(const class name & o){ When a temparary object is genareted (most
// body of the constructor commonly as a return value)???
}
y = func(); // y receives a temporary (returned)
 It is important to understand that C++ defined //object(copy constructor is called
two distinct type of situation in which the value //here). However at the time of
of one object is given to another.  //assignment of the returned
Assignment & initialization //value(object) to y, the overloaded
//assignment operator if any will be
//called
Copy Constructor initialization Assignment
class c1{
myclass x = y; // y explicitly initializating x -------------
}
func(y); // y passed as a parameter int main (){
c1 ob1, ob2;
y = func(); // temporary object generated as return
Prepared by Dr. Naveen Choudhary--------------- 62
//value ob1=-ob2; //Assignment
Copy constructor
// Copy Constructor
/* This program creates a "safe" array class. Since space
array::array(const array &a) {
for the array is allocated using new, a copy constructor
int i;
is provided to allocate memory when one array object is
try {
used to initialize another. */
p = new int[a.size];
#include <iostream>
} catch (bad_alloc xa) {
#include <new>
cout << "Allocation Failure\n";
#include <cstdlib>
exit(EXIT_FAILURE);
using namespace std;
}
for(i=0; i<a.size; i++) p[i] = a.p[i];
class array {
}
int *p;
int main()
int size;
{
public:
array num(10);
array(int sz) {
int i;
try {
for(i=0; i<10; i++) num.put(i, i);
p = new int[sz];
for(i=9; i>=0; i--) cout << num.get(i);
} catch (bad_alloc xa) {
cout << "\n";
cout << "Allocation Failure\n";
// create another array and initialize with num
exit(EXIT_FAILURE);
array x(num); // invokes copy constructor
}
for(i=0; i<10; i++) cout << x.get(i);
size = sz;
return 0;
}
}
~array() { delete [] p; }
// copy constructor
array(const array &a);
void put(int i, int j) {
if(i>=0 && i<size) p[i] = j;
}
int get(int i) {
return p[i];
}
};

Prepared by Dr. Naveen Choudhary 63


Copy constructor in Brief
1. array a = num; // copy constructor will be called

2. func1 (array a){ }


main{
func1(Num); // Copy constructor will be called while passing the arguments
}

3. funct1{
array Num;
---------
----------
return Num;
}

main() {
array a;
-----
----
a= funct1();
}

array a (10)
array b(10);

b=a; // does not call copy constructor, rather it is an assignment so bitwise copy will take place & in several
condition to avoid bitwise copy we need to overload the = operator

Prepared by Dr. Naveen Choudhary 64


Finding the address of an overloaded
function
#include <iostream>
using namespace std;
int myfunc(int a);
int myfunc(int a, int b);
int main() {
int (*fp)(int a); // pointer to int f(int)
fp = myfunc; // points to myfunc(int)
cout << fp(5);
return 0;
}

int myfunc(int a) {
return a;
}

int myfunc(int a, int b) {


return a*b;
}

Prepared by Dr. Naveen Choudhary 65


Default function arguments
void iputs (int indent = -1, char *str);//error
void myfunc (double d = 0.0)
{
int myfunc(float f, char *str, int i=0, int j); //Error
}
Default parameters can also be used in
myfunc(198.234); // pass an explict value
constructors of an object
myfunc(); // lets function use default

Reason & use - If a function uses lot of


class cube {
arguments but don't require all the
int x,y,z;
arguments in all the calls then default
arguments are quite a facility to use in public:
cube (inti=0, int j=0, int k=0){
such cases.
----------
}
When you are creating functions that have
};
default arguments, it is important to
main() {
remember that the default values must be
cube a(3,3,4);
specified only once, and this must be the
first time the function is declared within cube b; // call constructor with default arguments
the file.

We can specify different default arguments


for each version of an overloaded function
All parameters that take default values must
appear to the right of those that don't

Prepared by Dr. Naveen Choudhary 66


Default arguments v/s Overloading
Ambiguity due to C++ automatic type
conversion #include <iostream>
C++ Automatically attempts to convert the using namespace std;
arguments used to call a function into the type of char myfunc(unsigned char ch);
arguments expected by the function call char myfunc(char ch);
int main() {
int myfunc (double d){ cout << myfunc('c'); // this calls myfunc(char)
cout << myfunc(88) << " "; // ambiguous
} return 0;
cout<<myfunc('C'); // not an error, conversion applied }
//(character will be converted to double char myfunc(unsigned char ch) {
return ch-1;
#include <iostream> }
using namespace std;
float myfunc(float i);
char myfunc(char ch) {
double myfunc(double i); return ch+1;
int main() { }
cout << myfunc(10.1) << " ";// unambiguous,calls to
//myfunc(double) as
//constant fraction no. by
//default are double
cout << myfunc(10); // ambiguous
return 0;
}
float myfunc(float i)
{
return i;
}
double myfunc(double i)
{
return -i;
}
Prepared by Dr. Naveen Choudhary 68
Ambiguity due to default arguments in an
overloaded function
Some types of overloaded functions are simply inherently
#include <iostream>
ambiauous
using namespace std;
int myfunc(int i);
int myfunc(int i, int j=1);
// This program contains an error.
int main()
{
#include <iostream>
cout << myfunc(4, 5) << " "; // unambiguous
using namespace std;
cout << myfunc(10); // ambiguous
void f(int x);
return 0;
void f(int &x); // error
}
int main() {
int myfunc(int i) {
int a=10;
return i;
f(a); // error, which f()?
}
int myfunc(int i, int j) { return 0;
}
return i*j;
void f(int x) {
}
cout << "In f(int)\n";
}
void f(int &x){
cout << "In f(int &)\n";
}

Prepared by Dr. Naveen Choudhary 69


Operator
Overloading
Prepared
by
Naveen Choudhary
Prepared by Dr. Naveen Choudhary
Operator Overloading
ret_type classname::operator # (arg_list) void show() {
cout << longitude << " ";
{ cout << latitude << "\n";
//operations }
} loc operator+(loc op2);
};
// Overload + for loc.
when you are overloading a unary loc loc::operator+(loc op2)
operator, arg_list will be empty. when you {
loc temp;
are overloading binary operators, arg_list temp.longitude = op2.longitude + longitude;
will contain one parameter. temp.latitude = op2.latitude + latitude;
return temp;
}
int main()
#include <iostream> {
using namespace std; loc ob1(10, 20), ob2( 5, 30);
class loc { ob1.show(); // displays 10 20
int longitude, latitude; ob2.show(); // displays 5 30
public: ob1 = ob1 + ob2;
loc() {}
ob1.show(); // displays 15 50
loc(int lg, int lt) { return 0;
longitude = lg;
}
latitude = lt;
}

Prepared by Dr. Naveen Choudhary


Operator overloading of +, - , =, ++ (prefix)
Note:- In C++, if the = is not overloaded, a default assignment operation is created
automatically for any class you define. The default assignment is simply a
member-by-member bitwise copy. By overloading the =, you can define explicitly
what the assignment does relative to a class. In this example, the overload = does
exactly the same thing as the default, but in other situations, it could perform
other operations.

// Overload + for loc. // Overload prefix ++ for loc.


#include <iostream>
loc loc::operator+(loc op2) loc loc::operator++()
using namespace std;
{ {
class loc {
loc temp; longitude++;
int longitude, latitude;
temp.longitude = op2.longitude + longitude; latitude++;
public:
temp.latitude = op2.latitude + latitude; return *this;
loc() {} // needed to construct
return temp; }
//temporaries
} int main()
loc(int lg, int lt) {
// Overload - for loc. {
longitude = lg;
loc loc::operator-(loc op2) loc ob1(10, 20), ob2( 5, 30), ob3(90, 90);
latitude = lt;
{ ob1.show();
}
loc temp; ob2.show();
void show() {
// notice order of operands ++ob1;
cout << longitude << " ";
temp.longitude = longitude - op2.longitude; ob1.show(); // displays 11 21
cout << latitude << "\n";
temp.latitude = latitude - op2.latitude; ob2 = ++ob1;
}
return temp; ob1.show(); // displays 12 22
loc operator+(loc op2);
} ob2.show(); // displays 12 22
loc operator-(loc op2);
// Overload asignment for loc. ob1 = ob2 = ob3; // multiple assignment
loc operator=(loc op2);
loc loc::operator=(loc op2) ob1.show(); // displays 90 90
loc operator++();
{ ob2.show(); // displays 90 90
};
longitude = op2.longitude; return 0;
latitude = op2.latitude; }
Prepared by Dr. Naveen Choudhary return *this; // i.e., return object that generated
//call
}
Creating prefix & postfix forms of ++ & --
operators
if ++ precedes its operand (++ob)  operator ++() // function is valid
if ++ follows its operand (ob++)  operator++(int x)// function is called,
//where x is a dummy argument and has the value 0.

prefix Overloading short hand operators like


type operator ++ ( ) +=, -=
{
----- loc loc::operator += (loc op)
} {
longitude = op.longitude + longitude;
Postfix latitude = op.latitude + latitude;
return *this;
type operator ++ (int x) }
{
-----
}

Prepared by Dr. Naveen Choudhary


Operator overloading restrictions & friend
function
Operator overloading restrictions
Operator overloading using
Using operator overloading, you can
friend function
not alter the precedence of an
operator
Since a friend function is not a
member of the class, it does not
You can't change the no. of
have a this pointer, therefore an
operands that an operator takes
overloaded friend operator function
is passed the operands explicitly.
Operation functions can't have
This means that a friend function
default arguments (except for
that overloads a binary operator has
overloaded function call operator)
two parameters and a friend
function that overloads a unary
The . , :: , .*, ? operator can't be
operator has one parameter. when
overloaded
overloading a binary operator using
a friend function, the left operand is
passed in the first parameter and
the right operand is passed in the
second parameter.

Prepared by Dr. Naveen Choudhary


Operator overloading using friend
function
// Overload - for loc.
#include <iostream> loc loc::operator-(loc op2)
using namespace std; {
class loc { loc temp;
int longitude, latitude; // notice order of operands
public: temp.longitude = longitude - op2.longitude;
loc() {} // needed to construct temporaries temp.latitude = latitude - op2.latitude;
loc(int lg, int lt) { return temp;
longitude = lg; }
latitude = lt; // Overload assignment for loc.
} loc loc::operator=(loc op2)
void show() { {
cout << longitude << " "; longitude = op2.longitude;
cout << latitude << "\n"; latitude = op2.latitude;
} return *this; // i.e., return object that generated call
friend loc operator+(loc op1, loc op2); // friend }
loc operator-(loc op2); // Overload ++ for loc.
loc operator=(loc op2); loc loc::operator++()
loc operator++(); {
}; longitude++;
// Now, + is overloaded using friend function. latitude++;
loc operator+(loc op1, loc op2) return *this;
{ }
loc temp; int main() {
temp.longitude = op1.longitude + op2.longitude; loc ob1(10, 20), ob2( 5, 30);
temp.latitude = op1.latitude + op2.latitude; ob1 = ob1 + ob2;
return temp; ob1.show();
} Prepared by Dr. Naveenreturn 0;
Choudhary
}
Restriction on friend operator function

=, (), [] and  can not be overloaded using friend functions.


 if ++ or -- are overloaded using friend function then we will need to use reference
parameters {pass by reference is necessary because the change (due to ++) should
be reflected in the actual object}

int main() {
#include <iostream> // Overload assignment for loc.
loc ob1(10, 20), ob2;
using namespace std; loc loc::operator=(loc op2) {
ob1.show();
class loc { longitude = op2.longitude;
int longitude, latitude; latitude = op2.latitude; ++ob1;
ob1.show(); // displays 11
public: return *this; // i.e., return object
// 21
loc() {} //that generated call
ob2 = ++ob1;
loc(int lg, int lt) { }
longitude = lg; // Now a friend; use a reference ob2.show(); // displays 12
// 22
latitude = lt; //parameter.
--ob2;
} loc operator++(loc &op) {
ob2.show(); // displays 11
void show() { op.longitude++;
// 21
cout << longitude << " "; op.latitude++;
return 0;
cout << latitude << "\n"; return op;
}
} }
loc operator=(loc op2); // Make op-- a friend; use reference. //for post increment in friend
friend loc operator++(loc &op); loc operator--(loc &op) { //function a extra dummy
friend loc operator--(loc &op); op.longitude--; //argument will be reqired
// friend, postfix version of ++ op.latitude--;
//friend loc operator++(loc &op, int x); return op;
}; }
Prepared by Dr. Naveen Choudhary
Where friend is a must ?
object + integer } ob + 100;
integer + object } 100 + ob;
// overloaded operator member function can not work, so in such cases friend operator
// overloaded function is necessary.
// + is overloaded for int + loc.
#include <iostream>
loc operator+(int op1, loc op2) {
using namespace std;
loc temp;
class loc {
temp.longitude = op1 + op2.longitude;
int longitude, latitude;
temp.latitude = op1 + op2.latitude;
public:
return temp;
loc() {}
}
loc(int lg, int lt) {
int main() {
longitude = lg; latitude = lt;
} loc ob1(10, 20), ob2( 5, 30), ob3(7, 14);
ob1.show();
void show() {
ob2.show();
cout << longitude << " ";
ob3.show();
cout << latitude << "\n";
ob1 = ob2 + 10; // both of these
}
ob3 = 10 + ob2; // are valid
friend loc operator+(loc op1, int op2);
ob1.show();
friend loc operator+(int op1, loc op2);
ob3.show();
};
return 0;
// + is overloaded for loc + int.
}
loc operator+(loc op1, int op2) {
loc temp;
temp.longitude = op1.longitude + op2;
temp.latitude = op1.latitude + op2;
return temp; Prepared by Dr. Naveen Choudhary
}
Overloading new & delete
allocate an object
void * operator new (size_t, size)
size no. of bytes to be allocate {\\ size_t (in #include<new> )is a defined type capable of
containing the largest single piece of memory that can be allocated }

1. Perform allocation. Throw bad_alloc on failure

2. Constructor called automatically { no explict code required }

3. return pointer_to_memory {pointer to allocated memory}

Delete an object
void operator delete (void *p) //pointer to the memory to be freed
{
/*1. Free memory pointed to by p
2. Destruction called automatically */
}

Note:- The new and delete operators may be overloaded globally so that all users of these
operators call your custom versions. they may also be overloaded relative to one or more
class. The example below overloads new & delete relative to a class
Prepared by Dr. Naveen Choudhary
Overloading new & delete
#include <iostream>
#include <cstdlib> // delete overloaded relative to loc.
#include <new> void loc::operator delete(void *p) {
using namespace std; cout << "In overloaded delete.\n";
class loc { free(p);
int longitude, latitude; }
public: int main()
loc() {} {
loc(int lg, int lt) { loc *p1, *p2;
longitude = lg; try {
latitude = lt; p1 = new loc (10, 20);// float *f = new float;
} // uses default new
void show() { } catch (bad_alloc xa) {
cout << longitude << " "; cout << "Allocation error for p1.\n";
cout << latitude << "\n"; return 1;
} }
void * operator new(size_t size); try {
void operator delete(void *p); p2 = new loc (-10, -20);
}; } catch (bad_alloc xa) {
// new overloaded relative to loc. cout << "Allocation error for p2.\n";
void * loc::operator new(size_t size) return 1;;
{ }
void * p; p1->show();
cout << "In overloaded new.\n"; p2->show();
p = malloc(size); delete p1;
if(!p) { delete p2;
bad_alloc ba; return 0;
throw ba; }
}
return p; Prepared by Dr. Naveen Choudhary
}
Overloading new & delete
Note:- When new or delete are encountered, the compiler first checks to see whether they are
defined relative to the class they are operating on. if so, those specific versions are used. if not,
C++ uses the globally defined new & delete. if these have been overloaded, the overloaded
version are used.
// Global new
try {
#include <iostream> void *operator new(size_t size) p2 = new loc (-10, -20);
#include <cstdlib> { } catch (bad_alloc xa) {
#include <new> void *p; cout << "Allocation error for
using namespace std; p = malloc(size); p2.\n";
class loc { if(!p) { return 1;
int longitude, latitude; bad_alloc ba; }
public: throw ba; try {
loc() {} } f = new float; // uses overloaded
loc(int lg, int lt) { return p; //new, too
longitude = lg; } } catch (bad_alloc xa) {
latitude = lt; // Global delete
cout << "Allocation error for f.\n";
} void operator delete(void *p) { return 1;;
void show() { free(p); }
cout << longitude << " "; } *f = 10.10F;
cout << latitude << "\n"; int main() cout << *f << "\n";
} { p1->show();
}; loc *p1, *p2; p2->show();
float *f; delete p1;
try { delete p2;
p1 = new loc (10, 20); delete f;
} catch (bad_alloc xa) { return 0;
cout << "Allocation error for
}
p1.\n";
return 1;
} Prepared by Dr. Naveen Choudhary
overloading new & delete for arrays
if you want to be able to allocate arrays of objects using your own
allocation system, you will need to overload new & delete a second time.
//allocate an array of objects
void * operator new[] (size_t, size)
{
/* 1. perform allocation throw bad-allocation on failure
2. constructor for each element called automatically
3. return pointer-to-memory; */
}
// delete an array of objects
void operator delete[] (void*p)
{
/* 1. Free memory pointed to by p
2. Destruction for each element called automatically */
}
Note:- When allocating an array, the constructor function for each object in the
array is automatically called. when freeing an array, each objects destructor is
automatically called. you do not have to provide explicit code to accomplish these
actions. Prepared by Dr. Naveen Choudhary
overloading new & delete for arrays
// delete overloaded relative to loc.
#include <iostream> int main()
#include <cstdlib> void loc::operator delete(void *p) {
{
#include <new> loc *p1, *p2;
cout << "In overloaded delete.\n";
using namespace std; int i;
free(p);
class loc { try {
}
int longitude, latitude; p1 = new loc (10, 20);
// new overloaded for loc arrays.
public: // allocate an object
void *loc::operator new[](size_t size)
loc() {longitude = latitude = 0;} } catch (bad_alloc xa) {
{
loc(int lg, int lt) { cout << "Allocation
void *p;
longitude = lg; error for p1.\n";
cout << "Using overload new[].\n";
latitude = lt; } return 1;;
p = malloc(size);
void show() { }
cout << longitude << " "; if(!p) { try {
bad_alloc ba;
cout << latitude << "\n"; } p2 = new loc [10];
throw ba;
void *operator new(size_t size); // allocate an array
}
void operator delete(void *p); } catch (bad_alloc xa) {
return p;
void *operator new[](size_t size); cout << "Allocation
}
void operator delete[](void *p); error for p2.\n";
// delete overloaded for loc arrays.
}; return 1;;
// new overloaded relative to loc. void loc::operator delete[](void *p) }
{
void *loc::operator new(size_t size) p1->show();
cout << "Freeing array using overloaded
{
delete[]\n";
void *p; for(i=0; i<10; i++)
cout << "In overloaded new.\n"; free(p); p2[i].show();
}
p = malloc(size); delete p1; // free an
if(!p) { //object
bad_alloc ba; delete [] p2; // free an
throw ba; //array
} return 0;
Prepared by Dr. Naveen Choudhary
return p; }
Type conversion
int m;
float x = 3.14159;
m = x; // automatic type conversion take place
cout<<m; // 3 will be displayed

Three situations where data conversion is needed to be taken care by the


programmer

How the conversion from built-in type to class type will take place {
constructor with single argument}
How the conversion from class type to built-in type take place {
overloading casting function/ converts an operator}
how the conversion from one class type to another class type.
Will take place -> {constructor in destination class / conversion operation
in source class}

Prepared by Dr. Naveen Choudhary


Basic to class type
Class string {
char *p;
int len;
string (char *a);
}
string :: string (char *a) {
length = strlen (a); main()
p = new char [length + 1]; {
strcpy(p,a); int duration = 85;//duration in minutes
} time T1 = duration; // int to class type
char *name1 = “xyz”; time T2;
char *name2 = “abc”; T2 = duration // valid , first it will look for
string s1 = name1; // an string s1 = string (name1); // appropriately overloaded
// constructor will be called // assignment operator and if it
class time // is not found it will call any
{ // function (constructor or
int hrs; // conversion function) to
int mins; // achieve the conversion
public: }
time (int t)
{
hrs = t/60; // t in minutes
mins = t%60;
}
};

Prepared by Dr. Naveen Choudhary


Class to basic type
Conversion function
Operator typename () {
.
. }
const size = 3;
class vector {
int v[size];
operator double();
}
//scalar magnitude of a vector is calculated as the square root of the sum of the squares of its components
vector :: operator double() {
double sum = 0;
for (int i =0;i<size; i++)
sum = sum + v[i]* v[i];
return sqrt(sum);
}

double length = v1; // calls operator double ()


double length ;
length = v1; // calls operator double()
length = (double) v1; // calls operator double()
length = v1; // valid , first it will look for appropriately overloaded assignment operator and if it is not found it
// will call any function (constructor or conversion function) to achive the conversion although
// some books appreciate the syntax as given below  static_cast<double>(v1);

The casting operator ( or conversion) function should satisfy the following conditions.
 it must be a class member
 it must not specify a return type ( as by default it is the basic type to which the class is being
converted) Prepared by Dr. Naveen
 it must not have any arguments ( the invoking object is used as an argument) Choudhary
one class to another class
obj x = obj y

destination class = source class

two ways for achieving such conversion


have a single argument constructor in destination class taking
object of source class as argument
have a conversion operator/ function to destination class in
the source class definition.
 example on next slide

Prepared by Dr. Naveen Choudhary


one class to another class
class invent2 //destination class {
#include<iostream.h>
public:
class invent1 { //source class
int code;
int code;
float value;
int items; //no. of files
float price; //case of each file invent2 (){
}
public:
invent2(int x, float y) {
invent1(int a, int b, float )
}
{
------ void putdata(){
---
}
}
void putdata()
{
invent2(invent1 p) // conversion constructor requires
cout<<”Code”<<code;
//public function in invent1 which
}
//can access private members of
int getcode() { return code;}
int getitem() {return item;} //invent1
{ code = p.getcode();
int getprice() {return getprice;}
value = p.getitems () * p.getprice ();
}
operator float(){
};
return(item*price); }
main() {
/* operator invent2() //invent2 = invent1 {
invent1 s1(100,9,140);
invent2 temp;
invent2 d1;
temp.code = code;
float total-value;
temp.value = price*item;
total-value = s1; // operator float()
return temp;
d1 = s1; //invent2 (invent1) –constructor of invent2
} */
----
}
Prepared by Dr. Naveen Choudhary
Overloading some special operator
Keyword  mutable  a mutable data member of
Keyword  explicit  single argument constructor
a class can be modified even if the object of this
with explicit keyword can not be used for implicit
class is declared as constant
conversion
class ABC {
class ABC
int a;
{
mutalble float b;
----
explicit ABC (float i) public:
ABC (int , float j);
{
void seta(int a1) {
}
a=a1;
}
int main() }
void setb(float b1) {
{
b=b1;
ABC x = 37.4F; //error
}
ABC y;
}
y = 37.4F; // error
int main()
ABC x(37.4F); // OK
{
}
const ABC x(2,3.14F);
x.seta(5); //error
x.setb(7.14F);// allowed as b is mutable
}

Prepared by Dr. Naveen Choudhary


Inheritance

Prepared
by
Naveen Choudhary
Prepared by Dr. Naveen Choudhary 1
Inheritance
 Whatever is the access : private members of the base
Base class  Derived class class can not be accessed in the derived class

class base  If access == public :: Public members of the base


class becomes public members of the derived class,
{ Protected members of the base class becomes
}; protected members of the derived class
class derived-class: access base-class  if access == private :: All public & protected members
{ of the base class becomes private members in the
/* derived class.
class C1{
access == default for class – private private:
-----
== default for structure - public protected:
-----
*/ }; /* protected members can be accessed only
}; by the class members (like private) but they have a
greater role in case of inheritance & are treated
differently than private, when are used in inheritance.*/

 if access = protected :: public & protected members of


the base class becomes protected members of the
derived class

Prepared by Dr. Naveen Choudhary 2


Examples
// This program won't compile.
#include <iostream> #include <iostream>
using namespace std; using namespace std;
class base { class base {
int i, j; int i, j;
public: public:
void set(int a, int b) { i=a; j=b; } void set(int a, int b) { i=a; j=b; }
void show() { cout << i << " " << j << "\n"; } void show() { cout << i << " " << j << "\n";}
}; };
class derived : public base {
int k; class derived : private base {
public:
derived(int x) { k=x; } // as access specifier is private the public members of
void showk() { cout << k << "\n"; } //the base class will become private members of the
}; //derived class and so can not be accessed from
int main() //outside the class
{
derived ob(3); int k;
ob.set(1, 2); // access member of base public:
ob.show(); // access member of base derived(int x) { k=x; }
ob.showk(); // uses member of derived class void showk() { cout << k << "\n"; }
return 0; };
}
int main()
{
derived ob(3);
ob.set(1, 2); // error, can't access set()
ob.show(); // error, can't access show()
return 0;
Prepared by Dr. Naveen
} Choudhary 3
Examples
#include <iostream> Inheriting Multiple Base Class
using namespace std;
class base { // An example of multiple base classes.
protected: #include <iostream>
int i, j; // private to base, but accessible by derived using namespace std;
public: class base1 {
void setij(int a, int b) { i=a; j=b; } protected:
void showij() { cout << i << " " << j << "\n"; } int x;
}; public:
// Inherit base as protected. void showx() { cout << x << "\n"; }
class derived : protected base{ };
int k; class base2 {
public: protected:
// derived may access base's i and j and setij(). int y;
void setk() { setij(10, 12); k = i*j; } public:
// may access showij() here void showy() {cout << y << "\n";}
void showall() { cout << k << " "; showij(); } };
}; // Inherit multiple base classes.
int main() class derived: public base1, public base2 {
{ public:
derived ob; void set(int i, int j) { x=i; y=j; } // can access x and y
// ob.setij(2, 3); // illegal, setij() is protected member of derived //as they have become protected members of derived
};
ob.setk(); // OK, public member of derived int main()
ob.showall(); // OK, public member of derived {
// ob.showij(); // illegal, showij() is protected member of derived derived ob;
return 0; ob.set(10, 20); // provided by derived
} ob.showx(); // from base1
ob.showy(); // from base2
Prepared by Dr. Naveen Choudhary 4
return 0;
Constructor, Destructor and Inheritance
#include <iostream>
 constructor function are executed in the order of using namespace std;
derivation class base1 {
 destructor functions are executed in reverse order of public:
derivation base1() { cout << "Constructing base1\n"; }
~base1() { cout << "Destructing base1\n"; }
#include <iostream> };
using namespace std; class base2 {
class base { public:
public: base2() { cout << "Constructing base2\n"; }
base() { cout << "Constructing base\n"; } ~base2() { cout << "Destructing base2\n"; }
~base() { cout << "Destructing base\n"; } };
}; class derived: public base1, public base2 {
// note the order of declaration
class derived: public base { public:
public: derived() { cout << "Constructing derived\n"; }
derived() { cout << "Constructing derived\n"; } ~derived() { cout << "Destructing derived\n"; }
~derived() { cout << "Destructing derived\n"; } };
}; int main()
{
int main() derived ob;
{ // construct and destruct ob
derived ob; return 0;
// do nothing but construct and destruct ob }
return 0; Output:
} constructing base1
Output: constructing base constructing base2
constructing derived constructing derived
destructing derived destructing derived
destructing base
Prepared by Dr. Naveen Choudhary destructing base2 5
destructing base1
Passing parameters to Base-class constructors
derived-constrctor (arg_list): base1 (arg_list), base2(arg_list), ... baseN(arg_list)
{
//body of derived constructor
}

int main()
#include <iostream>
{
using namespace std;
derived ob(3, 4, 5);
class base1 {
ob.show(); // displays 4 3 5
protected:
return 0;
int i;
}
public:
base1(int x) { i=x; cout << "Constructing base1\n"; }
 Passing an argument along to a base class does not
~base1() { cout << "Destructing base1\n"; }
preclude its use by the derived class as well
};
class derived : public base
class base2 {
{ int i;
protected:
public:
int k;
// derived use both x & y and then passes them to base
public:
derived (int x, int y) :base (x,y)
base2(int x) { k=x; cout << "Constructing base2\n"; }
{
~base2() { cout << "Destructing base1\n"; }
j = x * y; cout<<"Constructing derived ";
};
}
class derived: public base1, public base2 {
Note:- One final point to keep in mind when passing
int j;
arguments to base-class constructors, the argument
public:
can consist of any expression valid at the time. this
derived(int x, int y, int z): base1(y), base2(z)
includes function calls and variable. this is in keeping
{ j=x; cout << "Constructing derived\n"; }
with the fact that C++ allows dynamic initialization.
~derived() { cout << "Destructing derived\n"; }
void show() { cout << i << " " << j << " "Prepared
<< k << "\n";
by Dr.} Naveen Choudhary 6
};
Virtual Base classes
/* derived3 inherits both derived1 and derived2.
A element of ambiguity can be introdcued into c++
This means that there are two copies of base
program when multiple base class are inherited
in derived3! */

class derived3 : public derived1, public derived2 {


// This program contains an error and will not
public:
//compile.
int sum;
};
#include <iostream>
using namespace std;
int main()
class base {
{
public:
derived3 ob;
int i;
ob.i = 10; // this is ambiguous, which i???
};
ob.j = 20;
ob.k = 30;
// derived1 inherits base.
class derived1 : public base {
// i ambiguous here, too
public:
ob.sum = ob.i + ob.j + ob.k;
int j;
};
// also ambiguous, which i?
cout << ob.i << " ";
// derived2 inherits base.
cout << ob.j << " " << ob.k << " ";
class derived2 : public base {
cout << ob.sum;
public:
return 0;
int k;
}
};

Prepared by Dr. Naveen Choudhary 7


Virtual Base classes
/* derived3 inherits both derived1 and derived2.
There can be 2 Solutions to the problem mentioned on the
This means that there are two copies of base
previous slide
in derived3! */
1. Use scope resolution operator
class derived3 : public derived1, public derived2 {
2. Use virtual base class
public:
int sum;
Use of scope resolution operator
};
// This program uses explicit scope resolution to select i.
int main()
#include <iostream>
{
using namespace std;
derived3 ob;
ob.derived1::i = 10; // scope resolved, use
class base {
//derived1's i
public:
ob.j = 20;
int i;
ob.k = 30;
};
// scope resolved
// derived1 inherits base.
ob.sum = ob.derived1::i + ob.j + ob.k;
class derived1 : public base {
public:
// also resolved here
int j;
cout << ob.derived1::i << " ";
};
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
// derived2 inherits base.
return 0;
class derived2 : public base {
}
public:
int k;
};
Prepared by Dr. Naveen Choudhary 8
Virtual Base classes
Virtual base class - Only one copy (instead of 2
int main()
copies) will be included in derived3, if virtual base
{
class is used
derived3 ob;
ob.i = 10; // now unambiguous
// This program uses virtual base classes.
ob.j = 20;
#include <iostream>
ob.k = 30;
using namespace std;
// unambiguous
class base {
ob.sum = ob.i + ob.j + ob.k;
public:
// unambiguous
int i;
cout << ob.i << " ";
};
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
// derived1 inherits base as virtual.
return 0;
class derived1 : virtual public base {
}
public:
int j;
};

// derived2 inherits base as virtual.


class derived2 : virtual public base {
public:
int k;
};

/* derived3 inherits both derived1 and derived2.


This time, there is only one copy of base class. */
class derived3 : public derived1, public derived2 {
public:
int sum;
}; Prepared by Dr. Naveen Choudhary 9
Link List Example
class link int main() {
{ public: linklist l;
int data; l.add(25);
link *next; l.add(36);
/*a class can't contain an object of the same class l.add(49);
but can contain pointer to object of the base class */ l.add(64);
} l.display();
class linklist { return 0;
private: }
link *first ; //pointer to the first link
64 49 36 25 NULL
public:
linklist(){
first = NULL;
}
void additem (int d);
void display(); some questions to be tried in lab ::
}; How to search & delete an item ?
void linklist::additem (int d) { How to insert an item after a given item?
link *newlink = new link; How to insert an item before a given item?
newlink->data = a; How to search a given item?
newlink->next=first;
first=newlink;
}
void linklist::display() {
link *current = first;
while (current != NULL)
{
cout<<cuurent->data<<"\n";
current=current->next;
} Prepared by Dr. Naveen Choudhary 10
}
Virtual Function & Polymorphism

Polymorphism

Compile time Runtime


(function & polymorphism
operator ( achieved
overloading) using
inheritance &
virtual
functions)

Prepared by Dr. Naveen Choudhary 11


Pointers to a derived type
(Remember?)
 let B is base class & D be the derived class
 A pointer of type B* (ie say B*ptr) may also point to an object of the type D
 A pointer of type *D (ie say D *ptr1) may not be able to point to an object of type
B
 Although we can use a base pointer to point to a derived object, we can access
only the members of the derived type that were imported/inherited from the
base. that is, we won't be able to access any members added by the derived
class {although we can cast a base pointer into derived pointer & gain full
access to the entire derived class}
int main() {
base *bp;
derived d;
class base {
bp = &d; // base pointer points to derived object
int i;
// access derived object using base pointer
public:
bp->set_i(10);
void set_i(int num) { i=num; }
cout << bp->get_i() << " ";
int get_i() { return i; }
/* The following won't work. You can't access element of a
};
derived class using a base class pointer. */
class derived: public base {
int j;
bp->set_j(88); // error --- ((derived *)bp)->set_j(88);//ok
public:
cout << bp->get_j(); //error--cout << ((derived *)bp) >get_j();//ok
void set_j(int num) { j=num; }
return 0;
int get_j() { return j; }
}
};

Prepared by Dr. Naveen Choudhary 12


Virtual Function & Polymorphism

Virtual function -> Basic concept -> One interface, multiple methods

1. A virtual function is a member function that is declared within a base class and redefined by
a derived class. To create a virtual function, precede the function's declaration in the base
class with the keyword virtual. when a class containing a virtual function is inherited, the
derived class redefines the virtual function to fit its own needs.

2. When a base pointer points to a derived object that contain a virtual function, c++
determines which version of that function to call based upon the type of object pointed to
by the pointer. And this determination is made at runtime. thus when different objects are
pointed to by the pointer; the different versions of the virtual functions are executed.

1. base class - virtual func_name(int)


derived class - func_name(int)// method overloading

2. base_class b1;
base_class *bp1;
derived_class d1;
bp1 = &d1;
bp1->func_name(int) ; // 1. derived version of virtual function is called
// 2. decision is made at run-time

Prepared by Dr. Naveen Choudhary 13


Examples
#include <iostream> int main()
using namespace std; {
base *p, b;
class base { derived1 d1;
public: derived2 d2;
virtual void vfunc() { // point to base
cout << "This is base's vfunc().\n"; p = &b;
} p->vfunc(); // access base's vfunc()
}; // point to derived1
p = &d1;
class derived1 : public base { p->vfunc(); // access derived1's vfunc()
public: // point to derived2
void vfunc() { p = &d2;
cout << "This is derived1's vfunc().\n"; p->vfunc(); // access derived2's vfunc()
} return 0;
}; }

class derived2 : public base {


public:
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
};

Prepared by Dr. Naveen Choudhary 14


Virtual Function Characterstics
1. Virtual function can also be called in a normal manner (ie using
dot operator) but then we are not using the benefits of run-time class base
polymorphism {
d2.vfunc(); // call derived 2's vfunc() public:
1 ~base();
2. If you change the prototype when you attempt to redefine a 2 //virtual ~base()
virtual function, the function will simply be considered overloaded {
by the c++ compiler and its virtual nature will be lost. cout << “base destroyed”
}
3. virtual functions must be non static members of the classes of };
which they are part
class derv : public base
4. virtual function can't be a friend function {
5. A constructor function can't be virtual but destructor function public:
can be a virtual function ~derv()
{
note : constructor can not be virtual because virtual function cout<<"Derv destroyed";
works depending on the type of object addressed but during }
construction we don’t know what type of object is being };
constructed
int main()
{
base * pbase = new derv;
O/P base destroyed delete pbase;
but if we comment (1) and uncomment (2) return 0;
O/P  derv destroyed base destroyed
}
Note : even if the destructor of base is defined as pure virtual then also
we should provide the body for the base destructor as the base
destructor will always be called whenever the object is destroyed
Prepared by Dr. Naveen Choudhary 15
Virtual function & Reference
when a virtual function is called through a base class reference, the version of the function
executed is determined by the object being referred to at the time of the call

/* Here, a base class reference is used to access // Use a base class reference parameter.
a virtual function. */ void f(base &r) {
#include <iostream> r.vfunc();
using namespace std; }
class base { int main()
public: {
virtual void vfunc() { base b;
cout << "This is base's vfunc().\n"; derived1 d1;
} derived2 d2;
}; f(b); // pass a base object to f()
class derived1 : public base { f(d1); // pass a derived1 object to f()
public: f(d2); // pass a derived2 object to f()
void vfunc() { return 0;
cout << "This is derived1's vfunc().\n"; }
}
};
class derived2 : public base {
public:
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
};
Prepared by Dr. Naveen Choudhary 16
Virtual Attribute Inheritance
The virtual attribute is inherited : no matter how many times a virtual
function is inherited, it remains virtual.

#include <iostream> int main()


using namespace std; {
class base { base *p, b;
public: derived1 d1;
virtual void vfunc() { derived2 d2;
cout << "This is base's vfunc().\n"; // point to base
} p = &b;
}; p->vfunc(); // access base's vfunc()
class derived1 : public base { // point to derived1
public: p = &d1;
void vfunc() { p->vfunc(); // access derived1's vfunc()
cout << "This is derived1's vfunc().\n"; // point to derived2
} p = &d2;
}; p->vfunc(); // access derived2's vfunc()
/* derived2 inherits virtual function vfunc() return 0;
from derived1. */ }
class derived2 : public derived1 {
public:
// vfunc() is still virtual
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
}; Prepared by Dr. Naveen Choudhary 17
Virtual function are hierarchical
if the derived class fails to override a virtual function of the base class then it not an error & if
object of the derived class access the virtual function, the function defined by the base will be
used.
In general when a derived class fails to override a virtual function the first redefinition found in
reverse order of derivation is used.

int main()
#include <iostream>
{
using namespace std;
base *p, b;
class base {
derived1 d1;
public:
derived2 d2;
virtual void vfunc() {
// point to base
cout << "This is base's vfunc().\n";
p = &b;
}
p->vfunc(); // access base's vfunc()
};
// point to derived1
class derived1 : public base {
p = &d1;
public:
p->vfunc(); // access derived1's vfunc()
void vfunc() {
// point to derived2
cout << "This is derived1's vfunc().\n";
p = &d2;
}
p->vfunc(); // use derived1's vfunc()
};
return 0;
class derived2 : public derived1 {
}
public:
/* vfunc() not overridden by derived2.
In this case, since derived2 is derived from
derived1, derived1's vfunc() is used.
*/
}; Prepared by Dr. Naveen Choudhary 18
Pure Virtual Function
A pure virtual function is a virtual function that has no definition within the base class. To declare
pure virtual function, use this general form.

virtual type func_name (arg_list) = 0;

when a virtual function is made pure, any derived class must provide its own definition. if the
derived class fails to override the pure virtual function, a compile time error will result.
#include <iostream> class octtype : public number {
using namespace std; public:
class number { void show() {
protected: cout << oct << val << "\n";
int val; }
public: };
void setval(int i) { val = i; } int main()
virtual void show() = 0; // show() is a pure virtual function {
}; dectype d;
class hextype : public number { hextype h;
public: octtype o;
void show() { d.setval(20);
cout << hex << val << "\n"; d.show(); // displays 20 - decimal
} h.setval(20);
}; h.show(); // displays 14 - hexadecimal
class dectype : public number { o.setval(20);
public: o.show(); // displays 24 - octal
void show() { return 0;
cout << val << "\n"; }
}
}; Prepared by Dr. Naveen Choudhary 19
Abstract classes
A class that contains at-least one pure virtual function is said to be abstract. No object of
abstract class can be created

But you can create pointers and reference to an abstract class

Using abstract class :: one interface - different action depending on slightly different (some
what similar) requirements

int main()
// Liters to gallons.
{
// Virtual function practical example. class l_to_g : public convert {
convert *p; // pointer to base class
#include <iostream> public:
l_to_g lgob(4);
using namespace std; l_to_g(double i) : convert(i) {}
f_to_c fcob(70);
class convert { void compute() {
// use virtual function mechanism to convert
protected: val2 = val1 / 3.7854;
p = &lgob;
double val1; // initial value }
cout << pgetinit() << " liters is ";
double val2; // converted value };
pcompute();
public: // Fahrenheit to Celsius
cout << pgetconv() << " gallons\n"; // l_to_g
convert(double i) { class f_to_c : public convert {
p = &fcob;
val1 = i; public:
cout << pgetinit() << " in Fahrenheit is ";
} f_to_c(double i) : convert(i) {}
pcompute();
double getconv() { return val2; } void compute() {
cout << pgetconv() << " Celsius\n"; // f_to_c
double getinit() { return val1; } val2 = (val1-32) / 1.8;
return 0;
virtual void compute() = 0; }
}
}; };

Prepared by Dr. Naveen Choudhary 20


Templates

Prepared
by
Naveen Choudhary
Prepared by Dr. Naveen Choudhary 1
Templates
Template are used to create generic functions & classes int main()
Generic function - Same action (code) but different data
{
int i=10, j=20;
double x=10.1, y=23.3;
// Function template example. char a='x', b='z';
#include <iostream> cout << "Original i, j: " << i << ' ' << j << '\n';
using namespace std; cout << "Original x, y: " << x << ' ' << y << '\n';
// This is a function template. cout << "Original a, b: " << a << ' ' << b << '\n';
template <class X> void swapargs(X &a, X &b) swapargs(i, j); // swap integers
/* this statement tells the compiler two things that a swapargs(x, y); // swap floats
template is being created and a generic definition is swapargs(a, b); // swap chars
beginning */ // Note :- Because swapargs() is generic function,
//the compiler automatically creates three
//<class X> or you can write <typename X> in place of //versions of swapargs() one that will exchange
//<class X> //integer values, one that will exchange floating
// the above statement can also be written as under //point values, and one that will swap characters.
// template <class X> //1 cout << "Swapped i, j: " << i << ' ' << j << '\n';
// void swapargs(X &a, X &b) //2 cout << "Swapped x, y: " << x << ' ' << y << '\n';
// but nothing else should be there b/w statements 1 cout << "Swapped a, b: " << a << ' ' << b << '\n';
and 2 return 0;
{ }
X temp;  note : the template function for a specific type
temp = a; will be generated when the compiler actually
a = b; encounters the call
b = temp;  note that standard type conversion are not
} applied to function templates

Prepared by Dr. Naveen Choudhary 2


Functions with Two Generic type
Template <class type1, class type2>
Void myfunc(type1 x, type2 y )

Calls

1. myfunc (10, "I like C++")

2. myfunc(98.6,19L);

Explicitly overloading a generic function

1) Even though a generic function overloads itself as needed, you can


explicitly overload one too

2) if you overload a generic function, that overloaded function overrides


(hides) the generic function relative to the specific version

3) generally should be used when functionality (action/code) of the


function differ for a particular data type
Prepared by Dr. Naveen Choudhary 3
Functions with Two Generic type - Example

// Overriding a template function. int main()


#include <iostream> {
using namespace std; int i=10, j=20;
template <class X> void swapargs(X &a, X &b) { double x=10.1, y=23.3;
X temp; char a='x', b='z';
temp = a; cout << "Original i, j: " << i << ' ' << j << '\n';
a = b; cout << "Original x, y: " << x << ' ' << y << '\n';
b = temp; cout << "Original a, b: " << a << ' ' << b << '\n';
cout << "Inside template swapargs.\n"; swapargs(i, j); // calls explicitly overloaded swapargs()
} swapargs(x, y); // calls generic swapargs()
swapargs(a, b); // calls generic swapargs()
/* This overrides the generic version of swapargs() for cout << "Swapped i, j: " << i << ' ' << j << '\n';
intigers. Generally should be used when functionality cout << "Swapped x, y: " << x << ' ' << y << '\n';
(action/code) of the function differ for a particular data cout << "Swapped a, b: " << a << ' ' << b << '\n';
type. */ return 0;
}
void swapargs(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
cout << "Inside swapargs int specialization.\n";
}

Prepared by Dr. Naveen Choudhary 4


New style of writing explicit specialization of
template function

// Use of new-style specialization syntax.

template<> void swapargs<int>(int &a, int &b) {


int temp;
temp = a;
a = b;
b = temp;
cout << "Inside swapargs int specialization.\n";
}

Note:- However, as a general rule, if you need to have different versions of


a function for different data types, you should use overloaded function
rather than templates.

Prepared by Dr. Naveen Choudhary 5


Overloading a function template
// Overload a function template declaration.
#include <iostream>
using namespace std;

// First version of f() template.

template <class X> void f(X a)


{
cout << "Inside f(X a)\n";
}

// Second version of f() template.

template <class X, class Y> void f(X a, Y b)


{
cout << "Inside f(X a, Y b)\n";
}

int main()
{
f(10); // calls f(X)
f(10, 20); // calls f(X, Y)
return 0;
}
Prepared by Dr. Naveen Choudhary 6
Using standard parameters with template
functions & Generic Classes
 We can mix standard parameters with generic type parameters in a template function
Template <class X> void tabout (x data, int tab) { ----- }

Calls ::
Tabout (“this is a test”, 0)
Tabout(100,1)
Tabout (‘x’, 2)
Tabout(3.14, 3)

Note : generic functions are similar to overloaded functions except that they are more restrictive. When
function are overloaded, you may have different actions performed within the body of each function. But a
generic function must perform the same general action for all versions. Only the type of data can differ.

Generic classes

 Useful when a class uses a logic that can be generalized


 Ex.1
queue (of integers)  delete front, add to rear {algorithm}
queue( of char)  ---------------- do ----------------------
Ex.2
linked list of various type - the operation performed will be same as insert, delete, search an item
in the linked list

Note:- Member functions of a generic class are themselves automatically generic. you need not use template to
explicitly specify them as such

syntax :- template <class type> class class-name


{
} Prepared by Dr. Naveen Choudhary 7
Generic Class Example
// This function demonstrates a generic stack. int main()
#include <iostream> {
using namespace std; // Demonstrate character stacks.
const int SIZE = 10;
// Create a generic stack class
stack<char> s1, s2; // create two character stacks
template <class StackType> class stack {
int i;
StackType stck[SIZE]; // holds the stack
s1.push('a');
int tos; // index of top-of-stack
s2.push('x');
public:
s1.push('b');
stack() { tos = 0; } // initialize stack
s2.push('y');
void push(StackType ob); // push object on stack
s1.push('c');
StackType pop(); // pop object from stack
s2.push('z');
};
for(i=0; i<3; i++) cout << "Pop s1: " << s1.pop() << "\n";
// Push an object.
for(i=0; i<3; i++) cout << "Pop s2: " << s2.pop() << "\n";
template <class StackType> void stack<StackType> ::
// demonstrate double stacks
push(StackType ob) {
if(tos==SIZE) { stack<double> ds1, ds2; // create two double stacks
cout << "Stack is full.\n"; ds1.push(1.1);
return; ds2.push(2.2);
} ds1.push(3.3);
stck[tos] = ob; ds2.push(4.4);
tos++; ds1.push(5.5);
} ds2.push(6.6);
// Pop an object. for(i=0; i<3; i++) cout << "Pop ds1: " << ds1.pop() << "\n";
template <class StackType> StackType stack<StackType> :: for(i=0; i<3; i++) cout << "Pop ds2: " << ds2.pop() << "\n";
pop() { return 0;
if(tos==0) { }
cout << "Stack is empty.\n";
return 0; // return null on empty stack
}
tos--;
return stck[tos];
}
Prepared by Dr. Naveen Choudhary 8
Generic Class Example……Contd
when a specific instance of stack is declared, the compiler automatically
generates all the functions and variables necessary for handling the actual
data.

Stack <char> s1, s2; // creates two char stack


Stack <double> ds1, ds2; // creates two double stack
stack <char *> *s1,*s2; // creates pointers s1 and s2 to stack type
// of object. This stack object stores
// character pointer
struct addr
{
char name[40];
char street[40];
char city[20];
char state[20];
char zip[12];
};

stack <addr> obj; //create a stack object obj. of user defined data
// type addr
Prepared by Dr. Naveen Choudhary 9
Two Generic Data Types -Example
/* This example uses two generic data types in a class definition. */
#include <iostream>
using namespace std;
template <class Type1, class Type2> class myclass {
Type1 i;
Type2 j;
public:
myclass(Type1 a, Type2 b) { i = a; j = b; }
void show() { cout << i << ' ' << j << '\n'; }
};

int main()
{
myclass<int, double> ob1(10, 0.23);
myclass<char, char *> ob2('X', "Templates add power.");
ob1.show(); // show int, double
ob2.show(); // show char, char *
return 0;
}
Prepared by Dr. Naveen Choudhary 10
Using non-type arguments with generic classes
In the template specification for a generic class, you may specify non-
type arguments also

template <class type, int size> class type {


.
.
.
}

Call:-
type <int, 10> intob; //integer array of size = 10
type <double, 15> dob; // double array of size = 15
Note:- The arguments that you pass to a non-type parameter must
consist of either an integer constant, (no float can be non type argument)
or a pointer or reference to a global function or object. & thus there
values inside the class's function can't be changed. Why because The
information contained in non –type arguments must be known at compile
time. these non-type parameters should themselves be thought as
constants.
Prepared by Dr. Naveen Choudhary 11
Using default arguments with template classes

template <class x = int> class myclass{ }

Note:- It is also permissible for non-type arguments to take default


argument. the default value is used when no explicit value is specified
when the class is initiated

template <class atype = int, int size = 10> class atype { }

Calls:-
atype <int, 100> intarray; // integer array , size 100

atype <double> doublearray; // double array, default size of 10

atype <> defarray; // default to int array of size 10

Prepared by Dr. Naveen Choudhary 12


Explicit class specialization
As with template function, you can create an explicit specialization of a generic class. to do so, use the template
construct, which works the same as it does for explicit function specialization.

// Demonstrate class specialization. int main()


#include <iostream> {
using namespace std; myclass<double> d(10.1);
template <class T> class myclass { cout << "double: " << d.getx() << "\n\n";
T x; myclass<int> i(5);
public: cout << "int: " << i.getx() << "\n";
myclass(T a) { return 0;
cout << "Inside generic myclass\n"; }
x = a; note : explicit class specialization expands the
}
utility of generic classes because it lets you easily
T getx() { return x; } handle one or two special cases while allowing all
}; others to be automatically processes by the
compiler
// Explicit specialization for int.

template <> class myclass<int> {


// the above statement tells the compiler that an explicit EXPORT KEYWORD
// integer specialization of myclass is being created
int x;
The export keyword can precede a template
public: declaration. It allows other files to use
myclass(int a) { template declared in a different file by
cout << "Inside myclass<int> specialization\n"; specifying only its declaration rather that
x = a * a; duplicating its entire definition
}
int getx() { return x; }
};
Prepared by Dr. Naveen Choudhary 13
Exception Handling
Exception handling allow you to manage run – time errors in an orderly fashion. Using exception handling, your
program can automatically invoke an error handling routine when an error occurs.
Exception handling fundamental
try { 1. only code within in the try block (including) function definition
block of the function called from within the try block) can be monitored for
//try exception
}
catch (type1 arg) { 2. catch block to catch & handle Exception
//catch block
}
catch (type2 arg) { 3. Multiple catch statement. so which catch to execute depends on type of
exception. i.e. the catch with the data type which
//catch block matches that of exception then that catch is executed

}
. 4. Any type of data can be caught i.e. build in data type & even user defined class
.
catch(typeN arg) { 5. In general, catch expression are checked in the order in which they occur in a
//catch block program & only the matching catch is executed and all other catch are ignored
}

 You can have a throw exception :: statement with in the try block to throw the exception manually
 If there is no corresponding catch block then standard library function terminate () will be invoked. By default
terminate () calls abort () to stop your program.

Prepared by Dr. Naveen Choudhary 14


Example
/* Throwing exception from with in the function
definition of the function call which is in try block. */
// A simple exception handling example.
#include <iostream>
#include <iostream> using namespace std;
using namespace std; void Xtest(int test) {
int main() { cout << "Inside Xtest, test is: " << test << "\n";
cout << "Start\n"; if(test) throw test;
try { // start a try block }
cout << "Inside try block\n"; int main() {
throw 100; // throw an error cout << "Start\n";
cout << "This will not execute"; try { // start a try block
} cout << "Inside try block\n";
catch (int i) { // catch an error Xtest(0);
cout << "Caught an exception -- value is: "; Xtest(1);
cout << i << "\n"; Xtest(2);
} }
cout << "End"; catch (int i) { // catch an error
return 0; cout << "Caught an exception -- value is: ";
} cout << i << "\n";
}
cout << "End";
return 0;
}

Prepared by Dr. Naveen Choudhary 15


Local try/catch to a function
/*The code associated with a catch statement will be
// Try block can be localized to a function
executed only if it catches an exception. Otherwise,
execution simply bypass the catch block. */
#include <iostream>
using namespace std;
#include <iostream>
// Localize a try/catch to a function.
using namespace std;
void Xhandler(int test) {
int main() {
try{
cout << "Start\n";
if(test) throw test;
try { // start a try block
}
cout << "Inside try block\n";
catch(int i) {
cout << "Caught Exception #: " << i << '\n'; cout << "Still inside try block\n";
}
}
catch (int i) { // catch an error
}
cout << "Caught an exception -- value is: ";
int main() {
cout << "Start\n"; // this catch block will not be executed as there is no
//exception in the try block
Xhandler(1);
cout << i << "\n";
Xhandler(2);
}
Xhandler(0);
cout << "End";
Xhandler(3);
return 0;
cout << "End";
}
return 0;
} o/p  start
Inside try block
o/p start
Still inside try block
Caught Exception # : 1
End
Caught Exception # : 2
Caught Exception # : 3
End
Prepared by Dr. Naveen Choudhary 16
Catching Class Types
/*Generally we create a class, which can describe the Using multiple catch statement
exception\error and use this object to throw exception. */ / *Catch expression are checked in the order in which
they occur in a program. Only a matching statement
#include <iostream> // Catching class type exceptions. is executed. All other catch blocks are ignored. */
#include <cstring>
using namespace std; #include <iostream>
class MyException { using namespace std;
public: // Different types of exceptions can be caught.
char str_what[80]; void Xhandler(int test) {
int what; try {
MyException() { *str_what = 0; what = 0; } if(test) throw test;
MyException(char *s, int e) { strcpy(str_what, s); what = e; } else throw "Value is zero";
}; }
int main() { catch(int i) {
int i; cout << "Caught Exception #: " << i << '\n';
try { }
cout << "Enter a positive number: "; catch(const char *str) {
cin >> i; cout << "Caught a string: ";
if(i<0) cout << str << '\n';
throw MyException("Not Positive", i); } o/p  start
// An object of type MyException is created & then thrown } Caught Exception # : 1
} int main() { Caught Exception #: 2
catch (MyException e) { // catch an error cout << "Start\n"; Caught a String: Value is
cout << e.str_what << ": "; Xhandler(1); zero
cout << e.what << "\n"; Xhandler(2); Caught Exception #: 3
} Xhandler(0); End
return 0; Xhandler(3);
} cout << "End";
return 0;
Prepared by Dr. Naveen
} Choudhary 17
Handling derived – class Exception
A catch class of a base class will also match any class derived from that base. Thus, if you want to catch
exception of both a base class type and a derived class type, put the derived class first in the catch sequence. If
you don’t do this, the base class catch will also catch all derived classes.

Exception Handling Options


// Catching derived classes.
Catching all Exception
#include <iostream>
using namespace std;
In some circumstances you will want an
class B {
exception handler to catch all exception, instead
};
of just a certain type. Simply use the form of
class D: public B {
}; catch shown below.
int main() {
Catch(…){
D derived;
// process all exception
try {
}
throw derived;
}
one very good use for catch (…) is as the last
catch(B b) {
catch of a cluster of catches. In this capacity it
cout << "Caught a base class.\n";
provides a useful default or “Catch all” statement.
}
catch(D d) {
cout << "This won't execute.\n";
}
return 0;
}
o/p  caught in base class

Prepared by Dr. Naveen Choudhary 18


Restricting exception
 You can restrict the type of exception that a // Restricting function throw types.
function can throw. #include <iostream>
using namespace std;
return_type func_name (arg_list) throw (type_list)
// This function can only throw ints, chars, and doubles.
 empty list, mean function can not
throw any exception. void Xhandler(int test) throw(int, char, double) {
if(test==0) throw test; // throw int
 The func_name can only throw those data type if(test==1) throw 'a'; // throw char
enclosed in the type_list. Throwing any other type if(test==2) throw 123.23; // throw double
will call the standard library function unexpected () }
to be called, which by default call abort () resulting in
program termination. int main() {
cout << "start\n";
 It is important to understand that a function can be try{
restricted only in what type of exceptions it throws Xhandler(0); // also, try passing 1 and 2 to Xhandler()
back to the try block that called it. That is, a try block }
within a function may throw any type of exception so catch(int i) {
long as it is caught with in that function. The cout << "Caught an integer\n";
restriction applies only when throwing an exception }
outside of the function. catch(char c) {
cout << "Caught char\n";
}
catch(double d) {
cout << "Caught double\n";
}
cout << "end";
return 0;
}
Prepared by Dr. Naveen Choudhary 19
Rethrowing an Exception
// Example of "rethrowing" an exception.
 If you wish to rethrow an expression #include <iostream>
from within an exception handler, you using namespace std;
void Xhandler() {
may do so by calling throw, by itself with try {
no exception (i.e. with no data or data throw "hello"; // throw a char *
}
type) catch(const char *) { // catch a char *
cout << "Caught char * inside Xhandler\n";
throw ; // rethrow char * out of function
Why to do it  one catch may do part }
of exception handling & other catch }
int main()
might be doing other part of exception {
handling cout << "Start\n";
try{
Xhandler();
An exception can only be rethrown }
catch(const char *) {
from within a catch block ( or from any cout << "Caught char * inside main\n";
function called from with in that block) }
cout << "End";
When you rethrow an exception, it will return 0;
not be recaught by the same catch }
o/p  start
statement, it will propagate outward to caught char * inside Xhandler
the next catch statement. caught char * inside main
End

Prepared by Dr. Naveen Choudhary 20


Understanding terminate () and unexpected ()

 However, you can change the function that are called


void terminate (); by terminate () & Unexpected(). Doing so allow your
void unexpected (); program to take full control of the exception handling
subsystem.
 void terminate()
 This function is called whenever the  To change the terminate handler use set_terminate ()
exception handling subsystem fails to function.
terminate_hamdler set_terminate (terminate_handler
find a matching catch statement for an newhandler) throw ();
exception //the function return the pointer to the new terminate
//handler.
It is also called if your program
attempts to rethrow an exception when New handler is a pointer to the new terminate handler.
no exception was originally thrown. The newterminate handler must be of type
terminate_handler which is defined like this

 void unexpected (); Typedef void ( *terminate_handler) (); pointer to a


This function is called when a function returning void
function attempts to throw an
exception that is not allowed by its The only thing that your terminate handler must do is
throw list. stop program execution. It must not return to program
or resume it in any way similarly.
Setting the Terminate & Unexpected Handlers By
unexpected_handler set_unexpected
default
(unexpected_handler newhandler) throw()
typedef void (*unexpected_handler) ();  returns
Terminate () –calls abort ()
pointer to a function returning void 21
Unexpected () –calls terminate () –calls
Prepared
abort ()by Dr. Naveen Choudhary
Example
 bool uncaught_exception ();
// Set a new terminate handler.
#include <iostream>  the function returns true if an
#include <cstdlib> exception has been thrown but not
#include <exception>
yet caught. Once caught the
using namespace std;
void my_Thandler() { function returns false.
cout << "Inside new terminate handler\n";
abort();
} The exception & bad_exception
int main() classes
{
// set a new terminate handler When a function supplied by
set_terminate(my_Thandler); the C++ standard library throws
try {
cout << "Inside try block\n"; an exception, it will be an object
throw 100; // throw an error derived from the base class
}
catch (double i) { // won't catch an int exception exception.
// ...
}
return 0;
}

Prepared by Dr. Naveen Choudhary 22


Exception handling (divide by zero)
#include <iostream>
using namespace std;
void divide(double a, double b);
int main() {
double i, j;
do {
cout << "Enter numerator (0 to stop): ";
cin >> i;
cout << "Enter denominator: ";
cin >> j;
divide(i, j);
} while(i != 0);
return 0;
}
void divide(double a, double b)
{
try {
if(!b) throw b; // check for divide-by-zero
cout << "Result: " << a/b << endl;
}
catch (double b) {
cout << "Can't divide by zero.\n";
}
}

Prepared by Dr. Naveen Choudhary 23


Prepared
by
Naveen choudhary

Prepared by Dr. Naveen Choudhary 1


include <iostream.h> ios
using namespace std;

A stream is a logical device istream streambuf ostream


that either produces or
consumes information. A
stream is linked to physical iostream
device by the I/O system.
Device can be of different
types like keyboard, disk
but stream provides a ifstream fstream ofstream
uniform interface to the
user. Note: - Some more classes are there in the hierarchy
but is not shown here
Stream  logical device,
connected to physical
device
Objective  uniform interface
Prepared by Dr. Naveen Choudhary 2
Predefined object of I/O streams
cin Standard Input Keyboard (Object of istream with assignment )
cout Standard Output Screen (Object of ostream with assignment)
cerr Stanadrd Error Screen ---------- do ----------------
clog Buffered version Screen ---------- do ----------------
of cerr

Formatted I/O Operation : Formatting data to be Input / Output

Two Ways :
Using ios member function :- Using ios member function & setting status flags of
ios class using the member function
Using manipulators :- These are special functions that can be included as part of
the I/O expression

Prepared by Dr. Naveen Choudhary 3


Formatting I/O using member functions
ios Formatting flags (there are two type of flags on/off and flags that work in a group )
Skipws When set, leading, white-space characters (space, tab & new lines) are ignored/skipped on/off flag
when performing input on a stream

left Left justified [12.34 ________ ] (Output)


right Right justified [_____12.34 ] (Output)
internal Use padding between sign or base indicator & number [+ 12.54 ]

dec Convert to decimal (output)


oct Convert to Octal (output)
hex Convert to Hexadecimal (output)

boolalpha When set, Booleans can be input or output using the keyboard True or False

showbase Use base indicator on output ( o for Octal, 0x for Hex ) -- on/off flag

showpoint Show decimal point on output (ie causes a decimal point & trailing zeros to be displayed
for all floating point output whether needed or not) -- -- on/off flag

uppercase By default, when scientific notation is displayed, the e is in lowercase. Also when a
hexadecimal value is displayed, the x is in lower case. When uppercase is set, these
characters are displayed in uppercase -- on/off flag
showpos Display + before positive intergers -- -- on/off flag

scientific Use exponential format on floating point output [9.1234E2]

fixed Use fixed format on floating point output [912.34]

unitbuf When unitbuf is set, the buffer is flushed after each insertion operation -- on/off flag

Prepared by Dr. Naveen Choudhary 4


Formatting I/O using member functions
…..contd
stdio Flush stdout, stderror after insertion ( used when you have a
program that uses both iostream and the C standaed I/O library.
If you discover your iostream output and printf() output are
occuring in the wrong order, try setting this flag -- on/off flag

basefield Oct, Dec & Hex fields are collectively called basefield

adjustfield Left, right, internal are collectively called adjustfield

floatfield Scientific, Fixed are collectively called floatfield

The ios class declares a bitmask enumeration called fmtflags in which


the above mentioned flags are defined

Prepared by Dr. Naveen Choudhary 5


Example-1
Setting Format Flag #include <iostream>
fmtflag setf (fmtflag flags1) using namespace std;
int main()
The function returns the previous {
setting of the format flag & turns on cout.setf(ios::showpoint);
those flags specified flags1 cout.setf(ios::showpos);
cout << 100.0; // displays +100.0
stream.setf (ios :: showpos)
return 0;
}
you can set more than one flag with
single setf command using Example-2
stream.setf (ios :: showpoint | ios :: showpos); #include <iostream>
using namespace std;
Clearning Formatting Flags int main()
void unsetf (fmtflags flags); {
cout.setf(ios::uppercase |
ios::scientific);
The flags specified by flags are cleared cout << 100.12; // displays
(all other flags are unaffected ) //1.0012E+02
cout.unsetf(ios::uppercase); // clear
//uppercase
cout << " \n" << 100.12; // displays
//1.0012e+02
return 0;
Prepared by Dr. Naveen Choudhary 6
}
Example – 2
An overloaded form of setf ( ) #include <iostream>
Used for group flags using namespace std;
fmtflags setf (fmtflags flag1. fmtflags flag2); int main()
{
In this version, only the flags specified by cout.setf(ios::hex, ios::basefield);
flag2 are affected. They are first cleared and cout << 100; // this displays 64 ie
then set according to the flag specified by 100 in hex form
flag1. note that even if flag1 contains other return 0;
flags, only those specified by flag2 will be }
affected. The previous flags setting is
returned. Example – 3(skip)
#include <iostream>
using namespace std;
int main()
Example – 1 {
#include <iostream> cout.setf(ios::showpos, ios::hex); //
using namespace std; //error, showpos not set
int main( ) cout << 100 << '\n'; // displays
{ 100, not +100
cout.setf(ios::showpoint | ios::showpos, cout.setf(ios::showpos, ios::showpos);
ios::showpoint); // this is correct
cout << 100.0; // displays 100.0, and not +100.0 cout << 100; // now displays +100
return 0; return 0;
} }
Prepared by Dr. Naveen Choudhary 7
Examining the format flags
fmtflag flags ( );
Simply returns the current setting of each
// This function displays the status of the
format flag
format flags.
void showflags()
Setting all flags
{
fmtflag flags(fmtflag f);
ios::fmtflags f;
The bit pattern found in f is used to set the
long i;
formatflag associated with the stream.
f = (long) cout.flags(); // get flag settings
Thus, all format flags are affected. The
// check each flag
function returns the previous setting.
for(i=0x4000; i; i = i >> 1)
if(i & f) cout << "1 ";
Example – 1 else cout << "0 ";
#include <iostream> cout << " \n"; }
using namespace std;
void showflags() ; Output:
int main() 000001000000001
{ 010001010010001
// show default condition of format flags
showflags();
cout.setf(ios::right | ios::showpoint |
ios::fixed);
showflags();
return 0;}
Prepared by Dr. Naveen Choudhary 8
Example – 3 Other ios Functions
#include <iostream>
using namespace std;
ch = fill () reads the current fill character
void showflags();
(default is space ) {int ios :: fill() }
int main()
fill (ch) Set the fill character & returns the
{
previous fill character { int ios ::
// show default condition of format flags
fill(int n )
showflags();
p = precision () Get the precision (no. of digits
// showpos, showbase, oct, right are on,
displayed after floating point)
// others off
precision (p) Set the precision
long f = ios::showpos | ios::showbase |
w = width () Get the current field width (in
ios::oct | ios::right;
characters)
cout.flags(f); // set all flags
width () Set the current field width
showflags();
return 0;
Note :: the width is reset to zero by each
}
insertion and extraction. If we want to have a
constant width, we need to call width() after
Output –
000001000000001 each insertion or extraction
000010010101000

Prepared by Dr. Naveen Choudhary 9


Example-1 ()
#include <iostream>
using namespace std;
int main()
{
cout.precision(4) ;//total 4 digits will be displayed
//if used with cout.setf(ios ::
//fixed) then precision will mean
//digits after decimal point only
cout.width(10);
cout << 10.12345 << "\n"; // displays 10.12
cout.fill('*');
cout.width(10);
cout << 10.12345 << "\n"; // displays ***10.12
// field width applies to strings, too
cout.width(10);
cout << "Hi!" << "\n"; // displays *******Hi!
cout.width(10);
cout.setf(ios::left); // left justify
cout << 10.12345; // displays 10.12*****
return 0;
}

Prepared by Dr. Naveen Choudhary 10


cout << endl;
24. Write a program implementing basic
cout << endl;
operation of class ios i.e. setf,unsetf,precision
cout.width( 10 );
etc. (skip)
cout << str << endl;
#include <iostream.h>
cout.width( 40 );
#include <conio.h>
cout.setf( ios::left, ios::adjustfield );
void main( )
cout.width( 40 );
{
cout << str << endl;
int i = 52;
float a = 425.0; cout.precision( 6 );
cout << "Precision" << cout.precision( );
float b = 123.500328;
cout.setf( ios::showpoint );
char str[ ] = "Dream. Then make it happend!";
cout.unsetf( ios::showpos );
clrscr( );
cout << endl << a;
cout.setf( ios::unitbuf );
cout.unsetf( ios::showpoint );
cout.setf( ios::stdio );
cout << endl << a;
cout.setf( ios::showpos );
cout << i << endl; cout.setf( ios::fixed, ios::floatfield );
cout << endl << b;
cout.setf( ios::showbase );
cout.setf( ios::scientific, ios::floatfield );
cout.setf( ios::uppercase );
cout << endl << b;
cout.setf( ios::hex, ios::basefield );
cout << i << endl; b = 5.375;
cout.precision( 14 );
cout.setf( ios::oct, ios::basefield );
cout.setf( ios::fixed, ios::floatfield );
cout << i << endl;
cout << endl << b;
cout.fill( '0' );
cout.setf( ios::scientific, ios::floatfield );
cout << "Fill character " << cout.fill( ) << endl;
cout << endl << b;
cout.setf( ios::dec, ios::basefield );
cout.unsetf( ios::showpoint );
cout.width( 10 );
cout << i << endl; cout.unsetf( ios::unitbuf );
cout.unsetf( ios::stdio );
cout << setf( ios::left, ios::adjustfield );
}
cout.width( 10 );
cout << i << endl;
cout.setf( ios::internal, ios::adjustfield );
cout.width( 10 );
Prepared by Dr. Naveen Choudhary 11
Manipulators
cout<< setiosflags (ios::fixed) << setiosflags (ios::showpoint);
Non-Argument ios Manipulators (include < iostream.h> )
ws/skipws Turn on whitespace skipping on input Noshowpos Turns off showpos flag Output
Dec Convert to decimal Showpoint Turns on showpoint flag Output
Oct Convert to Octal Showpos Turns on showpos flag Output
Hex Convert to Hexadecimal Skipws Turns on skipws flag Input
Endl Insert newline and flush the output stream Noskipws Turns off skipws flag Input
Ends Insert Null character to terminate a output Unitbuf Turns on unitbuf flag Input
string
Nounitbuf Turns off unitbuf flag Output
Flush Flush the output stream
Nouppercase Turns off uppercase flag Output
Lock Lock file handle
Left Turns on Left flag Output
Unlock Unlock file handle
Right Turns on Right flag Output
Boolalpha Turns on boolalpha flag I/O
Scientific Turns on scientific flag Output
Noboolalpha Turns off boolalpha Output

Fixed Use fixed notation for printing float values Note that manipulators affect only the data
Internal Use padding between sign or base indicator that follows them in the stream, not the
and value data that precedes them. Table
Left Left align, pad on right summarizes the important manipulators
Noshowbase Turns off showbase flag Output that take arguments. You need the
IOMANIP header file for these function.
Noshowpoint Do not Show decimal point Prepared
& trailing zeros
by Dr. Naveen Choudhary 12
for float values # include <iomanip.h>
Table
ios Manipulators with Arguments Example –2 (skip)
Manipulators Arguments Purpose
#include <iostream>
#include <iomanip>
setw (int ) Field width (int) Set field width for using namespace std;
output int main()
setfill (int ) Fill character Set fill character for {
(int) output (default is space)
cout.setf(ios::hex, ios::basefield);
setprecision (int ) Precision (int) Set precision (number of cout << 100 << "\n"; // 100 in hex ie 64
digits displayed after
decimal point) cout.fill('?');
setiosflags (long) Formatting flags Set format flags
cout.width(10);
(long) specified by n. setting cout << 2343.0;
remains in effect until // cout << 1232.0  now fill() & width()
next change
//will not be applicable here
resetiosflags Formatting flags Clear specified flags. return 0;
(long) (long) setting remains in effect
until next change }
setbase (int ) Base (int) Set the no. base to base (
Example –3 (SKIP )
0 – base 10, 8 – octol, 16 #include <iostream>
– hex ) #include <iomanip>
Example –1 using namespace std;
#include <iostream> int main()
#include <iomanip> {
using namespace std;
int main() cout << setiosflags(ios::showpos);
{ cout << setiosflags(ios::showbase);
cout << hex << 100 << endl;//64 cout << 123 << " " << hex << 123;//
cout << setfill('?') << setw(10) << 2343.0;//??????2343
return 0;} Prepared by Dr. Naveen Choudhary //+123 0x7b 13
return 0;}
#include<iostream.h>
#include <conio.h> resetiosflags ( ios::showpos )
#include <iomanip.h> «endl«a; //425.000000
void main( ) cout « resetiosflags ( ios::showpoint )
{ «endl«a; //425
int i=52; cout « setiosflags ( ios::fixed ) « endl « b ; //123.500328
float a = 425.0 ; cout « setiosflags ( ios::scientific ) « endl « b ;
float b = 123.500328 ; //1.235003E+02
char str[ ] = "Dream. Then make it happen!" ; b = 5.375 ;
clrscr( ) ; cout.precision ( 14 ) ;
cout « setiosflags ( ios::unitbuf | ios::stdio | ios::showpos ) cout « setiosflags ( ios::fixed ) « endl « b ; // 5.375
; cout « setiosflags ( ios::scientific ) « endl « b ;
cout« I «endl; // +52 //5.375E+00
cout « setiosflags ( ios::showbase | ios::uppercase ) ; cout « resetiosflags ( ios::showpoint | ios::unitbuf |
cout « hex « i « endl ; // 0X34 ios:stdio ) ;
cout « oct « i « endl ; // O64 }
cout « setfill ( '0' ) ;
cout « "Fill character:" « cout.fill( ) « endl ;//0
cout«dec«setw(10)«i«endl; // 0000000+52
cout « setiosflags ( ios::left)
«dec «setw(10)«i«endl; // +520000000
cout « setiosflags ( ios::internal )
«dec«setw(10)«i«endl; // +000000052
cout « i « endl ; // +52
cout « setw (10 ) « str « endl ; // dream.then make it happen
cout « setw ( 30 ) « str « endl ;//00000dream.then make it
//happen
cout « setiosflags ( ios::left ) « setw ( 40 ) « str « endl ;
//dream.then make it happen00000

cout«precision ( 6 ) ;
cout « "Precision: " « cout.precision( ) ; // +6
cout « setiosflags ( ios::showpoint ) « Prepared by Dr. Naveen Choudhary 14
Example –4
Example –4 #include <iostream>
#include <iostream> #include <cstring>
using namespace std; using namespace std;
int main() class phonebook {
{ public:
bool b; char name[80];
b = true; int areacode;
cout << b << " " <<boolalpha<< b << endl; // int prefix;
1 true int num;
cout << "Enter a Boolean value: ";//false phonebook(char *n, int a, int p, int nm)
cin >> boolalpha >> b; {
cout << "Here is what you entered:"<<b; strcpy(name, n);
//false areacode = a;
return 0; prefix = p;
} num = nm;
Overloading << & >> (insertion & }
};
extraction operator ) // Display name and phone number.
Inserter overloading ostream &operator<<(ostream &stream,
phonebook o) // can not be member function of
ostream & operator << ( ostream &stream,
//phonebook
class_type obj) {
{ stream << o.name << " ";
//body of inserter stream << "(" << o.areacode << ") ";
return stream; Prepared by Dr. Naveenstream << o.prefix << "-" << o.num << "\n"; 15
Choudhary
} return stream; } // must return stream
#include <iostream>
int main() #include <cstring>
{ using namespace std;
phonebook a("Ted", 111, 555, 1234); class phonebook {
phonebook b("Alice", 312, 555, 5768); // now private
phonebook c("Tom", 212, 555, 9991); char name[80];
cout << a << b << c; int areacode;
return 0; int prefix;
} int num;
public:
In the preceding program, notice that phonebook(char *n, int a, int p, int nm)
the phone book, inserter is not a {
member of phone book and it can not strcpy(name, n);
be as left side of the << operator is areacode = a;
stream and not the phonebook class prefix = p;
Beside 1st argument must be of type num = nm;
ostream & not of phone book. }
friend ostream &operator<<(ostream
But if inserter operator is not a member &stream, phonebook o);
function then we can’t access the private };
members of the class phonebook in the // Display name and phone number.
overloaded inserter operator. ostream &operator<<(ostream &stream,
Solution : make the inserter operator phonebook o)
function , friend of the phonebook {
class. stream << o.name << " ";
Prepared by Dr. Naveen Choudhary 16
stream << "(" << o.areacode << ") ";
stream << o.prefix << "-" << o.num << "\n"; Example
return stream; // must return stream #include <iostream>
} #include <cstring>
int main() using namespace std;
{ class phonebook {
phonebook a("Ted", 111, 555, 1234); char name[80];
phonebook b("Alice", 312, 555, 5768); int areacode;
phonebook c("Tom", 212, 555, 9991); int prefix;
cout << a << b << c; int num;
return 0; public:
} phonebook() { };
phonebook(char *n, int a, int p, int nm)
Inside inserter operator we have used: {
1. stream << o.name << “ ”; strcpy(name, n);
we could have also used
2. cout << o.name << “ ”;
areacode = a;
but 1 is more generic & can be used with any prefix = p;
ostream. Whereas 2 can only be used with cout. num = nm;
}
Overloading extractor operator friend ostream &operator<<(ostream
istream & operator >> (istream & stream, &stream, phonebook o);
class_type &obj) friend istream &operator>>(istream
{ &stream, phonebook &o);
//body of extractor };
return streanm;
} Prepared by Dr. Naveen Choudhary 17
// Display name and phone number.
ostream &operator<<(ostream &stream, (skip) Actually extractor operator defined
phonebook o) in the previous example is not correct. If
{ istream is cin then ok but if istream is
stream << o.name << " "; some disk file then we should not use cout
stream << "(" << o.areacode << ") "; (as we have used in the example).
stream << o.prefix << "-" << o.num << "\n";
return stream; // must return stream Creating your own
} manipulator function
// Input name and telephone number.
istream &operator>>(istream &stream, Manipulator can be with parameter or
phonebook &o) parameterless.
{
cout << "Enter name: "; stream >> o.name; 1. Parameterized manipulators can take
cout << "Enter area code: "; some argument in addition to istream/
stream >> o.areacode; ostream.
cout << "Enter prefix: "; stream >> o.prefix; 2. //(skip) Parameterless manipulators can
cout << "Enter number: "; stream >> o.num; take only a single argument which is of
cout << "\n"; type istream/ ostream.
return stream; 3. //(skip) creating customized
} parameterized manipulators is compiler
int main() dependent & you need to go through,
{ the compiler documentation. So these
phonebook a; type of manipulators are not further
cin >> a; cout << a; discussed.
Prepared by Dr. Naveen Choudhary 18
return 0;}
4. O/P manipulators
ostream & manip_name(ostream
Example-1(skip)
&stream)
#include <iostream>
{
#include <iomanip>
// your code here
using namespace std;
}
// A simple output manipulator.
istream & manip_name (istream &
ostream &sethex(ostream &stream)
stream)
{
{
stream.setf(ios::showbase);
// your code here
stream.setf(ios::hex, ios::basefield);
}
return stream;
}
The call to these manipulators is from the
int main()
insertion/ extraction operation as shown
{
below & we need not pass arguments
cout << 256 << " " << sethex << 256;
during the call.
return 0;
}
cout << 256 << “ ” << sethex <<256;
Or
cin>> getpass >> pw

Prepared by Dr. Naveen Choudhary 19


Example-2
#include <iostream> Example-3
#include <iomanip> #include <iostream>
using namespace std; #include <cstring>
// Right Arrow using namespace std;
ostream &ra(ostream &stream) // A simple input manipulator.
{ istream &getpass(istream &stream)
stream << "---------> "; {
return stream; cout << '\a'; // sound bell
} cout << "Enter password: ";
// Left Arrow return stream;
ostream &la(ostream &stream) }
{ int main()
stream << " <-------"; {
return stream; char pw[80];
} do {
int main() cin >> getpass >> pw;
{ } while (strcmp(pw, "password"));
cout << "High balance " << ra << 1233.23 cout << "Logon complete\n";
<< "\n";// -- > 1233.23 return 0;
cout << "Over draft " << ra << 567.66 << }
la;// --- >567.66 < ---
return 0;
} Prepared by Dr. Naveen Choudhary 20
istream function
Function Purpose ignore (max, Extract and discard upto MAX characters
DELIM) until (and including) the specified
>> extraction for all basic(and delimiter ( typically ‘\n’ ).
overloaded) types
peek (ch) Read one character, leave it in stream
get (ch) Extract one character into ch

get (str) Extract characters into array str,


until NULL count = gcount () Return number of character read by a
immediately preceding call to get(),
get (str, max) Extract upto max characters into
getline (), or read ()
array
read (str, max) For files – extract upto to MAX character
get (str, DELIM) Extract characters into array str
into str, until EOF
until specified delimeter (typically
‘\n’). Leave delimiting character in
stream
get (str, max, DELIM) Extract characters into array str seekg (pos, seek_dir) Set distance (in bytes) of file pointer
until MAX characters or the from specified place in the file. seek_dir
delimeter character. Leave can be ios::beg, ios::cur, ios::end
delimiting character in stream.
pos = tellg(pos) Return position (in bytes) of file pointer
getline (str, max, DELIM) Extract characters into array str from start of file.
until MAX characters or the
delimeter character. Extract
delimiting character
putback (ch) Insert last character read back into
input stream
Prepared by Dr. Naveen Choudhary 22
ostream function

Function Purpose badbit Invalid operation (no associated


<< Formatted insertion for all streambuf)
basic (and overloaded) types hardfail Unrecoverable error
put (ch) Insert character ch into stream

flush () Flush buffer contents and


insert newline Function for Error flags
write (str, SIZE) Insert SIZE character from
array str into file
seekp (position) Set distance in bytes of file Function Purpose
pointer from start of file int = eof () Returns true if EOF flag set
seekp (position, seek_dir) Set distance in bytes of file
pointer, from specified place
int = fail () Returns true if failbit or badbit flag
in file. seek_dir can be set
ios::beg, ios::cur or ios::end int = bad () Returns true if badbit or hardfail flag
pos = tellp() Return position of file pointer set
Error status flags int = good () Returns true if everything OK; no
Name Meaning flag set
goodbit No errors (no flags set, clear (int = 0) With no arguments, clears all error
value =0) bits; otherwise sets specified flags, as
in clear (ios::failbit)
eofbit Reached end of file
failbit Operation failed (user
error, prematurePrepared
EOF) by Dr. Naveen Choudhary 23
Note: (1) #include <fstream.h> {for disk I/O to/from
Probem of using cout with files files}
ofstream outfile;
outfile.open(“SAMPLE.TXT”); ios
outfile <<ch <<endl << j << endl << a
<<endl <<str;
istream ostream
in the above statement we need to give
endl ie “\n” after each variable because
since all these variables will be written in iostream
the file in char format and without the
delimiter the >>(extrraction operator) will
not be able to make out when the value ifstream ofstream
for a particular variable ends.

Note (2):(skip) fstream


The ifstream, ofstream and fstream
classes are declared in the header file
‘fstream.h’. this file is also includes the
‘iostream.h’ header file, so there is no
need to do it explicitly.
Prepared by Dr. Naveen Choudhary 24
First create file streams
ifstream in; //input
ofstream out; //output
fstream io; //input & output

After creating file streams, you need to associate these stream to files with the help
of open ().
void ifstream::open (const char *filename, ios::openmode) ios::in (default)
void ofstream::open (const char *filename, ios::openmode) ios::out | ios::trunc (default)
void fstream::open(const char *filename, ios::openmode) ios::in | ios::out (default)
modes
ios::app - Append to the end of file
ios::ate - File offset is set to the end of the file, although I/O
operation are allowed to occur anywhere in file.
ios::in - File capable of input
ios::out - File capable of output
ios::trunc - If the named file already exist, the file is destroyed & is truncated to
zero length.
ios::binary- ios::binary value causes a file to be opened in binary mode. By
default, all files are opened in text mode. In text mode the file store information as
character (like 439) will be stored as these characters ‘4’,’3’,’9’ moreover various character
translation may take place such as carriage return/ linefeed sequence being converted
into newlines. However when a file is opened in binary mode, no such character
translation will occur (also bytes in memory will be stored as it is in the file like if 257 =
0000000100000001 in memory will be stored
Prepared as it isChoudhary
by Dr. Naveen in the file. 25
Note :: Any file, whether it contains formatted text or raw data, can be opened in
either binary or text mode.
ofstream out;
out.open (“test”, ios::out); //out.open (“test”); as ios::out is default for ofstream.
To close  out.close()
If open ( ) fails, the stream will evaluated to false when used in a Boolean
expression.
if (!mystream)
{
cout<<”cannot open file\n”; //handle error
}

The ifstream, ofstream & fstream classes have constructor function that automatically
open the file. The constructor function have the same parameters & defaults as the
open ( ) function.

Ifstream mystream (“myfile”); // open file for input


As stated, if for some reason the file cannot be opened, the value of the
associated stream variable will evaluated to false.

You can also check to see if you have successfully opened a file by using
the is_open ( ) function, which is a member of fstream, ifstream ofstream.

Prepared by Dr. Naveen Choudhary 26


bool is_open ( ); Reading and writing text files
it returns true if the stream is linked (Formatted I/O)
to an open file & false otherwise.
Use << && >> as with other stream
If (! mystream.is_open () )
{ Example-1
cout<< “File is not open #include <iostream>
\n”; #include <fstream>
} using namespace std;
int main()
To close a file – mystream.close(); {
The close() function takes no ofstream out("INVNTRY"); // output,normal file
arguments and return no value if(!out) {
cout << "Cannot open INVENTORY file.\n";
return 1;
}
out << "Radios " << 39.95 << endl;
out << "Toasters " << 19.95 << endl;
out << "Mixers " << 24.80 << endl;
out.close();
return 0;
}

Prepared by Dr. Naveen Choudhary 28


Example-2 •When reading text files using >>
#include <iostream> operator keeps in mind that certain
#include <fstream> character translation will occur. For
using namespace std; example white-space characters are
int main() omitted. If you want to prevent any
{ character translation, you must open a
ifstream in("INVNTRY"); // input file for binary access & use the function
if(!in) { discussed in the next section.
cout << "Cannot open INVENTORY •When inputting, if end of file is
file.\n"; encountered, the stream linked to that
return 1; file will evaluate to false.
}
char item[20]; Unformatted (raw/ binary) reading/ writing of files using
various function { the function can be applied to text files
float cost; also but then some character translation may occur}
in >> item >> cost;
cout << item << " " << cost << "\n";
in >> item >> cost; put () & get()
cout << item << " " << cost << "\n"; istream &get(char &ch);
in >> item >> cost; ostream &put(char &ch);
cout << item << " " << cost << "\n"; the get() function reads a single character
in.close(); from the invoking stream & put that value in
return 0; ch. It returns a reference to the stream. The
} put() function writes ch to the stream &
returns a reference to the stream.
Prepared by Dr. Naveen Choudhary 29
Example-1 Example-2
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
using namespace std; using namespace std;
int main(int argc, char *argv[]) int main()
{ {
char ch; int i;
if(argc!=2) { ofstream out("CHARS", ios::out | ios::binary);
cout << "Usage: PR <filename>\n"; if(!out) {
return 1; cout << "Cannot open output file.\n";
} return 1;
ifstream in(argv[1], ios::in | ios::binary); }
if(!in) { // write all characters to disk
cout << "Cannot open file."; for(i=0; i<256; i++)
return 1; out.put((char) i);
} out.close();
while(in) { /* in will be false when eof is return 0;
reached, as get() returns a reference to }
the stream in & in will be false when the
end of file is encountered
in.get(ch);
if(in) cout << ch;
}
return 0;
Prepared by Dr. Naveen Choudhary 30
}
read() & write() int main()
to read block of binary data {
istream & read(char *buf, streamsize num); struct status acc;
ostream &write(const char *buf, streamsize strcpy(acc.name, "Ralph Trantor");
acc.balance = 1123.23;
num);
acc.account_num = 34235678;
the read() function reads num characters from the // write data
invoking stream & puts them in the buffer pointed to ofstream outbal("balance", ios::out | ios::binary);
by buf. The write() function writes num characters to if(!outbal) {
the invoking stream from the buffer pointed by buf. cout << "Cannot open file.\n";
As mentioned in the preceeding chapter, streamsize
is a type defined by the C++ libarary as some form of return 1;
integer. It is capable of holding the largest no. of }
characters that can be transferred in any one I/O outbal.write((char *) &acc, sizeof(struct status));
operation. outbal.close();
// now, read back;
ifstream inbal("balance", ios::in | ios::binary);
if(!inbal) {
#include <iostream> cout << "Cannot open file.\n";
return 1; }
#include <fstream>
inbal.read((char *) &acc, sizeof(struct status));
#include <cstring>
cout << acc.name << endl;
using namespace std; cout << "Account # " << acc.account_num;
struct status { cout.precision(2);
char name[80]; cout.setf(ios::fixed);
double balance; cout << endl << "Balance: $" << acc.balance;
unsigned long account_num; inbal.close();
}; returnChoudhary
Prepared by Dr. Naveen 0;} 31
• As you can see, only a single call to read()
or write() is necessary to read or write the int i;
entire structure. Each individual field need ofstream out("numbers", ios::out | ios::binary);
not be read or written separately & this if(!out) {
example illustrates, the buffer can be any cout << "Cannot open file.";
type of object. return 1;
}
• If the end of the file is reached before num out.write((char *) &fnum, sizeof fnum);
characters have been read, then read()
simply stops and the buffer contains as
out.close();
many characters as were available, you can for(i=0; i<4; i++) // clear array
find out how many characters have been fnum[i] = 0.0;
read by using another member function ifstream in("numbers", ios::in |
called gcount(). ios::binary);
streamsize gcount(); in.read((char *) &fnum, sizeof fnum);
It returns the no. of characters read by the // see how many bytes have been read
last binary input operation.
cout << in.gcount() << " bytes read\n";
for(i=0; i<4; i++) // show values read from file
cout << fnum[i] << " ";
#include <iostream> in.close();
#include <fstream> return 0;
using namespace std; }
int main()
{
double fnum[4] = {99.75, -34.4,
1776.0, 200.1}; Prepared by Dr. Naveen Choudhary 32
More get() function

istream *get(char *buf, streamsize num);


1
istream *get(char *buf, streamsize num, getline() // can be very useful with textfiles
char delim); 2
istream *get(); 3 istream &getline(char *buf, streamsize num);

1. read characters into array pointed by buf until similar to 1 but the new line character is
num-1 characters have been read or newline is
extracted from the stream but is not put into buf
found or the end of the file has been
encountered. The array pointed to by buf will be (i.e. it is basically removed)
NULL terminated by get(). If the newline
character is encountered in the input stream, it is istream &getline (char *buf, streamsize num, char delim)
not extracted, instead, it remains in the stream
until the next input operation. similar to 2 but the delim char is extracted from the
stream but is not put into buf (i.e. it is basically removed)
2. reads char until num -1 characters have been
read or char specified by delim has been found
or the end of the file has been encountered. buf
will be NULL terminated. If the delim char is
encountered in the input stream, it is not
extracted.

3. get() returns the next char, from the stream. It


returns EOF if the end of the file is encountered..

Prepared by Dr. Naveen Choudhary 33


#include <iostream> it returns true when the end of the file has
#include <fstream> been reaches; otherwise it returns false
using namespace std;
int main(int argc, char *argv[]) The following programs uses eof() to display the
{ content of a file in both hexadecimal & ASCII
if(argc!=2) { #include <iostream> (skip)
cout << "Usage: Display <filename>\n"; #include <fstream>
return 1; #include <cctype>
} #include <iomanip>
ifstream in(argv[1]); // input using namespace std;
if(!in) { int main(int argc, char *argv[])
cout << "Cannot open input file.\n"; {
return 1; if(argc!=2) {
} cout << "Usage: Display <filename>\n";
char str[255]; return 1;
while(in) { }
in.getline(str, 255); // delim defaults to '\n'ifstream in(argv[1], ios::in | ios::binary);
if(in) cout << str << endl; if(!in) {
} cout << "Cannot open input file.\n";
in.close(); return 1;
return 0; }
} register int i, j;
int count = 0;
Detecting EOF char c[16];
You can detect when the end of the file is cout.setf(ios::uppercase);
reached by using the member function while(!in.eof()) {
eof(). Which has this prototype. for(i=0; i<16 && !in.eof(); i++) {
bool eof(); Prepared by Dr. Naveenin.get(c[i]);
Choudhary 34
}
if(i<16) i--; // get rid of eof (EOF by default). If the delimiting characters is encountered ,
for(j=0; j<i; j++) it is not removed from the input stream. Here int_type is some
cout << setw(3) << hex << (int) c[j]; form of integer
for(; j<16; j++) cout << " "; The next program reads a file called TEST. It
cout << "\t"; ignores characters until either a space is
for(j=0; j<i; j++) encountered or 10 characters have bee read. It
if(isprint(c[j])) cout << c[j]; then displays the rest of the file.
else cout << ".";
cout << endl;
count++; #include <iostream>
if(count==16) { #include <fstream>
count = 0; using namespace std;
cout << "Press ENTER to continue: "; int main()
cin.get(); {
cout << endl; ifstream in("test");
} if(!in) {
} cout << "Cannot open file.\n";
in.close(); return 1;
return 0; }
} /* Ignore up to 10 characters or until first
space is found. */
ignore () function in.ignore(10, ' ');
char c;
istream & ignore(streamsize num=1, int_type while(in) {
delim = EOF); in.get(c);
it reads & discards characters until either num if(in) cout << c;
characters have been ignored (1 by default) or the
character specified by the delim is encountered
}
Prepared by Dr.in.close();
Naveen Choudhary 35
return 0;}
Random Access
int_type peek();
The C++ I/O system manages two pointers associated
// it returns the next characters in the with a file. one is the get pointer, which specifies
stream without removing the characters
where is the file’s the next input/read operation will
from the stream or EOF if the end of the
occur. The other is the put pointer, which specifies
file is encountered
where in the file, next output operation will occur.
Each time an input or output operation takes place,
istream &putback(char c); the appropriate pointer is automatically sequentially
// returns the last char read from a stream advanced. However, using the seekg() & seekp()
here c is the last char read function allow you to access the file in a non
sequential fashion.
flush()  when output is performed, data is
not necessary immediately written to the iostream &seekg (off_type offset, seekdir origin);
physical device linked to the stream. Instead, ios::beg - beginning of file
information is stored in an internal buffer until ios::cur - current location
the buffer is full. Only then are the content of ios::end - end of file
that buffer is written to disk. However you can
force the information to be physically written to seekp()/ seekg() – moves the associated file’s
disk before the buffer is full by calling flush().
current put/ get pointer offset no. of character
from the specified origin.
ostream &flush();
istream &seekp(off_type offset, seekdir origin)
closing a file or terminating a program also
flushes all buffers.
note:- generally random access should only be
performed on binary files as the character translation
that may occur on text files could cause a position
request to be out of sync with the actual contents of
Prepared by the file. Choudhary
Dr. Naveen 36
ex. next program display the contents of a file
change test 12 z beginning with the location you specify on the
here test is file to be modify command line.(use of seekg()) (skip)
and 12 is the 12th char in the file test should
be changed to z #include <iostream>
#include <fstream>
z is new char which will replace the already
#include <cstdlib>
existing char in file. using namespace std;
listing 19// shows the use of seekp() int main(int argc, char *argv[])
#include <iostream> {
#include <fstream> char ch;
#include <cstdlib> if(argc!=3) {
using namespace std; cout << "Usage: SHOW <filename> <starting
int main(int argc, char *argv[]) location>\n";
{ return 1;
if(argc!=4) { }
cout << "Usage: CHANGE <filename> ifstream in(argv[1], ios::in | ios::binary);
<character> <char>\n"; if(!in) {
return 1; cout << "Cannot open file.";
} return 1;
fstream out(argv[1], ios::in | ios::out | ios::binary); }
if(!out) { in.seekg(atoi(argv[2]), ios::beg);
cout << "Cannot open file."; while(in.get(ch))
return 1; } cout << ch;
out.seekp(atoi(argv[2]), ios::beg); return 0;
out.put(*argv[3]); }
out.close();
return 0;} Prepared by Dr. Naveen Choudhary 37
The following program uses both seekp() & seekg() > reverse test 10 Reverese the first 10
to reverse the first <num> character in a file. (skip) char (of 14 test file)
#include <iostream> concerned file
#include <fstream>
#include <cstdlib>
O/P this is a test
using namespace std; a si sithtest
int main(int argc, char *argv[])
{ Obtaining the current file position
if(argc!=3) {
cout << "Usage: Reverse <filename> <num>\n"; You can determine the current position of each file
return 1; } pointer by using these function.
fstream inout(argv[1], ios::in | ios::out | ios::binary);
if(!inout) { pos-type tellg();
cout << "Cannot open input file.\n"; return 1; } pos-type tellp();
long e, i, j;
char c1, c2; -some sort of int. defined in ios and is capable of
e = atol(argv[2]); holding the largest value that either function can
for(i=0, j=e; i<j; i++, j--) { return.
inout.seekg(i, ios::beg);
inout.get(c1); -You can use the values returnd by tellg() & tellp() as
arguments to the seekg() & seekp().
inout.seekg(j, ios::beg);
inout.get(c2);
inout.seekp(i, ios::beg); - These function allow you to save the current file
inout.put(c2); location, perform other file operation, and then reset
the file location to its previously saved location.
inout.seekp(j, ios::beg);
inout.put(c1); }
inout.close();
return 0;} Prepared by Dr. Naveen Choudhary 38
I/O Status
The C++ I/O system maintains status the program illustrates rdstate(). It displays the contents
information about the out come of each I/O of a text file. If an error occurs, the program reports it,
operation. The current state of the I/O system using checkstatus()
is held in an object of type iostate, which is #include <iostream>
an enumeration defined by ios that include #include <fstream>
the following members: using namespace std;
void checkstatus(ifstream &in);
ios:: goodbit int main(int argc, char *argv[])
{
ios:: eofbit
if(argc!=2) {
ios:: failbit
cout << "Usage: Display <filename>\n";
ios:: badbit
return 1;
ios:: hardfailbit
}
ifstream in(argv[1]);
there are two ways in which you can if(!in) {
obtain I/O status information cout << "Cannot open input file.\n";
return 1;
(1)- rdstate() -> iostate rdstate(); }
returns goodbit when no error has char c;
occurred otherwise, an error flag is while(in.get(c)) {
turned on if(in) cout << c;
checkstatus(in);
}
checkstatus(in); // check final status
in.close();
return 0;
Prepared by Dr. }Naveen Choudhary 39
(2) The other way that you can determine if an
void checkstatus(ifstream &in)
{
error has occurred is by using one or more of
ios::iostate i; these functions .
i = in.rdstate();
if(i & ios::eofbit) bool bad(); // returns true if badbit or hardfail
flag is set
cout << "EOF encountered\n";
else if(i & ios::failbit) bool eof(); // returns true if eofbit flag is set
cout << "Non-Fatal I/O error\n";
else if(i & ios::badbit) bool fail(); // returns true if failbit or badbit or
cout << "Fatal I/O error\n"; hardfail flag is set
}
bool good(); // returns true if no error bit is set
and no flag is set

clear(int = 0)  with no argument, clears all error bits;


otherwise sets specified flags, as in
clear (ios::failbit)  failbit will be set

once an error has occurred, it may need to be cleared


before your program continue. To do this, use the
clear() function, which has this prototype.
void clear(iostate flags = ios::goodbit);

if flags is goodbit (as it is by default), all error flags are


cleared otherwise, set flags as you desire.

Prepared by Dr. Naveen Choudhary 40


(2)
Multifile program once a file reaches EOF while reading then even if you take
the read pointer to the first char of the file using seekg() 
even than you will not be able to read the file as the eof flag
a.h xyz.cpp b.h
whould have been set  to overcome this problem you will
need to clear the flag using ios::clear() member function
(3)
Compiler streambuf class

Each stream object contains a pointer to a streambuf


a.obj xyz.obj b.obj object.This pointer can be accessed through a member
function called rdbuf(). Every stream object has this function.
It returns a pointer to the streambuf object.

One of the most interesting things that we can do with this


pointer is to connect it to another stream object using the <<
Linker operator. This would move all the bytes from the buffer of one
object into that of another. We can use this facility for file
copying

ifstream infile(sourcefile);
xyz.exe ofstream outfile(targetfile);
outfile << infile.rdbuf();
(1) this causes the entire contents of the source file to be
To open a file for read as well as write use File.open
(“EMP.DAT”, ios::binary |ios::in |ios::out); sent to the outfile/targetfile

Prepared by Dr. Naveen Choudhary 41


(4) s <<endl
strstreams class << setw(8) <<”ch = “ << ch << endl
strstreams class is used to treat memory array to << setw(8) << “i = “ << hex << i << endl
be used as stream and allow all the formatting << setw(8) <<”a = “
function as is available with other streams. <<setiosflags(ios::fixed) << a <<endl
If you want to extract character use istrstream
<< setw(8) <<”str = “ <<str
If you want to insert characters into stream use
<< ends;
ostrstream.
// An important thing to remember about
#include <strstream.h> ostrstreams is that zero terminator we normally need
#include <iomanip.h> at the end of a character array is not inserted for us.
int main() We need to specifically insert it using the
manipulator ends.
{
const int MAX = 100; cout << s.rdbuf();
int i = 350;
char ch = ‘Z’ // when we rdbuf the contents of the
float a = 3.14152869; buffer the get pointer inside the
char str[] = “strstreams at work”; streambuf is moved forward as the
char buffer[MAX]; characters are output. For this reason,
ostrstream s(buffer, MAX); if we say cout << s.rdbuf() a second
/* buffer is assumed to be a zero terminated
string, and time , nothing will happen because the
any new characters are added starting at the zero
get pointer is already at the end.
terminator */ }

Prepared by Dr. Naveen Choudhary 42


USING istrstreams // but while extracting the name only first component
of the name is extracted because of whitespace. The
int main() balance (left over) need to be extracted using rdbuf()
{
int age; cout << age << endl
float salary; << salary << endl
char name[50]; << name;
char str[] = “35 12004.50 sammer shekhar count << endl << s.rdbuf();
deshpande”; }
istrstream s (str);
automatic storage allocation (skip)
// the constructor takes zero terminated char array or pointer while using output strstreams (but not
to zero terminated string allocated on the heap
istrstreams) we have an option of allowing
//once the istrstream object is built we can now extract bytes the ostrstream to do its own memory
from it until the ‘\0’ is encountered allocation. For this we need to create
ostrstream object with no constructor
// (skip) there is one more form of istrstream constructor
available, this takes two argument  pointer and size of argument ie  ostrstream s;
array details if needed do from pg. 460 let us c++
In this case array does’t have to be zero terminated and from
such istrstream object you can extract bytes all the way to
buff[size], whether or not you encounter a zero along the
way.
s >> age >> salary >> name;
// extract age salary and name from istrstream s

Prepared by Dr. Naveen Choudhary 43


(5)
predefined filenames for hardware devices

con  console (keyboard and screen)


aux or com1  first serial port
com2  second serial port
prn or lpt1  first parallel port/ printer
lpt2  second parallel port/printer
lpt3  third parallel printer
nul  dummy (non existent ) device

The following program prints the contents of a disk file on the printer.
After printing the entire file contents a ‘\x0c’ is sent to the printer to
eject the paper

Ofstream outfile(“PRN”);
While (infile.get(ch) !=0) // ifstream infile(filename)
Outfile.put(ch)
Outfile.put(‘\x0C’);

Prepared by Dr. Naveen Choudhary 44


Q: Design a vector class
- vector (int,vsize)
- with overloaded multiplication & addition operator
- two vector can be added or multiplied
- different type of costructors
Q: Design a string class
- sining [char *p, int item]
- allocate memory dynamically
- create string from array of char
- copy costructor
- + -> concatinate
- overloaded = operator

Prepared by Dr. Naveen Choudhary 45

You might also like