0% found this document useful (0 votes)
19 views244 pages

Slides On C++

Object oriented programming in c++ notes

Uploaded by

Dinesh Baniya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views244 pages

Slides On C++

Object oriented programming in c++ notes

Uploaded by

Dinesh Baniya
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 244

Introduction to Object Oriented Programming

Bipin Thapa Magar


b
[email protected]
u.np
A quick lookback at Procedure Oriented
Programming
Examples: C, Fortran, COBOL, Example: Reading a book
Pascal
Procedures:
Characteristics: 1. Select a book
1. Program is divided into small procedures or 2. Open the book
functions. 3. Read the book
2. POP focuses on procedures rather than data. 4. Close the book
3. A global variable is made to share the data main()
between the functions.
4. Since global variable is transferred to each selectBoo
function, it might be altered. k()
5. The program design uses top-down approach.
openBook
() Boo
k
readBook(
)
writeInBoo
closeBook k()
Compiled By Bipin Thapa Magar () 2
A quick lookback at Procedure Oriented
Programming
Examples: C, Fortran, COBOL, Example: Reading a book
Pascal
Procedures:
Limitations: 1. Select a book
1. Focus on functions rather than data. 2. Open the book
2. In large program, it is difficult to identify 3. Read the book
belonging of data. 4. Close the book
3. Use of global data can be obstacle in code main()
maintenance.
4. Modification of global data needs selectBoo
modifications of the functions using it. k()
5. Maintaining and enhancing program is
difficult because of global data. openBook
() Boo
6. It doesn’t model real world problem as
k
functions are action oriented. readBook(
)
writeInBoo
closeBook k()
Compiled By Bipin Thapa Magar () 3
Basics of Object Oriented
Programming Example: Reading a book
1. What are the properties of a book?
a. Eg: No of pages, genre, popularity
2. What can we do with the book?
1. Select a book
Characteristics:
2. Open the book
1. Emphasis on data rather than procedures.
3. Read the book
2. Programs are divided into objects.
4. Close the book
3. Function and data are tied together in a single
unit.
4. Data can be hidden to prevent from Objec
accidental alteration. selectBoo t
5. Data access is done through visible functions k()
so that communication between objects is
possible. openBook
() Boo
6. Data structure are modeled as objects. k
7. Follows Bottom-up approach. readBook(
)
writeInBoo
closeBook k()
Compiled By Bipin Thapa Magar () 4
Basics of Object Oriented
Programming
Object
selectBoo 1
k()
openBook
() Boo
k
readBook( Object 2
) selectBoo
writeInBoo
closeBook k()
k()
() openBook
() Boo
k
readBook(
)
writeInBoo
closeBook k()
()

Compiled By Bipin Thapa Magar 5


Procedure Oriented vs Object Oriented
Programming
Procedure Oriented Programming Object Oriented Programming
1. Emphasis is given on procedures. 1. Emphasis is given on data.
2. Programs are divided into functions 2. Programs are divided into objects.
3. Follows top-down approach of program 3. Follows bottom-up approach of program
design. design.
4. Generally, data cannot be hidden. 4. Data can be hidden, so that non-member
function can’t access them.
5. It doesn’t model real world problem 5. It models real world problem very well.
perfectly.
6. Data moves from function to function. 6. Data and function are tied together. Only
related function can access them.
7. Maintaining and enhancing code is difficult. 7. Maintaining and enhancing code is easy.
8. Code reusability is still difficult. 8. Code reusability is easy in compare to
procedure oriented approach.
Examples: C, Fortran, COBOL, Pascal Examples: C++, Java, Smalltalk
Compiled By Bipin Thapa Magar 6
Concept/Features of
OOP
Data Encapsulati
Abstraction on

Polymorphis
OOP Object
m

Class Inheritance

Compiled By Bipin Thapa Magar 7


Concept/Features of
OOP
1. Data
Abstraction:
 Act of representing essential features without including background details
or explanations

Internal
Circuit
Switc
h Bulb

Fig: Abstraction during switching of


light bulb
Compiled By Bipin Thapa Magar 8
Concept/Features of
OOP
2. Encapsulation
 Wrapping data and function into a single unit
 The function are known as member functions and data can only be
accessed through them

Object

readData(
)
changeDat Dat
a() a
deleteDat
a()

Fig:
Encapsulation
Compiled By Bipin Thapa Magar 9
Concept/Features of
OOP
3. Object
 Runtime entities that are identifiable with some characteristic and
behavior

Characteristics: Taste, Size, Shape, Color


 Data

Behaviors: Is it ripe?, Is it sour? 


Functions

Appl
e
Fig: Object
Compiled By Bipin Thapa Magar 10
Concept/Features of
OOP
4. Class
 Group of objects that share common properties
 It is like a user defined data type with data and functions
 Objects are like variables to class. A class can be used to make various
objects. It is similar to ‘int a’ where int is data type and ‘a’ is integer.

Fruits

Characteristics: Taste, Size, Shape, Color


 Data

Behaviors: Is it ripe?, Is it sour? 


Orang Apple Banan Functions
e a

Fig: Class and


Object
Compiled By Bipin Thapa Magar 11
Concept/Features of
OOP
5. Inheritance
 Capability of one class to inherit the properties and functions of other
class
 Eg: like a son inherits the looks, height and many characteristics from his
father Vehicles Color, max speed, type
of oil

Max Height, flight time Ground Clearance, suspension


Aircraft
Vehicles

Jet Helicopter Cars Motorcycle

Objects: Toyota, Suzuki Objects: Bajaj, Honda

Fig:
Compiled By Bipin Thapa Magar 12
Inheritance
Concept/Features of
OOP
6. Polymorphism
 Meaning “Having different forms”
 It means that an object or entity can act different based on the message
sent or action
 Examples: Function overloading, Operator overloading
2 and 3
5
(Integers) Operator Overloading:

0.5 and Add()


a. 2+3= 5
0.8 1.3 b. “Ram” + “ Thapa” = “Ram
(Float) Thapa”

0.5 and 3
(Float and 3.5
integer)

Fig:
Compiled By Bipin Thapa Magar 13
Polymorphism
Concept/Features of
OOP
7. Dynamic Binding
 The process of linking function call to the code to be executed in response
to the call is called binding.
 Types: Static and Dynamic Binding
 Static Binding: Operator and Function Overloading, which happens at
compile time
 Dynamic Binding: Achieved through inheritance and happens during run
time.

Compiled By Bipin Thapa Magar 14


Concept/Features of
OOP
8. Message Passing
 In OOP, communication happens between objects by passing messages
 Messages are passed using member functions

Complex.set(10,
20)

Obje Messag Informati


ct e on

Here, Complex is an object. Set()is a function inside it which acts as a


messaging and information are passed to the object using it.

Compiled By Bipin Thapa Magar 15


Some Examples of OOP

• C++
• C#
• Java
• Smaltalk
• Eiiffel
• D

Read Yourself:
• History
• Basic Syntax/Example

Compiled By Bipin Thapa Magar 16


Advantages of
OOP
1. High Code reusability through inheritance and templates
2. Real World representation
3. Data hiding through abstraction so that data is secure
4. Dividing program into number of object makes software
development easy
5. Maintenance and upgrading of software is easy
6. Improve reliability and flexibility
7. Existing class can serve as library for further enhancement
8. Message passing makes the interface easy
9. Software complexity is less severe than conventional
programming techniques

Compiled By Bipin Thapa Magar 17


Disadvantages of
OOP
1. If the message passing between many object in an application,
it is difficult to trace the error
2. Compile time and execution time is high as it requires more
time for dynamic memory allocation and runtime polymorphism
3. Require full knowledge of OOP before using it properly
4. Benefits in the long run but for small project, programming can
take a lot of effort

Compiled By Bipin Thapa Magar 18


Introduction to C++

Bipin Thapa Magar


b
[email protected]
u.np
Introduction to
C++
• C++ is a high level programming language that supports OOP.
• It is improved C. It can be considered as a superset of C as it has all the
features of C and even more, but still both C and C++ should be
treated as separate languages.
• C++ was developed by Bjarne Stroustrup in 1985 to provide Simula’s
class features for OOP and C’s feature for system programming.
• It was previously called ‘C with Classes’.
• It is named C++ meaning it is an increment or an upgraded version of
C.
• It has been used to develop high performance software such as mysql,
Windows XP, Adobe products, Mozilla Firefox and many more.
Need of C+
+
• Initially, programming was done through binary code which was then
upgraded to Assembly Language. After that C was developed and the
trend was to make programs easier for humans to read and write. With
that in mind, and to solve and model complex programs, a real world
modelling technique i.e OOP was developed. The need of OOP in C was
obvious and C++ was born.
Relation between C
and C++
C++

Features not used in


C++

Procedure features
OOP features
common to C and
C++
Features of
C++
1. Namespace:
• It is used for logical grouping of program elements like functions,
variables, classes, etc.
• Similar program elements are kept in a single namespace.
• If multiple programmers are working in a project and are unknown
of the naming convention used by others, there might exist
collision in names. So, the name are separated into namespace to
make sure there is no naming conflict between different modules

2. Classes:
• A class is a user defined data type to define variable (instance) of
object.
• It logically combines data and function in a single unit.

3. Derived Classes:
• If a new class is made by inheriting any existing class, it is known
as derived class.
• It increases code reusability.
Features of
C++
4. Access Controllers:
• The keywords “public, private and protected” are known as access
controllers
• They define whether the data or functions of a class or object can
be accessed from outside of the class or not
• Public  can access from anywhere
• Private  cannot access outside of class
• Protected  can be accessed by the class itself and its derived class

5. Constructor and Destructor:


• Constructor and Destructor are member functions of the class
which are defined automatically
• Constructor are used to allocate memory for objects being created
and initializing data
• Destructor are used to free up memory when object is destroyed
• Constructor has the same name as the class and destructor also
has the same name but starting with tilde(~) sign
• Example : Class: Fruit  Constructor: Fruit()  Destructor: ~Fruit()
Features of
C++
6. Friend Function and Classes:
• Non member function of a class cannot access private members,
but using friend function we can access private members from
outside the class.

7. Reference variable:
• It is an alternative name given to a variable and used for passing
argument by reference.

8. Function overloading:
• Same function name is used for different operation.
• The operation depends upon the arguments provided to the
function.

9. Default arguments:
• If we don’t supply any arguments to a function, default value are
passed as arguments.
• Default value are set during function declaration.
Features of
C++
10. Inline function:
• If functions are small and has very small execution code, the
underlying code can be directly inserted to the function call. During
compile time, the compiler replaces the function call with the code
to reduce program execution time and increase efficiency.

11. Operator Overloading:


• It extends the meaning of operators for user defined data types.
Normally operators such as + ,- , etc are defined for standard data
types only but operator overloading allows it to work for user
defined data types

12. Easier way of memory management:


• On contrast to functions like calloc() and malloc() in C, C++ uses
keywords ‘new’ and ‘delete’ for dynamic memory allocation.

13. Stream Class library for easier input/output:


• C++ uses stream class <iostream> which uses objects ‘cin’ and
‘cout’ which doesn’t require conversion character like in printf()
Features of
C++
14. Run time polymorphism:
• If some function exists on a class and some other class inherits
that class but also has a function with same name, C++ allows to
decide which function to call during runtime.

15. Generic Programming:


• C++ has a template feature that allows development of reusable
software components such as class, functions, etc for different data
types.

16. Exception Handling:


• Exceptions are errors that occur during run time. C++ allows
feature to handle various exceptions such as running out of
memory, not being able to open a file, and so on. Eg: divide by
zero.

17. Standard Template Library(STL):


• STL defines powerful template-based reusable components that
implement many data structures and algorithms used to process
Features of
C++
18. Run-time type information(RTTI):
• During program execution, the type of user defined objects can
differ based on many actions. C++ allows language elements:
dynamic_cast, typeid and type_info .
• dynamic_cast is used to convert from base class to derived class
• typeid returns the type of the object
• type_info is used to hold the information returned by typeid.
C++ versus C

C C++
1. It follows procedural programming 1. It is multi-paradigm language(both POP and
paradigm. OOP)
2. Follows top-down approach of program 2. Follows bottom-up approach of program
design. design.
3. Data are not secure. 3. Data are secure because of OOP features
like data hiding.
4. Functions are the building blocks of C 4. C++ are object-driven, and objects are
program and so it is function driven. building blocks of C++.
5. C doesn’t support function overloading. 5. C++ enables function overloading with the
help of polymorphism.
6. The namespaces feature is absent in C. 6. C++ allows namespace feature.
7. C doesn’t allow use of reference variables. 7. C++ allows use of reference variables
8. C programs are faster to compile. 8. C++ programs are relatively slower to
compile.
C++ versus C

C C+
#include<stdio.h> +
#include<iostream>
#include<conio.h> using namespace std;

int main() { int main() {


printf(“Hello World”); cout<<“Hello World”;
return 0; return 0;
} }
History of C+
+
• C++ was earlier called “C with Classes”.
• It was developed by Bjarne Stroustrup in an attempt to add Simula like
features to C with its system programming features.
• In 1980, “C with Classes” was published as technical report by Bell
Labs.
• In 1982, C was named C84 and a successor of “C with Classes” was
being developed. In 1983 to 1984, Cfront compiler front end for C84
language was designed and implemented. It was then renamed to C++
as suggested by Rick Mascitti because it had better meaning.
• In 1985, first commercial version, Cfront version 1.0 was released.
• In 1987, first GNU C++ was released.
• In 1989, Cfront version 2.0 was released.
• In 1990, first ANSI X3J16 meeting was held where templates and
exception were accepted.
• In 1992, HP implemented exception handling in Cfront and in 1991,
they developed STL which was added in 1994.
• In 1992, RTTI and namespace were accepted.
• In 1994, string was approved.
C++ Language Constructs

Bipin Thapa Magar


b
[email protected]
u.np
C++ Program
Structure

Include File

Class Declaration

Member function Definition

Main function Program


C++ Program
Structure
C C+
#include<iostream>
+
#include<stdio.h>
#define pi 3.14159
#define pi 3.14159
using namespace std;
int main(){
int main(){
float r,a,c;
float r,a,c;
printf(“Enter radius of
cout<<“Enter radius of circle:
circle”);
”;
scanf(“%d”,&r);
cin>>r;
a=pi*r*r;
a=pi*r*r;
c=2*pi*r;
c=2*pi*r;
printf(“\nArea of circle=
cout<<“\nArea of
%f”,a);
circle=“<<a;
printf(“\nCircumference of
cout<<“\nCircumference of
circle=%f”,c);
circle=“<<c;
return 0;
return 0;
}
}
C++ Character Set

 Set of valid characters that a language can


recognize

Digit: 0-9
Letters: A-Z , a-z
White Spaces: Blank Space, Horizontal Tab, Carriage Return,
Newline, Form Feed
Special Symbols: Space + - * / \ % ^ ( ) { } [ ] = < > , ‘ “ $ & | !
~ : ? _ # <= >=
Other Characters: C++ can process any of the 256 ASCII character
as data or literals
C++ Tokens

 Collection of different characters


 Smallest unit of a program
 Keywords, Identifiers, Literals,
