R20CSE2103 Object Oriented Programming Using C
R20CSE2103 Object Oriented Programming Using C
3. All program code of c can be executed in C++ but converse many not be possible
For solving the problems, the problem is divided into a number of modules. Each
module is a subprogram.
9. Data in procedure oriented language is open and can be accessed by any function.
9. Data access is limited. It can be accessed by providing various visibility modes both
for data and member functions. there by providing data security by data hiding
1. Encapsulation
2. Data abstraction
3. Polymorphism
4. Inheritance
5. Dynamic binding
6. Message passing
Data abstraction :
Abstraction refers to the act of representing essential features without including the
back ground details or explanation. Classes use the concept of abstraction and are
defined as a list of attributes such as size, weight, cost and functions to operate on
these attributes. They encapsulate all essential properties of the object that are to be
created. The attributes are called as data members as they hold data and the functions
which operate on these data are called as member functions.
Class use the concept of data abstraction so they are called abstract data type (ADT)
Polymorphism: Polymorphism comes from the Greek words “poly” and “morphism”.
“poly” means many and “morphism” means form i.e.. many forms. Polymorphism
means the ability to take more than one form. For example, an operation have
different behavior in different instances. The behavior depends upon the type of the
data used in the operation.
1) Function overloading
2) Operator overloading
#include<iostream.h>
int main()
cout<<”a=”<<a<<endl; return 0;
Inheritance:
Inheritance is the process by which one object can acquire the properties of another.
Inheritance is the most promising concept of OOP, which helps realize the goal of
constructing software from reusable parts, rather than hand coding every system from
scratch. Inheritance not only supports reuse across systems, but also directly facilitates
extensibility within a system. Inheritance coupled with polymorphism and dynamic
binding minimizes the amount of existing code to be modified while enhancing a
system.
When the class child, inherits the class parent, the class child is referred to as derived
class (sub class) and the class parent as a base class (super class). In this case, the
class child has two parts: a derived part and an incremental part. The derived part is
inherited from the class parent. The incremental part is the new code written
specifically for the class child.
Dynamic binding:
Message passing:
An object oriented program consists of set of object that communicate with each
other.
A message for an object is a request for execution of a procedure and there fore
invoke the function that is called for an object and generates result
Ø Reusability:
In OOP‟ s programs functions and modules that are written by a user can be reused
by other users without any modification.
Ø Inheritance:
Through this we can eliminate redundant code and extend the use of existing classes.
Ø Data Hiding:
The programmer can hide the data and functions in a class from other classes. It helps
the programmer to
The given problem can be viewed as a collection of different objects. Each object is
responsible for a specific task. The problem is solved by interfacing the objects. This
technique reduces the complexity of the program design.
OOP makes it easy to maintain and modify existing code as new objects
can be created with small differences to existing ones. Software complexity can be
easily managed.
Ø Message Passing:
The technique of message communication between objects makes the interface with
external systems easier.
Ø Modifiability:
public interface that the external world has to a class is through the use of methods.
• C
// average of five number in C
average = sum / 5;
• C++
#include <iostream>
fact = fact * i;
cout << "Factorial of " << num << " is: " << fact << endl;
return 0;
predicates
sumoftwonumber(integer, integer)
clauses
sum(0, 0).
sum(n, r):-
n1=n-1,
sum(n1, r1),
r=r1+n
• Functional programming paradigms –
The functional programming paradigms has its roots in mathematics and it is
language independent. The key principle of this paradigms is the execution
of series of mathematical functions. The central model for the abstraction is
the function which are meant for some specific computation and not the data
structure. Data are loosely coupled to [Link] function hide their
implementation. Function can be replaced with their values without changing
the meaning of the program. Some of the languages like perl, javascript
mostly uses this paradigm.
The program written in C++ language follows this basic structure. The sequence of
sections should be as they are in the basic structure. A C program should have one or
more sections but the sequence of sections is to be followed.
1. Documentation section
2. Linking section
3. Definition section
6. Main function
section main()
} >>
2. LINKING SECTION : This section tells the compiler to link the certain
occurrences of keywords or functions in your program to the header files specified in
this section.
e.g. #include<iostream>
• directive causes the preprocessor to add the contents of the iostream file to the
program. It contains declarations for cout and cin.
• cout is a predefined object that represents the standard output stream. The
operator << is an insertion operator, causes the string in double quotes to be
displayed on the screen.
The statement cin>>n; is an input statement and causes the program to wait for the
user to type in a number. The number keyed is placed on the variable “n”. The
identifier cin is a predefined object in C++ that corresponds to the standard input
stream. The operator >> is known as extraction operator. It extracts the value from the
keyboard and assigns it to the value variable on its right.
Here #define is a compiler directive which tells the compiler whenever MAX is found
in the program replace it with 25.
This has all the sub programs or the functions which our program needs.
void display()
int main()
display() return 0;
6. MAIN FUNCTION SECTION : It tells the compiler where to start the execution
from main()
}
main function has two sections
1. declaration section : In this the variables and their data types are declared.
2. Executable section or instruction section : This has the part of program which
actually performs the task we need.
namespace:
namespace is used to define a scope that could hold global identifiers. ex:-namespace
scope for c++ standard library.
A classes ,functions and templates are declared within the namespace named std using
namespace std;-->directive can be used.
namespace namespace_name
ex: #include<iostream.h>
namespace sample
{`
it m;
void display(int n)
display(200);
#include<iostream.h>
This directive causes the preprocessor to add content of iostream file to the program.
some old versions of C++ used iostream.h .if complier does not support ANSI
(american nation standard institute) C++ then use header file iostream.h
DATA TYPES:
A data type is used to indicate the type of data value stored in a variable. All C
compilers support a variety of data types. This variety of data types allows the
programmer to select the type appropriate to the needs of the application as well as the
machine. ANSI C supports the following classes of data types:
This data type is used to store whole numbers. These numbers do not contain the
decimal part. The size of the integer depends upon the world length of a machine (16-
bit or 32-bit). On a 16-bit machine, the range of integer values is - 32,768 to
+32,[Link] variables are declared by keyword int. C provides control over range
of integer values and storage space occupied by these values through the data types:
short int, int, long int in both signed and unsigned forms.
=100(10)
00000000001100100(2)
-100(10)=1111111110011100(2)
NOTE: Signed bit (MSB BIT): 0 represents positive integer, 1 represents negative
numbers
Unsigned integers: Unsigned integers use all 16 bits to store the magnitude. Stores
numbers does not have any sign & Size qualifier and range of integer data
A single character can be defined as a character data type. Character data type
occupies one byte of memory for storage of character. The qualifiers signed or
unsigned can be applied on char data type. char is the key word used for declaring
variables
size and range of character data type on 16 bit or 32 bit machine can be shown below
Floating point number represents a real number with 6 digits precision occupies 4
bytes of memory. Floating point variables are declared by the keyword float.
Double floating point data type occupies 8 bytes of memory giving 14 digits of
precision. These are also known as double precision numbers. Variables are declared
by keyword double
long double refers to a floating point data type that is often more precise than double
precision.
Boolean or logical data type is a data type, having two values (usually denoted true
and false), intended to represent the truth values of logic and Boolean algebra. It is
named after George Boole, who first defined an algebraic system of logic in the mid
19th century. The Boolean data type is the primary result of conditional statements,
which allow different actions and change control flow depending on whether a
programmer-specified Boolean condition evaluates to true or false.
C99 added a Boolean (true/false) type which is defined in the <stdbool.h> header
Boolean variable is defined by kkey word bool; Ex:
bool b;
Void type
The void type has no values. This is usually used to specify the return type of
functions. The type of the function said to be void when it does not return any value to
the calling function. This is also used for declaring general purpose pointer called void
pointer.
The data types defined by the user are known as the user-defined data types. They are
structure,union,class and enumeration
OR
It is an identifier used to store the value of particular data type in the memory.
Since variable name is identifier we use following rules which are same as of
identifier Boolean data type:-
Ø Identifiers may have any length but only first 31 characters are significant.
Variable declaration: The declaration of variable gives the name for memory location
and its size and specifies the range of value that can be stored in that location.
Syntax:
Data type variable name;
Ex:
int a=10;
float x=2.3;
KEYWORDS :
There are certain words, called keywords (reserved words) that have a predefined
meaning in C++‟ language. These keywords are only to be used for their intended
purpose and not as identifiers.
1. Arithmetic operators
2. Relational operators
3. Logical operators
4. Assignment operators
5. Increment or Decrement operators
6. Conditional operator
8. unary operator
9. Special operators
operator meaning
+ add
- subtract
* multiplication
/ division
% modulo division(remainder)
#include<iostraem.h>
void main()
int a, b;
cin>>a>>b;
cout<<"a+b"<< a+b;
cout<<"a-b"<< a-b;
cout<<"a*b"<< a*b;
cout<<"a/b"<< a/b;
cout<<"a%b"<< a%b;
OUTPUT:
operator meaning
== is equal to
!= is not equal to
#include<iostream.h>
void main()
int a,b;
clrscr();
cout<<"Enter a, b values:";
cin>>a>>b;
cout<<"a>b"<< a>b;
cout<<"a>=b"<< a>=b;
cout<<"a<b"<< a<b;
cout<<"a<=b"<< a<=b;
cout<<"a==b"<< a==b;
cout<<"a!=b"<< a!=b;
} OUTPUT:
Enter a, b values: 5 9
a>b: 0 //false
a<b: 1 //true
a>=a: 1 //true
a<=b: 1 //true
a==b: 0 //false
a!=b: 1 //true
3. LOGICAL OPERATORS:
Logical Data: A piece of data is called logical if it conveys the idea of true or false. In
C++ we use int data type to represent logical data. If the data value is zero, it is
considered as false. If it is non -zero (1 or any integer other than 0) it is considered as
true. C++ has three logical operators for combining logical values and creating new
logical values:
#include<stdbool.h>
int main()
bool a,b;
/*logical and*/
a=0;b=0;
a=0;b=1;
a=1;b=0;
a=1;b=1;
/*logical or*/
a=0;b=0;
a=0;b=1;
a=1;b=0;
a=1;b=1;
cout<<" a||b "<< a||b<<endl;
/*logical not*/
a=0;
a=1;
return 0;
} OUTPUT:
0&&0=0
0&&1=0
1&&0=0
1&&1=1
0||0=0
0||1=1
1||0=1
1||1=1
!0 =1
!1 =0
4. ASSIGNMENT OPERATOR:
The assignment expression evaluates the operand on the right side of the operator (=)
and places its value in the variable on the left.
Note: The left operand in an assignment expression must be a single variable. There
are two forms of assignment:
•Simple assignment
•Compound assignment
Simple assignment :
Here, the left side operand must be a variable but not a constant. The left side variable
must be able to receive a value of the expression. If the left operand cannot receive a
value and we assign one to it, we get a compile error.
Compound Assignment:
Ex:
1. What appears on the left-hand side need not be repeated and therefore it becomes
easier to write.
The operator ++ adds one to its operand where as the operator - - subtracts one from
its operand. These operators are unary operators and take the following form:
Both the increment and decrement operators may either precede or follow the
operand.
The difference between a++ and a+1 is, if ++ is after the operand, the increment takes
place after the expression is evaluated.
int a=5;
int x=4; y=x--; Here the value of y is 4, x value is 3 Prefix Increment/Decrement (++a/
--a)
In prefix increment (decrement) the effect takes place before the expression that
contains the operator is evaluated. It is the reverse of the postfix operation. ++a has
the same effect as a=a+1.
A= ++b;
The effects of both postfix and prefix increment is the same: the variable is
incremented by
1. But they behave differently when they used in expressions as shown above. The
execution of these operators is fast when compared to the equivalent assignment
statement.
#include<iostream.h>
int main()
++a;
cout<<"a="<<a<<endl;
--b;
cout<<"b="<<b<<endl;
cout<<"a="<<a++<<endl;
cout<<"a="<<a<<endl;
cout<<"b="<<b--<<endl;
cout<<"b="<<b<<endl;
return 0;
#include<iostream.h>
void main()
int a, b,c;
cin>>a>>b;
c=a>b?a:b;
operator meaning
^ Bitwise exclusive OR
~ one's complement
The bitwise AND operator is a binary operator it requires two integral operands
(character or integer). It does a bitwise comparison as shown below:
Shift Operators
The shift operators move bits to the right or the left. These are of two types:
It is a binary operator it requires two integral operands. The first operand is the value
to be shifted and the second operand specifies the number of bits to be shifted. When
bits are shifted to right,the bits at the right most end are deleted and a zero is inserted
at the MSB bit.
#include<iostream.h>
void main()
int x,shift;
cout<<”Enter a number:”;
cin>>x;
cin>>shift;
x=x>>shift;
Run1:
Enter a number:8
(type) expression;
Or
type (expression);
Sequential control
statements ensures that the instructions(or
:Statements that are executed when a condition is true. These statements are divided
into three categories. they are
[Link] making statements:- These statements are used to control the flow of
execution of a program by making a decision depending on a condition, hence they
are named as decision making statements.
Syntax:
If(test expression)
List of statements;
{
int a,b;
if(a>b)
if(b>a)
return 0;
2. if –else statement:
If test expression is true block of statements following if are executed and if test
expression is false then statements in else block are executed
if (test expression)
else
statement block1;
statement block2;
#include<iostream.h>
int main()
{
int a,b;
if(a>b) cout<<“A is larger than B\n A=”<<a; else cout<<“B is larger than A\n
A=”<<b;
return 0;
3. Nesting of if-else statements It's also possible to nest one if statement inside
another. When a series of decisions are to be made.
If(test expression)
{If(test expression) {
//statements
else
{ //statements
else
{If(test expression) {
//statements
else
{ //statements
int main()
int a,b,c;
if(a>b)
else
{if(b>c)
if(a>c)
else
getch();
else
return 0;
4. if else ladder
if(condition1)
statement n;
else
default statement.
statement-x;
The nesting of if-else depends upon the conditions with which we have to deal.
The condition is evaluated from top to [Link] a condition is true the statement
associated with it is executed.
When all the conditions become false then final else part containing default statements
will be executed.
#include<iostream.h> void main()
cout<<”Secured
else cout<<”Fail”<<endl
selection. Multiway selection chooses among several alternatives. C has two different
ways to implement multiway selection: the switch statement and else-if construct
If for suppose we have more than one valid choices to choose from then we can use
switch statement in place of if statements.
switch(expression)
{.
block-1 break;
block-2 break;
default:
default block;
cin>>a>>oper>>b;
switch(opr)
case '+':
return 0;
The group of statements enclosed within curly brace is called block or compound
statement. We have two types of looping structures.
One in which condition is tested before entering the statement block called entry
control. The other in which condition is checked at exit called exit controlled loop.
Loop statements can be divided into three categories as given below [Link] loop
statement
1. WHILE STATEMENT :
While(test condition)
It is an entry controlled loop. The condition is evaluated and if it is true then body of
loop is executed. After execution of body the condition is once again evaluated and if
is true body is executed once again. This goes on until test condition becomes false.
int main()
while(i<=n)
sum = sum + i; i = i + 1;
}
2. DO WHILE STATEMENT :
The while loop does not allow body to be executed if test condition is false. The do
while is an exit controlled loop and its body is executed at least once.
do
body
}while(test condition);
int main()
do{
sum = sum + i; i = i + 1;
} while(i<=n);
Note: if test condition is false. before the loop is being executed then While loop
executes zero number of times where as do--while executes one time
3. FOR LOOP : It is also an entry control loop that provides a more concise structure
Syntax:
statements;
For statement is divided into three expressions each is separated by semi colon;
#include<stdio.h>
int main()
for(i=1;i<=n;i++)
sum = sum + i;
}
Nested loops:Writing one loop control statement within another loop control
statement is called nested loop statement
Ex:
for(i=1;i<=n;i++)
{fact=0;
NOT. for(j=1;j<=i;j++)
if(i%j==0) fact++;
if(fact==2)
cout<<i<<”\t”;
getch( );
Output:
Enter the number : 5
235
Statements that transfers control from on part of the program to another part
unconditionally Different unconditional statements are
int main()
i=1; L1:
sum = sum + i;
i++;
int main()
{
i=1; L1:
Continue:It is used to continue the iteration of the loop statement by skipping the
statements after continue statement. It causes the control to go directly to the test
condition and then to continue the loop.
int main()
}
A function is a set of statements that take inputs, do some specific
computation, and produce output. The idea is to put some commonly or
repeatedly done tasks together and make a function so that instead of writing
the same code again and again for different inputs, we can call the function.
In simple terms, a function is a block of code that only runs when it is called.
Syntax:
Return type function_name(parameters)
#include<iostream.h>
int a=5;
void main()
int a=1;
cout<<”Local a=”<<a<<endl;
cout<<”Global a=”<<::a<<endl;
function (formal object). Both actual and formal copies of objects are
stored at different memory
#include<iostream.h>
class sample2;
class sample1
{
int a;
public:
};
void sample1::getdata(int x)
a=x;
class sample2
int b;
public:
};
void sample2::getdata(int x)
{
b=x;
cout<<"a="<<x.a<<endl;
cout<<"b="<<y.b<<endl;
int t;
t=x.a;
x.a=y.b;
y.b=t;
int main()
sample1 obj1;
sample2 obj2;
[Link](5);
[Link](15);
"; display(obj1,obj2);
swap(obj1,obj2);
display(obj1,obj2);
#include<iostream.h>
class sample2;
class sample1
int a;
public:
};
void sample1::getdata(int x)
a=x;
class sample2
int b;
public:
};
void sample2::getdata(int x)
b=x;
cout<<"a="<<x.a<<endl;
cout<<"b="<<y.b<<endl;
int t;
t=x->a;
x->a=y->b;
y->b=t;
int main()
sample1 obj1;
sample2 obj2;
[Link](5);
[Link](15);
display(obj1,obj2);
swap(&obj1,&obj2);
display(obj1,obj2);
Ex:
int x=5;
int &y=x;
#include<iostream.h>
int main()
{
int i=0;
int &j=i;
int s=0;
int n;
cout<<"Enter n:";
cin>>n;
while(j<=n)
s=s+i;
i++;
cout<<"sum="<<s<<endl;
Output:
Enter n:10
sum=55
#include<iostream.h>
class sample2;
class sample1
int a;
public:
};
void sample1::getdata(int x)
a=x;
class sample2
int b;
public:
void sample2::getdata(int x)
b=x;
cout<<"a="<<x.a<<endl;
cout<<"b="<<y.b<<endl;
int t;
t=x.a;
x.a=y.b;
y.b=t;
int main()
{
sample1 obj1;
sample2 obj2;
[Link](5);
[Link](15);
display(obj1,obj2);
swap(obj1,obj2);
display(obj1,obj2);
Output:
Definition:
makes a program run faster because the overhead of a function call and
return is eliminated. It
function.
therefore, the usual error checking does not occur during compilation.
C++ has different solution to this problem. To eliminate the cost of calls
to small functions, C++
General Form:
inline function-header
function body;
Eg:
#include<iostream.h>
return (x*y);
return (p/q);
int main()
float a=12.345;
float b=9.82;
cout<<mul(a,b);
cout<<div(a,b);
return 0;
[Link] function has too many lines of code or if it has complicated logic
then it is executed as
normal function
➢
A function that is returning value , if it contains switch ,loop or both
then it is treated as
normal function.
DEFAULT ARGUMENTS
A default argument is a value provided in a function declaration that is
automatically assigned by the compiler if the calling function doesn’t provide a
value for the argument. In case any value is passed, the default value is
overridden.
1) The following is a simple C++ example to demonstrate the use of default
arguments. Here, we don’t have to write 3 sum functions; only one function
works by using the default values for 3rd and 4th arguments.
• CPP
#include <iostream>
using namespace std;
return (x + y + z + w);
// Driver Code
int main()
// Statement 1
// Statement 2
// Statement 3
cout << sum(10, 15, 25, 30) << endl;
return 0;
Output
25
50
80
Explanation: In statement 1, only two values are passed, hence the variables z
and w take the default values of 0. In statement 2, three values are passed, so
the value of z is overridden with 25. In statement 3, four values are passed, so
the values of z and w are overridden with 25 and 30 respectively.
RECURSIVE FUNCTION
A recursive function is a function that makes calls to itself. It works like the loops we
described before, but sometimes it the situation is better to use recursion than loops.
Every recursive function has two components: a base case and a recursive step.
The base case is usually the smallest input and has an easily verifiable solution. This is
also the mechanism that stops the function from calling itself forever. The recursive step is
the set of all cases where a recursive call, or a function call to itself, is made.
As an example, we show how recursion can be used to define and compute the factorial of
an integer number. The factorial of an integer nn is 1×2×3×...×(n−1)×n1×2×3×...×(n−1)×n.
The recursive definition can be written:
The base case is n=1n=1 which is trivial to compute: f(1)=1f(1)=1. In the recursive
step, nn is multiplied by the result of a recursive call to the factorial of n−1n−1.
TRY IT! Write the factorial function using recursion. Use your function to compute the
factorial of 3.
1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5. int factorial(int);
6. int fact,value;
7. cout<<"Enter any number: ";
8. cin>>value;
9. fact=factorial(value);
10. cout<<"Factorial of a number is: "<<fact<<endl;
11. return 0;
12. }
13. int factorial(int n)
14. {
15. if(n<0)
16. return(-1); /*Wrong value*/
17. if(n==0)
18. return(1); /*Terminating condition*/
19. else
20. {
21. return(n*factorial(n-1));
22. }
23. }
Output:
int main () {
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
*pvalue = 29494.99; // Store value at allocated address
cout << "Value of pvalue : " << *pvalue << endl;
return 0;
}
If we compile and run above code, this would produce the following result −
Value of pvalue : 29495
UNIT -II
Introduction of Class:
An object-oriented programming approach is a collection of objects and each object consists of
corresponding data structures and procedures. The program is reusable and more maintainable.
The important aspect in oop is a class which has similar syntax that of structure.
class: It is a collection of data and member functions that manipulate data. The data components of class are
called data members and functions that manipulate the data are called member functions.
It can also called as blue print or prototype that defines the variables and functions common to
all objects of certain kind. It is also known as user defined data type or ADT(abstract data type) A class
is declared by the keyword class.
Syntax:-
class class_name
{
Access specifier :
Variable declarations;
Access specifier :
function declarations;
};
Access Specifiers:
Access specifier or access modifiers are the labels that specify type of access given to members of a
class. These are used for data hiding. These are also called as visibility modes. There are three types of
access specifiers
[Link]
[Link]
[Link]
1. Private:
If the data members are declared as private access, then they cannot be accessed from other functions
outside the class. It can only be accessed by the functions declared within the class. It is declared by the key
word “private‟.
2. public:
If the data members are declared public access, then they can be accessed from other functions
outside the class. It is declared by the key word “public‟.
3. protected: The access level of protected declaration lies between public and private. This access
specifier is used at the time of inheritance
Note: - If no access specifier is specified then it is treated by default as private. The default access specifier of
structure is public where as that of a class is “private”
Example:
class student
{
private : int roll;
char name[30];
public:
void get_data()
{
cout<<”Enter roll number and name”:
cin>>roll>>name;
}
void put_data()
{
cout<<”Roll number:”<<roll<<endl;
cout<<”Name :”<<name<<endl;
}
};
Ex:student s;
[Link]-name(actual arguments);
Ex:
s.get_data();
s.put_data();
Note:
1. If the access specifier is not specified in the class the default access specifier is private
2. All member functions are to be declared as public if not they are not accessible outside the class.
Example: student s;
in the above example s is the object. It is a real time entity that can be used
Write a program to read data of a student
#include<iostream>
using namespace std;
class student
{
private:
int roll;
char name[20];
public:
void getdata()
{
cout<<”Enter Roll number:”;
cin>>roll;
cout<<”Enter Name:”;
cin>>name;
}
void putdata()
{
cout<<”Roll no:”<<roll<<endl;
cout<<Name:”<<name<<endl;
}
};
int main()
{
student s;
[Link]();
[Link]();
returm 0;
}
Scope Resolution operator:
Scope:-Visibility or availability of a variable in a program is called as scope. There are two
types of scope. i)Local scope ii)Global scope
Local scope: visibility of a variable is local to the function in which it is declared.
Global scope: visibility of a variable to all functions of a program
Scope resolution operator in “::” .
This is used to access global variables if same variables are declared as local and global
#include<iostream.h>
int a=5;
void main()
{
int a=1;
cout<<”Local a=”<<a<<endl;
cout<<”Global a=”<<::a<<endl;
}
Class Scope:
Scope resolution operator(::) is used to define a function outside a class.
#include <iostream>
using namespace std;
class sample
{
public:
void output(); //function declaration
};
// function definition outside the
class void sample::output()
{
cout << "Function defined outside the class.\n";
};
int main()
{
sample obj;
[Link]();
return 0;
}
Output of program:
Function defined outside the class.
void rectangle::get_data()
{
cout<<”Enter Length of rectangle”;
cin>>L;
cout<<”Enter breadth of rectangle”;
cin>>B;
}
int rectangle::area()
{
return L*B;
}
int main()
{
rectangle r;
r.get_data();
cout<<”Area of rectangle is”<<[Link]();
return 0;
}
FRIEND FUNCTIONS: The private members cannot be accessed from outside the class. i.e., a nonmember
function cannot have an access to the private data of a class. In C++ a nonmember function can access
private by making the function friendly to a class.
Definition: A friend function is a function which is declared within a class and is defined outside the class. It
does not require any scope resolution operator for defining. It can access private members of a class. It is
declared by using keyword “friend”
Ex:
class sample
{
int x,y;
public:
sample(int a,int b);
friend int sum(sample s);
};
sample::sample(int a,int b)
{
x=a;y=b;
}
int sum(samples s)
{
int sum;
sum=s.x+s.y;
return 0;
}
void main()
{
Sample obj(2,3);
int res=sum(obj);
cout<< “sum=”<<res<<endl;
}
void main()
{
sample1 obj1(3);
sample2 obj2(5);
max(obj1,obj2);
}
#include<iostream>
using namespace std;
class complex
{
float real,img;
public:
complex();
complex(float x,float y)
friend complex add_complex(complex c1,complex c2);
};
complex::complex()
{
real=img=0;
}
complex::complex(float x,float y)
{
real=x;img=y;
}
complex add_complex(complex c1,complex c2)
{
complex t;
[Link]=[Link]+[Link];
[Link]=[Link]+[Link];
return t;
}
void complex::display ()
{
if(img<0)
{img=-img;
cout<<real<<"-i"<<img<<endl
}
else
{
cout<<real<<"+i"<<img<<endl
}
}
int main()
{
complex obj1(2,3);
complex obj2(-4,-6);
complex obj3=add_compex(obj1,obj2);
[Link]();
return 0;
}
Friend Class: A class can also be declared to be the friend of some other class. When we create a friend class
then all the member functions of the friend class also become the friend of the other class. This requires the
condition that the friend becoming class must be first declared or defined (forward declaration).
Example:
#include <iostream.h>
class sample_1
{
public:
friend class sample_2;//declaring friend class int a,b;
void getdata_1()
{
cout<<"Enter A & B values in class sample_1";
cin>>a>>b;
void display_1()
{
cout<<"A="<<a<<endl;
cout<<"B="<<b<<endl;
}
};
class sample_2
{
public:
void getdata_2()
{
obj1.getdata_1();
cout<<"Enter C & D values in class sample_2";
cin>>c>>d;
}
void sum_2()
{
sum=obj1.a+obj1.b+c+d;
}
void display_2()
{
cout<<"A="<<obj1.a<<endl;
cout<<"B="<<obj1.b<<endl;
cout<<"C="<<c<<endl;
cout<<"D="<<d<<endl;
cout<<"SUM="<<sum<<endl;
}
};
int main()
{
sample_1 s1;
s1.getdata_1();
s1.display_1();
sample_2 s2;
s2.getdata_2();
s2.sum_2();
s2.display_2();
}
STATIC CLASS MEMBERS
#include<iostream.h>
class test
{
int code;
static int count;
public:
void setcode()
{
code=++count;
}
void showcode()
{
cout<<”object number”<<code;
}
static void showcount()
{
cout<<”count”<<count;
}
};
int test::count;
int main()
{
test t1,t2;
[Link]();
[Link]();
test::showcount();
test t3;
[Link]();
test::showcount();
[Link]();
[Link]();
[Link]();
return 0;
}
Output:
count 2
count 3
object number 1
object number 2
object number 3
Arrays of Objects: Arrays of variables of type "class" is known as "Array of objects". An array of objects is
stored inside the memory in the same way as in an ordinary array.
Syntax:
class class_name
{
private:
data_type members;
public:
data_type members;
member functions;
};
Array of objects:
Class_name object_name[size];
Where size is the size of array
Ex:
Myclass obj[10];
Write a program to initialize array of objects and print them
#include<iostream>
using namespace std;
class MyClass
{
int a;
public:
void set(int x)
{
a=x;
}
int get()
{
return a;
}
};
int main()
{
MyClass obj[5];
for(int i=0;i<5;i++)
obj[i].set(i);
for(int i=0;i<5;i++)
cout<<"obj["<<i<<"].get():"<<obj[i].get()<<endl;
}
Output:
obj[0].get():0
obj[1].get():1
obj[2].get():2
obj[3].get():3
obj[4].get():4
a. Pass-by-value – A copy of object (actual object) is sent to function and assigned to the object of called
function (formal object). Both actual and formal copies of objects are stored at different memory
locations. Hence, changes made in formal object are not reflected to actual object. write a program to
swap values of two objects
write a program to swap values of two objects
#include<iostream.h>
using namespace std;
class sample2;
class sample1
{
int a;
public:
void getdata(int x);
friend void display(sample1 x,sample2 y);
friend void swap(sample1 x,sample2 y);
};
void sample1::getdata(int x)
{
a=x;
}
class sample2
{
int b;
public:
void getdata(int x);
friend void display(sample1 x,sample2 y);
};
void sample1::getdata(int x)
{
a=x;
}
class sample2
{
int b;
public:
void getdata(int x);
friend void display(sample1 x,sample2 y);
friend void swap(sample1 *x,sample2 *y);
};
void sample2::getdata(int x)
{
b=x;
}
void display(sample1 x,sample2 y)
{
cout<<"Data in object 1 is"<<endl;
cout<<"a="<<x.a<<endl;
cout<<"Data in object 2 is"<<endl;
cout<<"b="<<y.b<<endl;
}
void swap(sample1 *x,sample2 *y)
{
int t;
t=x->a;
x->a=y->b;
y->b=t;
}
int main()
{
sample1 obj1;
sample2 obj2;
[Link](5);
[Link](15);
cout<<"Before Swap of data between Two objects\n ";
display(obj1,obj2);
swap(&obj1,&obj2);
cout<<"after Swap of data between Two objects\n ";
display(obj1,obj2);
}
Before Swap of data between Two objects
Data in object 1 is a=5
Data in object 2 is b=15
after Swap of data between Two objects
Data in object 1 is a=15
Data in object 2 is b=5
Ex:
int x=5;
int &y=x;
class integer
{
int m,n;
public:
integer( );
………..
………..
};
integer :: integer( )
{
m=0;
n=0;
}
int main()
{ integer obj1;
………..
………..
}
integer obj1; => not only creates object obj1 but also initializes its data members m and n to zero.
There is no need to write any statement to invoke the constructor function.
CHARACTERISTICS OF CONSTRUCTOR
They should be declared in the public section.
They are invoked automatically when the objects are created.
They do not have return type, not even void.
They cannot be inherited, though a derived class can call the base class constructor.
Like other c++ functions, they can have default arguments.
Constructors cannot be virtual.
We cannot refer to their addresses.
They make „implicit calls‟ to the operators new and delete when memory allocation is required.
Constructors are of 3 types:
1. Default Constructor
2. Parameterized Constructor
3. Copy Constructor
1. Default Constructor: A constructor that accepts no parameters is called the default constructor.
#include<iostream.h>
#include<conio.h>
class item
{
int m,n;
public:
item()
{
m=10;
n=20;
}
void put();
};
void item::put()
{
cout<<m<<n;
}
void main()
{
item t;
[Link]();
getch();
}
1. Parameterized Constructors:-The constructors that take parameters are called
parameterized constructors.
#include<iostream.h>
class item
{
int m,n;
public:
item(int x, int y)
{
m=x;
n=y;
}
};
When a constructor has been parameterized, the object declaration statement such as
item t; may not work. We must pass the initial values as arguments to the constructor function
when an object is declared. This can be done in 2 ways: item t=item(10,20); //explicit call
Multiple Constructors in a Class: Multiple constructors can be declared in a class. There can be any
number of constructors in a class.
class complex
{
float real,img;
public:
complex()//default constructor
{
real=img=0;
}
complex(float r)//single parameter parameterized constructor
{
real=img=r;
}
complex(float r,float i) //two parameter parameterized constructor
{
real=r;img=i;
}
complex(complex&c)//copy constructor
{
real=[Link];
img=[Link];
}
complex sum(complex c )
{
complex t;
[Link]=real+[Link];
[Link]=img+[Link];
return t;
}
void show()
{
If(img>0)
cout<<real<<"+i"<<img<<endl;
else
{
img=-img;
cout<<real<<"-i"<<img<<endl;
}
}
};
void main()
{
complex c1(1,2);
complex c2(2,2);
compex c3;
c3=[Link](c3);
[Link]();
DESTRUCTORS:A destructor, is used to destroy the objects that have been created by a constructor.
Like a constructor, the destructor is a member function whose name is the same as the class name
but is preceded by a tilde.
Eg: ~item() { }
1. A destructor never takes any argument nor does it return any value.
2. It will be invoked implicitly by the compiler upon exit from the program to clean up storage that is
no longer accessible.
3. It is a good practice to declare destructors in a program since it releases memory space for future use.
#include<iostream>
using namespace std;
class Marks
{
public:
int maths;
int science;
//constructor
Marks() {
cout << "Inside Constructor"<<endl;
cout << "C++ Object created"<<endl;
}
//Destructor
~Marks() {
cout << "Inside Destructor"<<endl;
cout << "C++ Object destructed"<<endl;
}
};
int main( )
{
M
ar
k
s
m
1;
M
ar
k
s
m
2;
re
tu
r
n
0;
}
Output:
Inside
Construct
or C++
Object
created
Inside
Construct
or C++
Object
created
Inside
Destructor
C++ Object
destructed
Inside
Destructor
C++ Object destructed
DEPARTMENT OF COMPUTER
SCIENCE AND ENGINEERING
You can clearly see that above process results in duplication of same code 3 times. This
increases the chances of error and data redundancy. To avoid this type of situation,
inheritance is used. If we create a class Vehicle and write these three functions in it and
inherit the rest of the classes from the vehicle class, then we can simply avoid the
duplication of data and increase re-usability. Look at the below diagram in which the three
classes are inherited from vehicle class.
Using inheritance, we have to write the functions only one time instead of three times as we
have inherited rest of the three classes from base class(Vehicle).
Implementing inheritance in C++: For creating a sub-class which is inherited from the
base class. We have to follow the below syntax.
Syntax:
Class sub class_name :access_mode base_class_name
{
//bodyofsubclass
};
Here, subclass_name is the name of the sub class, access_mode is the mode in which
youwant to inherit this sub class for example: public, private etc. and base_class_name is
the name of the base class from which you want to inherit the sub class.
Note:A derived class doesn’t inherit access to private data members .However ,It does inherit
a full parent object ,which contains any private members which that class declares.
//C++program to demonstrate implementation
//of Inheritance
#include
<iostream>using
namespace std;
//Base class
class Parent
{
Public
:int
id_p;
};
//main function
int main()
{
Child obj1;
[Link] mode: If we derive a sub class from a Protected base class. Then both
public member and protected members of the base class will become protected in derived
class.
[Link] mode: If we derive a sub class from a Private base class. Then both public
member and protected members of the base class will become Private in derived class.
Note: The private members in the base class cannot be directly accessed in the derived
class, while protected members can be directly accessed. For example, Classes B ,C and D all
contain the variables x, y and z in below example .It is just question of access.
class C:protected A
{
//x is protected
//y is protected
//z is not accessible from C
};
Salary:60000
Bonus:5000
[Link] Inheritance: In this type of inheritance, a derived class is created from another
derived class. As shown in below diagram, class A has class B and class C as parent classes.
Depending on the relation the level of inheritance can be extended to any level.
//C++programtoimplementMultilevel Inheritance
#include <iostream>
using namespace std;
class base //single base class
{
public:
int x;
void getdata()
{
cout<< "Enter value of x= "; cin>> x;
}
};
class derive1 : public base // derived class from base class
{
public:
int y;
void readdata()
{
cout<< "\nEnter value of y= "; cin>> y;
}
};
class derive2 : public derive1 // derived from class derive1
{
private:
int z;
public:
void indata()
{
cout<< "\nEnter value of z= "; cin>> z;
}
void product()
{
cout<< "\nProduct= " << x * y * z;
}
};
int main()
{
derive2 a; //object of derived class
[Link] data();
[Link] data();
[Link] data();
[Link]();
return 0;
} //end of program
Output
Enter value of x= 2
Enter value of y= 3
Enter value of z= 3
Product= 18
[Link] Inheritance: In this type of inheritance, more than one sub class is inherited
from a single base class. i.e., more than one derived class is created from a single base class.
1. #include <iostream>
2. using namespace std;
3. class Shape // Declaration of base class.
4. {
5. public:
6. int a;
7. int b;
8. void get_data(int n,int m)
9. {
10. a= n;
11. b = m;
12. }
13. };
14. class Rectangle : public Shape // inheriting Shape class
15. {
16. public:
17. int rect_area()
18. {
19. int result = a*b;
20. return result;
21. }
22. };
23. class Triangle : public Shape // inheriting Shape class
24. {
25. public:
26. int triangle_area()
27. {
28. float result = 0.5*a*b;
29. return result;
30. }
31. };
32. int main()
33. {
34. Rectangle r;
35. Triangle t;
36. int length,breadth,base,height;
37. std::cout << "Enter the length and breadth of a rectangle: " << std::endl;
38. cin>>length>>breadth;
39. r.get_data(length,breadth);
40. int m = r.rect_area();
41. std::cout << "Area of the rectangle is : " <<m<< std::endl;
42. std::cout << "Enter the base and height of the triangle: " << std::endl;
43. cin>>base>>height;
44. t.get_data(base,height);
45. float n = t.triangle_area();
46. std::cout <<"Area of the triangle is : " << n<<std::endl;
47. return 0;
48. }
Output:
1. #include <iostream>
2. using namespace std;
3. class A
4. {
5. protected:
6. int a;
7. public:
8. void get_a()
9. {
10. std::cout << "Enter the value of 'a' : " << std::endl;
11. cin>>a;
12. }
13. };
14.
15. class B : public A
16. {
17. protected:
18. int b;
19. public:
20. void get_b()
21. {
22. std::cout << "Enter the value of 'b' : " << std::endl;
23. cin>>b;
24. }
25. };
26. class C
27. {
28. protected:
29. int c;
30. public:
31. void get_c()
32. {
33. std::cout << "Enter the value of c is : " << std::endl;
34. cin>>c;
35. }
36. };
37.
38. class D : public B, public C
39. {
40. protected:
41. int d;
42. public:
43. void mul()
44. {
45. get_a();
46. get_b();
47. get_c();
48. std::cout << "Multiplication of a,b,c is : " <<a*b*c<< std::endl;
49. }
50. };
51. int main()
52. {
53. D d;
54. [Link]();
55. return 0;
56. }
Output:
Enter the value of 'a' :
10
Enter the value of 'b' :
20
Enter the value of c is :
30
Multiplication of a,b,c is : 6000
#include<iostream.h>
#include<conio.h>cla
ssClassA
{
public:
inta;
};
classClassB: publicClassA
{
public:
int b;
};
classClassC: publicClassA
{
public:
intc;
};
voidmain()
{
ClassD obj;
obj.b = 20;
obj.c =30;
obj.d = 40;
cout<< "\n B :
"<<obj.b;cout<< "\n C :
"<<obj.c;cout<<"\nD:"<
<obj.d;
}
Output:
A from ClassB: 10A
from ClassC: 100B :
20
C : 30
D: 40
In the above example, both Class B & Class C inherit Class A, they both have single copy
of Class A. However Class D inherit both Class B & Class C, therefore Class D have two
copies of Class A, one from Class B and another from Class C.
If we need to access the data member a of Class A through the object of Class D, we must
specify the path from which a will be accessed, whether it is from Class B or Class C,
bco’z compiler can’t differentiate between two copies of Class A in Class D.
class ClassA
{
public:
inta;
};
void main()
{
classD obj;
obj.b = 20;
obj.c =30;
obj.d = 40;
}
Output:
A: 100
B: 20
C: 30
D: 40
According to the above example, ClassD has only one copy of ClassA, t herefore, statement4
will overwrite the value of a, given at statement3.
Whenever we create an object of a class, the default constructor of that class is invoked
automatically to initialize the members of the class.
If we inherit a class from another class and create an object of the derived class, it is clear that
the default constructor of the derived class will be invoked but before that the default
constructor of all of the base classes will be invoke, i.e. the order of invocation is that the base
class’s default constructor will be invoked first and then the derived class’s default
constructor will be invoked.
The data members and member functions of base class comes automatically in derived
class based on the access specifier but the definition of these members exists in base class
only. So when we create an object of derived class, all of the members of derived class must
be initialized but the inherited members in derived class can only be initialized by the base
class’s constructor as the definition of these members exists in base class only. This is why
the constructor of base class is called first to initialize all the inherited members.
#include <iostream>
using namespace estd;
// base class
classParent{
public:
// base class constructor
Parent(){
cout<< "Inside base class"<<endl;
}};
// sub class
classChild : publicParent{
public:
//sub class constructor
Child(){
cout<< "Inside sub class"<<endl;
}};
// main function
intmain() {
// creating object of sub class
Child obj;
return0;
}
Output:
Inside base class
Inside sub class
Order of constructor call for Multiple Inheritance
For multiple inheritance order of constructor call is, the base class’s constructors are called in
the order of inheritance and then the derived class’s constructor .
// main function
intmain() {
Output:
Inside first base class
Inside second base class
Inside child class
How to call the parameterized constructor of base class in derived class constructor?
To call the parameterized constructor of base class when derived class’s parameterized
constructor is called, you have to explicitly specify the base class’s parameterized constructor
in derived class as shown in below program :
#include <iostream>
usingnamespacestd;
// base class
classParent {
intx;
public:
// base class's parameterised constructor
Parent(inti)
{
x = i;
cout<< "Inside base class's parameterised "
"constructor"
<<endl;
}
};
// sub class
classChild : publicParent {
public:
// sub class's parameterised constructor
Child(intx):Parent(x)
{
// main function
intmain()
{
Output:
Inside base class's parameterised constructor
Inside sub class's parameterised constructor
Important Points:
Whenever the derived class’s default constructor is called, the base class’s default
constructor is called automatically.
To call the parameterized constructor of base class inside the parameterized constructor of
sub class, we have to mention it explicitly.
The parameterized constructor of base class cannot be called in default constructor of sub
class, it should be called in the parameterized constructor of sub class.
Code Example
#include<iostream>
Using namespace std;
class Base
{
public:
Base ()
{
std::cout<< "Base class Constructor\n";
}
~Base ()
{
std::cout<< "Base class Destructor\n";
}
};
Output:
Base class Constructor
Derived classConstructor
Derived class Destructor
Base class Destructor
When two or more objects are derived from a common base class, we can prevent multiple
copies of the base class being present in an object derived from those objects by declaring the
base class as virtual when it is being inherited. Such a base class is known as virtual base
class. This can be achieved by preceding the base class’s name with the word virtual.
Virtual base classes are used in virtual inheritance in a way of preventing multiple
“instances” of a given class appearing in an inheritance hierarchy when using multiple
inheritances.
class A
{public:
voidshow()
{
cout<<"Hello form A \n";
}
};
classB : public A {
};
classC : public A {
};
int main()
{
D
object;object.s
how();
}
CompileErrors:
[Link]: Infunction'intmain()':
[Link]:9:error:requestformember'show'isambiguousobje
[Link]();
^
[Link]:8: note: candidates are: void
A::show()voidshow()
^
[Link]:8:note: voidA::show()
{
};
Syntax2:
class C : public virtual A
{
};
Note:virtual canbe written before or after the [Link] only one copy of data/function
member will be copied to class C and class B and class A becomes the virtual base
[Link] base classes offer a way to save space and avoid ambiguities in class
hierarchies thatuse multiple inheritances. When a base class is specified as a virtual base, it
can act as anindirect base more than once without duplication of its data members. A single
copy of itsdatamembers is shared by all thebaseclasses thatusevirtual base.
Example1
#include <iostream>
using namespace std;
class A
{public:
int a;
A()//constructor
{
a=10;
}
};
classB : publicvirtual A {
};
classC : publicvirtual A {
};
int main()
{
D object; // object creation of class
dcout<<"a ="<<object.a<<endl;
return0;
}
Output:
a=10
Explanation :The class A has just one data member a which is public. This class
isvirtually inherited in class B and class C. Now class B and class C becomes virtual
baseclassand no duplicationof data member a is done.
Example2:
#include<iostream>
Using namespace std;
class A
{public:
voidshow()
{
cout<<"Hello from A \n";
}
};
classB : publicvirtual A {
};
classC : publicvirtual A {
};
int main()
{
D
object;object.s
how();
}
Output:
HellofromA
VIRTUAL FUNCTIONS and POLYMORPHISM
Polymorphism
The term "Polymorphism" is the combination of "poly" + "morphs" which means many forms.
It is a greek word.. In simple words, we can define polymorphism as the ability of a message
to be displayed in more than one form. A real-life example of polymorphism, a person at the
same time can have different characteristics. Like a man at the same time is a father, a
husband, an employee. So the same person posses different behavior in different situations.
This is called polymorphism. Polymorphism is considered as one of the important features of
Object Oriented Programming.
o Compile time polymorphism: The overloaded functions are invoked by matching the
type and number of arguments. This information is available at the compile time and,
therefore, compiler selects the appropriate function at the compile time. It is achieved by
function overloading and operator overloading which is also known as static binding or
early binding. Now, let's consider the case where function name and prototype is same.
In the above case, the prototype of display() function is the same in both the base and derived
class. Therefore, the static binding cannot be applied. It would be great if the appropriate
function is selected at the run time. This is known as run time polymorphism.
o Run time polymorphism: Run time polymorphism is achieved when the object's
method is invoked at the run time instead of compile time. It is achieved by method
overriding which is also known as dynamic binding or late binding.
1. #include <iostream>
2. using namespace std;
3. class Animal {
4. public:
5. void eat(){
6. cout<<"Eating...";
7. }
8. };
9. class Dog: public Animal
10. {
11. public:
12. void eat()
13. { cout<<"Eating bread...";
14. }
15. };
16. int main(void) {
17. Dog d = Dog();
18. [Link]();
19. return 0;
20. }
Output:
Eating bread...
C++ Run time Polymorphism Example: By using two derived class
Let's see another example of run time polymorphism in C++ where we are having two derived
classes.
1. #include <iostream>
2. using namespace std;
3. class Shape { // base class
4. public:
5. virtual void draw(){ // virtual function
6. cout<<"drawing..."<<endl;
7. }
8. };
9. class Rectangle: public Shape // inheriting Shape class.
10. {
11. public:
12. void draw()
13. {
14. cout<<"drawing rectangle..."<<endl;
15. }
16. };
17. class Circle: public Shape // inheriting Shape class.
18.
19. {
20. public:
21. void draw()
22. {
23. cout<<"drawing circle..."<<endl;
24. }
25. };
26. int main(void) {
27. Shape *s; // base class pointer.
28. Shape sh; // base class object.
29. Rectangle rec;
30. Circle cir;
31. s=&sh;
32. s->draw();
33. s=&rec;
34. s->draw();
35. s=?
36. s->draw();
37. }
Output:
drawing...
drawing rectangle...
drawing circle...
The advantage of Function overloading is that it increases the readability of the program
because you don't need to use different names for the same action.
Let's see the simple example of function overloading where we are changing number of
arguments of add() method.
1. #include <iostream>
2. using namespace std;
3. class Cal {
4. public:
5. static int add(int a,int b){
6. return a + b;
7. }
8. static int add(int a, int b, int c)
9. {
10. return a + b + c;
11. }
12. };
13. int main(void) {
14. Cal C; // class object declaration.
15. cout<<[Link](10, 20)<<endl;
16. cout<<[Link](12, 20, 23);
17. return 0;
18. }
Output:
30
55
Let's see the simple example when the type of the arguments vary.
1. #include<iostream>
2. using namespace std;
3. int mul(int,int);
4. float mul(float,int);
5.
6.
7. int mul(int a,int b)
8. {
9. return a*b;
10. }
11. float mul(double x, int y)
12. {
13. return x*y;
14. }
15. int main()
16. {
17. int r1 = mul(6,7);
18. float r2 = mul(0.2,3);
19. std::cout << "r1 is : " <<r1<< std::endl;
20. std::cout <<"r2 is : " <<r2<< std::endl;
21. return 0;
22. }
Output:
r1 is : 42
r2 is : 0.6
C++ Operators Overloading
Operator overloading is a compile-time polymorphism in which the operator is overloaded to
provide the special meaning to the user-defined data type. Operator overloading is used to
overload or redefines most of the operators available in C++. It is used to perform the operation
on the user-defined data type. For example, C++ provides the ability to add the variables of the
user-defined data type that is applied to the built-in data types.
The advantage of Operators overloading is to perform different operations on the same operand.
Where the return type is the type of value returned by the function.
operator op is an operator function where op is the operator being overloaded, and the operator
is the keyword.
o When unary operators are overloaded through a member function take no explicit arguments,
but, if they are overloaded by a friend function, takes one argument.
o When binary operators are overloaded through a member function takes one explicit argument,
and if they are overloaded through a friend function takes two explicit arguments.
C++ Operators Overloading Example
Let's see the simple example of operator overloading in C++. In this example, void operator ++
() operator function is defined (inside Test class).
1. #include <iostream>
2. using namespace std;
3. class Test
4. {
5. private:
6. int num;
7. public:
8. Test(): num(8){}
9. void operator ++() {
10. num = num+2;
11. }
12. void Print() {
13. cout<<"The Count is: "<<num;
14. }
15. };
16. int main()
17. {
18. Test tt;
19. ++tt; // calling of a function "void operator ++()"
20. [Link]();
21. return 0;
22. }
Output:
1. #include <iostream>
2. using namespace std;
3. class A
4. {
5.
6. int x;
7. public:
8. A(){}
9. A(int i)
10. {
11. x=i;
12. }
13. void operator +(A);
14. void display();
15. };
16.
17. void A :: operator+(A a)
18. {
19.
20. int m = x+a.x;
21. cout<<"The result of the addition of two objects is : "<<m;
22.
23. }
24. int main()
25. {
26. A a1(5);
27. A a2(4);
28. a1+a2;
29. return 0;
30. }
Output:
Let's see a simple example of Function overriding in C++. In this example, we are
overriding the eat() function.
1. #include <iostream>
2. using namespace std;
3. class Animal {
4. public:
5. void eat(){
6. cout<<"Eating...";
7. }
8. };
9. class Dog: public Animal
10. {
11. public:
12. void eat()
13. {
14. cout<<"Eating bread...";
15. }
16. };
17. int main(void) {
18. Dog d = Dog();
19. [Link]();
20. return 0;
21. }
Output:
Eating bread...
C++ virtual function
o A C++ virtual function is a member function in the base class that you redefine in a derived
class. It is declared using the virtual keyword.
o It is used to tell the compiler to perform dynamic linkage or late binding on the function.
o There is a necessity to use the single pointer to refer to all the objects of the different classes. So,
we create the pointer to the base class that refers to all the derived objects. But, when base class
pointer contains the address of the derived class object, always executes the base class function.
This issue can only be resolved by using the 'virtual' function.
Output:
Value of x is : 5
In the above example, *a is the base class pointer. The pointer can only access the base class
members but not the members of the derived class. Although C++ permits the base pointer to
point to any object derived from the base class, it cannot directly access the members of the
derived class. Therefore, there is a need for virtual function which allows the base pointer to
access the members of the derived class.
Let's see the simple example of C++ virtual function used to invoked the derived class in a
program.
1. #include <iostream>
2. {
3. public:
4. virtual void display()
5. {
6. cout << "Base class is invoked"<<endl;
7. }
8. };
9. class B:public A
10. {
11. public:
12. void display()
13. {
14. cout << "Derived Class is invoked"<<endl;
15. }
16. };
17. int main()
18. {
19. A* a; //pointer of base class
20. B b; //object of derived class
21. a = &b;
22. a->display(); //Late Binding occurs
23. }
Output:
A virtual function is a member function of a class, whose functionality can be over-ridden in its
derived classes. It is one that is declared as virtual in the base class using the virtual keyword.
The virtual nature is inherited in the subsequent derived classes and the virtual keyword need
not be re-stated there. The whole function body can be replaced with a new set of
implementations in the derived class.
Binding:
Binding refers to the act of associating an object or a class with its member. If we can call a
method fn() on an object o of a class c, we say that the object o is binded with the method fn().
This happens at compile time and is known as static or compile – time binding. The calls to the
virtual member functions are resolved during run-time. This mechanism is known as dynamic
binding. The most prominent reason why a virtual function will be used is to have a different
functionality in the derived class. The difference between a non-virtual member function and a
virtual member function is, the non-virtual member functions are resolved at compile time.
a v – table is constructed for the class. The v-table consists of addresses to the virtual
functions for classes that contain one or more virtual functions.
The object of the class containing the virtual function contains a virtual pointer that
points to the base address of the virtual table in memory.
Whenever there is a virtual function call, the v-table is used to resolve to the function
address. An object of the class that contains one or more virtual functions contains a
virtual pointer called the vptr at the very beginning of the object in the memory.
Hence the size of the object in this case increases by the size of the pointer.
This vptr contains the base address of the virtual table in memory.
The virtual tables are class specific, i.e., there is only one virtual table for a class
irrespective of the number of virtual functions it contains.
This virtual table in turn contains the base addresses of one or more virtual functions of
the class.
At the time when a virtual function is called on an object, the vptr of that object provides
the base address of the virtual table for that class in memory.
This table is used to resolve the function call as it contains the addresses of all the virtual
functions of that class. This is how dynamic binding is resolved during a virtual function
call.
The following code shows how we can write a virtual function in C++ and then use the same to
achieve dynamic or runtime polymorphism.
#include <iostream.h>
class base
{
public:
virtual void display()
{
cout<<”\nBase”;
}
};
class derived : public base
{
public:
void display()
{
cout<<”\nDerived”;
}
};
void main()
{
In the above example, the pointer is of type base but it points to the derived class object. The
method display() is virtual in nature. Hence in order to resolve the virtual method call, the
context of the pointer is considered, i.e., the display method of the derived class is called and
not that of the base. If the method was non virtual in nature, the display() method of the base
class would have been called.
A constructor cannot be virtual because at the time when the constructor is invoked the virtual
table would not be available in the memory. Hence we cannot have a virtual constructor.
Conclusion:
Virtual methods should be used judiciously as they are slow due to the overhead involved in
searching the virtual table. They also increase the size of an object of a class by the size of a
pointer.
Example:
1. #include <iostream>
2. using namespace std;
3. // Abstract class
4. class Shape
5. {
6. public:
7. virtual float calculateArea() = 0; // pure virtual function.
8. };
9. class Square : public Shape
10. {
11. float a;
12. public:
13. Square(float l)
14. {
15. a = l;
16. }
17. float calculateArea()
18. {
19. return a*a;
20. }
21. };
22. class Circle : public Shape
23. {
24. float r;
25. public:
26.
27. Circle(float x)
28. {
29. r = x;
30. }
31. float calculateArea()
32. {
33. return 3.14*r*r ;
34. }
35. };
36.
37. };
38. int main()
39. {
40.
41. Shape *shape;
42. Square s(3.4);
43. Circle c(7.8);
44. shape =&s;
45. int a1 =shape->calculateArea();
46. shape = &c;
47. int a3 = shape->calculateArea();
48. cout << "Area of the square is " <<a1<<endl;
49. cout << "Area of the circle is " <<a3<<endl;
50. return 0;
51. }
Classes having virtual functions are Base class containing pure virtual function
not abstract. becomes abstract.
Syntax:
virtual<func_type><func_name>()
Syntax:
{
// code virtual<func_type><func_name>()
} = 0;
Base class having virtual function can Base class having pure virtual function becomes
be instantiated i.e. its object can be abstract i.e. it cannot be instantiated.
Virtual function Pure virtual function
made.
Abstract Class
Abstract Class is a class which contains atleast one Pure Virtual function in it. Abstract classes
are used to provide an Interface for its sub classes. Classes inheriting an Abstract Class must
provide definition to the pure virtual function, otherwise they will also become abstract class.
1. Abstract class object cannot be created, but pointers and refrences of Abstract class type
can be created.
2. Abstract class can have normal functions and variables along with a pure virtual
function.
3. Abstract classes are mainly used for Upcasting, so that its derived classes can use its
interface.
4. Classes inheriting an Abstract Class must implement all pure virtual functions, or else
they will become Abstract too.
int main()
{
Base obj; //Compile Time Error
Base *b;
Derived d;
b = &d;
b->show();
}
Output:
Virtual Destructor
Deleting a derived class object using a pointer of base class type that has a non-virtual
destructor results in undefined behavior. To correct this situation, the base class should be
defined with a virtual destructor. For example, following program results in undefined
behavior.
int main()
{
derived *d = new derived();
base *b = d;
delete b;
getchar();
return 0;
}
Although the output of following program may be different on different compilers, when
compiled using Dev-CPP, it prints following:
Constructing base
Constructing derived
Destructing base
Making base class destructor virtual guarantees that the object of derived class is destructed
properly, i.e., both base class and derived class destructors are called. For example,
class base {
public:
base()
{
cout << "Constructing base\n";
}
virtual ~base()
{
cout << "Destructing base\n";
}
};
Output:
Constructing base
Constructing derived
Destructing derived
Destructing base
UNIT - IV
C++ I/O
C++ supports two complete I/O systems.
Inherits from C.
Object-oriented I/O system defined by C++
NOTE: C++ programs can also use the C++-style header #include<cstdio>
.
I/O using C functions
It includes,
Console I/O
Streams
Files
Console I/O
This can be divided into Unformatted and Formatted Console I/O.
Unformatted Console I/O
a. Reading and Writing Characters
The simplest of the console I/O functions are getchar( ) and putchar().
getchar( ) : It reads a character from the keyboard. It waits until a key is pressed and then returns its
value. The key pressed is also automatically echoed to the screen.
Prototype: int getchar(void);
putchar( ): It prints or writes a character to the screen at the current cursor position.
Prototype: int putchar(int c);
Program:
#include <iostream>
#include<cstdio>
using namespace std;
int main()
{
char ch;
cout<<"\n Enter a character in lower case: ";
ch = getchar();
cout<<"\nThe entered character is ";
putchar(ch);
cout<<"\nCharacter in UPPER CASE: ";
putchar(ch - 32);
return 0;
}
Output:
Enter a character in lower case: t
The entered character is t
Character in UPPER CASE: T
b. Alternatives to getchar( )
getchar( ) is not useful in an interactive environment. Two of the most common alternative
functions, getch( ) and getche( )
1
getch( ) : It waits for a keypress, after which it returns immediately. It does not echo the character to
the screen.
Prototype: int getch(void);
Problem with gets( ) : It performs no boundary checks on the array that is receiving input. Thus, it is
possible for the user to enter more characters than the array can hold. One alternative is the fgets( )
function.
Program:
include <iostream>
#include<cstdio>
using namespace std;
int main()
{
char str[100];
cout << "Enter a string: ";
gets(str);
cout << "You entered: " << str;
puts(str1);
/* Printed on new line since '/n' is added */
puts(str2);
return 0;
}
Output:
[Link]:5: warning: ‘char* gets(char*)’ is deprecated [-Wdeprecated-declarations]
/usr/include/stdio.h:638:14: note: declared here
[Link]:13: warning: ‘char* gets(char*)’ is deprecated [-Wdeprecated-declarations]
/usr/include/stdio.h:638:14: note: declared here
[Link]:(.text+0x31): warning: the `gets' function is dangerous and should not be used.
Enter a string: rt
You entered: rtHappy New Year
Happy Birthday
2
Formatted Console I/O
The functions printf( ) and scanf( ) perform formatted output and input. Both functions can
operate on any of the built-in data types, including characters, strings, and numbers.
3
The control_string determines how values are read into the variables pointed to in the
argument list. The control string consists of three classifications of characters:
Format specifiers
White-space characters
Non-white-space characters
Format specifiers
The input format specifiers are preceded by a % sign and tell scanf( ) what type of data is to
be read next.
White-space characters
A white-space character in the control string causes scanf( ) to skip over one or more leading
white-space characters in the input stream. A white-space character is a space, a tab, vertical tab, form
feed, or a newline.
Non-white-space characters
A non-white-space character in the control string causes scanf( ) to read and discard matching
characters in the input stream. For example, "%d,%d" causes scanf( ) to read an integer, read and
discard a comma, and then read another integer
Program:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int f;
printf(" ff");
scanf("%d",f);
printf(f);
return 0;
}
4
Output: ff f
Streams
The C file system is designed to work with a wide variety of devices, including terminals,
disk drives, and tape drives. The file system transforms each into a logical device called a stream.
There are two types of streams: text and binary.
Text Streams
A text stream is a sequence of characters. Standard C allows (but does not require) a text
stream to be organized into lines terminated by a newline character.
Certain character translations may occur as required by the host environment. For example, a
newline may be converted to a carriage return/linefeed pair. Therefore, there may not be a one-to-one
relationship between the characters that are written (or read) and those on the external device. Also,
because of possible translations, the number of characters written (or read) may not be the same as
those on the external device.
Binary Streams
A binary stream is a sequence of bytes that have a one-to-one correspondence to those in the
external device that is, no character translations occur. Also, the number of bytes written (or read) is
the same as the number on the external device.
Program
#include <cstdio>
#include <cstdlib>
int main()
{
FILE* fp = fopen("[Link]","w");
fprintf(fp,"%s","This is written to [Link]");
if (freopen("[Link]","w",fp))
fprintf(fp,"%s","This is written to [Link]");
else
{
printf("freopen failed");
exit(1);
}
fclose(fp);
return 0;
}
5
Output:
Files
In C/C++, a file may be anything from a disk file to a terminal or printer. Each stream that is
associated with a file has a file control structure of type FILE.
File Operations
fopen( ) : It opens a stream for use and links a file with that stream. Then it returns the file pointer
associated with that file.
Prototype: FILE *fopen(const char *filename, const char *mode);
where filename is a pointer to a string of characters that make up a valid filename and may
include a path specification.
The legal values for mode are,
Program:
#include <cstdio>
#include <cstring>
6
#include<iostream>
using namespace std;
int main()
{
int c;
FILE *fp;
fp = fopen("[Link]", "w+r");
char str[20] = "Hello World!";
if (fp)
{
for(int i=0; i<strlen(str); i++)
putc(str[i],fp);
}
fclose(fp);
}
Output:
Hello World!
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
char str[] = "Testing putc() function";
FILE *fp;
fp = fopen("[Link]","w");
if (fp)
{
for(int i=0; i<strlen(str); i++)
{
putc(str[i],fp);
}
7
fclose(fp);
return 0;
}
Output:
Testing putc() functionTesting putc() function
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
int c;
FILE *fp;
fp = fopen("[Link]","r");
if (fp)
{
while(feof(fp) == 0)
{
c = getc(fp);
putchar(c);
}
while(feof(fp) == 0)
{
c = fgetc(fp);
putchar(c);
}
}
else
perror("File opening failed");
fclose(fp);
return 0;
}
Output:
Testing putc() functionTesting putc() function
feof( ): It determines when the end of the file has been encountered.
Prototype: int feof(FILE *fp);
feof( ) returns true if the end of the file has been reached; otherwise, it returns 0.
8
fputs( ) and fgets( )
These functions work just like putc( ) and getc( ), but instead of reading or writing a single
character, they read or write strings.
Prototypes:
int fputs(const char *str, FILE *fp);
char *fgets(char *str, int length, FILE *fp);
The fputs( ) function writes the string pointed to by str to the specified stream. It returns EOF
if an error occurs.
The fgets( ) function reads a string from the specified stream until either a newline character
is read or length −1 characters have been read.
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
int count = 10;
char str[10];
FILE *fp;
fp = fopen("[Link]","w+");
fputs("An example file\n", fp);
fputs("Filename is [Link]\n", fp);
rewind(fp);
while(feof(fp) == 0)
{
fgets(str,count,fp);
cout << str << endl;
}
fclose(fp);
return 0;
}
Output:
An exampl
e file
Filename
is file.t
xt
xt
rewind( )
The rewind( ) function resets the file position indicator to the beginning of the file specified as its
argument. That is, it "rewinds" the file.
Prototype: void rewind(FILE *fp);
9
where fp is a valid file pointer.
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
int c;
FILE *fp;
fp = fopen("[Link]", "r+w");
if (fp)
{
while ((c = getc(fp)) != EOF)
putchar(c);
rewind(fp);
putchar('\n');
Output:
welcome
welcome
ferror( )
The ferror( ) function determines whether a file operation has produced an error.
Prototype: int ferror(FILE *fp);
where fp is a valid file pointer. It returns true if an error has occurred during the last file
operation; otherwise, it returns false.
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
int ch;
FILE* fp;
fp = fopen("[Link]","w");
if(fp)
{
ch = getc(fp);
if (ferror(fp))
cout << "Can't read from file";
}
10
fclose (fp);
return 0;
}
Output:
Can't read from file
remove( )
The remove( ) function erases the specified file.
Prototype: int remove(const char *filename);
It returns zero if successful; otherwise, it returns a nonzero value.
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
char filename[] = "[Link]";
return 0;
}
Output:
File deleted successfully
fflush( )
If you wish to flush the contents of an output stream, use the fflush( ) function.
Prototype: int fflush(FILE *fp);
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
int x;
char buffer[1024];
setvbuf(stdout, buffer, _IOFBF, 1024);
printf("Enter an integer - ");
fflush(stdout);
scanf("%d",&x);
printf("You entered %d", x);
return(0);
}
11
Output:
Enter an integer - 89
You entered 89
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
int retVal;
FILE *fp;
char buffer[] = "Writing to a file using fwrite.";
fp = fopen("[Link]","wb");
retVal = fwrite(buffer,sizeof(buffer),1,fp);
cout << "fwrite returned " << retVal;
return 0;
}
Output:
fwrite returned 1
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
FILE *fp;
char buffer[100];
fp = fopen("[Link]","rb");
while(!feof(fp))
{
12
fread(buffer,sizeof(buffer),1,fp);
cout << buffer;
}
return 0;
}
Output:
Writing to a file using fwrite.
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
int main()
{
FILE *fp;
double d = 12.23;
int i = 101;
long l = 123023L;
if((fp=fopen("test", "wb+"))==NULL)
{
printf("Cannot open file.\n");
exit(1);
}
fwrite(&d, sizeof(double), 1, fp);
fwrite(&i, sizeof(int), 1, fp);
fwrite(&l, sizeof(long), 1, fp);
rewind(fp);
fread(&d, sizeof(double), 1, fp);
fread(&i, sizeof(int), 1, fp);
fread(&l, sizeof(long), 1, fp);
printf("%f %d %ld", d, i, l);
fclose(fp);
return 0;
}
Output:
12.230000 101 123023
fseek( )
You can perform random-access read and write operations using the C I/O system with the help of
fseek( ), which sets the file position indicator.
Prototype : int fseek(FILE *fp, long int numbytes, int origin);
Here, fp is a file pointer returned by a call to fopen( ). numbytes is the number of bytes from
origin that will become the new current position, and origin is one of the following macros:
Origin Macro Name
Beginning of file SEEK_SET
Current position SEEK_CUR
End of file SEEK_END
Program:
#include <cstdio>
13
#include <cstring>
#include<iostream>
using namespace std;
Output:
After this code is successfully executed, the file [Link] contains:
This is a sample.
Program:
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
fp = fopen("[Link]","w");
fprintf(fp, "%s %d", "Tim", 9);
fclose(fp);
fp = fopen("[Link]","r");
fscanf(fp, "%s %d", name, &age);
fclose(fp);
printf("Hello %s, You are %d years old\n", name, age);
return 0;
}
Output:
Hello Tim, You are 9 years old
14
Object-oriented I/O system defined by C++
C++ Streams
The C++ I/O system operates through streams. A stream is a logical device that either
produces or consumes information.
A stream is linked to a physical device by the I/O system. All streams behave the same, the
same I/O functions can operate
15
istream_withassign, ostream_withassign and iostream_withassign add assignment operators
to these classes.
Class hierarchies for 8-bit characters and wide characters.
Standard C++ also defines these four additional streams: win, wout, werr, and wlog. These
are wide-character versions of the standard streams. Wide characters are of type wchar_t and are
generally 16-bit quantities. Wide characters are used to hold the large character sets associated with
some human languages.
Operator Overloading
Overloading << and >>
<< and the >> operators are overloaded in C++ to perform I/O. the << output operator is
referred to as the insertion operator because it inserts characters into a stream. Likewise, the >> input
operator is called the extraction operator because it extracts characters from a stream. The functions
that overload the insertion and extraction operators are generally called inserters and extractors,
respectively.
16
{
// body of inserter
return stream;
}
The function returns a reference to a stream of type ostream. The first parameter to the
function is a reference to the output stream. The second parameter is the object being inserted.
Within an inserter function, you may put any type of procedures or operations that you want.
inserters cannot be members of the class for which they are defined seems to be a serious problem
because they cannot access the private elements of a class. Solution is to Make the inserter a friend of
the class
An inserter need not be limited to handling only text. An inserter can be used to output data in
any form like CAD plotters, graphics images, dialog boxes etc.
Program:
#include <iostream>
#include <cstring>
using namespace std;
class Box
{
double height;
double width;
double vol ;
public :
friend istream & operator >> (istream &, Box &);
friend ostream & operator << (ostream &, Box &);
};
17
stream << "Box Width : " << [Link] << endl ;
return(stream) ;
}
int main()
{
Box b1;
cin >> b1;
cout << b1;
}
Output:
Enter Box Height: 1
Enter Box Width : 2
Box Height : 1
Box Width : 2
The Volume of Box : 2
Types of manipulators
There are two basic types of manipulators:
Those that operate on input streams
Those that operate on output streams.
Using an output manipulator is particularly useful for sending special codes to a device. For
example, a printer may be able to accept various codes that change the type size or font, or that
18
position the print head in a special location. If these adjustments are going to be made frequently, they
are perfect candidates for a manipulator.
General Form
istream &manip-name(istream &stream)
{
// your code here
return stream;
}
An input manipulator receives a reference to the stream for which it was invoked. This stream
must be returned by the manipulator.
Program:
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
using namespace std;
// A simple output manipulator that sets the fill character to * and sets the field width to 10.
ostream &star_fill(ostream &stream)
{
stream << setfill('*') << setw(10);
return stream;
}
if(![Link]()) [Link]();
return stream;
}
int main()
{
string str;
// Demonstrate the custom output manipulator.
cout << 512 << endl;
cout << star_fill << 512 << endl;
// Demonstrate the custom input manipulator.
cout << "Enter some characters: ";
cin >> skip_digits >> str;
cout << "Contents of str: " << str;
return 0;
}
Output:
512
*******512
Enter some characters: abc
19
Contents of str: abc
General Form:
typedef basic_istringstream<char>istringstream;
typedef basic_ostringstream<char>ostringstream;
Stream input can be used to validate input data,stream output can be used to format the output.
Ostringstream constructors
explicit ostringstream(ios::openmode mode=ios::out);//default with empty string
explicit ostringstream(const string &str, ios::openmode
mode=ios::out);//with initial str
string str() const;//get contents
void str(const string &s)//set contents
Example:
ostringstream sout;
//write into string buffer
sout<<”apple”<<endl;
sout<<”orange”<<endl;
//get contents
cout<<[Link]()<<endl;
ostringstream is responsible for dynamic memory allocation and management.
istringstream constructors
explicit istringstream(ios::openmode mode=ios::in); //default with empty string
explicit istringstream(const string &str, ios::openmode mode=ios::in); //with initial str
Example:
istringstream sin(“123 12.34 hello”);
//read from buffer
int I;
double d;
string s;
sin>>i>>d>>s;
cout<<i<<”,”<<d<<”,”<<s<<endl;
stringstream constructors
explicit stringstream(ios::openmode mode = ios::in | ios::out);
explicit stringstream(const string &str,
ios::openmode mode = ios::in | ios::out);
Program:
// Demonstrate string streams.
#include <iostream>
#include <sstream>
using namespace std;
20
int main()
{
stringstream s("This is initial string.");
// get string
string str = [Link]();
cout << str << endl;
// output to string stream
s << "Numbers: " << 10 << " " << 123.2;
int i;
double d;
s >> str >> i >> d;
cout << str << " " << i << " " << d;
return 0;
}
Output:
File streams
Formatted file streams
To perform file I/O, you must include the header <fstream> in your program. It defines
several classes, including ifstream, ofstream, and fstream. These classes are derived from istream,
ostream, and iostream, respectively. Remember, istream, ostream, and iostream are derived from
ios, so ifstream, ofstream, and fstream also have access to all operations defined by ios
Prototype:
void ifstream::open(const char *filename, ios::openmode mode = ios::in);
void ofstream::open(const char *filename, ios::openmode mode = ios::out | ios::trunc);
void fstream::open(const char *filename, ios::openmode mode = ios::in | ios::out);
21
filename is the name of the file; it can include a path specifier. The value of mode determines how
the file is opened. It must be one or more of the following values
ios::app : Including ios::app causes all output to that file to be appended to the end. This
value can be used only with files capable of output.
ios::ate : Including ios::ate causes a seek
to the end of the file to occur when the file is opened.
ios::in : The ios::in value specifies that the file is capable of input.
ios::out : The ios::out value specifies that the file is capable of output.
ios::binary : The ios::binary value causes a file to be opened in binary mode. By default, all files
are opened in text mode.
ios::trunc : The ios::trunc value causes the contents of a preexisting file by the same name to be
destroyed, and the file is truncated to zero length.
Example:
if(!mystream.is_open()) {
cout << "File is not open.\n";
// ...
close()
To close a file, use the member function close( )
Prototype: [Link]();
The close( ) function takes no parameters and returns no value.
Program:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream in("INVNTRY"); // input
if(!in)
{
cout << "Cannot open INVENTORY file.\n";
return 1;
22
}
char item[20];
float cost;
in >> item >> cost;
cout << item << " " << cost << "\n";
in >> item >> cost;
cout << item << " " << cost << "\n";
in >> item >> cost;
cout << item << " " << cost << "\n";
[Link]();
ofstream out;
[Link]("INVNTRY");// output, normal file
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;
[Link]();
return 0;
}
Output:
Radios 39.95
Toasters 19.95
Mixers 24.8
get( )
get( ) will read a character
General form: istream &get(char &ch);
reads a single character and puts that value in ch. It returns a reference to the stream
Overloading of get()
The get( ) function is overloaded in several different ways.
Prototypes:
istream &get(char *buf, streamsize num);
reads characters into the array pointed to by buf until either num-1
int get( );
returns the next character from the stream
put( )
put( ) will write a character.
23
General form: ostream &put(char ch);
writes ch to the stream and returns a reference to the stream.
getline( )
It also performs input. It is a member of each input stream class.
Prototypes:
istream &getline(char *buf, streamsize num);
reads characters into the array pointed to by buf until either num-1
Detecting EOF
You can detect when the end of the file is reached by using the member function eof( )
Prototype: bool eof( );
It returns true when the end of the file has been reached; otherwise it returns false.
ignore( ) Function
You can use the ignore( ) member function to read and discard characters from the input stream.
Prototype:
istream &ignore(streamsize num=1, int_type delim=EOF);
It reads and discards characters until either num characters have been ignored (1 by default) or
the character specified by delim is encountered (EOF by default).
peek( )
You can obtain the next character in the input stream without removing it from that stream by
using peek( ).
Prototype: int_type peek( );
It returns the next character in the stream or EOF if the end of the file is encountered.
putback( )
You can return the last character read from a stream to that stream by using putback( ).
Prototype : istream &putback(char c);
where c is the last character read.
flush( )
We can force the information to be physically written to disk before the buffer is full by calling
flush( ).
Prototype: ostream &flush( );
Random Access
You perform random access by using the seekg( ) and seekp( ).
seekg( )
The seekg( ) function moves the associated file's current get pointer offset number
24
of characters from the specified origin, which must be one of these three values:
ios::beg Beginning-of-file
ios::cur Current location
ios::end End-of-file
seekp( )
The seekp( ) function moves the associated file's current put pointer offset number of
characters from the specified origin
Prototype: ostream &seekp(off_type offset, seekdir origin);
There are two ways in which you can obtain I/O status information.
Call the rdstate( ) function.
Prototype: iostate rdstate( );
It returns the current status of the error flags.
We can determine if an error has occurred is by using one or more of these functions:
bool bad( ); The bad( ) function returns true if badbit is set.
bool eof( ); returns true when end of the file has reached
bool fail( ); The fail( ) returns true if failbit is set.
25
bool good( ); The good( ) function returns true if there are no errors. Otherwise, it returns
false.
Clearing an Error
Once an error has occurred, it may need to be cleared before your program continues.
To do this, use the clear( ) function.
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.
Formatted I/O.
The C++ I/O system allows you to format I/O operations. There are two related but
conceptually different ways that you can format data.
1. Directly access members of the ios class.(flags and functions in ios class)
2. Special functions called manipulators
26
Common form: fmtflags setf(fmtflags flags);
This function returns the previous settings of the format flags and turns on those flags
specified by flags.
Example: [Link](ios::showpos);
stream is the stream you wish to affect.
NOTE: The format flags are defined within the ios class, you must access their values by
using ios and the scope resolution operator.
Program:
#include <iostream>
using namespace std;
int main ()
{
[Link] (ios::uppercase | ios::scientific);
cout << 100.12; // displays 1.001200E+02
[Link] (ios::uppercase); // clear uppercase
cout << " \n" << 100.12 << endl; // displays 1.001200e+02
//OVERLOADED FORM OF setf
[Link] (ios::showpoint | ios::showpos, ios::showpoint);
cout << 100.0<<endl; // displays 100.000, not +100.000
//TWO PARAMETER FORM of setf
[Link](ios::hex, ios::basefield);
cout << 100; // this displays 64
return 0;
}
Output:
1.001200E+02
1.001200e+02
1.000000e+02
64
27
Example: [Link](f);
Program:
#include <iostream>
using namespace std;
void showflags();
int main()
{
// show default condition of format flags
showflags();
// showpos, showbase, oct, right are on, others off
ios::fmtflags f = ios::showpos | ios::showbase | ios::oct | ios::right;
[Link](f); // set all flags
showflags();
return 0;
}
// This function displays the status of the format flags.
void showflags()
{
ios::fmtflags f;
long i;
f = [Link](); // get flag settings
// check each flag
for(i=0x4000; i; i = i >> 1)
if(i & f) cout << "1 ";
else cout << "0 ";
cout << " \n";
}
Output:
001000000000010
000101011000000
b. Functions
There are three member functions defined by ios.
width( )
By default, when a value is output, it occupies only as much space as the number of
characters it takes to display it. However, you can specify a minimum field width by using the width()
function.
Prototype; streamsize width(streamsize w);
Here, w becomes the field width, and the previous field width is returned. In some
implementations, the field width must be set before each output. If it isn't, the default field width is
used. The streamsize type is defined as some form of integer by the compiler.
After you set a minimum field width, when a value uses less than the specified width, the
field will be padded with the current fill character (space, by default) to reach the field width. If the
size of the value exceeds the minimum field width, the field will be overrun. No values are truncated.
precision( )
When outputting floating-point values, you can determine the number of digits of precision by
using the precision( ) function.
Prototype: streamsize precision(streamsize p);
28
The precision is set to p, and the old value is returned. The default precision is 6. In some
implementations, the precision must be set before each floating-point output. If it is not, then the
default precision will be used.
fill( )
By default, when a field needs to be filled, it is filled with spaces. You can specify the fill
character by using the fill( ) function.
Prototype: char fill(char ch);
After a call to fill( ), ch becomes the new fill character, and the old one is returned.
Program:
#include <iostream>
using namespace std;
int main ()
{
[Link] (4);
[Link] (10);
cout << 10.12345 << "\n"; // displays 10.12
[Link] ('*');
[Link] (10);
cout << 10.12345 << "\n"; // displays *****10.12
// field width applies to strings, too
[Link] (10);
cout << "Hi!" << "\n"; // displays *******Hi!
[Link] (10);
[Link] (ios::left); // left justify
cout << 10.12345; // displays 10.12*****
return 0;
}
Output:
10.12
*****10.12
*******Hi!
10.12*****
29
30
To access manipulators that take parameters (such as setw( )), you must include <iomanip>
in your program.
Program:
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
cout << hex << 100 << endl;
cout << setfill ('?') << setw (10) << 2343.0;
return 0;
}
Output:
64
??????2343
31
Advantage
The main advantage of using manipulators instead of
the ios member functions is that they often allow more compact code to be written.
You can use the setiosflags( ) manipulator to directly set the various format flags
related to a stream.
Program:
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
cout << setiosflags (ios::showpos);
cout << setiosflags (ios::showbase);
cout << 123 << " " << hex << 123;
return 0;
}
+123 0x7b
32
UNIT-V
EXCEPTION HANDILING
INDRODUCTION
Common types of Errors
The common types of errors are logic errors and syntactic errors.
Logic Errors: These occur due to poor understanding of the problem and solution procedure.
Examples: Assigning a value to the wrong variable, multiplying 2 numbers instead of adding
them etc.
Syntactic Errors: These occur due to poor understanding of the language itself.
Examples: Spelling mistakes, missing out quotes or brackets or semicolon etc.
Exception Handling
It is a C++ built in language feature that allows us 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.
1
General form of try and catch
try {
// try block
}
catch (type1 arg)
{
// catch block
}
catch (type2 arg)
{
// catch block
}
catch (type3 arg)
{
// catch block
}
...
Program:
// A simple exception handling example.
#include <iostream>
using namespace std;
int main ()
{
cout << "Start\n";
try
{ // start a try block
cout << "Inside try block\n";
throw 100; // throw an error
cout << "This will not execute";
}
catch (int i)
{ // catch an error
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}
cout << "End";
return 0;
2
}
Output:
Start
Inside try block
Caught an exception -- value is: 100
End
Abnormal Termination
The type of the exception must match the type specified in a catch statement. Usually, the
code within a catch statement attempts to remedy an error by taking appropriate action. If the
error can be fixed, execution will continue with the statements following the catch. However,
often an error cannot be fixed i.e. throw an exception for which there is no applicable catch
statement, an abnormal program termination may occur. Throwing an unhandled exception
causes the standard library function terminate ( ) to be invoked. By default, terminate ( ) calls
abort( ) to stop your program.
Program:
// This example will not work.
#include <iostream>
using namespace std;
int main ()
{
cout << "Start\n";
try
{ // start a try block
cout << "Inside try block\n";
throw 100; // throw an error
cout << "This will not execute";
}
catch (double i)
{ // won't work for an int exception
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}
cout << "End";
return 0;
}
Output:
Start
Inside try block
terminate called after throwing an instance of 'int'
Aborted (core dumped)
3
Throwing an exception from outside the try block
An exception can be thrown from outside the try block as long as it is thrown by a
function that is called from within try block.
Program:
/* Throwing an exception from a function outside the try block. */
#include <iostream>
using namespace std;
void
Xtest (int test)
{
cout << "Inside Xtest, test is: " << test << "\n";
if (test)
throw test;
}
int main ()
{
cout << "Start\n";
try
{ // start a try block
cout << "Inside try block\n";
Xtest (0);
Xtest (1);
Xtest (2);
}
catch (int i)
{ // catch an error
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}
cout << "End";
return 0;
}
Output:
Start
Inside try block
Inside Xtest, test is: 0
Inside Xtest, test is: 1
Caught an exception -- value is: 1
End
4
Program:
#include <iostream>
using namespace std;
// Localize a try/catch to a function.
void
Xhandler (int test)
{
try
{
if (test)
throw test;
}
catch (int i)
{
cout << "Caught Exception #: " << i << '\n';
}
}
int main ()
{
cout << "Start\n";
Xhandler (1);
Xhandler (2);
Xhandler (0);
Xhandler (3);
cout << "End";
return 0;
}
Output:
Start
Caught Exception #: 1
Caught Exception #: 2
Caught Exception #: 3
End
Program:
#include <iostream>
using namespace std;
int main ()
{
5
cout << "Start\n";
try
{ // start a try block
cout << "Inside try block\n";
cout << "Still inside try block\n";
}
catch (int i)
{ // catch an error
cout << "Caught an exception -- value is: ";
cout << i << "\n";
}
cout << "End";
return 0;
}
Output:
Start
Inside try block
Still inside try block
End
Program:
#include <iostream>
using namespace std;
// Different types of exceptions can be caught.
void
Xhandler (int test)
{
try
{
if (test)
throw test;
else
throw "Value is zero";
}
catch (int i)
{
cout << "Caught Exception #: " << i << '\n';
}
catch (const char *str)
{
6
cout << "Caught a string: ";
cout << str << '\n';
}
}
int main ()
{
cout << "Start\n";
Xhandler (1);
Xhandler (2);
Xhandler (0);
Xhandler (3);
cout << "End";
return 0;
}
Output:
Start
Caught Exception #: 1
Caught Exception #: 2
Caught a string: Value is zero
Caught Exception #: 3
End
General form:
catch(...)
{
// process all exceptions
}
Here, the ellipsis matches any type of data.
Program:
// This example catches all exceptions.
#include <iostream>
using namespace std;
void
Xhandler (int test)
{
try
{
if (test == 0)
7
throw test; // throw int
if (test == 1)
throw 'a'; // throw char
if (test == 2)
throw 123.23; // throw double
}
catch ( ...)
{ // catch all exceptions
cout << "Caught One!\n";
}
}
int main ()
{
cout << "Start\n";
Xhandler (0);
Xhandler (1);
Xhandler (2);
cout << "End";
return 0;
}
Output:
Start
Caught One!
Caught One!
Caught One!
End
One very good use for catch (...) is as the last catch of a cluster of catches which catch all
exceptions that you don't want to handle explicitly. Also, by catching all exceptions, you prevent
an unhandled exception from causing an abnormal program termination.
RETHROWING AN EXCEPTION
If you wish to rethrow an expression from within an exception handler, you may do so by
calling throw, by itself, with no exception.
Reason: It allows multiple handlers access to the exception. For example, perhaps one
exception handler manages one aspect of an exception and a second handler copes with another.
An exception can only be rethrown from within a catch block (or from any function called from
within that block). When you rethrow an exception, it will not be recaught by the same catch
statement. It will propagate outward to the next catch statement.
Program:
// Example of "rethrowing" an exception.
#include <iostream>
using namespace std;
8
void Xhandler ()
{
try
{
throw "hello"; // throw a char *
}
catch (const char *)
{ // catch a char *
cout << "Caught char * inside Xhandler\n";
throw; // rethrow char * out of function
}
}
int main ()
{
cout << "Start\n";
try
{
Xhandler ();
}
catch (const char *)
{
cout << "Caught char * inside main\n";
}
cout << "End";
return 0;
}
Output:
Start
Caught char * inside Xhandler
Caught char * inside main
End
General form
ret-type func-name(arg-list) throw(type-list)
{
// ...
}
only those data types contained in the comma-separated type-list may be thrown by the
function. If you don't want a function to be able to throw any exceptions, then use an empty list.
9
Attempting to throw an exception that is not supported by a function will cause the standard
library function unexpected ( ) to be called. By default, this causes abort( ) to be called, which
causes abnormal program termination.
Program:
// Restricting function throw types.
#include <iostream>
using namespace std;
// This function can only throw ints, chars, and doubles.
void Xhandler (int test)
throw (int, char, double)
{
if (test == 0)
throw test; // throw int
if (test == 1)
throw 'a'; // throw char
if (test == 2)
throw 123.23; // throw double
}
int main ()
{
cout << "start\n";
try
{
Xhandler (0); // also, try passing 1 and 2 to Xhandler()
}
catch (int i)
{
cout << "Caught an integer\n";
}
catch (char c)
{
cout << "Caught char\n";
}
catch (double d)
{
cout << "Caught double\n";
}
cout << "end";
return 0;
}
Output:
start
Caught an integer
10
end
A function can be restricted only in what types of exceptions it throws back to the try
block that called it. That is, a try block within a function may throw any type of exception so
long as it is caught within that [Link] restriction applies only when throwing an exception
outside of the function.
STACK UNWINDING
Stack unwinding is a process of calling all destructors for all automatic objects
constructed at run time when an exception is thrown. The objects are destroyed in the reverse
order of their formation.
When an exception is thrown, the runtime mechanism first searches for an appropriate
matching handler (catch) in the current scope. If no such handler exists, control is transferred
from the current scope to a higher block in the calling chain or in outward manner. - Iteratively,
it continues until an appropriate handler has been found. At this point, the stack has been
unwound and all the local objects that were constructed on the path from a try block to a throw
expression have been destroyed. - The run-time environment invokes destructors for all
automatic objects constructed after execution entered the try block. This process of destroying
automatic variables on the way to an exception handler is called stack unwinding.
Program:
#include <iostream>
#include <string>
class MyClass
{
private:
string name;
public:
MyClass (string s):name (s)
{
}
~MyClass ()
11
{
cout << "Destroying " << name << endl;
}
};
void fa ();
void fb ();
void fc ();
void fd ();
int main ()
{
try
{
MyClass mainObj ("M");
fa ();
cout << "Mission accomplished!\n";
}
catch (const char *e)
{
cout << "exception: " << e << endl;
cout << "Mission impossible!\n";
}
return 0;
}
void fa ()
{
MyClass a ("A");
fb ();
cout << "return from fa()\n";
return;
}
void fb ()
{
MyClass b ("B");
fc ();
cout << "return from fb()\n";
return;
}
void fc ()
{
MyClass c ("C");
fd ();
12
cout << "return from fc()\n";
return;
void fd ()
{
MyClass d ("D");
// throw "in fd(), something weird happened.";
cout << "return from fd()\n";
return;
}
Output:
return from fd()
Destroying D
return from fc()
Destroying C
return from fb()
Destroying B
return from fa()
Destroying A
Mission accomplished!
Destroying M
EXCEPTION OBJECT
The exception object holds the error information about the exception that had occurred.
The information includes the type errors i.e. logic errors or run time error and state of the
program when the error occurred.
An exception object is created as soon as exception occurs and it is passed to the
corresponding catch block as a parameter. The catch block contains the code to catch the
occurred exception.
An exception can be of any type, including class types that you create. Actually, in real-
world programs, most exceptions will be class types rather than built-in types. Perhaps the most
common reason that you will want to define a class type for an exception is to create an object
that describes the error that occurred. This information can be used by the exception handler to
help it process the error.
General Form:
try
{
Throw exception object;
}
catch(Exception &exceptionobject)
{
13
…
}
When a throw expression is evaluated, an exception object is initialized from the value of
the expression. The exception object which is thrown gets its type from the static type of the
throw expression.
Inside a catch block, the name initialized with the caught exception object is initialized
with this exception object
The exception object is available only in catch block. You cannot use the exception object
outside the catch block.
Program:
#include <iostream>
#include <cstring>
using namespace std;
class MyException
{
public:
char str_what[80];
int what;
MyException ()
{
*str_what = 0;
what = 0;
}
MyException (char *s, int e)
{
strcpy (str_what, s);
what = e;
}
};
int main ()
{
int i;
try
{
cout << "Enter a positive number: ";
cin >> i;
if (i < 0)
throw MyException ("Not Positive", i);
}
catch (MyException e)
{ // catch an error
cout << e.str_what << ": ";
cout << [Link] << "\n";
14
}
return 0;
}
Output:
Enter a positive number: -1
Not Positive: -1
15