Punctuators and Operators
1. Keywords:
The words that has special fixed meaning to the compiler and cannot be
changed are keywords.
C++ Tokens

2. Identifiers:
 User-defined names and consists of letters and digits, with a letter as a first
character.
 C++ is case-sensitive and it treats lowercase and uppercase differently
 Rules of defining identifier:
1. First character must be alphabet (or underscore)
2. Must consist of only letters, digits or underscore
3. Cannot use a keyword
4. Must not contain white space or special character

Examples:
Sagarmatha, _ram, bei1, oop_CPP

Invalid identifiers:
1Ram  First character cant be a digit
continue  keyword
Sagar-matha  ‘-’ not allowed
C++ Tokens

3. Literals:
Also known as constants
a. Integer Constant:
Whole numbers without any fractional part.
An integer constant must have at least one digit and must not contain
any decimal point
It can contain +ve or –ve sign. If no sign exists, it is considered as
positive.
Three types: Decimal(Base 10), Octal(Base 8) and Hexadecimal (Base
16)
 Decimal starts with a digit other than zero unless the digit is 0. eg:
+24, -16
 Octal number ranges from 0 to 7 and always start with zero. Eg: 12 in
decimal is written as 014 in octal.
 Hexadecimal starts with 0x or 0X. Eg: 20 in decimal is written as 0x14
in hexadecimals

b. Character constants:
Single character closed in single quotes.
 eg: ‘a’, ‘s’
C++ Tokens

Escape Nongraphic Character


Sequence
\t Horizontal Tab
\n Newline
\v Vertical Tab
\\ Backslash
\’ Single Quote
\” Double Quote
\? Question Mark
\a Audible bell(alert)
\b Backspace
\f Form feed
\r Carriage Return
\0 Null
Fig: Escape Sequence in
C++
C++ Tokens

c. Floating Constant:
Numbers having fractional parts
Fractional form and exponential form
Fractional form must have at least one digit before a decimal point and at
least one digit after the decimal point. It can be positive or negative. Eg: 10.0,
-12.125, -0.061012
Invalid fractional form: 11(No decimal point), 11. (No digit after decimal
point), +7/2 (Illegal symbol /)
 Exponential form has two parts: mantissa and an exponent. The mantissa
must be either an integer or a proper real constant. The mantissa is
followed by a letter E. The exponent must be an integer. Eg: 1.0128 x 10 3 =
1.0128 E03 where mantissa=1.0128 and exponent is 03.

d. String Literals:
Sequence of characters surrounded by double quotes.
Each string literal is automatically added with terminating character ‘\0’
 Eg: “Ram”
C++ Tokens

4. Punctuators:
The following characters are used as punctuators ( also known as
separators) in C++:
[ ] ( ) { } , ; : * … = #

5. Operators:
 Operators are tokens that trigger some computation or action when applied
to variables and other objects in an expression.

a. Arithmetic Operators
 Addition(+), Subtraction(-), Multiplication(*), Division(/) and
remainder(%)

b. Increment/Decrement Operators
 Increment Operator(++) and Decrement Operator (- -)
 Pre: (++a) and Post: (a++)
 a=5, c=5;
sum=a + (++c);  sum=11;
sum=a + (c++);  sum=10;
C++ Tokens

c. Relational Operators:
Operator Meaning
< is less than
<= is less than or equal to
> Is greater than
>= is greater than or equal to
== is equal to
!= not equal to

C++ considers 0 as false and all other non-zero as true.

d. Logical Operators:
Operator Meaning
&& Logical AND
|| Logical OR
! Logical NOT

e. Conditional Operator: (?:)


 expression1 ? expression2 : expression3
 If expression1 is true, the value of the whole expression is expression2 else
C++ Tokens Example of Bitwise
#include<iostream>
Operator
using namespace std;
f. Assignment Operator: int main(){
 firstOperand=secondOperand int a=12,b=7;
 Eg: a=5, c=a+b int c,d,e,f,g;
c=a&b;
g. Bitwise Operator: d=a|b;
Operator Meaning e=a^b;
& bitwise AND f=b<<2;
| bitwise OR g=b>>2;
^ bitwise exclusive OR
<< shift left cout<<“\nBitwise
>> shift right AND:”<<c;
cout<<“\nBitwise OR:”<<d;
Output cout<<“\nBitwise XOR:”<<e;
cout<<“\nBitwise
Bitwise AND: 4 leftshift:”<<f;
Bitwise OR: 15 cout<<“\nBitwise
Bitwise XOR: 11 rightshift:”<<g;
Bitwise leftshift: 28
Bitwise rightshift: 1 return 0;
}
C++ Tokens Example of Bitwise
#include<iostream>
Operator
using namespace std;
a = 12 = 1100 int main(){
b = 7 = 0111 int a=12,b=7;
int c,d,e,f,g;
c = 1100 & 0111 = 100 = 4 c=a&b;
d = 1100 | 0111 = 1111 = 15 d=a|b;
e = a^b=a’.b+ a.b’ = 0011 . 0111 + 1100 . 1000 = 0011 + 1000 = 1011 = 11
e=a^b;
f = (00111)<<2 = (11100) = 28 f=b<<2;
g = (0111)>>2 = (0001) = 1 g=b>>2;

cout<<“\nBitwise
AND:”<<c;
cout<<“\nBitwise OR:”<<d;
Output cout<<“\nBitwise XOR:”<<e;
cout<<“\nBitwise
Bitwise AND: 4 leftshift:”<<f;
Bitwise OR: 15 cout<<“\nBitwise
Bitwise XOR: 11 rightshift:”<<g;
Bitwise leftshift: 28
Bitwise rightshift: 1 return 0;
}
C++ Tokens

f. Some Other Operators:


 Comma Operator:
Eg: value=(x=5,y=10,x+y);
This first assign 5 to x , then 10 to y. Then it adds 5 and 10 and stores 15
to value.
 sizeof Operator: It returns the no of bytes the operator occupies.
Eg: sizeof(int)  returns 2

 C++ supports some other operators like &, *, . and ->


C++ Tokens

Operator Precedence and Associativity


Precedence Operator Description Associativity
1 :: Scope resolution Left-to-right
Suffix/postfix
a++ a--
increment and decrement
type() type{} Functional cast
2
a() Function call
a[] Subscript
. -> Member access
Prefix Right-to-left
++a --a
increment and decrement
+a -a Unary plus and minus
Logical NOT and
! ~
bitwise NOT
(type) C-style cast
3
*a Indirection (dereference)
&a Address-of
sizeof Size-of[note 1]
co_await await-expression (C++20)
new new[] Dynamic memory allocatio
delete delete[] n
Dynamic memory dealloca
Precedence Operator Description Associativity
5 a*b a/b a%b Multiplication, division, Left-to-right
6 a+b a-b and remainder
Addition and subtractio
n
Bitwise
7 << >>
left shift and right shift
Three-way comparison
8 <=> operator
(since
For C++20)
relational operators
< <=
< and ≤ respectively
9
For relational operators
> >=
> and ≥ respectively
For relational operators
10 == !=
= and ≠ respectively
11 & Bitwise AND
Bitwise XOR (exclusive
12 ^
or)
Bitwise OR (inclusive
13 |
or)
14 && Logical AND
15 || Logical OR
Right-to-left
throw throw operator
yield-expression (C+
co_yield
+20)
Direct assignment
= (provided by default
for C++ classes)
Compound assignment
+= -=
16 by sum and difference
Compound assignment
*= /= %= by product, quotient,
and remainder
Compound assignment
<<= >>= by bitwise left shift and
right shift
Compound assignment
&= ^= |= by bitwise AND, XOR,
and OR
17 , Comma Left-to-right
C++ Variable
 Variable is a data name that may be used to store data value.
 Unlike C, in C++ we can define a variable anywhere we need.
Eg:
int a;
cin>>a;
int b=a+10;

Defining Symbolic Constants:


We can define constants that doesn’t change its value for the entire program just
like in C like as:
#define symbolic-name value

i.e. #define pi 3.14

Declaring variable as Constant:


We can also declare certain variables as constants by using the const keyword.
Eg:
const int size =30;
C++ Data Types
 C++ data types are of two types:
1. Fundamental Types
2. Derived Types

1. Fundamental data types:


a. int – for integers
b. char – for characters i.e. letters, symbols, etc.
c. float – for floating point numbers
d. double – for double-precision floating-point numbers
e. void – for empty set of values and non-returning functions

2. Derived Types:
 array, functions, pointers, references, constants, classes, structures, unions and
enumerations
C++ Data Types

Data Type Modifiers:


int
Type Size (in Minimal Range
bytes)
short 2 -32768 to 32767
unsigned short 2 0 to 65535
signed short 2 same as short
int 2 -32768 to 32767
unsigned int 2 0 to 65535
signed int 2 same as int
long 4 -2,147,483,648 to
unsigned long 4 2,147,483,647
signed long 4 0 to 4,294,967,295
same as long
C++ Data Types

Data Type Modifiers:


char
Type Size (in Minimal Range
bytes)
char 1 -128 to 127
unsigned char 1 0 to 255
signed char 1 same as char
float
Type Size (in Minimal Range Digits of
bytes) precision
float 4 3.4x10-38 to 3.4x10-38 -1 7
double 8 1.7x10-308 to 1.7x10-308 - 15
long double 10 1 19
3.4x10-4932 to 3.4x10-4932
-1
Type
Conversion
 The process of converting one predefine type to another type is known as
type conversion.

1. Implicit Conversion:
 C++ automatically converts any intermediate value to proper type so
that expression can be evaluated without losing any significance.
 Example:
int a,b;
float c;
.
.
cout<<a+b+c; // the result becomes float

2. Explicit Conversion:
 It is the process in which we force a type conversion.
 Syntax: (type-name) expression
 Example:
x= (int) 7.5; // it gets converted to 7
Statemen
ts
 The instructions given to the computer to perform any kind of action are
called statements.
 Statements are terminated with a semicolon(;).
 Every expression, making decision or repeating action is known as
statements.

Compound Statement (Block):


 It is the sequence of statements enclosed by a pair of braces;
 Example:
{
statement1;
statement2;
}
 It can appear anywhere in the program. Also, since in C++, we can create
a variable anywhere. If we create a variable inside a block, it becomes
local to that block meaning that it cant be used outside of it.
 Example:
{
int b=30;
cout<<b; // Outputs 30
Statemen
ts
1. Selection Statements:
 Normally, statements are executed sequentially but we can control
the flow of control with statements such as:
1. if
2. if-else
3. else-if ladder
4. switch
5. conditional operator (?:)
2. Iteration Statements:
6. while
7. do
8. for
3. Jump Statements:
9. return
10.goto
11.break
12.continue

*Note: All the above statements are same as in C. Read yourself if


you have confusion.
Preprocessor
Directives
 The lines beginning with ‘#’ are called preprocessor directives.
 We have used ‘#include’ and ‘#define’ which are preprocessor directives.

Example:
#include<iostream>

This inserts the file ‘iostream’ from the ‘include’ folder.

If we want to insert some other file, we can insert the file by providing path :

#include “filename”
Eg:
#include “C:\\tc\\bin\\mydir\\filename”
Namespa
ce
 Logical grouping of declarations

 General Form:
namespace namespace_name{
//declaration of variable,function,class,etc;
}

 Example:
namespace Rectangle{
int width;
int height;
void volume();
}

In above example, if we want to access the member property or function,


we need to use the scope resolution operator(::) as:

Rectangle::width=10;

 If we don’t want to use that everytime, we can use the ‘using’ directive.
Namespa
ce
#include<iostream>
#include<iostream>
using namespace std;
using namespace std;
namespace Rectangle{
namespace Rectangle{
int width;
int width;
int height;
int height;
void volume();
void volume();
}
}
int main(){
int main(){
using namespace Rectangle;
Rectangle::width=2;
width=2;
Rectangle::height=4;
height=4;
Rectangle::volume();
volume();
return 0;
return 0;
}
}
void Rectangle::volume(){
void Rectangle::volume(){
cout<<“Volume is
cout<<“Volume is
“<<width*height;
“<<width*height;
}
Namespa
ce
namespace std:

 We use the namespace std which is defined as following in simple terms:

namespace std{
istream cin;
ostream cout;
.
.
.
//other stuffs
}
The definition of cin, cout and all others is in “iostream”. So, if we don’t use
namespace, our code would look like this:

std::cout<<“Hello”;

Since we add “using namespace std” in our code, we can use:

cout<<“Hello”;
Namespa #include<iostream>
ce using namespace std;
Nested Namespace: namespace Function{
 We can create another namespace inside a namespace as: namespace Data{
int x;
namespace NS1{ int y;
: //some members of NS1 }
namespace NS2{ void product(){
: //some members of NS2 using namespace Data;
int r; cout<<x*y;
} }
} void sum(){
using namespace Data;
Here, if we want to access the integer “r”, we do something like this: cout<<x+y;
}
NS1::NS2::r=10; }
int main(){
Function::Data::x=10;
Function::Data::y=3;
Function::product();
Function::sum();
}
Namespa
ce
Unnamed Namespace:
 Unnamed namespace are those which donot have any
name.
#include<iostream>
using namespace std;
namespace{
int x;
namespace{
int y;
int x;
}
int y;
}
 It is now globally accessible in the program. The above
program is actually equivalent to:
int main(){
x=10;
namespace $$${
y=20;
int x;
cout<< x*y;
int y;
return 0;
}
}
using namespace $$$;
Input/Output
Streams
1. Output Stream:
 The output stream allows us to write operations on standard output
devices such as screen, disk, etc.
 We use the object cout for output operation which is an object of
library class “ostream”. The “iostream” includes both “ostream” and
“istream”.
 ‘<<‘ is called insertion or put to operator and is overrided.

Syntax:

cout<<var1<<var2<<var3<<………<<varN;

Example:
cout<<“Hello”;
“Hello
Hello cout << ”

Screen
Input/Output
Streams
2. Input Stream:
 The input stream allows us to perform read operations from standard
input devices such as keyboard, disk, etc.
 We use the object cin for input operation which is an object of library
class “istream”. The “iostream” includes both “ostream” and
“istream”.
 ‘>>‘ is called extraction or get operator and is overrided.

Syntax:

cin>>var1>>var2>>var3>>………>>varN;

Example:
cin>>var_name;
variab
Hello cin >> le

Keyboa
rd
Manipulator
s
Certain instructions to input/output streams that modify the output in
various ways.
 Included in the header file <iomanip>
 Eg: endl, setw

endl:
 Similar to “\n”
 It sends a new line and flushes the stream i.e. puts all the pending
characters that is stored in internal buffer but not yet output.
Eg:

cout<<endl<<“Perimeter is”<<perimeter;
cout<<endl<<“Area is”<<area;

Output:

Perimeter is 9
Area is 20
Manipulator
s
setw:
 It causes the number or string that follows it in the
stream to be printed within a field specified in the
argument.
Eg:
cout<<setw(n)<<var_name; Outpu
LOCATION
t
cout<<setw(5)<<num; POPULATION
#include<iostream>
This displays num with character width if num is less than 5 Patan
#include<iomanip>
character. 5425678
using namespace std; Khotang
int main(){ 47000
long pop1=5425678,pop2=47000,pop3=76890; Butwal 76890
cout<<setw(8)<<“LOCATION”<<setw(12)<<“POPULATIO
N”<<endl
<<setw(8)<<“Patan”<<setw(12)<<pop1<<endl
<<setw(8)<<“Khotang”<<setw(12)<<pop2<<endl
<<setw(8)<<“Butwal”<<setw(12)<<pop3<<endl
return 0;
}
Dynamic Memory Allocation with new
and delete
 When we declare an array such as “int a[100]”, the compiler sets
aside the required memory but it might not be enough or it might
not be used during execution.
 So, if situation arises where we are unsure of the memory required
during compile time, the memory allocation can be performed during
run time, which is known as dynamic memory allocation.
 C++ uses new operator for dynamic memory allocation and delete
operator for dynamic memory de-allocation.

1. new:
 The new operator obtains memory at runtime from the memory heap
from the operating system and returns the address of the obtained
memory.
 It is designed keeping OOP in mind and throws an exception if
memory allocation fails.
Syntax:
int *iptr;
iptr= new int; //allocates space for single integer
iptr= new int[n]; //allocates space for an array of integer with n
elements
Dynamic Memory Allocation with new
and delete
2. delete:
 When we allocate memory using new at runtime, the memory is
reserved even after it is not needed or after the scope of the variable
ends.
Syntax:
delete data_type_ptr; //releases a single dynamic variable
delete [ ]data_type_ptr; // releases dynamically created array

Example:

int *iptr;
iptr= new int[4];
. . . .
. . . .
delete iptr;
Reference variable
 A reference variable is alias (alternative name) for a previously
defined variable.
 Syntax:
data_type & referenceName= variableName;
Example:
int &a=b;
Illustration:

1. Without reference variable


int b=10;
int a=b; 10 10
a++;
cout<<a<<b; //Output: 11 10 b a ( a variable copy of b)

2. With reference variable


int b=10; 10
int &a=b;
a++; b a ( a and b are same)
cout<<a<<b; // Output: 11 11
Functio
ns
Function Syntax
Function Types

Read Yourself:

 Function Call:
a. Call by value
b. Call by reference

We wont be talking about call by value because it is same as before. If you want, I can
show you an example.

Call by reference:
 When a function is called by reference, then the formal parameter becomes reference
(aliases) to the actual parameters in the calling function.
 During call by reference, the program doesn’t create a new copy of the variable but
refers to the same variable using a new name.
 Note that we can only use variable but not constants during call by reference.
Functio
ns Call by reference
Call by reference in
C++
in C
#include<iostream> #include<iostream>
using namespace std; using namespace std;
void area(int *); void area(int &);

int main(){ int main(){


int length=12; int length=12;
area(&length); area(length);
cout<<length; // 144 cout<<length; // 144
return 0; return 0;
} }

void area(int *a){ void area(int &a){


*a=(*a) * (*a); a= a*a;
} }

Address of
12 12 a
length

lengt a lengt
Functio
ns
Return by reference:
 Like a function can have alias as an argument, a function can also return a reference.
 For this, we have to pass by reference as local variable doesn’t have scope outside of
the function.
#include<iostream> int Large, small;
using namespace std; cout<<“\nEnter the value of c
and d”;
int & min(int &a, int &b) cin>>c>>d;
{ Large=max(c,d);
if(a<b) return a; small=min(c,d);
else return b; cout<<“\nLargest
} is:”<<Large;
cout<<“\nSmallest
int max(int &a, int &b) is:”<<small;
{
if(a>b) return a; //max(c,d)=-10; error
else return b; min(c,d)=-5;
} cout<<c<<d;
return 0;
int main(){ }
int c,d;
Functio
ns

Enter the value of c and d: 10


50
Largest is 50
Smallest is 10
-5 50
Functio
ns
Inline Functions:
 Normally, when function is called, it takes lots of extra time in executing a
series of instructions for tasks such as jumping to function, saving registers,
pushing arguments into stack and returning to the calling function.
 So, if a function is small, we can reduce such costs by using inline functions.
 Inline functions are such that during compile time, the function call is replaced
by the corresponding function code.
 Syntax:
inline return-type function_name(arguments){

}
Functio
ns

#include<iostream>
using namespace std;
void area(int); #include<iostream>
int main(){ using namespace std;
int length=12; void area(int);
area(length); int main(){
return 0; int length=12;
} cout<<length;
return 0;
inline void area(int a){ }
cout<<a;
}
Functio
ns
Default Argument:
 We can assign some values to arguments during function declaration which
are known as default arguments.
 Example:
float interest(float p, int time, float r=0.1)

#include<iostream>
using namespace std;

void interest(float p=1000,int t=5, float r=0.1){


cout<< p*t*r;
}

int main(){
interest(); //p=1000, t=5, r=0.1
interest(4000); //p=4000, t=5, r=0.1
interest(5000,10); //p=5000, t=10, r=0.1
interest(5000,10,0.14); //p=5000, t=10, r=0.14
return 0;
}
Functio
ns
Default Argument:
 Note that we can only set an argument with default value if all the arguments
to its right have default values set.
i.e.
float interest(float p, int t, float r=0.14) // OK
float interest(float p, int t=10, float r) // error
float interest(float p, int t=10, float r=0.14) // OK
float interest(float p=1000, int t, float r=0.14) // error
Functio
ns
Function Overloading:
 A function name having several definitions that are differentiable by the
number or the types of their arguments is function overloading.
 When either the number or type of argument differs but the name is same,
the compiler treats each of them as different functions and selects and bind
each function individually during compile time.
 So, it is called early-binding or static-binding or static-linking. It is also
known as compile-time polymorphism.
 Example:
float add(int a, int b);
float add(float x, float y); //different type of argument
float add(int a, int b, int c); //different number of argument

Categories/Types:
1. Number of Arguments
2. Type of Argument
3. Number and Type of Argument
Functio
ns
1. Number of Arguments:
 We can define same functions, which have different number of arguments.
#include<iostream> int main(){
using namespace std; add(5,10); //function 1
add(5,10,15); //function 2
void add(int a, int b){ //function 1 add(5,10,15,20); //function 3
cout<<a+b; return 0;
} }
void add(int a, int b, int c){
//function 2
cout<<a+b+c;
}
void add(int a, int b, int c, int d){
//function 3
cout<<a+b+c+d;
}
Functio
ns
2. Type of Argument
 We can define same functions, which have different type of arguments.
int main(){
#include<iostream>
add(5,10); //function 1
using namespace std;
add(5,10.5); //function 2
add(5.4,10.6); //function 3
void add(int a, int b){ //function 1
return 0;
cout<<a+b;
}
}
void add(int a, float b){ //function 2
cout<<a+b;
}
void add(float a, float b){ //function
3
cout<<a+b;
}
Functio
ns
3. Type and Number of Argument
 We can define same functions, which have different name as well as of
arguments.
int main(){
#include<iostream>
add(5,10); //function 1
using namespace std;
add(5,10.5); //function 2
add(5,10.6,15); //function 3
void add(int a, int b){ //function 1
return 0;
cout<<a+b;
}
}
void add(int a, float b){ //function 2
cout<<a+b;
}
void add(int a, float b, int c){
//function 3
cout<<a+b;
}
Arrays
 Collection of variable of the same type that are reference by a common base.

1. Single dimensional Array


2. Multi dimensional Array

1. Single dimensional Array:


 General form:
type array_name[size];
 Initialization:
type array_name[size] = {list of value};
Eg:
int number[3]= {1,2,3};
i.e. number[0]=1, number[1]=2, number[2]=3
Array index starts from 0.

2. Multi dimensional Array:


 General form:
type array_name[row_size] [column_size]
 Initialization:
int table[2][3]={0,0,0,1,1,1};
Arrays
2. Multi dimensional Array:
 General form:
type array_name[row_size] [column_size];
 Initialization:
int table[2][3]={0,0,0,1,1,1};
int table[2][3]={ {0,0,0}, {1,1,1} };
int table[ ][3]={
{0,0,0}
{1,1,1}
}
int table[ ][3]={
{1,1}
{2}
} //automatically initialize missing elements with zero

Data:
table[0][0]=0 table[0][1]=0 table[0][2]=0
table[1][0]=1 table[1][1]=1 table[1][2]=1
Pointer
 A pointer is a variable which holds a memory address of another variable in memory.
 General Form:
type * var_name;
Example:
int *iptr; //creates an integer pointer 10 10 20 100
char *cptr; //creates an character pointer 0 0
i ipt
int i=10; r
iptr=&i;
*iptr=20; // The value of i becomes 20

 Pointer Arithmetic:
iptr++; // iptr becomes 102 not 101
String
 It is a character array that is terminated by null character ‘\0’.
 General Form:
char string_name[size];
Example:
char name[10];
char name[11]=“SAGARMATHA”;
char name[11]={ ‘S’, ‘A’, ‘G’, ‘A’, ‘R’, ‘M’, ‘A’, ‘T’, ‘H’, ‘A’, ‘\0’ };

char name[]={ ‘S’, ‘A’, ‘G’, ‘A’, ‘R’, ‘M’, ‘A’, ‘T’, ‘H’, ‘A’, ‘\0’ }; //automatically creates
array of size 11

 Normally, cin can be used to take input to string as well but it cant take whitespaces as
input.
i.e If we input “Hello World” as
cin>>str;
str only stores “Hello”.
So, we use a function getline() to store whitespaces as well.
cin.getline(str,20);

str stores “Hello World”


Structur
e
 Collection of different type of variable referenced under single name.
 General Form:
struct struct_name{
data_type var_name1;
data_type var_name2;
.
.
data_type var_nameN;
}
Example:
struct date{
int day;
int month;
int year;
}
Then, we can declare variable as:
struct date var1, var2, …… , varN;

 Accessing Member:
var1.day=27;
Unions
 It is same as structure but the difference is all the members share the same memory so
that we can only use one member at a time.
#include<iostream>
using namespace std;

union data{
int x;
float y;
}; The size is: 4
int main(){ x=10
data d1; y=1.40 E-044
cout<<“The size x=12312
is:”<<sizeof(d1); y=11.2
d1.x=10;
cout<<“x=“<<d1.x;
cout<<“y=“<<d1.y;
d1.y=11.2;
cout<<“x=“<<d1.x;
cout<<“y=“<<d1.y;
return 0;
}
Enumeration
 User defined data type which provides a way of attaching names to numbers.
 General Form:
enum tag {enumerator’s list} variable-list;

Example:
enum days{sun,mon,tues};
days d1,d2;

In above list, default values are set as sun=0, mon=1 and tues=2.

Also, the values of d1 and d2 can only be one of the 3 listed.


i.e. d1=mon; //valid
d1= 4 // invalid

Also, we can initialize as:


enum days{sun,mon=15,tues};

In this case, sun=0, mon=15, tues=16.


Classes and Objects

Bipin Thapa Magar


b
[email protected]
u.np
Reference Example
Video
C++ Classes
 It binds data describing an entity and its associated function together.
 It is also known as a blueprint of the object.
class Complex{
float real; Syntax:
float Data
imaginary; Members class class_name{
Access
public: public:
Specifiers
void input(); //data_members
Member
void display(); declaration
Functions
float //member_function
magnitude(); declaration
}; protected:
//data_members
declaration
//member_function
declaration
private:
//data_members
declaration
//member_function
declaration
Defining Member
class Complex{
Function
 We can define member functions in two ways: float real;
1. Outside the class definition float imaginary;
2. Inside the class definition public:
void input();
1. Outside the class definition: void display();
 General Form: float magnitude();
return_type class_name::function_name(argument){
};
// Function Body void Complex::input(){
} cout<<“\n Enter real and imaginary:”;
cin>>real>>imaginary;
}
void Complex::display(){
cout<<“\n Real:”<<real;
cout<<“\n Imaginary:”<<imaginary;
}
float Complex::magnitude(){
float m=sqrt(real*real + imaginary
*imaginary);
return m;
}
Defining Member
Function
2. Inside the class definition:

class Complex{
float real;
float imaginary;
public:
void input(){
cout<<“\n Enter real and imaginary:”;
cin>>real>>imaginary;
}
void display(){
cout<<“\n Real:”<<real;
cout<<“\n Imaginary:”<<imaginary;
}
float magnitude(){
float m=sqrt(real*real + imaginary
*imaginary);
return m;
}
};
Objects
 When we create a class, it only specifies the type of information that the object of this
class type will be containing.
 Once class has been declared, we can create variables of that type by using class name:
class_name object1, object2, ….. , objectN;
class Complex{
int main(){
float real;
Complex c1,c2;
float imaginary;
c1.input();
public:
c1.display();
void input(){
cout<<c1.magnitud
cout<<“\n Enter real and imaginary:”;
e();
cin>>real>>imaginary;
}
}
void display(){
cout<<“\n Real:”<<real;
cout<<“\n Imaginary:”<<imaginary; Output:
}
float magnitude(){ Enter real and
float m=sqrt(real*real + imaginary imaginary: 3 4
*imaginary); Real: 3
return m; Imaginary: 4
} 5
Objects
Memory Allocation of Object:
c c
1 2

Rea 3 Rea
l l
Imagina 4 Imagina
ry ry

clas
s
input()

display()

magnitude
()
Access
Specifiers
1. public:
 All the data members and member functions which are under public can be
accessed from anywhere using objects.
2. private:
 All the data members and member functions which are under private can only be
accessed inside the class owning it.
 The members which are private are hidden from outside world. Also, friends can
access private members which is discussed later.
 At default, all the data members are private unless mentioned otherwise.
3. protected:
 The protected members act the same as private members in normal case. It’s
significance can be seen while studying inheritance later on.
Constructors
 A constructor is a member function of a class that is automatically called, when an
object of that class is created.
 It has the same name as that of the class’s name and it is mainly used to initialize the
data members of the class.
 It can be declared either inside or outside the class but note that it doesn’t have any
return type, not even void.

class Complex{
class Complex{ float real;
float real; float imaginary;
float imaginary; public:
public: Complex();
Complex(){ };
real=0; Complex::Complex(){
imaginary=0; real=0;
} imaginary=0;
}; }
Constructors
Types: class Complex{
1. Default Constructor float real;
2. Parameterized Constructor float imaginary;
3. Copy Constructor public:
Complex(){
1. Default Constructor: real=0;
 A constructor with no parameter is called default constructor. imaginary=0;
 Syntax: }
classname::classname(){ };
//body of constructor
}
 If no constructor is defined, the compiler will automatically supply a default constructor.
 Default constructor are used to initialize the data members with any dummy value.
Constructors
2. Parameterized Constructor:
 The constructor that can take arguments are called parameterized
constructor.
 It allows us to initialize the data members with different values when
they are created.
 Syntax:
class Complex{
classname::classname( arguments ){
float real;
//Body of constructor
float imaginary;
}
public:
 Note that if only parameterized constructor is created, the compiler
Complex(int a, int b){
doesn’t provide a default constructor so that we can only create
real=a;
objects by passing arguments.
imaginary=b;
i.e In given example,
}
Complex c2;
};
is invalid as no constructor handles it.
 We can call constructor using two ways:
int main(){
1. Implicit call:
Complex c1(3,4);
 Classname objectname(arglist)
//real=3, imaginary=4
 Eg: Complex c1(3,4);
}
2. Explicit call:
 Classname objectname = Classname(arglist)
Constructors
Temporary Instance:
 We can create a temporary object of a class by invoking itsclass Complex{
constructor. float real;
 It exists in memory only during execution and after that it dies.]
float imaginary;
public:
Constructor with primitive data type: Complex(int a, int b){
 The default and parameterized constructor exists for primitive real=a;
data type. imaginary=b;
 So, we can do the following: }
int a; //default constructor void display(){
int a(5); // parameterized constructor cout<<real<<ima
ginary;
}
};

int main(){
Complex c1(1,2);
Complex(3,4).display()
;
cout<<“Only c1 exists
Constructors
Constructor with default argument: class Complex{
 We can give default arguments to constructor as shown: float real;
float imaginary;
public:
Note that we can create multiple constructors of a class using concept
of Complex(int a=3, int b=4){
function overloading. real=a;
class Complex{ imaginary=b;
float real; }
float imaginary; };
public:
Complex(){ int main(){
real=0; Complex c1;// real=3,
imaginary=0; imag=4
} Complex c2(1); // real=1,
Complex(int a, int b){ imag=4
real=a; Complex c3(1,2); // real=1,
imaginary=b; imag=2
} }
};
Constructors
Initialization list:
 We can initialize data members as follows:

class Complex{
float real;
float imaginary;
public:
Complex(int a, int b) : real(a),
imaginary(b)
{ }
};
Constructors
3. Copy constructor:
 The constructor which is called when we initialize an object with
another object of same class is known as copy constructor.
Default copy constructor:
 It is the constructor which is built in default in every class when we
instantiate object with another object of same class.
 We need not define any constructor. Default copy constructor is
invoked when we create an object with another object of same class.
It causes member-by-member copy of the objects.

class Complex{
float real; int main(){
float imaginary; Complex c1(3,4); //c1.real=3,
public: c1.imaginary=4
Complex(int a, int b){ Complex c2(c1); //c2.real=3,
real=a; c2.imaginary=4
imaginary=b; Complex c3=c1; //c3.real=3,
} c3.imaginary=4
}; }
Constructors
User defined copy constructor:
 It takes a reference to an object of the same class as argument.

class Complex{
float real;
float imaginary;
public: int main(){
Complex(int a, int b){ Complex c1(3,4); //c1.real=3,
real=a; c1.imaginary=4
imaginary=b; Complex c2(c1); //c2.real=3,
} c2.imaginary=4
Complex(Complex &c) Complex c3=c1; //c3.real=3,
{ c3.imaginary=4
real=c.real; }

imaginary=c.imaginar
y;
}
};
Constructors
Order of constructor invocation:
 Normally, constructor is invoked in the order they are defined.
public:
class A{ ABC( ){
public: cout<<“\n ABC class”;
A( ){ }
cout<<“\n A };
class”; int main(){
} ABC obj;
}; }
class B{
public:
B( ){
cout<<“\n B
class”; OUTPUT:
} B class
}; A class
class ABC{ ABC class
B b;
A a;
Destructor
s
 The function which is called when an object of a class is destroyed is
called as Destructor.
 General Form:
~ classname(){
}

class Complex{
float real;
float imaginary;
public:
int main(){
Complex( ){
Complex c1; //Constructor of c1 called
cout<<“Constructor
{
called”;
Complex c2; //Constructor of c2 called
}
} //Destructor of c2 called at end of block
~Complex( ){
} //Destructor of c1 called at end of block
cout<<“Destructor
called”;
}
};
Destructor
s
Characteristics:
 They are invoked automatically when the objects are destroyed.
 If a class has destructor, each object of that class will be de-initialized
before the object goes out of scope.
 The Destructor doesn’t take any argument, which means that
destructors cannot be overloaded.
 Destructor functions also obey all the access rules as other member
functions.
 They cannot be inherited.
 A destructor may not be static.
 Member function may be called from within a destructor.
 An object of class with a destructor cannot be a member of a union.
 It is not possible to take the address of a destructor.
Others
1. Object as Function Arguments and Return type
2. Array of objects
3. Pointer to Objects and Member Access

Code is attached
Read the theory yourself
DMA for Objects and Object
Array
 DMA for object is same as that of normal data type.
 We use new and delete for DMA.

new:
className *pointer;
pointer=new className; //single object
pointer=new className[size]; //Array of object

delete:
delete[ ] pointer;
this
Pointer
 It is the pointer which points to the current object, i.e. the object invoking the
member function.
 Whenever a member function is called, the current object calling the function is
passed to this pointer.

 Example:
this->dataMember;
this->memberFunction();
Static Data Member and static
member function
 What is static??
 Just like in C, static members are those which are unique in a class just like
normal member functions.c c
1 2

Rea 3 Rea
l l
Imagina 4 Imagina
ry ry

clas
s
Static
Member
input()

display()
magnitude
()
Static Data Member and static
member function
Static Data Member:
 It is the variable which is globally available to all the objects of the class type.
 It is used to store values which is common to the entire class.
Properties:
 Only one copy of the member is created for entire class and is shared among all
the objects of the class.
 It is visible only within the class, but its lifetime is the entire program.

 Static Data member are declared inside the class but defined outside the
class using the keyword static.

class Sagarmatha{
static int count;
};
int Sagarmatha::count; //definition of static data member
to 0
Static Data Member and static
member function
Static Member Functions:
 Those member functions which can only access static data members are called
static member functions.
Properties:
 A static member function can only access static data member of the class.
 It is invoked using the class name instead of the object name.

 Static Member Functions are declared using the keyword static.

class Sagarmatha{
static int count;
int id;
….
static void show(){
cout<<count;
//cout<<id; error as id is not static
}
};
int Sagarmatha::count; //definition of static data member
to 0
Constant Member Functions and
Constant Object
Constant Member Functions:
 If a member function of a class doesn’t alter any data in the class, this member
function is declared as a constant member functions using the keyword const.
 Example:
void interest(int, int) const;
float interest(void) const;
 The keyword const should be used in both declaration and definition.
 A constant member function can only invoke other constant member functions of
same class.

class Sagarmatha{
int count;
public:
void show() const{
cout<<count;
count=2; //error as constant member functions cannot
alter data
}
};
Constant Member Functions and
Constant Object
Constant Objects:
 The objects of any class can be defined constant using const keyword.
 Constant objects cannot change any data member. So, to ensure that constant
objects can only call constant member functions.
class Sagarmatha{
 Example: int count;
const Sagarmatha s1; public:
void input(){
count=1;
}
void show() const{
cout<<count;
count=2; //error as constant member functions cannot
alter data
}
};
int main(){
const Sagarmatha s1;
s1.show();
s1.input(); //error as it is not constant
}
Constant Member Functions and
Constant
mutable:
Object class Sagarmatha{
 In some cases, there may arise mutable int count;
a condition where we create a public:
constant object but we need to void input(){
change certain data member. count=1;
In those cases, we define the }
data members as mutable. void change() const{
 Example: count=2;
mutable int a; }
void show() const{
cout<<count;
count=2; //error as constant member functions cannot
alter data
}
};
int main(){
const Sagarmatha s1;
s1.show();
s1.input(); //error as it is not constant
s1.change(); //allowed as change() is const and it can alter
mutable data
Friend Function and Friend
Classes
 Normally, the private and protected data members of a class can only be accessed by the
member functions of that class, but in some cases, we might need to access them from
outside. So, we define friend functions which can access the private and protected data
members.
Friend Function:

class Demo{
int id;
friend void check();
private:
….
public:
….
};
void check(){
Demo d;
d.id=2;
}
Friend Function and Friend
Classes
Friend Function:
 It doesn’t have class scope, rather it depends upon its original declaration and definition.
 It doesn’t require an object of the class for invoking. It can be called as normal functions.
 Since it is non member function, it cannot access the members of the class directly and has
to use and object name.
 It can be declared anywhere, private, public or protected in the class.
 A function may be declared as friend to more than one class.

Member function of a class as a friend of another class


class A{
:
void exchange();
:
};
class B{
:
friend void A::exchange();
:
};
Friend Function and Friend
Classes
Friend as a Bridge
 A friend function can be a friend to multiple classes and act as a bridge.

class B;
class A{
:
friend void exchange(A, B);
:
};
class B{
:
friend void exchange(A, B);
:
};

void exchange(A a, B b){


}
Friend Function and Friend
Classes
Friend Class
 We can declare the entire class as a friend of another class so that each member function of
that class can access the private and protected members of another.

class B;
class A{
:
friend class B;
:
};
class B{
:
void someFunction(){
//can access all members of
A
A a;
a.someMember;
}
:
};
Operator Overloading

Bipin Thapa Magar


b
[email protected]
u.np
Operation Overloading
 The mechanism of giving special meaning to an operator while using with user defined data
type is known as operator overloading.
 Almost all operators can be overloaded except a few listed below:
1. Class member access operator (. , .*)
2. Scope resolution operator (::)
3. sizeof() operator
4. Conditional operator (?:)
 We can update the meaning but the grammatical rules such as number of operands,
precedence and associativity cannot be changed.
Eg: ++ operator can only take one operand but we can change how the operator works on
that operand.
 At least one of the operand needs to be an object of class for operator overloading.
 It displays the polymorphism feature of OOP.
Syntax of Operator
Overloading
 To define an operator overloading, we define a function that defines the task which the
operator needs to perform.
 Operator function must be either a member function or a friend function.
 Syntax:
return_type classsname::operator operator_symbol(arguments){
//body
}
Rules of Operator
Overloading
1. Only existing operators can be overloaded. New operators cannot be created.
2. The overloaded operator must have at least one operand that is of user defined type.
3. Overloaded operators follow the syntax rules of original operators. They cannot be
overridden.
4. Some operators cannot be overloaded defined before.
5. The operators which cannot be overloaded using friend functions are:
1. = Assignment Operator
2. () Function Call Operator
3. [] Subscripting Operator
4. -> Class Member Access Operator
6. In binary operator overloading using friend function, we can specify left-hand operand as
class object or built-in type same as in right-hand operand. But in binary operator overloading
Unary Operator
Overloading
 Those operators which only use a single operand are called unary operators.
 The unary operators are - (negative sign), ++ (post and pre), -- (post and pre).
 Let us take an example:
class Coordinate{
int x;
int y;
public:
int main(){
void addData(int a, int b){
Coordinate c1;
x=a;
c1.addData(4,5);
y=b;
c1.display();
}
-c1; // same as c1.operator -
void display(){
()
cout<<endl<<x <<y;
c1.display();
}
return 0;
void operator -(){
}
x=-x;
y=-y;
}
};
Unary Operator
Overloading
 Using Friend Function
class Coordinate{
int x;
int y;
public:
void addData(int a, int b){
x=a;
y=b; int main(){
} Coordinate c1;
void display(){ c1.addData(4,5);
cout<<endl<<x <<y; c1.display();
} -c1; // same as operator -
friend void operator - (c1)
(Coordinate &); c1.display();
}; return 0;
void operator -(Coordinate &c){ }
c.x=-c.x;
c.y=-c.y;
}
Binary Operator
Overloading
+
 >>
 <<
 []
 ()
=
Data Type Conversion
1. Basic to Basic
 When constants and variables of diferent type are mixed in an expression, they are
converted to same type.

a. Implicit type conversion:


 If type conversion is done by compiler without programmer’s intervention, it is known as
implicit type conversion.
 Eg:
int a=10,b=20;
float c=30,d;
d=a+b+c; //here output is in float
b. Explicit type conversion:
 If user forces a type conversion, it is called explicit type conversion.
 Syntax
(type) expression
OR
static_cast<type>object
 Eg:
int a;
float f=9.8;
a=(int)f;
Data Type Conversion
2. Conversion between basic and user-defined(class) type
a. Basic to user defined
b. User Defined to Basic
c. User Defined to User Defined

d. Basic to User Defined


 C++ allows us to convert a basic data type variable to a user defined or an object by using
constructors.
 Syntax:
constructor(basic type)
{
//conversion;
}
Data Type Conversion
a. Basic to User Defined
int main(){
class String{ String S1,S2;
char *name; char *n1=“Ram”;
int length; char *n2=“Thapa”;
public:
String() {} S1=String(n1);
String(char *s) { S2=n2;
length=strlen(s); S1.display();
name=new char[length]; S2.display();
strcpy(name,s); }
}
void display(){
cout<<endl<<name;
}
}; OUTPUT
Ram
Thapa
Data Type Conversion
b. User Defined to Basic
 Syntax:
operator type_name(){
//statements;
} int main(){
String S1=“Ram”;
class String{ String S2=“Thapa”;
char *name; char *n1, *n2;
int length; n1=S1;
public: n2=static_cast<char*>(S2);
String() {} cout<<endl<<n1;
String(char *s) { cout<<endl<<n2;
length=strlen(s); }
name=new char[length];
strcpy(name,s);
} OUTPUT
operator char*(){ Ram
return name; Thapa
}
};
Data Type Conversion
c. User Defined to User Defined
 This can be performed by using any of the two methods mentioned before, but first we have
to identify the source and destination class.
 Example:
obj1=obj2;
 Here, obj2 is the object of source class and obj1 is the object of the destination class.

Using Constructor:
 In this method, a constructor needs to be placed inside the destination class with argument
of source data type.
 Syntax:
Class1(Class2 obj){
//statements
}
Using cast operator:
 In this method, cast operator needs to be placed inside source class with type name of
destination class.
 Syntax:
operator Class1() //inside Class2
//statements
}
Data Type Conversion
c. User Defined to User Defined
class Celsius;
class Fahrenheit{ void display(){
float F; cout<<endl<<C;
public: }
void input(){ };
cout<<“Enter Fahrenheit
temperature:”; Fahrenheit::operator Celsius(){
cin>>F; Celsius temp( (F-32)/1.8);
} return temp;
operator Celsius(); }
};
class Celsius{ int main(){
float C; Fahrenheit F1;
public: Celsius C1;
Celsius(){ } F1.input();
Celsius(float c1){ C1=F1;
C=c1; C1.display();
} }
class Polar{
float Rad; Rectangle(){ }
float Ang; Rectangle(Polar p){
public:
int main(){
Polar(){}; x=p.getRad()*cos(p.getAng());
Polar p1;
Polar(Rectangle);
cout<<“Enter value of
void input(){ y=p.getRad()*sin(p.getAng());
polar:”;
cin>>Rad>>Ang; }
p1.input();
} void input(){
void display(){ cin>>x>>y;
Rectangle r1;
cout<<“\ }
r1=p1;
nRadius:”<<Rad; void display(){
r1.display();
cout<<“\ cout<<“\nX :”<<x;
nAngle:”<<Ang; cout<<“\nY :”<<y;
Rectangle r2;
} }
Polar p2;
float getRad(){ float getX(){ return x; }
cout<<“\nEnter value in
return Rad; float getY(){ return y; }
rect:”;
} };
r2.input();
float getAng(){
p2=r2;
return Ang; Polar::Polar(Rectangle r){
p2.display();
} Rad=sqrt(r.getX()*r.getX()
}
}; +r.getY()*r.getY());
class Rectangle{ Ang=atan(r.getY()/r.getX());
float x; }
float y;
Data Type Conversion
Explicit:
 There might be times when you donot want conversion to take place. In such times, if we are
using cast operator, we can simply remove it from code but constructor cannot be removed
trivially. In such case, they can be defined as explicit to prevent from type casting.
 Eg: class XYZ{
int a;
public:
explicit XYZ(int m){
 In the example shown, a=m;
XYZ obj(5); }
}; object.
is valid as it uses the contructor definition to create the

XYZ obj = 5;
is invalid although we studied that type cast allows us to create such object using
constructor. It is invalid because we used the ‘explicit’ keyword.
Inheritance

Bipin Thapa Magar


b
[email protected]
u.np
Inheritance
 The capability of one class to inherit the properties of another class is known as inheritance.
 The process of deriving a new class from old class where the old class is called base class
and the new class is called derived class.
 Using inheritance, we can increase code reusability as the same base class can be used in
various other classes.

Need for Inheritance:


 It gives the capability to express the inheritance relationship that ensures the closeness with
the real world models.
 It allows code reusability as one can derive an existing class and add new features to it.
 Because of transitive nature of inheritance, if one class D inherits the properties of another
class B, all the derived class of D automatically inherits the properties of B.

 A derived class (sub class) is the class that inherits the properties of another class called
base class (super class).
 Syntax:
class derivedClassName : visibilityMode BaseClassName{
: //members of derived class
};
 Example:
Inheritance
class D : public B{ //public derivation
//members of D
};
class D : protected B{ //protected derivation
//members of D
};
class D : private B{ //private derivation
//members of D
};
class D : B{ //private derivation by default
//members of D
};
Visibility Modes
Inheritance

class Base{
protected:
int n;
public:
void input(){ int main(){
cout<<“\n Enter a value:”; Derived D1;
cin>>n; D1.input();
} D1.display();
}; system(“pause”);
class Derived: public Base{ return 0;
public: }
void display(){
cout<<“\n n=“<<n;
}
};
Member function overriding
 Overriding and Overloading are two different things. In Overloading, we create a function
with same name but different type or number of arguments. In Overriding, we create
identical functions in both base and derived class.
 If we create the members identical to the base class, the members of derived class override
its parent’s members and the members of base class are hidden.
class Base{
void input(){
protected:
cout<<“\n Enter a value in
int n;
Derived:”;
public:
cin>>n;
void input(){
}
cout<<“\n Enter a value in
void display(){
Base:”;
cout<<“\n n=“<<n;
cin>>n;
}
}
};
};
int main(){
class Derived: public Base{
Derived D1;
protected:
D1.input();
int n;
D1.display();
public:
}
Member function overriding
 If we want to access the hidden members of base class, we use:
baseClassName::member
 We can use it inside derived class or main().

void input(){
class Base{ Base::input();
protected: cout<<“\n Enter a value in
int n; Derived:”;
public: cin>>n;
void input(){ }
cout<<“\n Enter a value in void display(){
Base:”; cout<<“\n n=“<<n;
cin>>n; cout<<“\n n=“<<Base::n;
} }
}; };
class Derived: public Base{ int main(){
protected: Derived D1;
int n; D1.input();
public: D1.display();
}
Member function overriding

void input(){
class Base{
cout<<“\n Enter a value in
protected:
Derived:”;
int n;
cin>>n;
public:
}
void input(){
void display(){
cout<<“\n Enter a value in
cout<<“\n n=“<<n;
Base:”;
cout<<“\n n=“<<Base::n;
cin>>n;
}
}
};
};
int main(){
class Derived: public Base{
Derived D1;
protected:
D1.input();
int n;
D1.Base::input();
public:
D1.display();
}
Member function overriding
 In case of base class having overloaded
functions or if we overload the function in
derived class, we cannot access them from void input(int c, int d){
derived class as they are hidden. So, we have to n=c;
invoke them
class Base{as before. m=d;
protected: }
int n; void display(){
public: cout<<“\n n=“<<n;
void input(){ cout<<“\n m=“<<m;
cout<<“\n Enter a value in cout<<“\n n=“<<Base::n;
Base:”; }
cin>>n; };
} int main(){
void input(int a){ Derived D1;
n=a; D1.input(10,20); //ok
} D1.input() //error
}; D1.input(5) //error
class Derived: public Base{ D1.Base::input(); //ok
protected: D1.Base::input(5); //ok
int m,n; D1.display();
public: }
Forms of Inheritance
 A class can be derived in various ways which are listed as follows:

1. Single Inheritance
2. Multiple Inheritance
3. Hierarchical Inheritance
4. Multilevel Inheritance
5. Hybrid Inheritance

1. Single Inheritance:
 When a subclass inherits from only one base class, it is known as single inheritance.
 Syntax: class DerivedClassName: visibilityMode BaseClassName{
//members
}
B Base Class

D Derived Class
Forms of Inheritance
2. Multiple Inheritance:
 When a subclass inherits from multiple base class, it is known as multiple inheritance.
 Syntax: class DerivedClassName: visibilityMode Base1, visibilityMode Base2, [,
visibilityMode BaseN]{
//members
}
B1 B2 Base Class

D Derived Class

Ambiguity in Member Access:


 If two or more base class has the member with same name, the derived class will be
confused of which member to call. So, in such cases ambiguity occurs. To remove such
ambiguity, we call the base class member with the base class name and scope resolution
operator as:
BaseClassName::member
Forms of Inheritance
3. Hierarchical Inheritance:
 When many sub class inherit from the same base class, it is known as hierarchical
inheritance.
 Syntax: class DerivedClassName1: visibilityMode Base{
//members
}
class DerivedClassName2: visibilityMode Base{
//members
}
B1 Base Class

D1 D2 Derived Class
Forms of Inheritance
4. Multilevel Inheritance:
 When a subclass inherits from a class which itself inherits from another class, it is known as
multilevel inheritance.
 Syntax: class DerivedClassName1: visibilityMode Base{
//members
}
class DerivedClassName2: visibilityMode DerivedClassName1{
//members
}
B Base Class to D1

D1 Derived Class of B
Base Class to D2

D2 Derived Class of D2
Forms of Inheritance
5. Hybrid Inheritance:
 When a subclass inherits from multiple base class and all of its base class inherit from a
single base class, it is known as hybrid inheritance.

B1
B1 B2

D
D1 D2

D1 D2
D3
Multipath Inheritance and virtual base
class
 When a base class is derived to two or more than two derived class and the derived classes
are again inherited to the another class, the main base class is inherited from two different
paths which is known as multipath inheritance.
 In such cases, the grandchild gets two copy of the main base class. To prevent it, we cant
inherit the class as virtual.
B1

D1 D2

D3
Constructor and Destructor invocation in
Inheritance
 When we inherit a class, the constructor of the base class is called and after that the
constructor of derived class.
 Similarly, destructor of derived class is called before base class. It is due to the fact the base
class’s members need to be defined before the derived as the base class are inherited.
class Base{ ~Derived(){
public: cout<<“\n Derived Destructor”;
Base(){ }
cout<<“\n Base Constructor”; };
}
~Base(){ int main(){
cout<<“\n Base Destructor”; Derived D1;
} }
};
class Derived: public Base{
public: OUTPUT:
Derived(){ Base Constructor
cout<<“\n Derived Derived Constructor
Constructor”; Derived Destructor
} Base Destructor
Constructor and Destructor invocation in
Inheritance
 If we want to pass arguments to base class, we use initialization list.

class Base{
protected:
int x;
public:
Base(int a){
x=a;
} int main(){
}; Derived D1;
class Derived: public Base{ }
public:
Derived():Base(10)
{
cout<<“\n Derived
Constructor”;
}
};
Constructor and Destructor invocation in
Inheritance
 Normally, we pass the argument from main function as follows:

class Base{
protected:
int x;
public:
Base(int a){
x=a;
}
}; int main(){
class Derived: public Base{ Derived D1(10,5);
int y; }
public:
Derived(int a, int b):Base(a)
{
y=b;
}
};
Constructor and Destructor invocation in
Inheritance
 In case of multiple constructors in the base class, the constructor defined will be called.

class Derived: public Base{


int y;
public:
class Base{ Derived(): Base(10)
protected: {
int x; y=5;
public: }
Base(){ Derived(int b) {
x=0; y=b;
} }
Base(int a){ };
x=a;
} int main(){
}; Derived D1; // Derived() and
Base(int a)
Derived D2(5); // Derived(int b)
and Base()
}
Constructor and Destructor invocation in
Inheritance
 If base class constructors don't take arguments, class
derived class needn't
Derived: specify a constructor,
public Base1,public
else it does.
class Base1{ Base2{
public: public:
Base1(){ Derived() {
cout<<“\n Base1 constructor”; cout<<“\n Derived
} Constructor”;
~Base1(){ }
cout<<“\n Base1 destructor”; ~Derived() {
} cout<<“\n Derived Destructor”;
}; }
class Base2{ };
public: int main(){
Base2(){ Derived D1;
cout<<“\n Base2 constructor”; }
OUTPUT:
} Base1 Constructor
~Base2(){ Base2 Constructor
cout<<“\n Base2 destructor”; Derived Constructor
} Derived Destructor
}; Base2 Destructor
Base1 Destructor
Constructor and Destructor invocation in
Inheritance
 If base class has parameterized constructor, invocation is based on declaration not
class Derived: public Base1,public
initialization list.
class Base1{ Base2{
protected: int c;
int a; public:
public: Derived(int x, int y, int z):Base2(y),
Base1(int x){ Base1(x) {
cout<<“\n Base1 constructor”; cout<<“\n Derived
a=x; Constructor”;
} c=z;
}; }
class Base2{ };
protected: int main(){
int b; Derived D1(1,2,3);
public: }
Base2(int y){
cout<<“\n Base2 constructor”; OUTPUT:
b=y; Base1 Constructor
} Base2 Constructor
}; Derived Constructor
Constructor and Destructor invocation in
Inheritance
 The constructor of virtual base class are invoked before other non-virtual base classes. If
there are multiple virtual base classes, it is invoked in order of declaration of inheritance.

Method of Inheritance Order of execution


class B: public A{ A(): base constructor
… B(): derived constructor
}
class C: public A, public B{ A()
… B()
} C()
class C: public A, virtual public B()
B{ A()
… C()
}
class C: virtual public A, virtual A()
public B{ B()
…. C()
}
Nested Classes
 We can use the properties of one class in another, not only with inheritance but nested
classes too.
class Z{
Y obj1;
X obj2;
class X{
public:
public:
Z(){
X(){
cout<<“\n Z Constructor”;
cout<<“\n X constructor”;
}
}
};
};
int main(){
class Y{
Z obj;
public:
}
Y(){
cout<<“\n Y constructor”;
}
}; OUTPUT:
Y Constructor
X Constructor
Z Constructor
Nested Classes
 We can pass values to constructor as follows.

class X{
protected:
int x;
public:
X(int a){
x=a;
}
}; int main(){
class Y{ Y obj(1,2);
X obj1; }
int y;
public:
Y(int a, int b): obj1(a)
{
y=b;
}
};
Polymorphism and Dynamic Binding

Bipin Thapa Magar


b
[email protected]
u.np
Polymorphism
 Polymorphism means multiple forms. If a single entity can have multiple forms or can
perform multiple actions based on the situation, it can be termed as polymorphism.
 We can achieve Polymorphism using operator overloading, function overloading and virtual
function.
 If polymorphism occurs during compilation, it is known as compile time polymorphism.
Function overloading and Operator overloading are examples of run time polymorphism.
 If polymorphism occurs during execution, it is known as run time polymorphism which can be
seen using virtual function.
Polymorphism

Compile time Run Time

Function Operator
Overloading Overloading Virtual Function
Pointer to Derived Class
 We can normally create pointer to both base class an derived class as needed.
Eg:
Base *bptr,bobj;
bptr=&bobj;
 Similarly we can create pointer to derived class as well, but also we can use the pointer to
base class to point to an object of derived class. It is because the derived class contains all
the contents of the base class. Note that since the base class pointer only knows of the
members of the base class, if we assign an object of derived class to it, we can still only use
the members of base class which is inherited.
 Also, the vice-versa doesn’t exits, meaning we cant assign a pointer of derived class to
object of base class.
Base Object
Base Pointer
Derived
Object

Derived Derived
Pointer Object
Pointer to Derived Class

class Base{ int main(){


public: Base *bptr;
int n; Derived d1;
void display(){ bptr=&d1;
cout<<“Base class: “<<n; bptr->n=10;
} //bptr->d=5;
}; bptr->display(); // Invokes Base
class Derived: public Base{ class
public:
int d; Derived *dptr;
void display(){ dptr=&d1;
cout<<“Derived class: dptr->d=5;
“<<d<<“ ”<<n; dptr->display(); // Invokes
} Derived class
}; }
Virtual Function
 As seen in the example, when we assign an object to the pointer, the function is invoked
based on the type of the pointer and not the object. If we want to invoke the members based
on object, we use virtual function.
 A virtual function is a member function that is declared within a base class and redefined by
a derived class.
 Syntax:
class Base{

virtual returnType functionName(args){
….
}

}
 In normal conditions, virtual function act similar to other functions.
 When a class containing virtual function is inherited, the derived class redefines its own
member function. So, when a base class pointer is used to point to the object of derived
class, the virtual function forces the program to invoke the function of the derived class by
checking the type of object stored in the pointer.
Virtual Function

class Base{ int main(){


public: Base *bptr,B1;
virtual void display(){ Derived D1;
cout<<“\nBase class display”;
} bptr=&B1;
void show(){ bptr->display();
cout<<“\nBase class show”; bptr->show();
}
}; bptr=&D1;
class Derived: public Base{ bptr->display();
public: bptr->show();
void display(){ }
cout<<“\nDerived class
display”;
} OUTPUT:
void show(){ Base class display
cout<<“\nDerive class show”; Base class show
} Derived class display
}; Base class show
Virtual Function
 The virtual attribute is also inherited if another class is derived from the already derived
class Base{
class.
public:
virtual void display(){
cout<<“\nBase class display”; int main(){
} Base *bptr;
}; Derived1 *dptr,D1;
class Derived1: public Base{ Derived2 D2;
public:
void display(){ bptr=&B1;
cout<<“\nDerived1 class bptr->display();
display”;
} bptr=&D1;
}; bptr->display();
class Derived2: public Derived1{
public: dptr=&D2;
void display(){ dptr->display();
cout<<“\nDerived2 class }
display”;
}
};
Array of Pointer to the Base
Class
 So, using virtual functions, we can invoke various functions using the same pointer.
class Father{ int main(){
public: Father F1;
virtual void display(){ Son S1;
cout<<“\nFather class Daughter D1;
display”;
} Father *fptr[]={&F1, &S1,
}; &D1};
class Son: public Father{
public: for(int i=0;i<3;i++){
void display(){ fptr[i]->display();
cout<<“\nSon class display”; }
} }
};
class Daughter: public Father{
public: OUTPUT:
void display(){ Father class display
cout<<“\nDaughter class Son class display
display”; Daughter class display
}
};
Pure Virtual Function and Abstract
Classes
 In normal cases, if the derived class doesn’t override the virtual function, the object can then
invoke the base class function. But in most cases, base class function is not defined or we
don’t create or invoke the function and object of base class. So, in such cases, we defined
them as pure virtual function.
 A pure virtual function is virtual function that has no definition within the base class.
 Syntax:
virtual returnType functionName(args) = 0;
 A class with a pure virtual function in it is called abstract class. Since, it has functions with
no definition, we cannot create any object but pointers are still allowed.
 Also, if the deriving class doesn’t override the pure virtual function, it itself becomes an
abstract class as well.
Pure Virtual Function and Abstract
Classes
class Rectangle: public Dimension{
class Dimension{
public:
protected:
Rectangle(int x, int y):
int l,b;
Dimension(x,y)
public:
{}
Dimension(int x, int y){
void area(){
l=x;
cout<<“\nArea is “<<l*b;
b=y;
}
}
};
virtual void area()=0;
};
int main(){
class Square: public Dimension{
Square S(10);
public:
Rectangle R(10,20);
Square(int x): Dimension(x,x)
{}
Dimension *dptr[]={&S, &R};
void area(){
cout<<“\nArea is “<<l*b;
for(int i=0;i<2;i++){
}
dptr[i]->area();
};
}
}
Virtual
Destructor
 A destructor needs to be set virtual if object are created using dynamic memory allocation
and delete operation needs to be done in base and derived class.
 If a base class operator is pointing towards derived class object, normally the destructor of
base class will be invoked. To invoke the destructor of derived class, virtual destructor are
used.
Virtual
Destructor
class Base{
public:
Derived(char *n,char *a):
protected:
Base(n){
char *name;
cout<<“\nDerived
public:
Constructor”;
Base(char *n){
int l=strlen(a);
cout<<“\nBase
address=new char[l];
Constructor”;
strcpy(address,a);
int l=strlen(n);
}
name=new char[l];
~Derived(){ Output:
strcpy(name,n);
cout<<“\nDerived Base Constructor
}
Destructor”; Derived Constructor
virtual ~Base(){
delete[] address; Derived Destructor
cout<<“\nBase
} Base Destructor
Destructor”;
};
delete[] name;
int main(){
}
Base *bptr;
};
class Derived: public Base{
bptr=new
protected:
Derived(“Ram”,”Sanepa”);
char *address;
delete bptr;
reinterpret_cast
Operator
 This operator is used to convert one type into fundamentally different type.
 Syntax:
reinterpret_cast<type>(object);

 Here, type specifies the target type of the cast and the object being cast to the new type.
 The reinterpret_cast converts the object fro one type to another type without checking the bit
pattern or size of source and destination type.

int main(){
int a=10;
float *d=reinterpret_cast<float
OUTPUT:
*>(a);
int f= reinterpret_cast<int>(d);
0xa 10 10
cout<<d<< “ “<<f<< “ “<<a;
return 0;
}
Run-Time Type
Information
 In run-time polymorphism, we learnt that the type of pointer can vary based on the object it
is holding at run-time. There may arise situations where we need to change the type or even
find out the type of the pointers. At such case, we can use the following operators which are
termed as Run-Time Type Information.

1. dynamic_cast operator
 The dynamic_cast operator performs a run time cast along with verifying the validity of a
cast. If the cast is invalid at runtime, then the cast fails by returning NULL.
 Syntax:
dynamic_cast<type>(expr)

 Casting from derived class to base class is called upcast. In C++, a derived class pointer can
be assigned to base class pointer due to inheritance and it is done implicitly.
 Casting from base class to derived class is called downcast. The base class pointer can have
the address of derived class object, then this address of derived class can be assigned to
derived class pointer. This is done using dynamic_cast operator.
 For dynamic_cast to work, base class should be polymorphic, i.e. it must have at least one
virtual function.
Run-Time Type
Information
class Base{
public:
virtual void display(){
cout<<“\nBase Class”; int main(){
} check(new Base());
}; check(new Derived());
class Derived: public Base{ }
public:
void display(){
cout<<“\nDerived
Class”;
}
};
void check(Base *b){ Output:
Derived *d; Base Class
if(d=dynamic_cast<Derived Derived Class
*>(b)){
d->display();
}
else{
b->display();
}
Run-Time Type
Information
2. typeid operator
 This is used to get the type of the object or variable during runtime.
 To use this, we need to include <typeinfo> header file.
 It returns an object of class type_info with the following public members:
bool operator ==(const type_info &obj)
bool operator !=(const type_info &obj)
bool before(const type_info &obj)
const char *name()
 Syntax:
typeid(object);
Run-Time Type
Information
class temp1{ };
class temp2{ };
int main(){
int a;
char *name;
temp1 t1;
temp2 t2;
OUTPUT:
cout<<“\nType of a is
Type of a is int
“<<typeid(a).name();
Type of name is char *
cout<<“\nType of name is
Type of a is class temp1
“<<typeid(name).name();
Type of a is class temp2
cout<<“\nType of t1 is
Different type of t1 and t2
“<<typeid(t1).name();
cout<<“\nType of t2 is
“<<typeid(t2).name();
if( typeid(t1) !=typeid(t2)){
cout<<“\nDifferent type of t1 and t2”;
}
}
Stream Computation for Console and File Input
Output

Bipin Thapa Magar


b
[email protected]
u.np
Stream Computation for Console and File
Input Output
 A stream is a sequence of byte that acts as a source from which input data can be obtained
or as a destination to which output data can be sent. In C++, there are various stream to
deal with both console and disk files known as stream classes.

ios

istream ostream
streambuf

iostream

Istream Iostream Ostream


Testing Stream
Errors
 During input or output using cout and cin, errors may occur which can be checked using
following:
 ios::eof() = This function return true or 1 when input operation reaches end of input
sequence.
 ios::bad() = Return true or 1 when I/O cannot be performed.
 ios::fail() = return true or 1 if input fails to read sequence or output fails to display
 ios::clear() = clears all the flags
Unformatted I/O
 We used the object cin and cout in iostream for input and output of data of various types. In
addition, there are some other functions which can be used with the above objects for
unformatted I/O.
a. put()
b. get()
c. getline()
d. write()
Unformatted I/O

put() and get()


 The get() function is used with the object cin and has two variances: get(char &) and
get(void).
 eg:
char ch;
cin.get(ch);

char ch= cin.get();


 In both examples, an input character from the keyboard is stored to ch.
 The difference between get() and normal input using “>>” is that when using “>>”, it
ignores the blank spaces while get() doesn’t.
 The other form of get() is:
istream& get(char *str, int num, char delim=‘\n’)
Here, str is the array where string or characters are stored. num is the number of
characters to store and delim is a character which allows the reading of input to stop when
encountered. By default, it is newline.
cin.get(str,20,’$’);
 The put() function is used with the object cout as:
eg:
cout.put(‘a’);
cout.put(ch);
Unformatted I/O
int main(){
char ch, string[20];
cout<<“Enter the string:”;
int i=0;
while(1){
ch=cin.get();
if(ch==“\n”){
string[i]=“\0”;
break;
} OUTPUT:
string[i]=ch; Enter the string: Ram Thapa
i++; The string is: Ram Thapa
} Character wise display: Ram Thapa
cout<<“\n The string is :”<<string;
cout<<“\n Character wise
display:”;
for(int i=0;string[i]!=“\0”;i++){
cout.put(string[i]);
}
return 0;
}
Unformatted I/O

getline()
 The getline() is different than normal “>>” because it doesn’t discard any whitespaces just
like the get() function.
istream& getline(char *str, Stringsize S, char delim=‘\n’)

int main(){
char name[20];
OUTPUT:
char Address[50];
Enter name of student: Ram Thapa
cout<<“\nEnter name of student:”;
Enter the address: Sanepa
cin.getline(name,20);
Lalitpur
cout<<“\nEnter the address:”;
Nepal$
cin.getline(Address,50,’$’);
Name: Ram Thapa
cout<<“\nName:”<<name;
Address: Sanepa
cout<<“\nAddress:”<<Address;
Lalitpur
return 0;
Nepal
}
Unformatted I/O

write()
 Just like getline(), to display an entire line, we have a write function.
ostream& write(char *s, Streamsize size);
 The first argument, s , is the string to display and the size is the number of characters to
show which is always less than or equal to size of string.
int main(){
char name[50];
cout<<“\n Enter the name:”; OUTPUT:
cin>>name; Enter the name: Ramesh
cout<<“\nDisplaying in triangular Displaying in triangular format:
format:\n”; R
int length=strlen(name); Ra
for(int i=1;i<=length;i++){ Ram
cout.write(name,i); Rame
cout<<“\n”; Rames
} Ramesh
return 0;
}
Formatted I/O

 We have three options for formatted output:


1. ios stream class member functions and flags
2. Standard manipulators
3. user-defined manipulators

1. Formatted I/O using ios Member functions and flags:


 The ios class contains a number of member function that can be used to format the output is
different ways.

a. Defining field width: width()


 It is used to defined the number of fields to display an item:
 Syntax:
cout.width(w);
where w is the width or number of columns. The output is printed from right hand side. If
field width is smaller than the size, the width() is neglected.
 Example: 1 0 7
cout.width(5);
cout<<107; 1 0 7 2 0 0
cout<<200;
Note that the width() is used for only one item immediately following it and all others will
Formatted I/O

b. fill()
 It is used to fill the empty spaces which is filled with white spaces by default.
 Syntax:
cout.fill(ch);
where ch is some characted
 Example:
cout.width(5);
cout.fill(‘*’); * * 1 0 7
cout<<107;
This function fill remains unchanged until we change it.

c. precision()
 By default, floating numbers are shown with six digit after decimal point. We can change it
as:
cout.precision(d);
where d is the number of digits to the right of decimal point.
 Example:
cout.precision(3);
cout<<10.200124
OUTPUT: 10.2
 This setting also is saved unless changed.
Formatted I/O

d. setf():
 We know that width() displays value from right but what if we need to display from left. For
such and may others, we can set flags as:
cout.setf(arg1,arg2);

The arg1 is one of the formatting flags defined in the ios class and arg2 is known as bit flag
which is used to specify the group to which the formatting flag belongs.

Format Required Flag value Bit-field value


Left-justified output ios::left ios::adjustfield
Right-justified output ios::right ios::adjustfield
Filling the characters ios::internal ios::adjustfield
to display after sign
or base
Scientific notation ios::scientific ios::floatfield
Fixed point notation ios::fixed ios::floatfield
Decimal base ios::dec ios::basefield
Octal base ios::oct ios::basefield
Formatted I/O

 Example:
cout.width(12);
cout.precision(3); * * 1 . 0 3 0 e + 0 0 1
cout.fill(*);
cout.setf(ios::internal,ios::adjustfield);
cout.setf(ios::scientific,ios::floatfield);
cout<<10.298235
 Following are some flags that don’t have bit flags:

Flag value Meaning


ios::showpoint Show point and trailing zeros
ios::showbase Use base indicator on output
ios::showpos Show + sign for positive number
ios::uppercase Show uppercase letters for hex
output
ios::skipus Skip whitespace character on
input
ios::unitbuf Flush all streams after insertion
Formatted I/O

2. Standard Manipulators:
 The header file iomanip provides a set of manipulators which has already been discussed
before:
 There are two types of manipulators: Parameterized manipulator and Non-parameterized
manipulator
 Parameterized: setw(), setprecision()
 Non-parameterized: endl
 The difference between manipulator and ios function is that manipulators can be cascaded in
a single line but ios function cannot. Also, ios functions can be called once to have its effect
throughout the program while manipulators cannot.
 eg:
Manipulator Equivalent
cout<<setfill(‘*’)<<setw(10)<<123123;
setw(int w) width()
setprecision(int d) precision()
setfill(char ch) fill()
setiosflags(long f) setf()
resetiosflags(long f) unsetf()
endl \n
Formatted I/O

3. User-defined manipulators or Stream Operator Overloading


 In C++, user can define their own manipulators like aa built in manipulator for formatting the
output.
ostream& manipulator(ostream & output){
.
.
return output;
}
ostream & Dollar(ostream &out){
out<<“\t”;
out<<“$”;
return out;
} OUTPUT:
int main(){ Salary is: $1200.234
cout<<“Salary
is:”<<Dollar<<1200.234;
return 0;
}
File I/O with
Stream
 The fstream library provides a set of operations for handling file related input and output.

File Stream Class Hierarchy

ios

iostream istream streambuf ostream


File
iostream

fstream File ifstream fstream ofstream filebuf

fstreambas
e
File Stream Class
Hierarchy
filebuf: It sets the file buffers to read and write. It contains close() and open() member functions
in it. It is derived from streambuf and is internally used by file stream classes for buffer
management.

fstreambase: This is the base class for fstream, ifstream and ofstream. It also has open() and
close() functions.

ifstream: It provides input operations for file. It inherits the functions get(), getline(), read() and
functions supporting random access like seekg() and tellg() from istream class defined inside
iostream.h

ofstream: It provides output operations. It inherits put() and write() functions along with
functions supporting random access (seekp() and tellp()) from ostream class defined inside
iostream.h

fstream: It is an input-output file stream class. It provides support for simultaneous input and
output operations. It contains open() with default input mode. It inherits all the functions from
istream and ostream classes through iostream class defined inside iostream.h
Opening and Closing
files
 In C++, to open a file, we need to obtain a stream. There are three types of streams: input,
output and input/output using ifstream, ofstream and fstream classes.
 There are two ways of opening files:
a. Using the constructor function of stream class
b. Using the function open()

 The first method is preferred when a single file is used with stream, however, for managing
multiple files with the same stream, the second method is preferred.

a. Opening files using Constructor:


 The stream classes, ifstream, ofstream and fstream takes the filename as arguments to open
files.
 Example:
ifstream fin(“Student.txt”);
 The above example creates an object of ifstream which allows reading from the file as
int d;
fin>>d; //read an integer from file
char ch;
fin>>ch; //read a character from file
 Similarly, if we want to write to the file, we open using ofstream:
ofstream fout(“Teacher”);
Opening and Closing
files
 The files are closed automatically when the input and output stream objects expire. Also, we
can manually close the connections as:
fin.close();
fout.close();
 Note that the file connection only closes but the stream objects still exists and can be
connected to another connection.
#include<iostream> strcpy(name,” “);
#include<fstream> roll=0;
using namespace std;
int main(){ ifstream fin(“Student”);
char name[20]; fin>>name>>roll;
int roll;
cout<<“\nEnter the name of cout<<“\nName:”<<name;
student:”; cout<<“\nRoll:”<<roll;
cin>>name; return 0;
cout<<“\nEnter the roll of student:”; }
cin>>roll;

ofstream fout(“’Student”);
fout<<name<<“\n”<<roll;
fout.close();
Opening and Closing
files
b. Opening files using open() function:
 If we want to open more than one file using the same object, we use open() function.
ifstream fin;
fin.open(“SomeFile”);
fin.close();
fin.open(“SomeOtherFile”);
#include<iostream> strcpy(name,” “);
#include<fstream> roll=0;
using namespace std;
int main(){ ifstream fin;
char name[20]; fin.open(“Student”);
int roll; fin>>name>>roll;
cout<<“\nEnter the name of
student:”; cout<<“\nName:”<<name;
cin>>name; cout<<“\nRoll:”<<roll;
cout<<“\nEnter the roll of student:”; return 0;
cin>>roll; }
ofstream fout;
fout.open(“’Student”);
fout<<name<<“\n”<<roll;
fout.close();
Opening and Closing
files
File Modes:
 Normally, the files are opened in default mode, i.e. ifstream for read and ofstream for write.
 We can change the modes by specifying a second parameter to the open() function as:
stream_object.open(“filename”,filemode);
 The available file modes are as follows:
ios::in : This mode allows you to open a file for reading only.
ios::out : This mode allows you to open a file for writing only. It also opens the file in ios::trunc
mode which means the file is truncated on open, meaning all previous contents will be
discarded.
ios::ate : This seeks to end-of-file upon opening the file. The input and output operation can be
performed anywhere wihin the file.
ios::app: This causes all output to be appended to the end of the file. This is used only with file
where only write operation is performed. This is similar to ios::ate but ios::ate can move the
pointer anywhere in the file but it doesn’t.
ios::trunc: This causes the contents of the pre-existing file by same name to be flushed and
truncates the file to zero length.
ios::nocreate : This causes the open() method to fail if the file doesn’t already exist.
ios::binary : This causes a file to be opened in binary mode. By default, all files are opened in
text mode.

We can combine two or more modes as:


Read and Write from
file
a. Insertion Operator(<<) and Extraction operator(>>)

#include<iostream> strpy(name,” “);


#include<fstream> roll=0;
using namespace std;
int main(){ ifstream fin(“Student”);
char name[20]; fin>>name>>roll;
int roll;
cout<<“\nEnter the name of cout<<“\nName:”<<name;
student:”; cout<<“\nRoll:”<<roll;
cin>>name; return 0;
cout<<“\nEnter the roll of student:”; }
cin>>roll;

ofstream fout(“’Student”);
fout<<name<<“\n”<<roll;
fout.close();
Read and Write from
file
b. get() and put() function
#include<iostream>
#include<fstream> fout.close();
using namespace std; cout<<“\nTeacher name is:”;
int main(){ ifstream fin;
char ch; fin.open(“Teacher”,ios::in);
cout<<“\nEnter the name of if(!fin){
teacher:”; cout<<\nFile cannot be
ofstream fout; opened”;
fout.open(“Teacher”,ios::app); return 1;
if(!fout){ }
cout<<“\n File cannot be while(1){
opened”; fin.get(ch);
return 1; if(fin.eof()){
} break;
while(1){ }
cin.get(ch); cout.put(ch);
if(ch==“\n”){ }
break; fin.close();
} return 0;
fout.put(ch); }
Read and Write from
file
c. read() and write() function
 These functions are used for binary files.
 Syntax:
streamObj.write((char *) &variable, sizeof(variable));
streamObj.read((char *) &variable, sizeof(variable));

We can cast the variable to char * as:


streamObj.write(reinterpret_cast<char *>(&variable), sizeof(variable));
int main(){
char name[20];
ifstream fin;
char ch;
fin.open(“Teacher”,ios::binary);
cout<<“\nEnter the name of
fin.read((char
teacher:”;
*)&name,sizeof(name));
cin>>name;
cout<<“\nTeacher name
ofstream fout;
is:”<<name;
fout.open(“Teacher”,ios::binary);
fin.close();
fout.write((char
return 0;
*)&name,sizeof(name));
}
fout.close();
Read and Write from
file
Reading and Writing Class Object:

class Student{
int main(){
char name[20];
fstream file;
int roll;
file.open(“student”,ios::app|ios::out|
char address[20];
ios::binary);
public:
Student s;
void input(){
s.input();
cout<<“\nEnter name, roll and
file.write((char *)&s, sizeof(s));
address”;
file.close();
cin>>name>>roll>>address;
}
file.open(“student”,ios::in|ios::binary);
void display(){
while(file.read((char *)&s, sizeof(s)){
cout<<“\nName:”<<name;
s.display();
cout<<“\nRoll:”<<roll; cout<<“\
}
nAddress:”<<address;
file.close();
}
}
};
File Access Pointer and their
Manipulators
 C++ allows us to access file sequentially as well as randomly. To access in random, we use
seekg() , seekp(), tellg() and tellp() to get the pointer location and set it during file operation.
tellg() and tellp()
 The tellg() function is used for ifstream and tellp() for ofstream. If both are used for fstream,
both returns same value.
 These pointers return the position of get_pointer and put_pointer in terms of byte number
from output and input file respectively.
 Prototypes:
long tellg();
long tellp();
 Example:
int position_read=fin.tellg();
int position_write=fout.tellp();
seekg() and seekp()
 The seekg() function is used for ifstream and seekp() for ofstream.
 These pointers sets the get_pointer during reading and put_pointer during writing.
 Prototypes:
istream& seekg(long);
ostream& seekp(long);

istream& seekg(long, seek_dir);


ostream& seekp(long, seek_dir);
File Access Pointer and their
Manipulators
fin.seekg(20); //will move get_pointer to 20byte in a file
fout.seekp(40); //will move put_pointer to 40byte in a file

 We have the following for seek_dir:


a. ios::beg for beginning of the file
b. ios:: cur for current location
c. ios::end for end of the file

fin.seekg(20, ios::beg); //will move get_pointer to 20 byte from start of file

fout.seekp(-40, ios::end); //will move put_pointer to 40 byte back from end of file

fout.seekp(20, ios::cur);
Testing error during file operations
 We have several functions to check for error during file operations:
a. eof()
 This function returns non-zero (true) value if end of file is encountered during reading
otherwise zero is returned.
while(1){
//read operation
if(fin.eof()){
//stop reading
}
}
b. bad()
 This function returns non-zero (true) value if invalid operation is attempted or any
unrecovered error has occurred such as disk space is full or using to read content of file using
stream object not connected to file.
ofstream fout;
fout.open(“somefile”);

if(fout.bad()){
//show error
}
Testing error during file operations
c. fail()
 This function returns non-zero (true) value if input or output operation has failed.
fout.write((char *) &s, sizeof(s));
if(fout.fail()){
//file not opened
}
d. good()
 This function returns non-zero (true) value if no error has occur and read and write can be
performed to a file
ofstream fout;
fout.open(“somefile”);

if(fout.good()){
// no error has occured
}
e. We can check error by checking stream class object is null. If null, error has occurred.
ifstream fin;
fin.open(“somefile”);
if(!fin){
// file doesn’t exist for reading
}
Templates

Bipin Thapa Magar


b
[email protected]
u.np
Template
s
 Templates allows us to write a generic program for different data types. The data type may
be built in data type or user defined.

Function
Template
 Function overloading allows us to define multiple functions with same name but different
arguments. Normally, if the body is same but the type of argument is different, we use
function overloading. In such cases, we can use template instead.
 The general form is:
template<class T>
return_type function_name(T type arguments){
//body
}
Example:
template<class T>
T abs(T n){
return (n<0)? –n : n;
}
Now this function abs() can be called with any type
abs(10.5);
abs(5);
Function
Template
 Creating template doesn’t necessarily create all versions of the function. When the function
call is encountered, complier creates a version of the data type on function call. If similar
function call exists, compiler creates a single version only.
template<class T1>
T1 largest(T1 *a,int size){
T1 L=a[0];
for(int i=1;i<size;i++){
if(L<a[i]){
L=a[i];
}
}
return L;
}
int main(){
int a[]={1,5,7,10,2,3};
cout<<“\n Largest element in Integer
Array:”<<largest(a,6);
float b[]={10.25,25.36,22.3,12.56};
cout<<“\nLargest element is float
array:”<<largest(b,4);
}
Function Template with Multiple
Argument
 We can use more than one generic type while defining functions as:
template<class T1,class T2….> template<class T1, class T2>
returnType functionName(arguments of T1,T2,….){ void cal(T1 p[], int size, T2 &sum, T2
//body of function &av){
} for(int i=0;i<size; i++){
sum+=p[i];
av=sum/size;
}
}
int main(){
OUTPUT: int n[]={1,2,3,4,5};
Sum:15 Average:3 float sum=0.0, avg=0.0;
Sum:52.64 Average:13.16 cal(n,5,sum,avg);
cout<<“\n Sum:”<<sum<<“\t
Average:”<<avg;
float a[]={1.12, 10.25, 36.25, 5.02};
double sa=0.0, av=0.0;
cal(a,4,sa,av);
cout<<“\n Sum:”<<sa<<“\t
Average:”<<av;
}
Overloading of template
function
 There may arise situations where we need to overload as well as create templates. We can
overload in two ways:
a. Overloading of function template with normal functions
b. Overloading of function template with other templates

a. Overloading of function template with normal functions:


 If we call an overloaded function template, compiler will try to deduce its template
arguments and if it is successful, it will instantiate a function template and adds it to set of
candidate function used in overload resolution.
 The compiler then proceeds with overload resolution, choosing the most appropriate function
from set of candidate functions.
 Non-template functions take precedence over template functions.
Overloading of template
function

int main(){
template<class T>
mini(10,20);
void mini(T a, T b){
mini(10.25,20.25);
cout<<“\nTemplate function”;
return 0;
if(a<b)
}
cout<<a;
else
cout<<b;
}
void mini(int a, int b){
cout<<“\nInteger function”; OUTPUT:
if(a<b) Integer Function: 10
cout<<a; Template Function: 10.25
else
cout<<b;
}
Overloading of template
function
 In above example, the error with the second function call can be removed with the following
line:
mini<double>(10,20.25);
 This tells the compiler to use double as the data type in the template.
 The choosing of the overloaded function is done in the following steps:
a. Call an ordinary function that has an exact match.
b. Call a template function that could be created with an exact match.
c. Try normal overloading resolution to normal functions and call the one that matches.
An error is generated if no match is found.
Overloading of template
function
b. Overloading of function template with other templates
 We can create multiple function templates with same name and the function which is most
specialized or matching
template<class T> will be called.
void mini(T a, T b){ int main(){
cout<<“\nTwo argument Template mini(10,20);
function”; //mini(10,20.25); no match found (int,
if(a<b) double);
cout<<a; mini(30,20,50);
else }
cout<<b;
}
template<class T>
void mini(T a, T b, T c){
cout<<“\nThree argument Template
function”; OUTPUT:
if(a<b && a<c) Two argument Template Function: 10
cout<<a; Three argument Template Function : 20
else if(b<a && b<c)
cout<<b;
else
cout<<c;
Class Template
 Just like with functions, if different classes have same functionality for different data types,
class template can be defined.
 General Form:
template<class T>
class className{
//members
};
 We can then declare the objects of the class as:
className<type>objectName(argList);
 Example:
template<class T>
class Array{
T a[10];
public:
void input();
};
We can then define the object as:
Array<int> obj1;
Array<float> obj2;
Defining member functions of class
template
 If the functions are defined outside the template class body, they should always be defined
with the full template function. template<class T1>
template<class T1> T1 Array<T1>::Largest(){
returnType className<T1>::functionName(args){ T1 L=a[0];
//body for(int i=0;i<size;i++){
} template<class T> if(a[i]>L)
class Array{ L=a[i];
T *a; }
int size; return L;
public: }
Array(T *n,int s){ int main(){
a=new T[s]; int temp[]={1,5,8,10,3};
for(int i=0;i<s;i++){ Array<int>Obj1(temp,5);
a[i]=n[i]; cout<<“\nLargest in
} integer:”<<Obj1.Largest();
size=s; double
} test[]={10.25,145.2,52.6,96.354};
T Largest(); Array<double>Obj2(test,4);
}; cout<<“\nLargest in
double:”<<Obj2.Largest();
return 0;
Class Template with multiple
parameters
 We can define multiple parameters in template for class as following:
template<class T1, class T2,…>
class className{
//members
};
 We can then define the object as following:
classname<type1,type2,…>objectName;
 We can then define the member function outside the class as:
template<class T1, class T2,…>
returnType className<T1,T2,…>::functionName(args){
//body of function
}
Class Template with multiple
parameters int main(){
template<class T1,class T2,class T3> Record<int,char,double>
class Record{ R1(10,’R’,1045.12);
T1 a; Record<double,char,int>
T2 b; R1(20.1245,’S’,12);
T3 c; R1.show();
public: R2.show();
Record(T1 x, T2 y, T3 z){ return 0;
a=x; }
b=y;
c=z;
}
void show(); OUTPUT:
}; 10 R 1045.12
template<class T1,class T2,class T3> 20.1245 S 12
void Record<T1,T2,T3>::show(){
cout<<endl<<a<<“ “<<b<<“ “<<c;
}
Non-Type Template Arguments
 A non-type template argument provided within a template argument list is an expression
whose value can be determined at compile time. Such arguments must be constant
expressions, addresses of functions or objects with external linkage, or addresses of static
class members.
 Non-type template arguments are normally used to initialize a class or to specify the sizes of
class members.
 General Form is:
template<class T, int size>
class array{
T a[size];
….
};
 The object can then be defined as following:
Stack<double,20> obj1;
Stack<double,10+10>obj2;

Note: Study Stack yourself.


Default Argument with class Template
 Template parameters can have default arguments.
 Just like in functions, the default argument can be set if all to the right is set.
template<class T,class U, class V=int>class X {}; // is valid
template<class T=char, class U, class V=int>class X{}; // is invalid. either remove from
class T or add to class U
 Multiple template declarations can also accumulate as follows:
template<class R,class T=int>class A;
template<class R=float,class T>class A;
template<class R,class T>
class A{
//members
};
Object declaration:
A<> a; //since both have some default type
 Also, we cannot define multiple templates with same parameters:
template<class T=char>class X;
template<class T=char>class X{};
 The scope of the template parameter starts from the point of its declaration to end of the
template definition:
template<class V, V obj>class A;
template<class T, class U=T>class B;
Derived Class Template
 During inheritance, base class can be template and we can define the type in derived as:

template<class T>
class Base{
protected:
T a;
public:
void display(){
Base(T x){
Base<int>::display();
a=x;
cout<<endl<<b;
}
}
void display(){
};
cout<<endl<<a;
int main(){
}
Derived d(1,2);
};
d.display();
class Derived: public Base<int>{
}
int b;
public:
Derived(int x, int y):Base<int>(x){
b=y;
}
Derived Class Template
 We can also define base class as template as:
template<class T>
class Base{
protected:
T a;
public:
Base(T x){ void display(){
a=x; Base<int>::display();
} cout<<endl<<b;
void display(){ }
cout<<endl<<a; };
} int main(){
}; Derived<int>d(1,2);
template<class T> d.display();
class Derived: public Base<int>{ }
T b;
public:
Derived(int x, T y):Base<int>(x){
b=y;
}
Derived Class Template
 Also, we can get the template of both base and derived as:
template<class T>
class Base{
protected:
T a;
public:
Base(T x){ void display(){
a=x; Base<T1>::display();
} cout<<endl<<b;
void display(){ }
cout<<endl<<a; };
} int main(){
}; Derived<float,int> d(1,2);
template<class T1,class T> d.display();
class Derived: public Base<T1>{ }
T b;
public:
Derived(T1 x, T y):Base<T1>(x){
b=y;
}
Derived Class Template
 Also, we can get the template only derived as:

class Base{
protected:
int a;
public:
Base(int x){
void display(){
a=x;
Base::display();
}
cout<<endl<<b;
void display(){
}
cout<<endl<<a;
};
}
int main(){
};
Derived<int> d(1,2);
template<class T>
d.display();
class Derived: public Base {
}
T b;
public:
Derived(int x, T y):Base(x){
b=y;
}
Standard Template Library
 STL is a feature in C++ which includes a lot of general purpose, templatized class and
functions that implement many popular and commonly used algorithms and data structures.
 It has three major components:
a. Containers
b. Algorithms
c. Iterators

Algorithm Algorithm
1 Container Iterator 2 2
Iterator 1
Object 1

Object 3 Object 2

Iterator 3

Algorithm
3
Standard Template Library
a. Containers:
 Containers are objects that hold other objects. It is a way data is organized in memory. The
STL defines ten containers that are grouped into three categories:
a. Sequence container –Vector,List,Deque
b. Associative container – set, multiset, map, multimap
c. Derived container - stack, queue, priority_queue
b. Algorithm:
 An algorithm is a procedure that is used to process the data in containers. STL provides sixty
standard algorithms to support more extended or complex operations.
 Algorithms arenot part of container class so that the same algorithm can be used for various
containers.
 They are categorized as:
a. Mutating algorithms
b. Sorting algorithm
c. Set algorithm
d. Relational algorithm
e. Retrieve or non-mutating algorithm
c. Iterators:
 Iterator behaves like a pointer and are used to access individual elements of a container.
 They are used to traverse from element to element in a container, known as iterating.
 Types: input, output, forward, bidirectional, random
Exception Handling

Bipin Thapa Magar


b
[email protected]
u.np
Introduction
 Exceptions are errors that occur at run time.
 They are of two types: Synchronous exception and asynchronous exception.
 An error such as array range checks and I/O errors belong to the synchronous exception.
 Asynchronous exception is the errors that are caused by event beyond the control of the
program such as keyboard interrupts and certain arithmetic errors. They tend to be system
dependent and are not described here.
 C++ exception handling mechanisms is designed to handle only synchronous exceptions.
Error
Handling
 A programmer can detect runtime errors but in general, they do not have any idea what to
do about them. Like in C program, returning value from function is which it occurs often
signals errors.
 Eg: We can check error while opening from file as:
File *fp;
fp=fopen(“file.txt”,”a+”);
if(fp==NULL){
exit(0);
}
else if(ferror(fp)){
printf(“Error occurred”);
}
 Similarly, we can check in other functions as:
if(function()==null){
//handle error
}
else if(function2()==0){
//handle error
}
else{
//process normal
Error
Handling
 In above method, the problem is that we have to check error for every function. Also, the
code becomes very complex and hard to read.
 Also, if we implement class, the complexity increases exponentially. We might get error in the
constructor but if we cant handle that, problem might occur. Further, we can use STL and
other library where we need to learn how to handle errors independently. So, this method
becomes complex and very hard.
 So, we use exception handling which reduces the effort and makes the task very easy.
Exception
Handling
 For handling exception in C++, we use the keywords try, catch and throw.
 try keyword is used to a block of statements surrounded by braces which may generate
exception. When an exception is detected it is thrown using a throw statement in the try
block. The program control then leaves the try block and enters the catch block comparing
the catch argument type and the exception thrown type.
 If the two types match, catch block is executed or else program is aborted with the help of
abort() function which is invoked by default.
 If no exception occurs in the try block, the program automatically skips the catch block.
try block
 General Form:
Detect and
try{ throw
// exception
throw exception;
//
} catch block
catch(argument){
//handle exception catch and
} handle
exception
Exception
Handling
void Calculate(int a, int b){
int main(){
if(b==0)
int x,y;
throw b;
cout<<“Enter value of x and
cout<<“\nQuotation
y:”;
is:”<<a/b;
cin>>x>>y;
try{
}
if(y==0)
int main(){
throw y;
try{
cout<<“\nQuotion
Calculate(10,20);
is:”<<x/y;
Calculate(10,0);
}
}
catch(int c){
catch(int c){
cout<<“\nException”;
cout<<“\nException”;
}
}
cout<<“\nEnd of Program”;
cout<<“\nEnd of Program”;
return 0;
return 0;
}
}
Exception
Handling
try block:
 All the statements that might cause exception are kept inside the try block.
 Not all code needs to be inside the try block. Also, a single program can have as many try
blocks as needed.
throw block:
 When an exception is detected in program, it is handle by throwing it through any of the
following throw statement:
throw exception;
throw (exception);
throw; //used for rethrowing
 We can throw any type of variable including objects. Throw point can be deeply inside
function call or nested scope and it still transfers control to the closest catch statement.
catch Statement:
 catch statement handles all the exception:
catch(type argument){
//handle exceptions
}
 The type specifies the type of exception the catch block handles. It is the argument with the
throw statement.
 After finishing the catch block, the program control goes to the code following it.
Multiple catch
statements
 A program may have multiple cases which throw an exception. So, to handle all of those, we
have multiple catch statements with one try statement.
 General form:
try{
//try block
}
catch(type1 arg){
//catch block 1
}
catch(type2 arg){
//catch block 2
}
..
..
catch(typeN arg){
//catch block N
}
 Whenever an exception is occurred, the type of argument thrown is checked with the type in
catch block sequentially. The one which matches the type is executed and control is
transferred to the statement below the catch block. If no match is found, the program stops
abruptly.
Multiple catch
statements OUTPUT:
void test(int b){ test(0):
cout<<“\n Inside function”; Inside function
try{ catch(char c){ Integer
if(b==0) cout<<“\nCharacter Exception
throw b; Exception”; End of Function
if(b==1) } test(1):
throw 1.0; cout<<“\nEnd of function”; Inside function
if(b==2) } Double
throw ‘R’; int main(){ Exception
} cout<<“\ntest(0):”<<test(0); End of Function
catch(int c){ cout<<“\ntest(1):”<<test(1); test(2):
cout<<“\nInteger cout<<“\ntest(2):”<<test(2); Inside function
Exception”; cout<<“\ntest(3):”<<test(3); Character
} cout<<“\nEnd of program”; Exception
catch(double c){ return 0; End of Function
cout<<“\nDouble } test(3):
Exception”; Inside function
} End of Function
End of Program
Exception class hierarchy in multiple
catch
class Base{ }; catch(Derived1 c){
class Derived1:public Base{ }; cout<<“\nDerived1
OUTPUT:
class Derived2:public Base{ }; Exception”;
test(0):
void test(int b){ }
Inside function
cout<<“\n Inside function”; catch(Derived2 c){
Base Exception
try{ cout<<“\nDerived2
End of Function
if(b==0) Exception”;
test(1):
throw Base(); }
Inside function
if(b==1) cout<<“\nEnd of function”;
Base Exception
throw Derived1(); }
End of Function
if(b==2) int main(){
test(2):
throw Derived2(); cout<<“\ntest(0):”<<test(0);
Inside function
} cout<<“\ntest(1):”<<test(1);
Base Exception
catch(Base c){ cout<<“\ntest(2):”<<test(2);
End of Function
cout<<“\nBase cout<<“\nEnd of program”;
End of Program
Exception”; return 0;
} }
Exception class hierarchy in multiple
catch
 As we have already discussed, the derived class object is also a type of base class. So, the
base class catch statement matches the throw with derived class object too. Hence the error
before occurs. We can fix this program by changing the catch statements as follows:

catch(Derived1 c){
cout<<“\nDerived1
void test(int b){ Exception”;
cout<<“\n Inside function”; }
try{ catch(Derived2 c){
if(b==0) cout<<“\nDerived2
throw Base(); Exception”;
if(b==1) }
throw Derived1(); catch(Base c){
if(b==2) cout<<“\nBase class
throw Derived2(); Exception”;
} }
cout<<“\nEnd of function”;
}
Rethrowing an
exception
 If an exception occurs, there may be times when the exception doesn’t have a matching
catch block or handlers. In such case, we can rethrow the exception to another block and
handle it there.
 It can be done by using throw statement without any arguments.

void Calculate(int a, int b){


int main(){
try{
int x,y;
cout<<“\n Inner try:”; OUTPUT:
try{
if(b==0) Outer try:
cout<<“\nOuter try”;
throw b; Inner try:
Calculate(20,1);
cout<<“\n Quotion Quotation is:20
Calculate(10,0);
is:”<<a/b; Inner try:
}
} Inner catch
catch(int c){
catch(int c){ Outer catch
cout<<“\n Outer Catch”;
cout<<“\nInner catch”; End of
}
throw; program
cout<<“\nEnd of Program”;
}
}
}
Rethrowing an
exception
 A rethrow is indicated by a throw without an operand. If void Calculate(int a, int b){
a rethrow is attempted when there is no exception to try{
rethrow, terminate() will be called. cout<<“\n Inner try:”;
 If we update the previous function as follows, the if(b==0)
program will terminate abnormally. It is because when throw b;
we call the function with Calculate(20,1), there will be cout<<“\n Quotation
no exception but it still attempts to rethrow an is:”<<a/b;
exception and hence, terminate() will be called. throw;
}
catch(int c){
cout<<“\nInner catch”;
throw;
}
}
Catching all
exception
 In some situation, we may not be able to anticipate all possible types of exceptions and
therefore may not be able to design independent catch handlers to catch them. In such
cases, we can force a catch statement to catch all exception instead of certain type alone:
 General form:
catch(…){ OUTPUT:
//statements for handling exceptions test(0):
} void test(int b){ Inside function
Exception
cout<<“\n Inside function”; Caught
try{ test(1):
if(b==0) Inside function
int main(){
throw b; Exception
cout<<“\ntest(0):”<<test(0);
if(b==1) Caught
cout<<“\ntest(1):”<<test(1);
throw 1.0; test(2):
cout<<“\ntest(2):”<<test(2);
if(b==2) Inside function
cout<<“\ntest(3):”<<test(3);
throw ‘R’; Exception
cout<<“\nEnd of program”;
} Caught
return 0;
catch(…){ test(3):
}
cout<<“\nException Inside function
Caught”; End of Program
}
Exception with
argument
 It is better if we can get the information about exception. So, we can throw object with the
const int size=3;
message as follows:
class Stack{
else{
int A[size];
top++;
int top;
A[top]=data;
public:
}
class out_Of_Range{
}
public:
void pop(){
char *message;
if(top<0){
out_Of_Range(char *name){
throw out_Of_Range(“Stack
message=name;
Empty”);
}
}
};
else{
Stack(){
cout<<“\nPopped element
top=-1;
is:”<<A[top];
}
top--;
void push(int data){
}
if(top==size-1){
}
throw out_Of_Range(“Stack
};
Overflow”);
}
Exception with
argument

int main(){
Stack obj;
try{
obj.push(1);
obj.push(2);
obj.push(3);
//obj.push(4); OUTPUT:
obj.pop(); Popped Element:3
obj.pop(); Popped Element:2
obj.pop(); Popped Element:1
obj.pop(); Exception: Stack Empty
}
catch(Stack::out_Of_Range Range){
cout<<“\
nException:”<<Range.message;
}
}
Specifying exception
 Throwing or catching an exception affects the way a function relates to other functions. It
can be therefore worthwhile to specify the set of exceptions that might be thrown as part
of the function declaration.
 To restrict a function to throw only certain specified exceptions, we do this by adding a
throw list clause to the function definition. int main(){
 General form: int x,y;
returnType function(args) throw (type-list){ try{
//body Calculate(20,0);
} Calculate(10,1);
If the function throws any other type of exception which is not listed,
}
it will cause an abnormal termination. catch(int c){
void Calculate(int a, int b)
cout<<“\nInteger
throw(int,double){
Exception”;
cout<<“\n Inside function:”;
}
if(b==0)
catch(double c){
throw b;
cout<<“\nDouble
if(b==1)
Exception”;
throw 1.0;
}
cout<<“\n Quotion is:”<<a/b
cout<<“\nEnd of Program”;
}
}
Handling uncaught
exception
 terminate() function is called when an exception is thrown but not caught.
 Also, it is called when program tries to rethrow an exception but no exception is thrown
beforehand.
 terminate() function calls abort() by default and program stops. We can change the
behavior of this function using set_terminate() function as:
terminate_handler set_terminate(terminate_handler newHandler);

Here, newHandler is a pointer to the terminate handler which must be a function of


typeterminate_handler, which is defined like this:
typedef void(*terminate_handler)();

The terminate handler should be a function which take no argument and do not have a
return type. It must stop the program execution and must not return to the program or
resume it in any way.
Handling uncaught
exception

void test_handler(){
cout<<“\nInside test handler:”;
}

int main(){
set_terminate(test_handler); OUTPUT:
try{ Inside try block
cout<<“\nInside try block”; Inside test handler
throw 10; **Program terminates
} abnormally**
catch(char ch){
cout<<“\nCharacter Exception”;
}
return 0;
}
Handling unexpected
exception
 Similarly to uncaught exception, the system throws an error when exception is thrown
which is not in the exception throw list. It invokes unexpected() function.
 By default unexpected() calls terminate(), but we can change the function that is called by
unexpected().
 General form:
void test_handler(){
unexpected_handler set_unexpected(unexpected_handler newHandler);
cout<<“\nInside test handler:”;
} catch(int c){
void Calculate(int a, int b) throw (int) cout<<“\nInteger
{ Exception”;
cout<<“\nInside function”; }
if(b==0) cout<<“\nEnd of Program”;
throw ‘A’; }
cout<<“\nQuotion is:”<<a/b;
}
int main(){ OUTPUT:
set_unexpected(test_handler); Inside function
int x,y; Inside test handler
try{ **Program terminates
Calculate(10,0); abnormally**
}

You might also like