oops unit -5

125
1 UNIT -1 Basic concepts of OOPS and Structure of C++ program In this tutorial you will learn about Objects, Classes, Inheritance, Data Abstraction, Data Encapsulation, Polymorphism, Overloading, Reusability. Before starting to learn C++ it is essential that one must have a basic knowledge of the concepts of Object oriented programming. Some of the important object oriented features are namely: In order to understand the basic concepts in C++, the programmer must have a command of the basic terminology in object-oriented programming. Below is a brief outline of the concepts of Object-oriented programming languages: Objects: Object is the basic unit of object-oriented programming. Objects are identified by its unique name. An object represents a particular instance of a class. There can be more than one instance of an object. Each instance of an object can hold its own relevant data. An Object is a collection of data members and associated member functions also known as methods.

Upload: ishash1005165

Post on 20-Jan-2016

55 views

Category:

Documents


0 download

DESCRIPTION

OOPS

TRANSCRIPT

Page 1: OOPS unit -5

1

UNIT -1

Basic concepts of OOPS and Structure of C++ program

In this tutorial you will learn about Objects, Classes, Inheritance, Data Abstraction, Data

Encapsulation, Polymorphism, Overloading, Reusability.

Before starting to learn C++ it is essential that one must have a basic knowledge of the concepts

of Object oriented programming. Some of the important object oriented features are namely:

In order to understand the basic concepts in C++, the programmer must have a command of the

basic terminology in object-oriented programming. Below is a brief outline of the concepts of

Object-oriented programming languages:

Objects:

Object is the basic unit of object-oriented programming. Objects are identified by its unique

name. An object represents a particular instance of a class. There can be more than one instance

of an object. Each instance of an object can hold its own relevant data.

An Object is a collection of data members and associated member functions also known as

methods.

Page 2: OOPS unit -5

2

Classes:

Classes are data types based on which objects are created. Objects with similar properties and

methods are grouped together to form a Class. Thus a Class represent a set of individual objects.

Characteristics of an object are represented in a class as Properties. The actions that can be

performed by objects becomes functions of the class and is referred to as Methods.

For example consider we have a Class of Cars under which Santro Xing, Alto and WaganR

represents individual Objects. In this context each Car Object will have its own, Model, Year of

Manufacture, Colour, Top Speed, Engine Power etc., which form Properties of the Car class

and the associated actions i.e., object functions like Start, Move, Stop form the Methods of Car

Class.

No memory is allocated when a class is created. Memory is allocated only when an object is

created, i.e., when an instance of a class is created.

Inheritance:

Inheritance is the process of forming a new class from an existing class or base class. The base

class is also known as parent class or super class, The new class that is formed is called derived

class. Derived class is also known as a child class or sub class. Inheritance helps in reducing the

overall code size of the program, which is an important concept in object-oriented programming.

Data Abstraction:

Data Abstraction increases the power of programming language by creating user defined data

types. Data Abstraction also represents the needed information in the program without presenting

the details.

Data Encapsulation:

Data Encapsulation combines data and functions into a single unit called Class. When using Data

Encapsulation, data is not accessed directly; it is only accessible through the functions present

inside the class. Data Encapsulation enables the important concept of data hiding possible.

Polymorphism:

Polymorphism allows routines to use variables of different types at different times. An operator

or function can be given different meanings or functions. Polymorphism refers to a single

function or multi-functioning operator performing in different ways.

Overloading:

Overloading is one type of Polymorphism. It allows an object to have different meanings,

depending on its context. When an exiting operator or function begins to operate on new data

type, or class, it is understood to be overloaded.

Page 3: OOPS unit -5

3

Reusability:

This term refers to the ability for multiple programmers to use the same written and debugged

existing class of data. This is a time saving device and adds code efficiency to the language.

Additionally, the programmer can incorporate new features to the existing class, further

developing the application and allowing users to achieve increased performance. This time

saving feature optimizes code, helps in gaining secured applications and facilitates easier

maintenance on the application.

The implementation of each of the above object-oriented programming features for C++ will be

highlighted in later sections.

A sample program to understand the basic structure of C++

//program to read employee details and to output the data

#include <iostream.h> → Preprocessor directive

class employee → Class Declaration

{

private:

char empname[50];

int empno;

public:

void getvalue()

{

cout<<”INPUT EMP NAME:”;

cint>>empname;

cout<<”INPUT EMP NO:”;

cint>>empno;

}

void displayvalue()

{

cout<<”EMP NAME:”<<empname;

coout<<EMP NO:”<<empno;

}

};

main()

{

employee e1; → Creation of Object

e1.getvalue();

e1.displayvalu();

}

Page 4: OOPS unit -5

4

Variables

A variable is the storage location in memory that is stored by its value. A variable is identified or

denoted by a variable name. The variable name is a sequence of one or more letters, digits or

underscore, for example: character _

Rules for defining variable name:

A variable name can have one or more letters or digits or underscore for example

character _.

.

White space, punctuation symbols or other characters are not permitted to denote variable

name. .

A variable name must begin with a letter.

.

Variable names cannot be keywords or any reserved words of the C++ programming

language.

.

C++ is a case-sensitive language. Variable names written in capital letters differ from

variable names with the same name but written in small letters. For example, the variable

name EXFORSYS differs from the variable name exforsys.

As previously explained, a variable is the storage location in memory that is stored by variable

value. The amount of memory allocated or occupied by each variable differs as per the data

stored. The amount of memory used to store a single character is different from that of storing a

single integer. A variable must be declared for the specific data type.

Data Types

Below is a list of the most commonly used Data Types in C++ programming language:

short int

int

long int

float

double

long double

char

bool

short int : This data type is used to represent short integer.

int: This data type is used to represent integer.

Page 5: OOPS unit -5

5

long int: This data type is used to represent long integer.

float: This data type is used to represent floating point number.

double: This data type is used to represent double precision floating point number.

long double: This data type is used to represent double precision floating point number.

char: This data type is used to represent a single character.

bool: This data type is used to represent boolean value. It can take one of two values: True or

False.

Using variable names and data type, we shall now learn how to declare variables.

Declaring Variables:

In order for a variable to be used in C++ programming language, the variable must first be

declared. The syntax for declaring variable names is

data type variable name;

The date type can be int or float or any of the data types listed above. A variable name is given

based on the rules for defining variable name (refer above rules).

Example:

int a;

This declares a variable name a of type int.

If there exists more than one variable of the same type, such variables can be represented by

separating variable names using comma.

For instance

int x,y,z

This declares 3 variables x, y and z all of data type int.

The data type using integers (int, short int, long int) are further assigned a value of signed or

unsigned. Signed integers signify positive and negative number value. Unsigned integers signify

only positive numbers or zero.

For example it is declared as

Page 6: OOPS unit -5

6

unsigned short int a;

signed int z;

By default, unspecified integers signify a signed integer.

For example:

int a;

is declared a signed integer

It is possible to initialize values to variables:

data type variable name = value;

Example:

int a=0;

int b=5;

Constants

Constants have fixed value. Constants, like variables, contain data type. Integer constants are

represented as decimal notation, octal notation, and hexadecimal notation. Decimal notation is

represented with a number. Octal notation is represented with the number preceded by a zero

character. A hexadecimal number is preceded with the characters 0x.

Example

80 represent decimal

0115 represent octal

0x167 represent hexadecimal

By default, the integer constant is represented with a number.

The unsigned integer constant is represented with an appended character u. The long integer

constant is represented with character l.

Example:

78 represent int

85u present unsigned int

78l represent long

Page 7: OOPS unit -5

7

Floating point constants are numbers with decimal point and/or exponent.

Example

2.1567

4.02e24

These examples are valid floating point constants.

Floating point constants can be represented with f for floating and l for double precision floating

point numbers.

Character constants have single character presented between single quotes.

Example

„c‟

„a‟

are all character constants.

Strings are sequences of characters signifying string constants. These sequence of characters are

represented between double quotes.

Example:

“Exforsys Training”

is an example of string constant.

C++ Objects and Classes

An Overview about Objects and Classes

In object-oriented programming language C++, the data and functions (procedures to manipulate

the data) are bundled together as a self-contained unit called an object. A class is an extended

concept similar to that of structure in C programming language, this class describes the data

properties alone. In C++ programming language, class describes both the properties (data) and

behaviors (functions) of objects. Classes are not objects, but they are used to instantiate objects.

Features of Class:

Classes contain data known as members and member functions. As a unit, the collection of

members and member functions is an object. Therefore, this unit of objects make up a class.

Page 8: OOPS unit -5

8

How to write a Class:

In Structure in C programming language, a structure is specified with a name. The C++

programming language extends this concept. A class is specified with a name after the keyword

class.

The starting flower brace symbol, {is placed at the beginning of the code. Following the flower

brace symbol, the body of the class is defined with the member functions data. Then the class is

closed with a flower brace symbol} and concluded with a colon;.

class exforsys

{

data;

member functions;

……………

};

There are different access specifiers for defining the data and functions present inside a class.

Access specifiers:

Access specifiers are used to identify access rights for the data and member functions of the

class. There are three main types of access specifiers in C++ programming language:

private

public

protected

A private member within a class denotes that only members of the same class have

accessibility. The private member is inaccessible from outside the class.

.

Public members are accessible from outside the class.

.

A protected access specifier is a stage between private and public access. If member

functions defined in a class are protected, they cannot be accessed from outside the class

but can be accessed from the derived class.

When defining access specifiers, the programmer must use the keywords: private, public or

protected when needed, followed by a semicolon and then define the data and member functions

under it.

class exforsys

{

Page 9: OOPS unit -5

9

private:

int x,y;

public:

void sum()

{

………

………

}

};

In the code above, the member x and y are defined as private access specifiers. The member

function sum is defined as a public access specifier.

General Template of a class:

General structure for defining a class is:

class classname

{

acess specifier:

data member;

member functions;

acess specifier:

data member;

member functions;

};

Generally, in class, all members (data) would be declared as private and the member functions

would be declared as public. Private is the default access level for specifiers. If no access

specifiers are identified for members of a class, the members are defaulted to private access.

class exforsys

{

int x,y;

public:

void sum()

{

………

………

}

};

Page 10: OOPS unit -5

10

In this example, for members x and y of the class exforsys there are no access specifiers

identified. exforsys would have the default access specifier as private.

Creation of Objects:

Once the class is created, one or more objects can be created from the class as objects are

instance of the class.

Juts as we declare a variable of data type int as:

int x;

Objects are also declared as:

class name followed by object name;

exforsys e1;

This declares e1 to be an object of class exforsys.

For example a complete class and object declaration is given below:

class exforsys

{

private:

int x,y;

public:

void sum()

{

………

………

}

};

main()

{

exforsys e1;

……………

……………

}

The object can also be declared immediately after the class definition. In other words the object

name can also be placed immediately before the closing flower brace symbol } of the class

declaration.

Page 11: OOPS unit -5

11

For example

class exforsys

{

private:

int x,y;

public:

void sum()

{

………

………

}

}e1;

The above code also declares an object e1 of class exforsys.

It is important to understand that in object-oriented programming language, when a class is

created no memory is allocated. It is only when an object is created is memory then allocated.

How to Access C++ Class Members

It is possible to access the class members after a class is defined and objects are created.

General syntax to access class member:

Object_name.function_name (arguments);

The dot („.‟) used above is called the dot operator or class member access operator. The dot

operator is used to connect the object and the member function. This concept is similar to that of

accessing structure members in C programming language. The private data of a class can be

accessed only through the member function of that class.

For example,

A class and object are defined below:

class exforsys

{

int a, b;

public:

void sum(int,int);

} e1;

Then the member access is written as:

Page 12: OOPS unit -5

12

e1.sum(5,6);

Where e1 is the object of class exforsys and sum() is the member function of the class.

The programmer now understands declaration of a class, creation of an object and accessibility

of members of a class.

It is also possible to declare more than one object within a class:

class exforsys

{

private:

int a;

public:

void sum(int)

{

………

………

}

};

main()

{

exforsys e1,e2;

…………

…………

}

In these two objects e1 and e2 are declared of class exforsys.

By default, the access specifier for members of a class is private. The default access specifier for

a structure is public. This is an important difference to recognize and understand in object-

oriented C++ programming language.

class exforsys

{

int x; //Here access specifier is private by default

};

whereas

struct exforsys

Page 13: OOPS unit -5

13

{

int x; //Here access specifier is public by default

};

It is not always the case that the member function declaration and definition takes place within

the class itself. Sometimes, declaration of member function alone can occur within the class. The

programmer may choose to place the definition outside the class. In a situation such as this, it is

important to understand the identifying member function of a particular class. This is performed

by using the operator :: this is called scope resolution operator.

class exforsys

{

private:

int a;

public:

void getvalues() // Only Member Function declaration is done

};

void exforsys :: void getvalues() // Here Member Function is defined

{

………………

………………

}

main()

{

exforsys e1,e2;

…………

}

So the usage of scope resolution operator is as follows:

Page 14: OOPS unit -5

14

Overview of the Basic Structure of C++ Programming

The next structure present in the program is the class definition. This starts with the

keyword class followed by class name employee. Within the class are data and functions.

The data defined in the class are generally private and functions are public. These

explanations we will be detailed in later sections. The class declaration ends with a

semicolon.

.

main() function is present in all C++ programs.

.

An object e1 is created in employee class. Using this e1 the functions present in the

employee class are accessed and there by data are accessed.

.

The input namely ename and eno is got using the input statement namely cin and the

values are outputted using the output statement namely cout.

What is a function?

A function is a structure that has a number of program statements grouped as a unit with a name

given to the unit. Function can be invoked from any part of the C++ program.

Features of Function:

To understand why the program structure is written separately and given a name, the

programmer must have a clear idea of the features and benefits of function. This will encourage

better understanding of function usage:

Use of Functions gives a Structured Programming Approach

Reduces Program Size:

The piece of code that needs to be executed, or the piece of code that is repeated in different

parts of the program, can be written separately as a function and stored in a place in memory.

Whenever and wherever needed, the programmer can invoke the function and use the code to be

executed. Thus, the program size is reduced.

Having known about the function and its features let us see how to declare, define and call a

function in a C++ program.

Declaring a Function:

It has been discussed that, in order for a variable to be used, it must be declared. Just like

variables, it follows that function definitions must be declared. The general method of declaring

a function is to declare the function in the beginning of the program.

The general format for declaring a function is

Page 15: OOPS unit -5

15

return_datatype function name(arguments);

Suppose we have a function named as exforsys which return nothing from the function it is

declared as

void exforsys( );

This declared would inform the compiler that the presence of the function exforsys is there in the

program. In the above the return type void tells the compiler that the function has no return value

and also the empty braces ( ) indicate that the function takes no arguments.

Defining a function:

The definition is the place where the actual function program statements or in other words the

program code is placed.

The general format of the function definition is as follows:

return_datatype functionname(arguments) //Declarator

{

program statements //Function Body

……..

……….

}

In the above the declarator must match the function declaration already made. That is the

function name, the return type and the number of arguments all must be same as the function

declaration made. In fact if arguments are declared and defined. The order of arguments defined

here must match the order declared in the function declaration.

After the declarator the braces starts and the function body is placed. The function body has the

set of program statements which are to be executed by the function. Then the function definition

ends with } ending braces.

For example let us see how to define a function exforsys declared as void that prints first five

integers.

void exforsys( )

{

int i;

for (i=1;i<=5;i++)

cout<< i;

}

The output of the function when it is called would be

Page 16: OOPS unit -5

16

12345

Calling the function:

The function must be called for it to get executed. This process is performed by calling the

function wherever required.

The general format for making the function call would be as follows:

functionname();

When the function is called the control, transfers to the function and all the statements present in

the function definition gets executed and after which the control, returns back to the statement

following the function call.

In the above example when the programmer executes the function exforsys, he can call the

function in main as follows:

exforsys();

Let us see a complete program in C++ to help the programmer to understand the function

concepts described above:

The output of the above program is

12345

End of Program

Concept of Function with Arguments

In this C++ Tutorial you will learn about Concept of Function with Arguments - What is an

argument Declaring a function, Function Definition and Calling the function.

Previous chapters of this tutorial have discussed simple function definition writing, declaration

of function and function call. In this chapter, the definition, declaration and call function with

arguments will be addressed.

What is an argument?

An argument is the value that is passed from the program to the function call. This can also be

considered as input to the function from the program from which it is called.

How to declare a function passed with argument

Declaring a function:

Page 17: OOPS unit -5

17

The general format for declaring the function remains the same as before except the data type

passed as arguments in functions are in the same order in which it is defined in function.

The format for declaring a function with arguments is:

return_datatype functionname(datatype1,datatype2,..);

In this example, the data types are the types of data passed in the function definition as

arguments to the function. Care must be taken to mention the number of arguments and the order

of arguments in the same way as in function definition.

For example, suppose a function named exforsys takes two integer values as arguments in its

functions definition and returns an integer value. The function declaration of exforsys would be

written:

int exforsys(int,int);

Function Definition:

The function definition has the same syntax as the function definition previously defined, but

with added arguments. The general format for defining a function with arguments is written as:

return_datatype functionname(datatype1 variable1,datatype2 variable2,..)

{

………….

Program statements

………….

return( variable);

}

In the above example, the return data type defines the data type of the value returned by the

function. The arguments are passed inside the function name after parentheses with the data type

and the variable of each argument. Care must be taken to mention the number of arguments and

the order of arguments in the same way as in function declaration.

For example, if the function exforsys takes two integer values x and y and adds them and returns

the value z the function definition would be defined as follows:

int exforsys(int x,int y)

{

int z;

z=x+y;

return(z);

}

In the above program segment, a return statement takes the general format

Page 18: OOPS unit -5

18

return(variable) ;

This value specified in the return as argument would be returned to the calling program. In this

example, the value returned is z, which is an integer value, the data type returned by the function

exforsys is mentioned as int.

Calling the function:

The calling of function takes the same syntax as the name of the function but with value for the

arguments passed. The function call is made in the calling program and this is where the value of

arguments or the input to the function definition is given.

The general format for calling the function with arguments is

functionname(value1,value2,…);

In the above exforsys function suppose integer value 5 and 6 are passed, the function call would

be as follows:

exforsys(5,6);

As soon as the function call exforsys is made the control, transfers to the function definition and

the assignment of 5 to x and 6 to y are made as below.

int exforsys(int x,int y)

exforsys(5,6);

It is possible to store the return value of the function in a variable. In the above example, the

assignment of the function call to integer variable b can be produced as follows:

int b;

b = exforsys(5,6);

The above statement assigns the returned value of the function exforsys. The value z is then

added to the value of x and y to the variable b. So, variable b takes the value 11.

Let us see the whole program to understand in brief the concept of function with arguments

The output of the above program would be

Page 19: OOPS unit -5

19

#include

int exforsys(int,int);

void main()

{

int b;

int s=5,u=6;

b=exforsys(s,u);

cout&lt;&lt;”\n The Output is:”&lt;

}

int exforsys(int x,int y)

{

int z;

z=x+y;

return(z);

}

The Output is:11

C++ Function Passing Types

In this C++ tutorial, you will learn about function passing types, two types of arguments passing

in functions - passed by value and passed by reference are discussed here.

The arguments passed to a function can be performed in two ways:

Passed By Value

Passed By Reference

Passed By Value:

In the earlier chapter, all examples for the function with arguments were passed by value.

Arguments passed by value are the copies of the values of variables and are passed to the

function. The variables defined in the calling function are not passed in this manner.

For example:

int s=5, u=6;

int z;

z = exforsys(s,u)

would pass values as

int exforsys(int x, int y)

z = exforsys(5,6);

Page 20: OOPS unit -5

20

Thus, the copies of the values 5 and 6 are passed to the function definition and not the variables s

and u. Thus, any changes in the variable x and y would not have any effect or change the

variables s and u. Because s and u are not passed in this manner, only copies of the variables are

passed to the function definition.

Passed By Reference:

Passed by reference indicates a contrast in that the variables are not passed by value. When a

variable is passed by reference, it passes the variable to the function definition and not the copies

of the value. Any changes to the variable in function definition would effect or reflect

corresponding changes in the variables passed as reference.

The symbol used for denoting the passed by reference is & (ampersand).

For Example:

Suppose two integer variables x and y are defined in the calling function, the main program with

values x=5 and y=4.

Suppose the function exforsys receives the value as passed by reference from this function it is

defined and called as follows:

#include <iostream.h>

void main( )

{

void exforsys(int&,int&);

//Function Declaration - & denotes passed by reference

int x=5,y=4;

exforsys(x,y);

cout<<”\n The output from Calling program is:”;

cout<<”\n x=”<< x;

cout<<”\n y=”<< y;

}

void exforsys(int& s, int& u)

//Function Definition - & denotes passed by reference

{

s=s*10;

u=u*10;

}

Page 21: OOPS unit -5

21

In the above example, the reference arguments are indicated by the symbol ampersand &

following the data type of the argument. In the above program, since the variables or arguments

are passed by reference the assignment is as follows:

void exforsys(int& s, int& u)

exforsys(x, y);

The variable x and y are passed to the called function exforsys where it is associated with

variables s and u. Whatever changes were made in the variable s and u effect or reflect on the

variables x and y respectively and vice versa. Only in the above, the function multiplied the

value of variable s and u by 10 which is reflected in the variable a and b. Thus, in this case, it

has not returned any value by using return statement. The programmer must take careful notice

and make use of the passed by reference concept by returning more than one value. By using the

concept of passing by reference, it is possible to return more than one value.

The output of the above program would be

The output from Calling program is:

x=50

y=40

C++ Inline Functions

In this C++ tutorial, you will learn about Inline function, what is inline function, reason for the

need of inline function, what happens when an inline function is written, general format of inline

function explained with example.

What is Inline Function?

Inline functions are functions where the call is made to inline functions. The actual code then

gets placed in the calling program.

Reason for the need of Inline Function:

Normally, a function call transfers the control from the calling program to the function and after

the execution of the program returns the control back to the calling program after the function

call. These concepts of function saved program space and memory space are used because the

function is stored only in one place and is only executed when it is called. This concept of

function execution may be time consuming since the registers and other processes must be saved

before the function gets called.

The extra time needed and the process of saving is valid for larger functions. If the function is

short, the programmer may wish to place the code of the function in the calling program in order

for it to be executed. This type of function is best handled by the inline function. In this situation,

Page 22: OOPS unit -5

22

the programmer may be wondering “why not write the short code repeatedly inside the program

wherever needed instead of going for inline function?” Although this could accomplish the task,

the problem lies in the loss of clarity of the program. If the programmer repeats the same code

many times, there will be a loss of clarity in the program. The alternative approach is to allow

inline functions to achieve the same purpose, with the concept of functions.

What happens when an inline function is written?

The inline function takes the format as a normal function but when it is compiled it is compiled

as inline code. The function is placed separately as inline function, thus adding readability to the

source program. When the program is compiled, the code present in function body is replaced in

the place of function call.

General Format of inline Function:

The general format of inline function is as follows:

inline datatype function_name(arguments)

The keyword inline specified in the above example, designates the function as inline function.

For example, if a programmer wishes to have a function named exforsys with return value as

integer and with no arguments as inline it is written as follows:

inline int exforsys( )

Example:

The concept of inline functions:

#include <iostream.h>

int exforsys(int);

void main( )

{

int x;

cout << “\n Enter the Input Value: ”;

cin>>x;

cout<<”\n The Output is: “ << exforsys(x);

}

inline int exforsys(int x1)

{

return 5*x1;

}

Page 23: OOPS unit -5

23

The output of the above program is:

Enter the Input Value: 10

The Output is: 50

The output would be the same even when the inline function is written solely as a function. The

concept, however, is different. When the program is compiled, the code present in the inline

function exforsys( ) is replaced in the place of function call in the calling program. The concept

of inline function is used in this example because the function is a small line of code.

The above example, when compiled, would have the structure as follows:

#include <iostream.h>

int exforsys(int);

void main( )

{

int x;

cout << “\n Enter the Input Value: ”;

cin>>x;

//The exforsys(x) gets replaced with code return 5*x1;

cout<<”\n The Output is: “ << exforsys(x);

}

When the above program is written as normal function the compiled code would look like below:

#include <iostream.h>

int exforsys(int);

void main( )

{

int x;

cout << “\n Enter the Input Value: ”;

cin>>x;

//Call is made to the function exforsys

cout<<”\n The Output is: “ << exforsys(x);

}

int exforsys(int x1)

{

return 5*x1;

}

Page 24: OOPS unit -5

24

A programmer must make wise choices when to use inline functions. Inline functions will save

time and are useful if the function is very small. If the function is large, use of inline functions

must be avoided.

Scope of Variables in Function

In this C++ Tutorial you will learn about Scope of Variables in Function viz Local Variables -

Scope of Local Variables, Global Variables - Scope of Global Variables.

The scope of the variables can be broadly be classified as

Local Variables

Global Variables

Local Variables:

The variables defined local to the block of the function would be accessible only within the block

of the function and not outside the function. Such variables are called local variables. That is in

other words the scope of the local variables is limited to the function in which these variables are

declared.

Let us see this with a small example:

#include <iostream.h>

int exforsys(int,int);

void main( )

{

int b;

int s=5,u=6;

b=exforsys(s,u);

cout<<”\n The Output is:”<<b;

}

int exforsys(int x,int y)

{

int z;

z=x+y;

return(z);

}

In the above program the variables x, y, z are accessible only inside the function exforsys( ) and

their scope is limited only to the function exforsys( ) and not outside the function. Thus the

variables x, y, z are local to the function exforsys. Similarly one would not be able to access

variable b inside the function exforsys as such. This is because variable b is local to function

main.

Page 25: OOPS unit -5

25

Global Variables:

Global variables are one which are visible in any part of the program code and can be used

within all functions and outside all functions used in the program. The method of declaring

global variables is to declare the variable outside the function or block.

For instance

#include <iostream.h>

int x,y,z; //Global Variables

float a,b,c; //Global Variables

void main( )

{

int s,u; //Local Variables

float w,q; //Local Variables

……..

…………….

}

In the above the integer variables x, y and z and the float variables a, b and c which are declared

outside the block are global variables and the integer variables s and u and the float variables w

and q which are declared inside the function block are called local variables.

Thus the scope of global variables is between the point of declaration and the end of compilation

unit whereas scope of local variables is between the point of declaration and the end of innermost

enclosing compound statement.

Let us see an example which has number of local and global variable declarations with number

of inner blocks to understand the concept of local and global variables scope in detail.

#include <iostream.h>

int g;

void main( )

{

int a;

{

int b;

b=25;

a=45;

g=65;

}

a=50;

exforsys( );

}

void exforsys( )

Page 26: OOPS unit -5

26

{

g = 30; //Scope of g is throughout the program and so is used between function calls

}

Scope of b is till the first braces shaded as Yellow

Scope of a is till the end of main brace shaded as red

In the context of scope of variables in functions comes the important concept named as storage

class which is discussed in detail in next section.

Static Functions - An Introduction

The static member functions have a class scope and they do not have access to the 'this' pointer

of the class. When a member is declared as static that is a static member of class have only one

such data for the entire class even though there are many objects created for the class. The main

usage of static function is when the programmer wants to have a function which is accessible

even when the class is not instantiated.

Defining Static Function:

This is done by using the keyword static before the member function which is to be declared as

static function.

General syntax:

static return_data_type fucntionname()

//Static function defined with keyword static

{

statement1;

statement2;

//Statements for execution inside static function

..........

..........

}

For example if a function exforsys returning nothing is to be declared as staic function it is done

as follows:

static void exforsys()

{

........;

.......;

}

Accessing Static Function:

Page 27: OOPS unit -5

27

We have seen in our earlier sections about accessing a normal member function. To recollect a

normal member function gets accessed using the object and an operator called as the dot member

access operator. The function declared as static or static functions gets accessed using just the

class name and the operator called as scope resolution operator which is not possible in case of

normal member functions.

Let us see an example to understand the declaration of static member function and how to access

static member function in detail:

#include <iostream.h>

class example

{

private:

static int sum; //Static data

int x;

public:

example() //Constructor of the class

{

sum=sum+1;

x=sum;

}

~example() //Destructor of the class

{

sum=sum-1;

}

static void exforsys()

//Static function exforsys( ) defined with keyword static

{

cout<<"\nResult is: "<<sum;

}

void number() //Normal member function number( )

{

cout<<"\nNumber is: "<<x;

}

};

void main()

{

example e1;

example::exforsys();

//Static function exforsys() accessed using class name example and the scope resolution operator

::

example e2,e3,e4;

Page 28: OOPS unit -5

28

example::exforsys();

e1.number();

e2.number();

//Normal member function accessed using object e1 and the dot member access operator .

e3.number();

e4.number();

}

The output of the above program is:

Result is: 1

Result is: 4

Number is: 1

Number is: 2

Number is: 3

Number is: 4

In the above we have seen that the function exforsys() s defined as static function and the integer

data type sum is declared as static data type. We see that four objects e1, e2, e3 and e4 are

created for the class example. The constructor of the class example increments the sum by 1 and

the destructor of the class decrements sum by 1.

We can see that the static function is accessed using the class name example and the scope

resolution operator :: as

example::exforsys();

But the normal member function number() is accessed using the object name and the dot member

access operator as

e1.number()

e2.number()

e3.number()

e4.number()

The first time when the static function exforsys() is called there was one object created and this

the sum gets incremented by 1 in the constructor printing the result of sum as 1.When the static

function exforsys() is called the second time there were three more objects e2,e3 and e4 created

which makes the sum to gets incremented thrice from 1 in the constructor of the corresponding

class namely example making the value of sum as 4 which is displayed in the second result.

From the above explanation it is clear that the static function operate on the class and not in

object generally. Also for accessing static function one can use the class name followed by the

scope resolution operator as seen in example above.

One must note the following while using static member functions:

Page 29: OOPS unit -5

29

A static member function can access only static member data, static member functions and data

and functions outside the class. So one must take essential care not to use static member function

like a non-static member function which can access all of the above including the static data

member.

A non-static member functions can be declared as virtual but care must be taken not to declare a

static member function as virtual.

One must first understand the concept of static data also while learning the context of static

functions. It is possible to declare a data member of a class as static irrespective of it being

public or private type in class definition. If a data is declared as static then the static data gets

created and initialized only once. That is unlike non-static data members that are created again

and again, for each separate object of the class the static data gets created and initialized only

once. Just like the concept of static data, in which the variables are shared by all objects of the

class in static functions also it apply to all objects of the class

A non-static member function can be called only after instantiating the class as an object. But it

is not the case with static member functions. Because a static member function can be called,

even when a class is not instantiated,

Also a static member function cannot have access to the 'this' pointer of the class.

C++ Friend Functions

In this C++ tutorials, you will learn about friend functions, need for friend function, how to

define and use friend function and few important points regarding friend function, explained with

example.

Need for Friend Function:

As discussed in the earlier sections on access specifiers, when a data is declared as private inside

a class, then it is not accessible from outside the class. A function that is not a member or an

external class will not be able to access the private data. A programmer may have a situation

where he or she would need to access private data from non-member functions and external

classes. For handling such cases, the concept of Friend functions is a useful tool.

What is a Friend Function?

A friend function is used for accessing the non-public members of a class. A class can allow non-

member functions and other classes to access its own private data, by making them friends. Thus,

a friend function is an ordinary function or a member of another class.

How to define and use Friend Function in C++:

Page 30: OOPS unit -5

30

The friend function is written as any other normal function, except the function declaration of

these functions is preceded with the keyword friend. The friend function must have the class to

which it is declared as friend passed to it in argument.

Some important points to note while using friend functions in C++:

The keyword friend is placed only in the function declaration of the friend function and

not in the function definition.

.

It is possible to declare a function as friend in any number of classes.

.

When a class is declared as a friend, the friend class has access to the private data of the

class that made this a friend.

.

A friend function, even though it is not a member function, would have the rights to

access the private members of the class.

.

It is possible to declare the friend function as either private or public.

.

The function can be invoked without the use of an object. The friend function has its

argument as objects, seen in example below.

Example to understand the friend function:

#include

class exforsys

{

private:

int a,b;

public:

void test()

{

a=100;

b=200;

}

friend int compute(exforsys e1)

//Friend Function Declaration with keyword friend and with the object of class

exforsys to which it is friend passed to it

};

int compute(exforsys e1)

{

//Friend Function Definition which has access to private data

Page 31: OOPS unit -5

31

return int(e1.a+e2.b)-5;

}

main()

{

exforsys e;

e.test();

cout<<"The result is:"<

//Calling of Friend Function with object as argument.

}

The output of the above program is

The result is:295

The function compute() is a non-member function of the class exforsys. In order to make this

function have access to the private data a and b of class exforsys , it is created as a friend

function for the class exforsys. As a first step, the function compute() is declared as friend in the

class exforsys as:

friend int compute (exforsys e1)

The keyword friend is placed before the function. The function definition is written as a normal

function and thus, the function has access to the private data a and b of the class exforsys. It is

declared as friend inside the class, the private data values a and b are added, 5 is subtracted from

the result, giving 295 as the result. This is returned by the function and thus the output is

displayed as shown above.

Concept of Pointers:

Every storage location of memory has an associated address. Address is a number that grows

sequentially. For every program placed in memory, each variable or function in the program has

an associated address.

The address of operator:

The address of operator or Reference operator is denoted by the notation &. When the user wants

to get the address of a variable, then the reference operator & can be used. The operator & is

used to find the address associated with a variable.

The syntax of the reference operator is as follows:

&variablename

This means that the address of the variablename is achieved.

Page 32: OOPS unit -5

32

For Example

#include <iostream.h>

void main()

{

int exf=200;

int test=300;

cout<<endl<<&exf

<<endl<<&test;

}

The output of the above program is:

0x92343456

0x78252348

The &exf has the address associated with the integer variable exf and the &test has the address

associated with the integer variable test which are displayed using the cout statement.

Using the understanding of address of operators, the discussion turns to the concept of pointers.

exforsys = 100;

test = exforsys;

x = &exforsys;

Using the above information, the assignment takes place as below:

exforsys is an integer variable having the value of 100 stored in memory address location 3501.

When the variable exforsys is assigned to the variable test in the second statement:

test = exforsys;

The value of the variable exforsys 100 is copied to the variable test.

In the third statement, the address of the variable exforsys is denoted by reference operator

&exforsys is assigned to the variable x as:

Page 33: OOPS unit -5

33

x = &exforsys;

The address of the variable 3501 and not the contents of the variable exforsys is copied into the

variable x. The pointers concept fits in this statement. Pointers are the variable that store the

reference to another variable. Pointers are variables that store the address of the variable that it is

pointed by. Variable x is referred to as the pointer in the above example.

The programmer must note that the address operator placed before a variable is not the same as

operator & placed after the variable. For example, &x is not same as x&. Variable &x refers to

address operator whereas x& refer to reference operator&.

Pointer is a variable that holds the address, also called pointer variable.

Defining Pointer Variables or Pointer:

In order to define pointer variables, the programmer must use the operator denoted as * in C++.

The symbol * when placed before a pointer, variable means that it as a pointer to.

While defining variables, the data type is placed before it. When the programmer wants to define

the integer variable i it is written:

int i;

A programmer may think that to define pointer variable there is a separate data type. But this is

not the case. There is no separate data type for pointer available. When a programmer defines a

pointer variable, he or she can point to integer, float, char. The compiler must know the type of

data the pointer is pointing to.

To define pointer variable is as follows:

datatype_of_ variable_pointedto* pointer_varaible;

For example:

char* ch; This defines that ch is a pointer variable which points to char data type.

int* i;

This defines that i is a pointer variable which points to int data type.

float* f;

This defines that f is a pointer variable which points to float data type.

C++ Void Pointer and Null Pointer

Page 34: OOPS unit -5

34

In this C++ tutorial, you will learn about two interesting types of pointers; void pointers and Null

Pointer. These pointers will be discussed in conjunction with syntax, usage and example.

Pointer to Void

General Syntax:

void* pointer_variable;

Void is used as a keyword.

Referring back to pointer definitions and usage, it is known that the data type the pointer variable

defines is the same as the data type the pointer points to. The address placed in a pointer must

have the same type as the pointer.

For example:

int i;

float f;

int* exf;

float* test;

then

exf=&i;

Is correct because the address of integer variable is stored in an integer pointer.

If a user writes the statement:

exf=&f;

Then this statement produces an error. The address of the float variable is stored in an integer

pointer that is incorrect.

Similarly, if the programmer tries to place the address of an integer variable to a float pointer,

such as: test=&i;

The above statement will also show an error.

The Pointer to Void is a special type of pointer that the programmer can use to point to any data

type.

Using the above example, the programmer declares pointer to void in this manner:

void* sample;

Page 35: OOPS unit -5

35

Using the above example‟s definition and assigning the pointer to void to the address of an

integer variable is perfectly correct.

sample=&i;

Using the above example to define the pointer to void and assign the pointer to void to the

address of a float variable as below is also perfectly correct.

sample=&f;

Pointer to void, or a void pointer, is a special type of pointer that has a great facility of pointing

to any data type. There are limitations in the usage of void pointers that are explained below.

The concept of dereferencing using the operator * has been explained in an earlier section of this

tutorial. The programmer must note that void pointers cannot be de-referenced in the same

manner. Direct dereferencing of void pointer is not permitted. The programmer must change the

pointer to void as any other pointer type that points to valid data types such as, int, char, float and

then dereference it. This conversion of pointer to some other valid data type is achieved by using

the concept of type-casting (refer to type-casting section of this tutorial).

NULL Pointer:

The concept of NULL pointer is different from the above concept of void pointer. NULL pointer

is a type of pointer of any data type and generally takes a value as zero. This is, however, not

mandatory. This denotes that NULL pointer does not point to any valid memory address.

For example:

int* exforsys;

exforsys=0;

The above statement denotes exforsys as an integer pointer type that does not point to a valid

memory address. This shows that exforsys has a NULL pointer value.

The difference between void pointers and NULL pointers:

A Void pointer is a special type of pointer of void and denotes that it can point to any data type.

NULL pointers can take any pointer type, but do not point to any valid reference or memory

address. It is important to note that a NULL pointer is different from a pointer that is not

initialized.

For example, if a programmer uses the program below:

#include <iostream.h>

int *exforsys;

Page 36: OOPS unit -5

36

void main()

{

*exforsys=100;

}

The output of the above program is

NULL POINTER ASSIGNMENT

The above program will result in a runtime error. This means that the pointer variable exforsys is

not assigned any valid address and, therefore, attempting to access the address 0 gives the above

error message.

UNIT-2

What is Type Conversion

It is the process of converting one type into another. In other words converting an

expression of a given type into another is called type casting.

How to achieve this

There are two ways of achieving the type conversion namely:

Automatic Conversion otherwise called as Implicit Conversion

Type casting otherwise called as Explicit Conversion

Let us see each of these in detail:

Automatic Conversion otherwise called as Implicit Conversion

This is not done by any conversions or operators. In other words value gets automatically

converted to the specific type in which it is assigned.

Let us see this with an example:

#include <iostream.h>

void main()

{

short x=6000;

Page 37: OOPS unit -5

37

int y;

y=a;

}

In the above example the data type short namely variable x is converted to int and is

assigned to the integer variable y.

So as above it is possible to convert short to int, int to float and so on.

Type casting otherwise called as Explicit Conversion

Explicit conversion can be done using type cast operator and the general syntax for doing

this is

datatype (expression);

Here in the above datatype is the type which the programmer wants the expression to gets

changed as

In C++ the type casting can be done in either of the two ways mentioned below namely:

C-style casting

C++-style casting

The C-style casting takes the synatx as

(type) expression

This can also be used in C++.

Apart from the above the other form of type casting that can be used specifically in C++

programming language namely C++-style casting is as below namely:

type (expression)

This approach was adopted since it provided more clarity to the C++ programmers rather

than the C-style casting.

Say for instance the as per C-style casting

(type) firstVariable * secondVariable

is not clear but when a programmer uses the C++ style casting it is much more clearer as

below

type (firstVariable) * secondVariable

Page 38: OOPS unit -5

38

Let us see the concept of type casting in C++ with a small example:

#include <iostream.h>

void main()

{

int a;

float b,c;

cout<< “Enter the value of a:”;

cin>>a;

cout<< “\n Enter the value of b:”;

cin>>b;

c = float(a)+b;

cout<<”\n The value of c is:”<<c;

}

The output of the above program is

Enter the value of a: 10

Enter the value of b: 12.5

The value of c is: 22.5

Constructors:

What is the use of Constructor

The main use of constructors is to initialize objects. The function of initialization is

automatically carried out by the use of a special member function called a constructor.

General Syntax of Constructor

Constructor is a special member function that takes the same name as the class name. The

syntax generally is as given below:

<class name> { arguments};

The default constructor for a class X has the form

X::X()

In the above example the arguments is optional.

The constructor is automatically named when an object is created. A constructor is named

whenever an object is defined or dynamically allocated using the "new" operator.

There are several forms in which a constructor can take its shape namely:

Page 39: OOPS unit -5

39

Default Constructor:

This constructor has no arguments in it. Default Constructor is also called as no

argument constructor.

For example:

class Exforsys

{

private:

int a,b;

public:

Exforsys();

...

};

Exforsys :: Exforsys()

{

a=0;

b=0;

}

Copy constructor:

This constructor takes one argument. Also called one argument constructor. The main use

of copy constructor is to initialize the objects while in creation, also used to copy an

object. The copy constructor allows the programmer to create a new object from an

existing one by initialization.

For example to invoke a copy constructor the programmer writes:

Exforsys e3(e2);

or

Exforsys e3=e2;

Both the above formats can be sued to invoke a copy constructor.

For Example:

Page 40: OOPS unit -5

40

#include <iostream.h>

class Exforsys()

{

private:

int a;

public:

Exforsys()

{ }

Exforsys(int w)

{

a=w;

}

Exforsys(Exforsys& e)

{

a=e.a;

cout<<” Example of Copy Constructor”;

}

void result()

{

cout<< a;

}

};

void main()

{

Exforsys e1(50);

Exforsys e3(e1);

cout<< “\ne3=”;e3.result();

}

In the above the copy constructor takes one argument an object of type Exforsys which is

passed by reference. The output of the above program is

Example of Copy Constructor

e3=50

Some important points about constructors:

A constructor takes the same name as the class name.

The programmer cannot declare a constructor as virtual or static, nor can the

programmer declare a constructor as const, volatile, or const volatile.

No return type is specified for a constructor.

The constructor must be defined in the public. The constructor must be a public

member.

Page 41: OOPS unit -5

41

Overloading of constructors is possible. This will be explained in later sections of

this tutorial.

Destructors

What is the use of Destructors

Destructors are also special member functions used in C++ programming language.

Destructors have the opposite function of a constructor. The main use of destructors is to

release dynamic allocated memory. Destructors are used to free memory, release

resources and to perform other clean up. Destructors are automatically named when an

object is destroyed. Like constructors, destructors also take the same name as that of the

class name.

General Syntax of Destructors

~ classname();

The above is the general syntax of a destructor. In the above, the symbol tilda ~

represents a destructor which precedes the name of the class.

Some important points about destructors:

Destructors take the same name as the class name.

Like the constructor, the destructor must also be defined in the public. The

destructor must be a public member.

The Destructor does not take any argument which means that destructors cannot

be overloaded.

No return type is specified for destructors.

For example:

class Exforsys

{

private:

……………

public:

Exforsys()

{ }

~ Exforsys()

{ }

}

Operator Overloading

Page 42: OOPS unit -5

42

Operator overloading is a very important feature of Object Oriented Programming.

Curious to know why!!? It is because by using this facility programmer would be able to

create new definitions to existing operators. In fact in other words a single operator can

take up several functions as desired by programmers depending on the argument taken by

the operator by using the operator overloading facility.

After knowing about the feature of operator overloading now let us see how to define and

use this concept of operator overloading in C++ programming language.

We have seen in previous sections the different types of operators. Broadly classifying

operators are of two types namely:

Unary Operators

Binary Operators

Unary Operators:

As the name implies takes operate on only one operand. Some unary operators are

namely ++ called as Increment operator, -- called as Decrement Operator, ! , ~, unary

minus.

Binary Operators:

The arithmetic operators, comparison operators, and arithmetic assignment operators all

this which we have seen in previous section of operators come under this category.

Both the above classification of operators can be overloaded. So let us see in detail each

of this.

Operator Overloading – Unary operators

As said before operator overloading helps the programmer to define a new functionality

for the existing operator. This is done by using the keyword operator.

The general syntax for defining an operator overloading is as follows:

return_type classname :: operator operator symbol(argument)

{

…………..

statements;

}

Thus the above clearly specifies that operator overloading is defined as a member

function by making use of the keyword operator.

Page 43: OOPS unit -5

43

In the above:

return_type – is the data type returned by the function

class name - is the name of the class

operator – is the keyword

operator symbol – is the symbol of the operator which is being overloaded or

defined for new functionality

:: - is the scope resolution operator which is used to use the function definition

outside the class. The usage of this is clearly defined in our earlier section of How

to define class members.

For example

Suppose we have a class say Exforsys and if the programmer wants to define a operator

overloading for unary operator say ++, the function is defined as

Inside the class Exforsys the data type that is returned by the overloaded operator is

defined as

class Exforsys

{

private:

……….

public:

void operator ++( );

…………

};

So the important steps involved in defining an operator overloading in case of unary

operators are namely:

Inside the class the operator overloaded member function is defined with the return data

type as member function or a friend function. The concept of friend function we will

Page 44: OOPS unit -5

44

define in later sections. If in this case of unary operator overloading if the function is a

member function then the number of arguments taken by the operator member function is

none as seen in the below example. In case if the function defined for the operator

overloading is a friend function which we will discuss in later section then it takes one

argument.

The operator overloading is defined as member function outside the class using the scope

resolution operator with the keyword operator as explained above

Now let us see how to use this overloaded operator member function in the program

#include <iostream.h>

class Exforsys

{

private:

int x;

public:

Exforsys( ) { x=0; } //Constructor

void display();

void Exforsys ++( );

};

void Exforsys :: display()

{

cout<<”\nValue of x is: “ << x;

}

void Exforsys :: operator ++( ) //Operator Overloading for operator ++ defined

{

++x;

}

void main( )

{

Exforsys e1,e2; //Object e1 and e2 created

cout<<”Before Increment”

cout <<”\nObject e1: ”<<e1.display();

cout <<”\nObject e2: ”<<e2.display();

++e1; //Operator overloading applied

++e2;

cout<<”\n After Increment”

cout <<”\nObject e1: ”<<e1.display();

cout <<”\nObject e2: ”<<e2.display();

}

The output of the above program is:

Page 45: OOPS unit -5

45

Before Increment

Object e1:

Value of x is: 0

Object e1:

Value of x is: 0

Before Increment

Object e1:

Value of x is: 1

Object e1:

Value of x is: 1

In the above example we have created 2 objects e1 and e2 f class Exforsys. The operator

++ is overloaded and the function is defined outside the class Exforsys.

When the program starts the constructor Exforsys of the class Exforsys initialize the

values as zero and so when the values are displayed for the objects e1 and e2 it is

displayed as zero. When the object ++e1 and ++e2 is called the operator overloading

function gets applied and thus value of x gets incremented for each object separately. So

now when the values are displayed for objects e1 and e2 it is incremented once each and

gets printed as one for each object e1 and e2.

This is how unary operators get overloaded. We will see in detail how to overload binary

operators in next section

Operator Overloading – Binary Operators

Binary operators, when overloaded, are given new functionality. The function defined for

binary operator overloading, as with unary operator overloading, can be member function

or friend function.

The difference is in the number of arguments used by the function. In the case of binary

operator overloading, when the function is a member function then the number of

arguments used by the operator member function is one (see below example). When the

function defined for the binary operator overloading is a friend function, then it uses two

arguments.

Binary operator overloading, as in unary operator overloading, is performed using a

keyword operator.

Binary operator overloading example:

Page 46: OOPS unit -5

46

#include <iostream.h>

class Exforsys

{

private:

int x;

int y;

public:

Exforsys() //Constructor

{ x=0; y=0; }

void getvalue( ) //Member Function for Inputting Values

{

cout << “\n Enter value for x: “;

cin >> x;

cout << “\n Enter value for y: “;

cin>> y;

}

void displayvalue( ) //Member Function for Outputting Values

{

cout <<”value of x is: “ << x <<”; value of y is: “<<y

}

Exforsys operator +(Exforsys);

};

Exforsys Exforsys :: operator + (Exforsys e2)

//Binary operator overloading for + operator defined

{

int x1 = x+ e2.x;

int y1 = y+e2.y;

return Exforsys(x1,y1);

}

void main( )

{

Exforsys e1,e2,e3; //Objects e1, e2, e3 created

cout<<\n”Enter value for Object e1:”;

e1.getvalue( );

cout<<\n”Enter value for Object e2:”;

e2.getvalue( );

e3= e1+ e2; //Binary Overloaded operator used

cout<< “\nValue of e1 is:”<<e1.displayvalue();

cout<< “\nValue of e2 is:”<<e2.displayvalue();

Page 47: OOPS unit -5

47

cout<< “\nValue of e3 is:”<<e3.displayvalue();

}

The output of the above program is:

Enter value for Object e1:

Enter value for x: 10

Enter value for y: 20

Enter value for Object e2:

Enter value for x: 30

Enter value for y: 40

Value of e1 is: value of x is: 10; value of y is: 20

Value of e2 is: value of x is: 30; value of y is: 40

Value of e3 is: value of x is: 40; value of y is: 60

In the above example, the class Exforsys has created three objects e1, e2, e3. The values

are entered for objects e1 and e2. The binary operator overloading for the operator „+‟ is

declared as a member function inside the class Exforsys. The definition is performed

outside the class Exforsys by using the scope resolution operator and the keyword

operator.

The important aspect is the statement:

e3= e1 + e2;

The binary overloaded operator „+‟ is used. In this statement, the argument on the left

side of the operator „+‟, e1, is the object of the class Exforsys in which the binary

overloaded operator „+‟ is a member function. The right side of the operator „+‟ is e2.

This is passed as an argument to the operator „+‟ . Since the object e2 is passed as

argument to the operator‟+‟ inside the function defined for binary operator overloading,

the values are accessed as e2.x and e2.y. This is added with e1.x and e1.y, which are

accessed directly as x and y. The return value is of type class Exforsys as defined by the

above example.

There are important things to consider in operator overloading with C++ programming

language. Operator overloading adds new functionality to its existing operators. The

programmer must add proper comments concerning the new functionality of the

overloaded operator. The program will be efficient and readable only if operator

overloading is used only when necessary.

Some operators cannot be overloaded:

scope resolution operator denoted by ::

member access operator or the dot operator denoted by .

the conditional operator denoted by ?:

and pointer to member operator denoted by .*

Page 48: OOPS unit -5

48

C++ Memory Management operators

Need for Memory Management operators

The concept of arrays has a block of memory reserved. The disadvantage with the

concept of arrays is that the programmer must know, while programming, the size of

memory to be allocated in addition to the array size remaining constant.

In programming there may be scenarios where programmers may not know the memory

needed until run time. In this case, the programmer can opt to reserve as much memory as

possible, assigning the maximum memory space needed to tackle this situation. This

would result in wastage of unused memory spaces. Memory management operators are

used to handle this situation in C++ programming language

What are memory management operators?

There are two types of memory management operators in C++:

new

delete

These two memory management operators are used for allocating and freeing memory

blocks in efficient and convenient ways.

New operator:

The new operator in C++ is used for dynamic storage allocation. This operator can be

used to create object of any type.

General syntax of new operator in C++:

The general syntax of new operator in C++ is as follows:

pointer variable = new datatype;

In the above statement, new is a keyword and the pointer variable is a variable of type

datatype.

For example:

int *a=new int;

In the above example, the new operator allocates sufficient memory to hold the object of

datatype int and returns a pointer to its starting point. The pointer variable a holds the

address of memory space allocated.

Page 49: OOPS unit -5

49

Dynamic variables are never initialized by the compiler. Therefore, the programmer

should make it a practice to first assign them a value.

The assignment can be made in either of the two ways:

int *a = new int;

*a = 20;

or

int *a = new int(20);

delete operator:

The delete operator in C++ is used for releasing memory space when the object is no

longer needed. Once a new operator is used, it is efficient to use the corresponding delete

operator for release of memory.

General syntax of delete operator in C++:

The general syntax of delete operator in C++ is as follows:

delete pointer variable;

In the above example, delete is a keyword and the pointer variable is the pointer that

points to the objects already created in the new operator. Some of the important points the

programmer must note while using memory management operators are described below:

The programmer must take care not to free or delete a pointer variable that has

already been deleted.

.

Overloading of new and delete operator is possible (to be discussed in detail in

later section on overloading).

.

We know that sizeof operator is used for computing the size of the object. Using

memory management operator, the size of the object is automatically computed.

.

The programmer must take care not to free or delete pointer variables that have

not been allocated using a new operator.

.

Null pointer is returned by the new operator when there is insufficient memory

available for allocation.

Page 50: OOPS unit -5

50

Example: to understand the concept of new and delete memory management operator in

C++:

#include <iostream.h>

void main()

{

//Allocates using new operator memory space in memory for storing a integer

datatype

int *a= new a;

*a=100;

cout << " The Output is:a="<<a;

//Memory Released using delete operator

delete a;

}

The output of the above program is

The Output is:a=100

In the above program, the statement:

int *a= new a;

Holds memory space in memory for storing a integer datatype. The statement:

*a=100

This denotes that the value present in address location pointed by the pointer variable a is

100 and this value of a is printed in the output statement giving the output shown in the

example above. The memory allocated by the new operator for storing the integer

variable pointed by a is released using the delete operator as:

delete a;

C++ Dereference Operator

In this C++ tutorial, you will learn how to access the value of variables pointed by the

pointer variables using pointer concept discussed in detail.

It is possible to access the value of variables pointed by the pointer variables using

pointer. This is performed by using the Dereference operator in C++ which has the

notation *.

Page 51: OOPS unit -5

51

The general syntax of the Dereference operator is as follows:

*pointer_variable

In this example, pointer variable denotes the variable defined as pointer. The * placed

before the pointer_variable denotes the value pointed by the pointer_variable.

For example:

exforsys = 100;

test = exforsys;

x = &exforsys;

y=*x;

In the above example, the assignment takes place as below:

In the above example, the exforsys is a integer variable having the value of 100 stored in

memory address location 3501.

The variable exforsys is assigned to the variable test in the second statement:

test = exforsys;

The value of the variable exforsys is 100 and is then copied to the variable test.

Page 52: OOPS unit -5

52

In the third statement, the address of the variable exforsys denoted by reference operator

&exforsys is assigned to the variable x as:

x = &exforsys;

The address of the variable 3501 and not the contents of the variable exforsys is then

copied into the variable x.

The fourth statement makes use of the deference operator:

y=*x

This means that the value pointed to by the pointer variable x gives the value 100 to y.

Some points for the programmer to note:

The programmer must note that the x refers to the address 3501 whereas *x refers

to the value stored in the address 3501 namely 100.

.

The reference operator is denoted by & and deference operator denoted by * .

Both differ in their meaning and functionality. The reference operator denotes the

address of. The dereference operator denotes the value pointed by. In short, a

deference variable can be denoted as referenced.

.

If the programmer wants to define more than two pointer variables, then comma

operator may be used in this instance. The programmer must carefully place

pointer symbol * before each pointer variable.

For instance, if the user wishes to define two integer pointer variables, e1 and e2, this can

be done as follows:

int *e1,*e2;

If the programmer declares:

int *e1,e2;

This means that e1 is a pointer variable pointing to integer data type but e2 is only an

integer data type and not a pointer type. The programmer must ensure to place * before

each pointer variable.

The dereferencing or indirect addressing is performed using the indirection operator *

used to access the value stored in an address.

The defining of pointer variable:

Page 53: OOPS unit -5

53

int* exf;

The definition of pointer variable as in the above case is the pointer variable exf.

It is also possible to assign value to pointer variable using indirection operator. This gives

the same effect as working with variables.

For Example:

#include

void main()

{

int example,test;

int* exforsys;

exforsys=&example;

example=200;

test=200;

*exforsys=100;

test=*exforsys;

cout< cout< }

The output of the above program is

100

100

In the above example, the pointer variable exforsys points to integer variable example

and takes the address of the variable example as:

test and example have initial values of 200.

Page 54: OOPS unit -5

54

The statement:

*exforsys=100

Sets the value of the variable pointed by pointer variable exforsys as 100. This is

equivalent to setting example=100.

The assignment is as follows:

example test

The statement

test=*exforsys;

sets the value of variable test with the value pointed by the pointer variable exforsys

which is 100 as seen in the above example. Test also becomes 100 and the assignment

becomes:

Both results are displayed having the value 100.

Page 55: OOPS unit -5

55

UNIT-3

C++ Inheritance

Introduction

What is Inheritance?

Inheritance is the process by which new classes called derived classes are created from existing

classes called base classes. The derived classes have all the features of the base class and the

programmer can choose to add new features specific to the newly created derived class.

For example, a programmer can create a base class named fruit and define derived classes as

mango, orange, banana, etc. Each of these derived classes, (mango, orange, banana, etc.) has all

the features of the base class (fruit) with additional attributes or features specific to these newly

created derived classes. Mango would have its own defined features, orange would have its own

defined features, banana would have its own defined features, etc.

This concept of Inheritance leads to the concept of polymorphism.

Features or Advantages of Inheritance:

Reusability:

Inheritance helps the code to be reused in many situations. The base class is defined and once it

is compiled, it need not be reworked. Using the concept of inheritance, the programmer can

create as many derived classes from the base class as needed while adding specific features to

each derived class as needed.

Saves Time and Effort:

The above concept of reusability achieved by inheritance saves the programmer time and effort.

Since the main code written can be reused in various situations as needed.

Increases Program Structure which results in greater reliability.

Polymorphism

General Format for implementing the concept of Inheritance:

class derived_classname: access specifier baseclassname

For example, if the base class is exforsys and the derived class is sample it is specified as:

Page 56: OOPS unit -5

56

class sample: public exforsys

The above makes sample have access to both public and protected variables of base class

exforsys. Reminder about public, private and protected access specifiers:

If a member or variables defined in a class is private, then they are accessible by

members of the same class only and cannot be accessed from outside the class.

.

Public members and variables are accessible from outside the class.

.

Protected access specifier is a stage between private and public. If a member functions or

variables defined in a class are protected, then they cannot be accessed from outside the

class but can be accessed from the derived class.

Inheritance Example:

class exforsys

{

public:

exforsys(void) { x=0; }

void f(int n1)

{

x= n1*5;

}

void output(void) { cout<<x; }

private:

int x;

};

class sample: public exforsys

{

public:

sample(void) { s1=0; }

void f1(int n1)

{

s1=n1*10;

}

void output(void)

{

exforsys::output();

cout << s1;

Page 57: OOPS unit -5

57

}

private:

int s1;

};

int main(void)

{

sample s;

s.f(10);

s.output();

s.f1(20);

s.output();

}

The output of the above program is

50

200

In the above example, the derived class is sample and the base class is exforsys. The derived

class defined above has access to all public and private variables. Derived classes cannot have

access to base class constructors and destructors. The derived class would be able to add new

member functions, or variables, or new constructors or new destructors. In the above example,

the derived class sample has new member function f1( ) added in it. The line:

sample s;

creates a derived class object named as s. When this is created, space is allocated for the data

members inherited from the base class exforsys and space is additionally allocated for the data

members defined in the derived class sample.

The base class constructor exforsys is used to initialize the base class data members and the

derived class constructor sample is used to initialize the data members defined in derived class.

The access specifier specified in the line:

class sample: public exforsys

Public indicates that the public data members which are inherited from the base class by the

derived class sample remains public in the derived class.

Page 58: OOPS unit -5

58

Inheritance leads to various issues such as:

What is Inherited

types of inheritance

accessibility modes (public, private and protected) in inheritance

Friend function and inheritance etc.

#include <iostream>

using namespace std;

class Cpolygon

{

protected:

int width, height;

public:

void input_values (int one, int two)

{

width=one;

height=two;

}

};

class Crectangle: public Cpolygon

{

public:

int area ()

{

return (width * height);

}

};

class Ctriangle: public Cpolygon

{

public:

int area ()

{

return (width * height / 2);

}

};

int main ()

{

Crectangle rectangle;

Ctriangle triangle;

rectangle.input_values (2,2);

Page 59: OOPS unit -5

59

triangle.input_values (2,2);

cout << rectangle.area() << endl;

cout << triangle.area() << endl;

return 0;

}

In the example above we have used the protected members of the class Cpolygon in the class

Crectangle and in the Ctriangle class. This is only possible through Inheritance.

What is inherited?

When inheritance is done, various links and tables (index, virtual etc) are created which are used

to provide the accessibility of the members of the base class in derived class and in other class

hierarchy. This means saying “public members are inherited” is better to say as “public

members become accessible”.

A derived class inherits every member of a base class except:

its constructor and its destructor

its friends

its operator=() members

Types of Inheritance

There are five different inheritances supported in C++:

(1) Simple / Single

(2) Multilevel

(3) Hierarchical

(4) Multiple

(5) Hybrid

Page 60: OOPS unit -5

60

Multiple Inheritance

Multiple inheritance is achieved whenever more than one class acts as base classes for other

classes. This makes the members of the base classes accessible in the derived class, resulting in

better integration and broader re-usability.

Take a look at an example:

#include <iostream>

using namespace std;

class Cpolygon

{

protected:

int width, height;

public:

void input_values (int one, int two)

{

width=one;

height=two;

}

};

class Cprint

{

public:

void printing (int output);

Page 61: OOPS unit -5

61

};

void Cprint::printing (int output)

{

cout << output << endl;

}

class Crectangle: public Cpolygon, public Cprint

{

public:

int area ()

{

return (width * height);

}

};

class Ctriangle: public Cpolygon, public Cprint

{

public:

int area ()

{

return (width * height / 2);

}

};

int main ()

{

Crectangle rectangle;

Ctriangle triangle;

rectangle.input_values (2,2);

triangle.input_values (2,2);

rectangle.printing (rectangle.area());

triangle.printing (triangle.area());

return 0;

}

Note:the two public statements in the Crectangle class and Ctriangle class.

Accessibility modes and Inheritance

We can use the following chart for seeing the accessibility of the members in the Base class (first

class) and derived class (second class).

Page 62: OOPS unit -5

62

Here X indicates that the members are not inherited, i.e. they are not accessible in the derived

class.

C++ Polymorphism

Introduction

Polymorphism is the ability to use an operator or function in different ways. Polymorphism gives

different meanings or functions to the operators or functions. Poly, referring to many, signifies

the many uses of these operators and functions. A single function usage or an operator

functioning in many ways can be called polymorphism. Polymorphism refers to codes,

operations or objects that behave differently in different contexts.

Below is a simple example of the above concept of polymorphism:

6 + 10

The above refers to integer addition.

The same + operator can be used with different meanings with strings:

"Exforsys" + "Training"

The same + operator can also be used for floating point addition:

7.15 + 3.78

Polymorphism is a powerful feature of the object oriented programming language C++. A single

operator + behaves differently in different contexts such as integer, float or strings referring the

concept of polymorphism. The above concept leads to operator overloading. The concept of

Page 63: OOPS unit -5

63

overloading is also a branch of polymorphism. When the exiting operator or function operates on

new data type it is overloaded. This feature of polymorphism leads to the concept of virtual

methods.

Polymorphism refers to the ability to call different functions by using only one type of function

call. Suppose a programmer wants to code vehicles of different shapes such as circles, squares,

rectangles, etc. One way to define each of these classes is to have a member function for each

that makes vehicles of each shape. Another convenient approach the programmer can take is to

define a base class named Shape and then create an instance of that class. The programmer can

have array that hold pointers to all different objects of the vehicle followed by a simple loop

structure to make the vehicle, as per the shape desired, by inserting pointers into the defined

array. This approach leads to different functions executed by the same function call.

Polymorphism is used to give different meanings to the same concept. This is the basis for

Virtual function implementation.

In polymorphism, a single function or an operator functioning in many ways depends upon the

usage to function properly. In order for this to occur, the following conditions must apply:

All different classes must be derived from a single base class. In the above example, the

shapes of vehicles (circle, triangle, rectangle) are from the single base class called Shape.

The member function must be declared virtual in the base class. In the above example,

the member function for making the vehicle should be made as virtual to the base class.

Features and Advantages of the concept of Polymorphism:

Applications are Easily Extendable:

Once an application is written using the concept of polymorphism, it can easily be extended,

providing new objects that conform to the original interface. It is unnecessary to recompile

original programs by adding new types. Only re-linking is necessary to exhibit the new changes

along with the old application. This is the greatest achievement of C++ object-oriented

programming. In programming language, there has always been a need for adding and

customizing. By utilizing the concept of polymorphism, time and work effort is reduced in

addition to making future maintenance easier.

Helps in reusability of code.

Provides easier maintenance of applications.

Helps in achieving robustness in applications.

Types of Polymorphism:

C++ provides three different types of polymorphism.

Virtual functions

Function name overloading

Operator overloading

Page 64: OOPS unit -5

64

In addition to the above three types of polymorphism, there exist other kinds of polymorphism:

run-time

compile-time

ad-hoc polymorphism

parametric polymorphism

Other types of polymorphism defined:

run-time:

The run-time polymorphism is implemented with inheritance and virtual functions.

compile-time:

The compile-time polymorphism is implemented with templates.

ad-hoc polymorphism:

If the range of actual types that can be used is finite and the combinations must be individually

specified prior to use, this is called ad-hoc polymorphism.

parametric polymorphism:

If all code is written without mention of any specific type and thus can be used transparently

with any number of new types it is called parametric polymorphism.

In general, there are two main categories of Polymorphism namely

Ad Hoc Polymorphism

Pure Polymorphism

Overloading concepts fall under the category of Ad Hoc Polymorphism and Virtual methods.

Templates or parametric classes fall under the category of Pure Polymorphism.

Virtual Functions

What are Virtual Functions?

Virtual, as the name implies, is something that exists in effect but not in reality. The concept of

virtual function is the same as a function, but it does not really exist although it appears in

needed places in a program. The object-oriented programming language C++ implements the

concept of virtual function as a simple member function, like all member functions of the class.

The functionality of virtual functions can be over-ridden in its derived classes. The programmer

must pay attention not to confuse this concept with function overloading. Function overloading is

Page 65: OOPS unit -5

65

a different concept and will be explained in later sections of this tutorial. Virtual function is a

mechanism to implement the concept of polymorphism (the ability to give different meanings to

one function).

Need for Virtual Function:

The vital reason for having a virtual function is to implement a different functionality in the

derived class.

For example: a Make function in a class Vehicle may have to make a Vehicle with red color. A

class called FourWheeler, derived or inherited from Vehicle, may have to use a blue background

and 4 tires as wheels. For this scenario, the Make function for FourWheeler should now have a

different functionality from the one at the class called Vehicle. This concept is called Virtual

Function.

Properties of Virtual Functions:

Dynamic Binding Property:

Virtual Functions are resolved during run-time or dynamic binding. Virtual functions are also

simple member functions. The main difference between a non-virtual C++ member function and

a virtual member function is in the way they are both resolved. A non-virtual C++ member

function is resolved during compile time or static binding. Virtual Functions are resolved during

run-time or dynamic binding

Virtual functions are member functions of a class.

Virtual functions are declared with the keyword virtual, detailed in an example below.

Virtual function takes a different functionality in the derived class.

Declaration of Virtual Function:

Virtual functions are member functions declared with the keyword virtual.

For example, the general syntax to declare a Virtual Function uses:

class classname //This denotes the base class of C++ virtual function

{

public:

virtual void memberfunctionname() //This denotes the C++ virtual function

{

.............

............

}

};

Page 66: OOPS unit -5

66

Referring back to the Vehicle example, the declaration of Virtual function would take the shape

below:

class Vehicle //This denotes the base class of C++ virtual function

{

public:

virtual void Make() //This denotes the C++ virtual function

{

cout <<"Member function of Base Class Vehicle Accessed"<<endl;

}

};

After the virtual function is declared, the derived class is defined. In this derived class, the new

definition of the virtual function takes place.

When the class FourWheeler is derived or inherited from Vehicle and defined by the virtual

function in the class FourWheeler, it is written as:

class Vehicle //This denotes the base class of C++ virtual function

{

public:

virtual void Make() //This denotes the C++ virtual function

{

cout <<"Member function of Base Class Vehicle Accessed"<<endl;

}

};

class FourWheeler : public Vehicle

{

public:

void Make()

{

cout<<"Virtual Member function of Derived class FourWheeler Accessed"<<endl;

}

};

void main()

{

Vehicle *a, *b;

a = new Vehicle();

a->Make();

b = new FourWheeler();

b->Make();

}

Page 67: OOPS unit -5

67

In the above example, it is evidenced that after declaring the member functions Make() as virtual

inside the base class Vehicle, class FourWheeler is derived from the base class Vehicle. In this

derived class, the new implementation for virtual function Make() is placed.

The programmer might be surprised to see the function call differs and the output is then printed

as above. If the member function has not been declared as virtual, the base class member

function is always called because linking takes place during compile time and is therefore static.

In this example, the member function is declared virtual and the address is bounded only during

run time, making it dynamic binding and thus the derived class member function is called.

To achieve the concept of dynamic binding in C++, the compiler creates a v-table each time a

virtual function is declared. This v-table contains classes and pointers to the functions from each

of the objects of the derived class. This is used by the compiler whenever a virtual function is

needed.

C++ Pure Virtual Function and Virtual Base Class

In this C++ tutorial, you will learn about pure virtual function, declaration of pure virtual

function and virtual base class, virtual base class and how to implement a virtual base class,

explained with examples.

What is Pure Virtual Function:

Pure Virtual Function is a Virtual function with no body.

Declaration of Pure Virtual Function:

Since pure virtual function has no body, the programmer must add the notation =0 for declaration

of the pure virtual function in the base class.

General Syntax of Pure Virtual Function takes the form:

class classname //This denotes the base class of C++ virtual function

{

public:

virtual void virtualfunctioname() = 0 //This denotes the pure virtual function in C++

};

The other concept of pure virtual function remains the same as described in the previous section

of virtual function.

Page 68: OOPS unit -5

68

To understand the declaration and usage of Pure Virtual Function, refer to this example:

class Exforsys

{

public:

virtual void example()=0; //Denotes pure virtual Function Definition

};

class Exf1:public Exforsys

{

public:

void example()

{

cout<<"Welcome";

}

};

class Exf2:public Exforsys

{

public:

void example()

{

cout<<"To Training";

}

};

void main()

{

Exforsys* arra[2];

Exf1 e1;

Exf2 e2;

arra[0]=&e1;

arra[1]=&e2;

arra[0]->example();

arra[1]->example();

}

Since the above example has no body, the pure virtual function example() is declared with

notation =0 in the base class Exforsys. The two derived class named Exf1 and Exf2 are derived

from the base class Exforsys. The pure virtual function example() takes up new definition. In the

main function, a list of pointers is defined to the base class.

Page 69: OOPS unit -5

69

Two objects named e1 and e2 are defined for derived classes Exf1 and Exf2. The address of the

objects e1 and e2 are stored in the array pointers which are then used for accessing the pure

virtual function example() belonging to both the derived class EXf1 and EXf2 and thus, the

output is as in the above example.

The programmer must clearly understand the concept of pure virtual functions having no body in

the base class and the notation =0 is independent of value assignment. The notation =0 simply

indicates the Virtual function is a pure virtual function as it has no body.

Some programmers might want to remove this pure virtual function from the base class as it has

no body but this would result in an error. Without the declaration of the pure virtual function in

the base class, accessing statements of the pure virtual function such as, arra[0]->example() and

arra[1]->example() would result in an error. The pointers should point to the base class Exforsys.

Special care must be taken not to remove the statement of declaration of the pure virtual function

in the base class.

Virtual Base Class

In the above example, there are two derived classes Exf1 and Exf2 from the base class Exforsys.

As shown in the above diagram, the Training class is derived from both of the derived classes

Exf1 and Exf2. In this scenario, if a user has a member function in the class Training where the

user wants to access the data or member functions of the class Exforsys it would result in error if

it is performed like this:

class Exforsys

{

protected:

int x;

};

class Exf1:public Exforsys

{ };

Page 70: OOPS unit -5

70

class Exf2:public Exforsys

{ };

class Training:public Exf1,public Exf2

{

public:

int example()

{

return x;

}

};

The above program results in a compile time error as the member function example() of class

Training tries to access member data x of class Exforsys. This results in an error because the

derived classes Exf1 and Exf2 (derived from base class Exforsys) create copies of Exforsys

called subobjects.

This means that each of the subobjects have Exforsys member data and member functions and

each have one copy of member data x. When the member function of the class Training tries to

access member data x, confusion arises as to which of the two copies it must access since it

derived from both derived classes, resulting in a compile time error.

When this occurs, Virtual base class is used. Both of the derived classes Exf1 and Exf2 are

created as virtual base classes, meaning they should share a common subobject in their base

class.

For Example:

class Exforsys

{

protected:

int x;

;

class Exf1:virtual public Exforsys

{ };

class Exf2:virtual public Exforsys

{ };

class Training:public Exf1,public Exf2

{

Page 71: OOPS unit -5

71

public:

int example()

{

return x;

}

};

In the above example, both Exf1 and Exf2 are created as Virtual base classes by using the

keyword virtual. This enables them to share a common subobject of their base class Exforsys.

This results in only one copy that the member function example() of Class Training can access

the member data x.

C++ Polymorphism and Abstract Base Class

Before you start reading this C++ tutorial on polymorphism you should have a good

understanding of class inheritance and pointers.

Introduction to Polymorphism

Polymorphism is by far the most important and widely used concept in object oriented

programming. Some of the widely used technologies and libraries like COM, MFC etc. have

polymorphism as their foundation. If you look at all the original design patterns, almost every

pattern uses polymorphism in its structure.

Polymorphism is a mechanism that allows you to implement a function in different ways.

Pointers to base class

We have seen that it is possible to derive a class from a base class and that we can add

functionality to member functions.

One of the features of derived classes is that a pointer to a derived class is type-compatible with a

pointer to its base class. Polymorphism takes advantage of this feature.

Let‟s take a look at an example of a base class and derived classes:

#include <iostream>

using namespace std;

class CPolygon

{

protected:

int width, height;

public:

Page 72: OOPS unit -5

72

void setup (int first, int second)

{

width= first;

height= second;

}

};

class CRectangle: public CPolygon

{

public:

int area()

{

return (width * height);

}

};

class CTriangle: public CPolygon

{

public:

int area()

{

return (width * height / 2);

}

};

int main ()

{

CRectangle rectangle;

CTriangle triangle;

CPolygon * ptr_polygon1 = &rectangle;

CPolygon * ptr_polygon2 = &triangle;

ptr_polygon1->setup(2,2);

ptr_polygon2->setup(2,2);

cout << rectangle.area () << endl;

cout << triangle.area () << endl;

return 0;

}

As you can see, we create two pointers (ptr_polygon1 and ptr_polygon2) that point to the objects

of class CPolygon. Then we assign to these pointers the address of (using the reference

Page 73: OOPS unit -5

73

ampersand sign) the objects rectangle and triangle. Both rectangle and triangle are objects of

classes derived from CPolygon.

In the cout statement we use the objects rectangle and triangle instead of the pointers

ptr_polygon1 and ptr_polygon2. We do this because ptr_polygon1 and ptr_polygon2 are of the

type CPolygon. This means we can only use the pointers to refer to members that CRectangle

and CTriangle inherit from Cpolygon.

If we want to use the pointers to class CPolygon then area() should be declared in the class

CPolygon and not only in the derived classes CRectangle and Ctriangle.

The problem is that we use different versions of area() in the derived classes – CRectangle and

Ctriangle – so we can‟t implement one version of area() in the base class CPolygon. (If they were

the same we had no problem.)

We can fix this by using virtual members.

Virtual Members

A virtual member is a member of a base class that we can redefine in its derived classes. To

declare a member as virtual we must use the keyword virtual.

Let‟s change our previous example:

#include <iostream>

using namespace std;

class CPolygon

{

protected:

int width, height;

public:

void setup (int first, int second)

{

width= first;

height= second;

}

virtual int area()

{

return (0);

}

};

class CRectangle: public CPolygon

{

Page 74: OOPS unit -5

74

public:

int area()

{

return (width * height);

}

};

class CTriangle: public CPolygon

{

public:

int area()

{

return (width * height / 2);

}

};

int main ()

{

CRectangle rectangle;

CTriangle triangle;

CPolygon polygon;

CPolygon * ptr_polygon1 = &rectangle;

CPolygon * ptr_polygon2 = &triangle;

CPolygon * ptr_polygon3 = &polygon;

ptr_polygon1->setup(2,2);

ptr_polygon2->setup(2,2);

ptr_polygon3->setup(2,2);

cout << ptr_polygon1->area () << endl;

cout << ptr_polygon2->area () << endl;

cout << ptr_polygon3->area () << endl;

return 0;

}

Because of the change – adding area() as a virtual member of CPolygon – now all the three

classes have all the same members (width, height, setup() and area().)

A class that declares or inherits a virtual function is called a polymorphic class.

Page 75: OOPS unit -5

75

Abstract Base Classes (ABC)

At the design level, an abstract base class (ABC) corresponds to an abstract concept. For

instance: if you ask to draw a shape, I will probably ask what kind of shape. The term “shape” is

an abstract concept, it could be a circle, a square, etc, etc. You could say in C++ that class

CShape is an abstract base class (ABC) and class circle (etc) could be a derived class.

As we look at the C++ language we could say that an abstract base class has one or more pure

virtual member functions.

In the example above we put an implementation (return (0);) in the virtual member function

area(). If we want to change it into a pure virtual member function we use =0; instead of the

return (0). So the class will look like this:

class CPolygon

{

protected:

int width, height;

public:

void setup (int first, int second)

{

width= first;

height= second;

}

virtual int area() = 0;

};

This pure virtual function area() makes CPolygon an abstract base class. But you have to

remember the following: by adding a pure virtual member to the base class, you are forced to

also add the member to any derived class.

So our example should now look like this:

#include <iostream>

using namespace std;

class CPolygon

{

protected:

int width, height;

public:

void setup (int first, int second)

{

Page 76: OOPS unit -5

76

width= first;

height= second;

}

virtual int area() = 0;

};

class CRectangle: public CPolygon

{

public:

int area(void)

{

return (width * height);

}

};

class CTriangle: public CPolygon

{

public:

int area(void)

{

return (width * height / 2);

}

};

int main ()

{

CRectangle rectangle;

CTriangle triangle;

CPolygon * ptr_polygon1 = &rectangle;

CPolygon * ptr_polygon2 = &triangle;

ptr_polygon1->setup(2,2);

ptr_polygon2->setup(2,2);

cout << ptr_polygon1->area () << endl;

cout << ptr_polygon2->area () << endl;

return 0;

}

Note: there is also an extra void in the derived classes CRectangle and CTriangle.

Using a unique type of pointer (CPolygon*) we can point to objects of different but related

classes.

Page 77: OOPS unit -5

77

We can make use of that. For instance: we could implement an extra function member in the

abstract base class CPolygon that can print the result of the area() function. (Remember that

CPolygon itself has no implementation for the function area() and still we can use it, isn‟t it

cool.) After implementation of such a function the example will look like this:

#include <iostream>

using namespace std;

class CPolygon

{

protected:

int width, height;

public:

void setup (int first, int second)

{

width= first;

height= second;

}

virtual int area(void) = 0;

void onscreen(void)

{

cout << this->area() << endl;

}

};

class CRectangle: public CPolygon

{

public:

int area(void)

{

return (width * height);

}

};

class CTriangle: public CPolygon

{

public:

int area(void)

{

return (width * height / 2);

}

};

int main ()

{

Page 78: OOPS unit -5

78

CRectangle rectangle;

CTriangle triangle;

CPolygon * ptr_polygon1 = &rectangle;

CPolygon * ptr_polygon2 = &triangle;

ptr_polygon1->setup(2,2);

ptr_polygon2->setup(2,2);

ptr_polygon1->onscreen();

ptr_polygon2->onscreen();

return 0;

}

As you can see this can be very useful.

Dynamic Allocation

In an earlier tutorial we already looked at dynamic allocation using the „new‟ operator. (So we

don‟t have to explain that again). In this last section we will change the previous example and we

will dynamically allocate the objects.

Take a look at the next example:

#include <iostream>

using namespace std;

class CPolygon

{

protected:

int width, height;

public:

void setup (int first, int second)

{

width= first;

height= second;

}

virtual int area(void) = 0;

void onscreen(void)

{

cout << this->area() << endl;

}

};

Page 79: OOPS unit -5

79

class CRectangle: public CPolygon

{

public:

int area(void)

{

return (width * height);

}

};

class CTriangle: public CPolygon

{

public:

int area(void)

{

return (width * height / 2);

}

};

int main ()

{

CPolygon * ptr_polygon1 = new CRectangle;

CPolygon * ptr_polygon2 = new CTriangle;

ptr_polygon1->setup(2,2);

ptr_polygon2->setup(2,2);

ptr_polygon1->onscreen();

ptr_polygon2->onscreen();

delete ptr_polygon1;

delete ptr_polygon2;

return 0;

}

Typecasting

Typecasting is the concept of converting the value of one type into another type. For example,

you might have a float that you need to use in a function that requires an integer.

Page 80: OOPS unit -5

80

Implicit conversion

Almost every compiler makes use of what is called automatic typecasting. It automatically

converts one type into another type. If the compiler converts a type it will normally give a

warning. For example this warning: conversion from „double‟ to „int‟, possible loss of data.

The problem with this is, that you get a warning (normally you want to compile without

warnings and errors)

and you are not in control. With control we mean, you did not decide to convert to another type,

the compiler did. Also the possible loss of data could be unwanted.

Explicit conversion

The C and C++ languages have ways to give you back control. This can be done with what is

called an explicit conversion. Sure you may still lose data, but you decide when to convert to

another type and you don‟t get any compiler warnings.

Let‟s take a look at an example that uses implicit and explicit conversion:

#include <iostream>

using namespace std;

int main()

{

int a;

double b=2.55;

a = b;

cout << a << endl;

a = (int)b;

cout << a << endl;

a = int(b);

cout << a << endl;

}

Note: the output of all cout statements is 2.

The first conversion is an implicit conversion (the compiler decides.) As explained before, the

compiler should give a warning.

The second conversion is an explicit typecast, in this case the C style explicit typecast.

Page 81: OOPS unit -5

81

The third conversion is also explicit typecast, in this case the C++ style explicit typecast.

Four typecast operators

The C++ language has four typecast operators:

static_cast

reinterpret_cast

const_cast

dynamic_cast

Static_cast

Automatic conversions are common in every C++ program. You have:

Standard conversion. For instance: from short to int or from int to float.

User defined conversions (Class conversions.)

Conversion from derived class to base class.

(Take a look at the inheritance tutorial)

The static_cast can be used for all these types of conversion. Take a look at an example:

int a = 5;

int b = 2;

double out;

// typecast a to double

out = static_cast<double>(a)/b;

It may take some time to get used to the notation of the typecast statement. (The rumour goes

that Bjarne Stroustrup made it difficult on purpose, to discourage the use of typecasting.)

Between the angle brackets you place to which type the object should be casted. Between the

parentheses you place the object that is casted.

It is not possible to use static_cast on const objects to non-const objects. For this you have to use

const_cast. (Further down we take a look at const_cast.)

If an automatic conversion is valid (from enum to int for instance) then you can use static_cast to

do the opposite (from int to enum.)

For instance:

enum my_numbers { a=10, c=100, e=1000 };

Page 82: OOPS unit -5

82

const my_numbers b = static_cast<my_numbers> (50);

const my_numbers d = static_cast<my_numbers> (500);

Note: We add some new values (b and d). These are type-cast from int to enum.

Reinterpret_cast

The reinterpret_cast is used for casts that are not save:

Between integers and pointers

Between pointers and pointers

Between function-pointers and function-pointers

For instance the typecast from an integer to a character pointer:

char *ptr_my = reinterpret_cast<char *>(0xb0000);

Note: the example above uses a fixed memory location.

If we use the reinterpret_cast on a null-pointer then we get a null-pointer of the asked type:

char *ptr_my = 0;

int *ptr_my_second = reinterpret_cast<int *>(ptr_my);

The reinterpret_cast is almost as dangerous as an “old fashion” cast. The only guaranty that you

get is that if you cast an object back to the original data-type (before the first cast) then the

original value is also restored (of course only if the data-type was big enough to hold the value.)

The only difference with an old fashion cast is that const is respected. This means that a

reinterpret_cast can not be used to cast a const object to non-const object. For instance:

char *const MY = 0;

// This is not valid because MY is a const!!

int *ptr_my = reinterpret_cast<int *>( MY);

Page 83: OOPS unit -5

83

Const_cast

The only way to cast away the const properties of an object is to use const_cast. Take a look at

an example:

void a(Person* b);

int main()

{

const Person *ptr_my = new Person("Joe");

a( const_cast<Person *>(ptr_my) );

}

The use of const_cast on an object doesn‟t guarantee that the object can be used (after the const

is cast away.) Because it is possible that the const-objects are put in read-only memory by the

program.

The const_cast can not be used to cast to other data-types, as it is possible with the other cast

functions.

Take a look at the next example:

int a;

const char *ptr_my = "Hello";

a = const_cast<int *>(ptr_my);

a = reinterpret_cast<const char*>(ptr_my);

a = reinterpret_cast<int *>(const_cast<char *>(ptr_my) );

Note: casting from const char * to int * isn‟t very good (not to say a very dirty trick.) Normally

you won‟t do this.

The first statement (const_cast) will give an error, because the const_cast can‟t convert the type.

The second statement (reinterpret_cast) will also give an error, because the reinterpret_cast can‟t

cast the const away. The third statement will work (mind the note. It is a dirty trick, better not

use it.)

That is all for this tutorial. In typecasting part 2 we will look at RTTI, dynamic_cast, typeid and

type_info.

Page 84: OOPS unit -5

84

RTTI, dynamic_cast, typeid and type_info

Before you start this C++ programming tutorial on RTTI, dynamic_cast, typeid and type_info,

make sure you fully understand the previous tutorial on static_cast, const_cast and

reinterpret_cast.

Runtime Type Information (RTTI)

Runtime Type Information (RTTI) is the concept of determining the type of any variable during

execution (runtime.) The RTTI mechanism contains:

The operator dynamic_cast

The operator typeid

The struct type_info

RTTI can only be used with polymorphic types. This means that with each class you make, you

must have at least one virtual function (either directly or through inheritance.)

Compatibility note: On some compilers you have to enable support of RTTI to keep track of

dynamic types.

So to make use of dynamic_cast (see next section) you have to enable this feature. See you

compiler documentation for more detail.

Dynamic_cast

The dynamic_cast can only be used with pointers and references to objects. It makes sure that the

result of the type conversion is valid and complete object of the requested class. This is way a

dynamic_cast will always be successful if we use it to cast a class to one of its base classes. Take

a look at the example:

class Base_Class { };

class Derived_Class: public Base_Class { };

Base_Class a; Base_Class * ptr_a;

Derived_Class b; Derived_Class * ptr_b;

ptr_a = dynamic_cast<Base_Class *>(&b);

ptr_b = dynamic_cast<Derived_Class *>(&a);

The first dynamic_cast statement will work because we cast from derived to base. The second

dynamic_cast statement will produce a compilation error because base to derived conversion is

not allowed with dynamic_cast unless the base class is polymorphic.

Page 85: OOPS unit -5

85

If a class is polymorphic then dynamic_cast will perform a special check during execution. This

check ensures that the expression is a valid and complete object of the requested class.

Take a look at the example:

// dynamic_cast

#include <iostream>

#include <exception>

using namespace std;

class Base_Class { virtual void dummy() {} };

class Derived_Class: public Base_Class { int a; };

int main () {

try {

Base_Class * ptr_a = new Derived_Class;

Base_Class * ptr_b = new Base_Class;

Derived_Class * ptr_c;

ptr_c = dynamic_cast< Derived_Class *>(ptr_a);

if (ptr_c ==0) cout << "Null pointer on first type-cast" << endl;

ptr_c = dynamic_cast< Derived_Class *>(ptr_b);

if (ptr_c ==0) cout << "Null pointer on second type-cast" << endl;

} catch (exception& my_ex) {cout << "Exception: " << my_ex.what();}

return 0;

}

In the example we perform two dynamic_casts from pointer objects of type Base_Class*

(namely ptr_a and ptr_b) to a pointer object of type Derived_Class*.

If everything goes well then the first one should be successful and the second one will fail. The

pointers ptr_a and ptr_b are both of the type Base_Class. The pointer ptr_a points to an object of

the type Derived_Class. The pointer ptr_b points to an object of the type Base_Class. So when

the dynamic type cast is performed then ptr_a is pointing to a full object of class Derived_Class,

but the pointer ptr_b points to an object of class Base_Class. This object is an incomplete object

of class Derived_Class; thus this cast will fail!

Because this dynamic_cast fails a null pointer is returned to indicate a failure. When a reference

type is converted with dynamic_cast and the conversion fails then there will be an exception

thrown out instead of the null pointer. The exception will be of the type bad_cast.

Page 86: OOPS unit -5

86

With dynamic_cast it is also possible to cast null pointers even between the pointers of unrelated

classes.

Dynamic_cast can cast pointers of any type to void pointer(void*).

Typeid and typ_info

If a class hierarchy is used then the programmer doesn‟t have to worry (in most cases) about the

data-type of a pointer or reference, because the polymorphic mechanism takes care of it. In some

cases the programmer wants to know if an object of a derived class is used. Then the

programmer can make use of dynamic_cast. (If the dynamic cast is successful, then the pointer

will point to an object of a derived class or to a class that is derived from that derived class.) But

there are circumstances that the programmer (not often) wants to know the prizes data-type.

Then the programmer can use the typeid operator.

The typeid operator can be used with:

Variables

Expressions

Data-types

Take a look at the typeid example:

#include <iostream>

#include <typeinfo>

using namespace std;

int main ()

{

int * a;

int b;

a=0; b=0;

if (typeid(a) != typeid(b))

{

cout << "a and b are of different types:\n";

cout << "a is: " << typeid(a).name() << '\n';

cout << "b is: " << typeid(b).name() << '\n';

}

return 0;

}

Note: the extra header file typeinfo.

Page 87: OOPS unit -5

87

The result of a typeid is a const type_info&. The class type_info is part of the standard C++

library and contains information about data-types. (This information can be different. It all

depends on how it is implemented.)

A bad_typeid exception is thrown by typeid, if the type that is evaluated by typeid is a pointer

that is preceded by a dereference operator and that pointer has a null value.

UNIT-4

What is a Stream?

A stream is an object where a program can either insert or extract characters to or from it. The

standard input and output stream objects of C++ are declared in the header file iostream.

Standard Input Stream

Generally, the device used for input is the keyboard. For inputting, the keyword cin is used,

which is an object. The overloaded operator of extraction, >>, is used on the standard input

stream, in this case: cin stream. Syntax for using the standard input stream is cin followed by the

operator >> followed by the variable that stores the data extracted from the stream.

For example:

int prog;

cin >> prog;

In the example above, the variable prog is declared as an integer type variable. The next

statement is the cin statement. The cin statement waits for input from the user‟s keyboard that is

then stored in the integer variable prog.

The input stream cin wait before proceeding for processing or storing the value. This duration is

dependent on the user pressing the RETURN key on the keyboard. The input stream cin waits for

the user to press the RETURN key then begins to process the command. It is also possible to

request input for more than one variable in a single input stream statement. A single cin

statement is as follows:

cin >> x >> y;

is the same as:

cin >> x;

cin >> y;

Page 88: OOPS unit -5

88

In both of the above cases, two values are input by the user, one value for the variable x and

another value for the variable y.

// This is a sample program This is a comment Statement

#include <iostream.h> Header File Inclusion Statement

void main()

{

int sample, example;

cin >> sample;

cin >> example;

}

If a programmer wants to write comments in C++ program, the comments should follow after a

pair of slashes denoted by //. All the characters after the // are ignored by C++ compiler and the

programmer can choose to comment after the //

In the above example, two integer variables are input with values. The programmer can produce

input of any data type. It is also possible to input strings in C++ program using cin. This is

performed using the same procedures. The vital point to note is cin stops when it encounters a

blank space. When using a cin, it is possible to produce only one word. If a user wants to input a

sentence, then the above approach would be tiresome. For this purpose, there is a function in

C++ called getline.

Standard Output Stream

By default, the device used for output is the screen of the computer. For outputting values the

keyword cout is used, which is an object. The insertion operator << is used on the standard

output cout stream. The syntax for using the standard output stream is cout followed by the

operator << followed by the value to be inserted or output by the insertion operator.

For example:

int prog;

cin >> prog;

cout << prog;

In the above example, the variable prog is declared as an integer type variable. The next

statement is the cin statement that waits for input from the user‟s keyboard. This information is

then stored in the integer variable prog. The value of prog is displayed on the screen by the

standard output stream cout. It is also possible to display a sentence as follows:

cout << “ Training given by Exforsys”;

Page 89: OOPS unit -5

89

The above gives output as:

Training given by Exforsys

If a programmer chooses to use constant strings of characters, they must be enclosed between

double quotes “ ”.

In this situation, it is important to note the difference between the two statements below:

cout << "exforsys";

cout << exforsys;

In the above, the first statement displays on the screen as exforsys. The second statement outputs

the value of the variable exforsys. As previously explained, the extraction operator >> can be

used more than once in a single cin statement. Similarly, it is possible to use the insertion

operator << more than once in a cout statement.

For example

cout << "Exforsys" << "gives" << "excellent training";

This produces output on the screen as:

Exforsys gives excellent training

The above concept is mainly used if the programmer chooses to print string constants followed

by variables.

In this next example, the programmer chooses to display a combination of string constants and

variables.

For example

int a=50;

cout << "Exforsys has given" << a << "numbers of trainings";

This produces the output as:

Exforsys has given 50 numbers of trainings

Below is one more example:

Page 90: OOPS unit -5

90

cout << “Exforsys”;

cout << “Training”;

The above produces output as:

Exforsys Training

An important point to note from the above example is cout does not give a line break unless

specified. If the programmer chooses to display output in a new line, it must be explicitly

specified in cout by using the \n which denotes newline character.

for example

cout << "Exforsys\n ";

cout << "Training";

gives output as

Exforsys

Training

There is also another way for specifying newline that is by using endl manipulator.

For example

cout << "Exforsys" << endl;

cout << "Training";

gives the same output as

Exforsys

Training

Example to demonstrate the use of input and output streams

// Example to demonstrate the use of Input and Output streams

#include <iostream.h>

void main()

{

int a,b;

cout << “Enter the value of a:”;

cin >> a;

b=a+10;

Page 91: OOPS unit -5

91

cout << “Value of b is:”<<b;

}

File IO in C++ (text and binary files)

This C++ programming language tutorial will be in two parts. The first (this one) will cover the

theory behind IO and in the second tutorial we will look at some examples.

Input-Output

Input – Output is a process of transfer of data from one computer device to another or from one part

of the computer to another.

There are three categories of Input-Output:

Standard IO

Memory IO

Network IO

Standard IO is used frequently for which C++ provides cin, cout, cerr and clog streams. IO in C++ is

done through stream classes, which are having the following inheritance hierarchy:

We can use the ifstream, ofstream and fstream classes to perform file IO. (cin is an object of class

istream and cout is an object of class ostream.)

Page 92: OOPS unit -5

92

File IO means transfer of data from secondary memory (hard disk) to main memory or vice-versa. A

schematic showing the flow of data and classes involved is as follows:

Note: The arrows indicate the flow of data.

Text and binary files

The C++ language supports two types of files:

Text files

Binary files

The basic difference between text files and binary files is that in text files various character

translations are performed such as “\r+\f” is converted into “\n”, whereas in binary files no such

translations are performed.

By default, C++ opens the files in text mode.

In the tables below we will see the various steps and operations that can (or must) be performed to

use files in C++:

1)Creating or opening a

file

For writing data

Text Files

ofstream out (”myfile.txt”);

or

ofstream out;

Binary Files

ofstream out (”myfile.txt”,ios::binary);

or

ofstream out;

Page 93: OOPS unit -5

93

out.open(”myfile.txt”); out.open(”myfile.txt”, ios::binary);

For Appending (adding text at the end of the existing file)

Text Files

ofstream out(”myfile.txt”,ios::app);

or

ofstream out;

out.open(”myfile.txt”, ios::app);

Binary Files

ofstream out

(”myfile.txt”,ios::app|ios::binary);

or

ofstream out;

out.open(”myfile.txt”, ios::app | ios::binary);

For reading data

Text Files

ifstream in (”myfile.txt”);

or

ifstream in ;

in.open(”myfile.txt”);

Binary Files

ifstream in (”myfile.txt”, ios::binary);

or

ifstream in ;

in.open(”myfile.txt”, ios::binary);

2) Closing Files (after reading or writing)

ofstream object

“out”

Ifstream object

“in”

out.close(); in.close();

3) Reading / Writing Data to and from files

Data Functions for reading file Function for writing into file

Page 94: OOPS unit -5

94

char get(); put();

1 word >> (extraction operator) << (insertion operator)

>=1 word getline(); << (insertion operator)

Objects read() write()

Binary data Same as above Same as above

4) Functions that can be used to perform special tasks

Operation function Description

Checking end of

file.

eof() Used to check eof during

the reading of file

Check if an

operation

fails.

bad() Returns true

if a reading or writing operation fails.

Check if an

operation

fails.

Fail() Returns true

in the same cases as bad(), but also in the

case that a format error

happens.

Checking for

opened

file.

is_open(); Checks if the file is

opened or not, returns true if the file is

opened else

false

Number of bytes

already

read.

gcount() Returns count of the

bytes read from the file

Page 95: OOPS unit -5

95

Ignoring characters

during file read.

ignore() Ignores n bytes from the

file. (get pointer is positioned after n

character)

Checking next

character.

peek() Checks the next available

character, will not increase the get pointer

to next

character.

Random access

(only for

binary files).

seekg()

seekp()

tellg()

tellp()

In case of binary files random access is

performed using these functions. They

either give or set the position of get and put

pointers on the particular location

Read and Write characters (text file)

In the example below we will write and read characters from a text file.

We will write a character (given by the user) to a file test.txt as long as the answer to the question

“Continue?:” is replayed with y (from yes). If we answer with something else the program must

close the test.txt file. The last part of the program will read all characters in the file test.txt.

#include<iostream>

#include<fstream>

using namespace std;

int main(int argc, char *argv[])

{

//code to write characters in a file

char c, ans;

ans='y';

//Open an output stream

ofstream out ("test.txt");

if(out.is_open())

{

//Loop will continue until something other then y is entered

Page 96: OOPS unit -5

96

while (ans=='y')

{

cout <<endl << "Continue ?";

cin >> ans;

if(ans=='y')

{

cout << endl << "Enter Character :";

cin >> c;

out.put(c);

}

}

}

out.close();

//code for reading file completely

ifstream in("test.txt");

if(in.is_open())

{

while(!in.eof())

{

c = in.get();

if(!in.eof())

cout << c;

}

}

in.close();

}

Special flags

The table below shows the special flags that can be used to manage files. (These flags are used

during opening of the files).

ios::app Opens the file in append mode

ios::ate Opens the file and set the cursor at end of the file

ios::binary Opens the file in binary mode

ios::in Opens the file for reading

ios::out Opens the file for writing

ios::trunc Opens the file and truncates all the contents from it

Page 97: OOPS unit -5

97

Binary copy

In the next example we will copy a binary file to another binary file. We will open two files in binary

mode,

one for reading and one for writing.

If both are open then we will copy the content of one file to another.

#include<iostream>

#include<fstream>

using namespace std;

int main(int argc, char *argv[])

{

//Open an input and output stream in binary mode

ifstream in("myimage.jpg",ios::binary);

ofstream out("myimage1.jpg",ios::binary);

if(in.is_open() && out.is_open())

{

while(!in.eof())

{

out.put(in.get());

}

}

//Close both files

in.close();

out.close();

}

Note: of course you need to supply the myimage.jpg file to copy (or any other jpg file).

Reading and writing an object

In this last example we will write and read an object (student object) to and from a file:

#include<iostream>

#include<fstream>

using namespace std;

class Student

Page 98: OOPS unit -5

98

{

char name[20];

int mark;

public:

void GetStudentData();

void ShowStudentData();

};

void Student :: GetStudentData()

{

cout << "Enter Student Name:" << endl;

cin >> name;

cout << "Enter Student Mark:" << endl;

cin >> mark;

}

void Student :: ShowStudentData()

{

cout << "Student Details are:" << endl;

cout << "Name: " << name << endl

<< "Mark: " << mark << endl;

}

int main(int argc, char *argv[])

{

char ans='y';

Student sobj;

//We open student.dat in append mode

ofstream out("student.dat", ios::app);

if(out.is_open())

{

//Loop will continue until something other then y is entered

while( ans == 'y')

{

cout << endl << "Continue ?";

cin >> ans;

if(ans == 'y')

{

sobj.GetStudentData();

out.write((char*) & sobj, sizeof(sobj));

}

}

}

out.close();

Page 99: OOPS unit -5

99

ifstream in("student.dat");

if(in.is_open())

{

while(!in.eof())

{

in.read((char*) &sobj, sizeof(sobj));

if(!in.eof())

{

sobj.ShowStudentData();

}

}

}

in.close();

}

As you can see there are many ways to do file IO in the C++ programming language.

IOstream Library (Standard Input / Output Streams Library )

The iostream library is an object-oriented library that provides input and output functionality

using streams.

A stream is an abstraction that represents a device on which input and ouput operations are

performed. A stream can basically be represented as a source or destination of characters of

indefinite length.

Page 100: OOPS unit -5

100

Streams are generally associated to a physical source or destination of characters, like a disk file,

the keyboard, or the console, so the characters gotten or written to/from our abstraction called

stream are physically input/output to the physical device. For example, file streams are C++

objects to manipulate and interact with files; Once a file stream is used to open a file, any input

or output operation performed on that stream is physically reflected in the file.

To operate with streams, C++ provides the standard iostream library, which contains the

following elements:

Basic class templates

The base of the iostream library is the hierarchy of class templates. The class

templates provide most of the functionality of the library in a type-independent

fashion.

This is a set of class templates, each one having two template parameters: the char

type (charT) parameter, that determines the type of elements that are going to be

manipulated and the traits parameter, that provides additional characteristics specific

for a particular type of elements.

The class templates in this class hierarchy have the same name as their char-type

instantiations but with the prefix basic_. For example, the class template which

istream is instantiated from is called basic_istream, the one from which fstream is is

called basic_fstream, and so on... The only exception is ios_base, which is by itself

type-independent, and therefore is not based on a template, but is a regular class.

Class template instantiations

The library incorporates two standard sets of instantiations of the entire iostream

class template hierarchy: one is narrow-oriented, to manipulate elements of type char

and another one, wide-oriented, to manipulate elements of type wchar_t.

The narrow-oriented (char type) instantiation is probably the better known part of the

iostream library. Classes like ios, istream and ofstream are narrow-oriented. The

diagram on top of this page shows the names and relationships of narrow-oriented

classes.

The classes of the wide-oriented (wchar_t) instatiation follow the same naming

conventions as the narrow-oriented instantiation but with the name of each class and

object prefixed with a w character, forming wios, wistream and wofstream, as an

example.

Standard objects

As part of the iostream library, the header file <iostream> declares certain objects

that are used to perform input and output operations on the standard input and

output.

Page 101: OOPS unit -5

101

They are divided in two sets: narrow-oriented objects, which are the popular cin,

cout, cerr and clog and their wide-oriented counterparts, declared as wcin, wcout,

wcerr and wclog.

Types

The iostream classes barely use fundamental types on their member's prototypes. They

generally use defined types that depend on the traits used in their instantiation. For the

default char and wchar_t instantiations, types streampos, streamoff and streamsize are

used to represent positions, offsets and sizes, respectively.

Manipulators

Manipulators are global functions designed to be used together with insertion (<<) and

extraction (>>) operators performed on iostream stream objects. They generally modify

properties and formatting settings of the streams. endl, hex and scientific are some

examples of manipulators.

Organization

The library and its hierarchy of classes is split in different files:

<ios>, <istream>, <ostream>, <streambuf> and <iosfwd> aren't usually included directly

in most C++ programs. They describe the base classes of the hierarchy and are

automatically included by other header files of the library that contain derived classes.

<iostream> declares the objects used to communicate through the standard input and

output (including cin and cout).

<fstream> defines the file stream classes (like the template basic_ifstream or the class

ofstream) as well as the internal buffer objects used with these (basic_filebuf). These

classes are used to manipulate files using streams.

<sstream>: The classes defined in this file are used to manipulate string objects as if they

were streams.

<iomanip> declares some standard manipulators with parameters to be used with

extraction and insertion operators to modify internal flags and formatting options.

Compatibility notes

The names, prototypes and examples included in this reference for the iostream classes mostly

describe and use the char instantiations of the class templates instead of the templates

themselves, even though these classes are only one of their possible instantiations. We believe

this provides a better readability and is arguably as easy to obtain the names and prototypes of

the basic template from the char instantiation as the opposite.

Elements of the iostream library (char instantitation)

Classes:

ios_base

Base class with type-independent members for the standard stream classes (class)

ios Base class with type-dependent members for the standard stream classes (class)

Page 102: OOPS unit -5

102

istream Input stream (class)

ostream Output Stream (class)

iostream Input/Output Stream (class)

ifstream Input file stream class (class)

ofstream Output file stream (class)

fstream Input/output file stream class (class)

istringstream Input string stream class (class)

ostringstream Output string stream class (class)

stringstream Input/output string stream class (class)

streambuf Base buffer class for streams (class)

filebuf File stream buffer (class)

stringbuf String stream buffer (class)

Objects:

cin Standard input stream (object)

cout Standard output stream (object)

cerr Standard output stream for errors (object)

clog Standard output stream for logging (object)

Types:

fpos Stream position class template (class template)

streamoff Stream offset type (type)

streampos Stream position type (type)

streamsize Stream size type (types)

Manipulators:

boolalpha Alphanumerical bool values (manipulator function)

dec Use decimal base (manipulator function)

endl Insert newline and flush (manipulator function)

Page 103: OOPS unit -5

103

ends Insert null character (manipulator function)

fixed Use fixed-point notation (manipulator function)

flush Flush stream buffer (manipulator function)

hex Use hexadecimal base (manipulator function)

internal Adjust field by inserting characters at an internal position (manipulator function)

left Adjust output to the left (manipulator function)

noboolalpha No alphanumerical bool values (manipulator function)

noshowbase Do not show numerical base prefixes (manipulator function)

noshowpoint Do not show decimal point (manipulator function)

noshowpos Do not show positive signs (manipulator function)

noskipws Do not skip whitespaces (manipulator function)

nounitbuf Do not force flushes after insertions (manipulator function)

nouppercase Do not generate upper case letters (manipulator function)

oct Use octal base (manipulator function)

resetiosflags Reset format flags (manipulator function)

right Adjust output to the right (manipulator function)

scientific Use scientific notation (manipulator function)

setbase Set basefield flag (manipulator function)

setfill Set fill character (manipulator function)

setiosflags Set format flags (manipulator function)

setprecision Set decimal precision (manipulator function)

Page 104: OOPS unit -5

104

setw Set field width (manipulator function)

showbase Show numerical base prefixes (manipulator function)

showpoint Show decimal point (manipulator function)

showpos Show positive signs (manipulator function)

skipws Skip whitespaces (manipulator function)

unitbuf Flush buffer after insertions (manipulator function)

uppercase Generate upper-case letters (manipulator function)

ws Extract whitespaces (manipulator function)

What is a Manipulator?

Manipulators are operators used in C++ for formatting output. The data is manipulated by the

programmer‟s choice of display.

There are numerous manipulators available in C++. Some of the more commonly used

manipulators are provided here below:

endl Manipulator:

This manipulator has the same functionality as the „\n‟ newline character.

For example:

cout << "Exforsys" << endl;

cout << "Training";

Page 105: OOPS unit -5

105

produces the output:

Exforsys

Training

setw Manipulator:

This manipulator sets the minimum field width on output. The syntax is:

setw(x)

Here setw causes the number or string that follows it to be printed within a field of x characters

wide and x is the argument set in setw manipulator. The header file that must be included while

using setw manipulator is <iomanip.h>

#include <iostream.h>

#include <iomanip.h>

void main( )

{

int x1=12345,x2= 23456, x3=7892;

cout << setw(8) << ”Exforsys” << setw(20) << ”Values” << endl

<< setw(8) << “E1234567” << setw(20)<< x1 << end

<< setw(8) << “S1234567” << setw(20)<< x2 << end

<< setw(8) << “A1234567” << setw(20)<< x3 << end;

}

The output of the above example is:

setw(8) setw(20)

Exforsys Values

E1234567 12345

Page 106: OOPS unit -5

106

S1234567 23456

A1234567 7892

setfill Manipulator:

This is used after setw manipulator. If a value does not entirely fill a field, then the character

specified in the setfill argument of the manipulator is used for filling the fields.

#include <iostream.h>

#include <iomanip.h>

void main( )

{

cout << setw(10) << setfill('$') << 50 << 33 << endl;

}

The output of the above program is

$$$$$$$$5033

This is because the setw sets 10 width for the field and the number 50 has only 2 positions in it.

So the remaining 8 positions are filled with $ symbol which is specified in the setfill argument.

setprecision Manipulator:

The setprecision Manipulator is used with floating point numbers. It is used to set the number of

digits printed to the right of the decimal point. This may be used in two forms:

fixed

scientific

These two forms are used when the keywords fixed or scientific are appropriately used before

the setprecision manipulator. The keyword fixed before the setprecision manipulator prints the

Page 107: OOPS unit -5

107

floating point number in fixed notation. The keyword scientific before the setprecision

manipulator prints the floating point number in scientific notation.

#include <iostream.h>

#include <iomanip.h>

void main( )

{

float x = 0.1;

cout << fixed << setprecision(3) << x << endl;

cout << sceintific << x << endl;

}

The above gives ouput as:

0.100

1.000000e-001

C++ Tutorial – Namespaces and anonymous namespaces

Namespaces are used in the C++ programming language to create a separate region for a group

of variables, functions and classes etc. Namespaces are needed because there can be many

functions, variables for classes in one program and they can conflict with the existing names of

variables, functions and classes. C++ uses namespace to avoid the conflicts.

The concept can be depicted using the following diagram:

Page 108: OOPS unit -5

108

The following will list the primary reasons due to which a conflict can occur:

Between User defined variables/functions/classes and built in Library

variables/functions/classes (e.g. sqrt(), abs() etc.)

Between the separately included library and built in library

Between the variables/functions/classes of the one separately included library and the

same of the other separately included library

Creating Namespaces

The C++ language include the keyword “namespace” for creating namespaces.

namespace

{

members of namespace;

}

Take a look at an example:

#include<iostream>

using namespace std;

namespace myconstants {

const double pi = 3.141592;

}

namespace myshapes {

double area;

double perimeter;

void AreaOfCircle(double radius)

{

area = myconstants::pi * radius * radius;

}

void PerimeterOfCircle(double radius)

{

perimeter = 2 * myconstants::pi * radius;

}

}

int main(int argc, char * argv[])

{

Page 109: OOPS unit -5

109

double r;

cout << endl << "Enter Radius:";

cin >> r;

myshapes::AreaOfCircle(r);

cout << endl << "Area of the Circle is :" << myshapes::area;

myshapes::PerimeterOfCircle(r);

cout << endl << "Perimeter of the Circle is :" << myshapes::perimeter;

}

Namespaces have the following important points:

1) We can have more than one namespace of the same name. This gives the advantage of

defining the same namespace in more than one file (although they can be created in the same file

as well).

Take a look at an example:

#include<iostream>

using namespace std;

namespace mynamespace

{

int x;

}

namespace mynamespace

{

int y;

}

int main(int argc, char * argv[])

{

mynamespace::x = mynamespace::y =5;

cout << mynamespace::x << endl << mynamespace::y;

}

2)We can have anonymous namespaces (namespace with no name). They are directly usable in

the same program and are used for declaring unique identifiers. It also avoids making global

static variable.

The “anonymous” namespace you have created will only be accessible within the file you

created it in.

Page 110: OOPS unit -5

110

Take a look at an example:

/*This is file1.cpp*/

#include<iostream>

using namespace std;

namespace

{

int local;

}

void func();

int main()

{

local = 1;

cout << "Local=" << local << endl;

func();

cout << "Local=" << local << endl;

return 0;

}

/* This is file2.cpp */

namespace

{

// Should not collide with other files

int local;

}

void func()

{

local = 2;

}

Note: you will need to include both the files in the same project.

The result of this program should be:

Local = 1

Local = 1

Page 111: OOPS unit -5

111

It should not be:

Local = 1

Local = 2

3) C++ has a default namespace named std, which contains all the default library of the C++

included using #include directive.

Using Namespaces

Namespaces are used with the „using‟ keyword, which makes all the members of the namespace

available in the current program and the members can be used directly, without taking reference

of the namespace.

Namespaces are also usable by taking their name reference with scope resolution operator. This

method allows distinguishing between the members of the same name in two different

namespaces.

Take a look at an example:

#include<iostream>

using namespace std;

namespace mynamespace

{

int i,j;

}

using namespace mynamespace;

int main(int argc, char *argv[])

{

cout << endl << i << ", " << j;

}

Or without the „using‟ keyword:

#include<iostream>

using namespace std;

namespace mynamespace

{

Page 112: OOPS unit -5

112

int i,j;

}

int main(int argc, char *argv[])

{

std::cout << endl << mynamespace::i << ", " << mynamespace::j;

}

Namespace alias

It is also possible to declare an alternate name for an existing namespace.

We can use the following format:

namespace new_name = current_name;

Namespace std

All the files in the C++ standard library declare all of its entities within the std namespace. For

that reason we include the „using namespace std;‟ statement in most programs that is using any

entity defined in iostream.

UNIT-5

Unit-5

C++ Function templates are those functions which can handle different data types without

separate code for each of them. For a similar operation

on several kinds of data types, a programmer need not write different versions by overloading a

function. It is enough if he writes a C++ template based function. This will take care of all the

data types.

There are two types of templates in C++, viz., function templates and class templates. This

article deals with only the function templates.

There are lot of occasions, where we might need to write the same functions for different data

types. A favorite example can be addition of two variables. The variable can be integer, float or

double. The requirement will be to return the corresponding return type based on the input type.

If we start writing one function for each of the data type, then we will end up with 4 to 5

different functions, which can be a night mare for maintenance.

Page 113: OOPS unit -5

113

C++ templates come to our rescue in such situations. When we use C++ function templates,

only one function signature needs to be created. The C++ compiler will automatically generate

the required functions for handling the individual data types

. This is how a programmer's life is made a lot easier.

C++ Template functions - Details:

Let us assume a small example for Add function. If the requirement is to use this Add function

for both integer and float, then two functions are to be created for each of the data type

(overloading).

int Add(int a,int b) { return a+b;} // function Without C++ template

float Add(float a, float b) { return a+b;} // function Without C++ template

If there are some more data types to be handled, more functions should be added.

But if we use a c++ function template, the whole process is reduced to a single

c++ function template. The following will be the code fragment for Add function.

template <class T>

T Add(T a, T b) //C++ function template sample

{

return a+b;

}

This c++ function template definition will be enough. Now when the integer version of the

function, the compiler generates an Add function compatible for integer data type and if float is

called it generates float type and so on.

Here T is the typename. This is dynamically determined by the compiler according to the

parameter passed. The keyword class means, the parameter can be of any type. It can even be a

class.

C++ Template functions - Applicability:

C++ function templates can be used wherever the same functionality has to be performed with

a number of data types. Though very useful, lots of care should be taken to test the C++ template

functions during development. A well written c++ template will go a long way in saving time for

programmers.

C++ Class Templates are used where we have multiple copies of code for different data types

with the same logic. If a set of functions or classes have the same functionality for different data

types, they becomes good candidates for being written as Templates.

Page 114: OOPS unit -5

114

One good area where this C++ Class Templates are suited can be container classes. Very

famous examples for these container classes will be the STL classes like vector, list etc., Once

code is written as a C++ class template, it can support all data types. Though very useful, It is

advisable to write a class as a template after getting a good hands-on experience on the logic (by

writing the code with normal data types). There are cases where we need specialization for

writing optimized code for specific data types. This C++ class template Specialization article

gives a brief description.

This article describes how to declare, define and use the C++ Class Templates in practice. This

tries to build a very preliminary Queue, using the STL::Vector container class. This code is

written and tested with Microsoft Visual C++ 5.00.

Declaring C++ Class Templates:

Declaration of C++ class template should start with the keyword template. A parameter should

be included inside angular brackets. The parameter inside the angular brackets, can be either the

keyword class or typename. This is followed by the class body declaration with the member data

and member functions. The following is the declaration for a sample Queue class.

//Sample code snippet for C++ Class Template

template <typename T>

class MyQueue

{

std::vector<T> data;

public:

void Add(T const &d);

void Remove();

void Print();

};

The keyword class highlighted in blue color, is not related to the typename. This is a

mandatory keyword to be included for declaring a template class.

Defining member functions - C++ Class Templates:

If the functions are defined outside the template class body, they should always be defined with

the full template definition. Other conventions of writing the function in C++ class templates are

the same as writing normal c++ functions.

template <typename T> void MyQueue<T> ::Add(T const &d)

{

data.push_back(d);

}

template <typename T> void MyQueue<T>::Remove()

{

Page 115: OOPS unit -5

115

data.erase(data.begin( ) + 0,data.begin( ) + 1);

}

template <typename T> void MyQueue<T>::Print()

{

std::vector <int>::iterator It1;

It1 = data.begin();

for ( It1 = data.begin( ) ; It1 != data.end( ) ; It1++ )

cout << " " << *It1<<endl;

}

The Add function adds the data to the end of the vector. The remove function removes the first

element. These functionalities make this C++ class Template behave like a normal Queue. The

print function prints all the data using the iterator.

Full Program - C++ Class Templates:

//C++_Class_Templates.cpp

#include <iostream.h>

#include <vector>

template <typename T>

class MyQueue

{

std::vector<T> data;

public:

void Add(T const &);

void Remove();

void Print();

};

template <typename T> void MyQueue<T> ::Add(T const &d)

{

data.push_back(d);

}

template <typename T> void MyQueue<T>::Remove()

{

data.erase(data.begin( ) + 0,data.begin( ) + 1);

}

template <typename T> void MyQueue<T>::Print()

{

Page 116: OOPS unit -5

116

std::vector <int>::iterator It1;

It1 = data.begin();

for ( It1 = data.begin( ) ; It1 != data.end( ) ; It1++ )

cout << " " << *It1<<endl;

}

//Usage for C++ class templates

void main()

{

MyQueue<int> q;

q.Add(1);

q.Add(2);

cout<<"Before removing data"<<endl;

q.Print();

q.Remove();

cout<<"After removing data"<<endl;

q.Print();

}

Advantages of C++ Class Templates:

One C++ Class Template can handle different types of parameters.

Compiler generates classes for only the used types. If the template is instantiated for int

type, compiler generates only an int version for the c++ template class.

Templates reduce the effort on coding for different data types to a single

set of code.

Testing and debugging efforts are reduced.

Templates

Function templates

Function templates are special functions that can operate with generic types. This allows us to

create a function template whose functionality can be adapted to more than one type or class

without repeating the entire code for each type.

In C++ this can be achieved using template parameters. A template parameter is a special kind

of parameter that can be used to pass a type as argument: just like regular function parameters

can be used to pass values to a function, template parameters allow to pass also types to a

function. These function templates can use these parameters as if they were any other regular

type.

Page 117: OOPS unit -5

117

The format for declaring function templates with type parameters is:

template <class identifier> function_declaration;

template <typename identifier> function_declaration;

The only difference between both prototypes is the use of either the keyword class or the

keyword typename. Its use is indistinct, since both expressions have exactly the same meaning

and behave exactly the same way.

For example, to create a template function that returns the greater one of two objects we could

use:

template <class myType>

myType GetMax (myType a, myType b) {

return (a>b?a:b);

}

Here we have created a template function with myType as its template parameter. This template

parameter represents a type that has not yet been specified, but that can be used in the template

function as if it were a regular type. As you can see, the function template GetMax returns the

greater of two parameters of this still-undefined type.

To use this function template we use the following format for the function call:

function_name <type> (parameters);

For example, to call GetMax to compare two integer values of type int we can write:

int x,y;

GetMax <int> (x,y);

When the compiler encounters this call to a template function, it uses the template to

automatically generate a function replacing each appearance of myType by the type passed as

the actual template parameter (int in this case) and then calls it. This process is automatically

performed by the compiler and is invisible to the programmer.

Here is the entire example:

// function template

#include <iostream>

6

10

Page 118: OOPS unit -5

118

using namespace std;

template <class T>

T GetMax (T a, T b) {

T result;

result = (a>b)? a : b;

return (result);

}

int main () {

int i=5, j=6, k;

long l=10, m=5, n;

k=GetMax<int>(i,j);

n=GetMax<long>(l,m);

cout << k << endl;

cout << n << endl;

return 0;

}

In this case, we have used T as the template parameter name instead of myType because it is

shorter and in fact is a very common template parameter name. But you can use any identifier

you like.

In the example above we used the function template GetMax() twice. The first time with

arguments of type int and the second one with arguments of type long. The compiler has

instantiated and then called each time the appropriate version of the function.

As you can see, the type T is used within the GetMax() template function even to declare new

objects of that type:

T result;

Therefore, result will be an object of the same type as the parameters a and b when the function

template is instantiated with a specific type.

In this specific case where the generic type T is used as a parameter for GetMax the compiler can

find out automatically which data type has to instantiate without having to explicitly specify it

within angle brackets (like we have done before specifying <int> and <long>). So we could have

written instead:

int i,j;

GetMax (i,j);

Page 119: OOPS unit -5

119

Since both i and j are of type int, and the compiler can automatically find out that the template

parameter can only be int. This implicit method produces exactly the same result:

// function template II

#include <iostream>

using namespace std;

template <class T>

T GetMax (T a, T b) {

return (a>b?a:b);

}

int main () {

int i=5, j=6, k;

long l=10, m=5, n;

k=GetMax(i,j);

n=GetMax(l,m);

cout << k << endl;

cout << n << endl;

return 0;

}

6

10

Notice how in this case, we called our function template GetMax() without explicitly specifying

the type between angle-brackets <>. The compiler automatically determines what type is needed

on each call.

Because our template function includes only one template parameter (class T) and the function

template itself accepts two parameters, both of this T type, we cannot call our function template

with two objects of different types as arguments:

int i;

long l;

k = GetMax (i,l);

This would not be correct, since our GetMax function template expects two arguments of the

same type, and in this call to it we use objects of two different types.

We can also define function templates that accept more than one type parameter, simply by

specifying more template parameters between the angle brackets. For example:

template <class T, class U>

Page 120: OOPS unit -5

120

T GetMin (T a, U b) {

return (a<b?a:b);

}

In this case, our function template GetMin() accepts two parameters of different types and

returns an object of the same type as the first parameter (T) that is passed. For example, after that

declaration we could call GetMin() with:

int i,j;

long l;

i = GetMin<int,long> (j,l);

or simply:

i = GetMin (j,l);

even though j and l have different types, since the compiler can determine the appropriate

instantiation anyway.

Class templates

We also have the possibility to write class templates, so that a class can have members that use

template parameters as types. For example:

template <class T>

class mypair {

T values [2];

public:

mypair (T first, T second)

{

values[0]=first; values[1]=second;

}

};

The class that we have just defined serves to store two elements of any valid type. For example,

if we wanted to declare an object of this class to store two integer values of type int with the

values 115 and 36 we would write:

mypair<int> myobject (115, 36);

this same class would also be used to create an object to store any other type:

mypair<double> myfloats (3.0, 2.18);

Page 121: OOPS unit -5

121

The only member function in the previous class template has been defined inline within the class

declaration itself. In case that we define a function member outside the declaration of the class

template, we must always precede that definition with the template <...> prefix:

// class templates

#include <iostream>

using namespace std;

template <class T>

class mypair {

T a, b;

public:

mypair (T first, T second)

{a=first; b=second;}

T getmax ();

};

template <class T>

T mypair<T>::getmax ()

{

T retval;

retval = a>b? a : b;

return retval;

}

int main () {

mypair <int> myobject (100, 75);

cout << myobject.getmax();

return 0;

}

100

Notice the syntax of the definition of member function getmax:

template <class T>

T mypair<T>::getmax ()

Confused by so many T's? There are three T's in this declaration: The first one is the template

parameter. The second T refers to the type returned by the function. And the third T (the one

between angle brackets) is also a requirement: It specifies that this function's template parameter

is also the class template parameter.

Page 122: OOPS unit -5

122

Template specialization

If we want to define a different implementation for a template when a specific type is passed as

template parameter, we can declare a specialization of that template.

For example, let's suppose that we have a very simple class called mycontainer that can store one

element of any type and that it has just one member function called increase, which increases its

value. But we find that when it stores an element of type char it would be more convenient to

have a completely different implementation with a function member uppercase, so we decide to

declare a class template specialization for that type:

// template specialization

#include <iostream>

using namespace std;

// class template:

template <class T>

class mycontainer {

T element;

public:

mycontainer (T arg) {element=arg;}

T increase () {return ++element;}

};

// class template specialization:

template <>

class mycontainer <char> {

char element;

public:

mycontainer (char arg) {element=arg;}

char uppercase ()

{

if ((element>='a')&&(element<='z'))

element+='A'-'a';

return element;

}

};

int main () {

mycontainer<int> myint (7);

mycontainer<char> mychar ('j');

cout << myint.increase() << endl;

cout << mychar.uppercase() << endl;

return 0;

}

8

J

Page 123: OOPS unit -5

123

This is the syntax used in the class template specialization:

template <> class mycontainer <char> { ... };

First of all, notice that we precede the class template name with an emptytemplate<> parameter

list. This is to explicitly declare it as a template specialization.

But more important than this prefix, is the <char> specialization parameter after the class

template name. This specialization parameter itself identifies the type for which we are going to

declare a template class specialization (char). Notice the differences between the generic class

template and the specialization:

template <class T> class mycontainer { ... };

template <> class mycontainer <char> { ... };

The first line is the generic template, and the second one is the specialization.

When we declare specializations for a template class, we must also define all its members, even

those exactly equal to the generic template class, because there is no "inheritance" of members

from the generic template to the specialization.

Non-type parameters for templates

Besides the template arguments that are preceded by the class or typename keywords , which

represent types, templates can also have regular typed parameters, similar to those found in

functions. As an example, have a look at this class template that is used to contain sequences of

elements:

// sequence template

#include <iostream>

using namespace std;

template <class T, int N>

class mysequence {

T memblock [N];

public:

void setmember (int x, T value);

T getmember (int x);

};

template <class T, int N>

100

3.1416

Page 124: OOPS unit -5

124

void mysequence<T,N>::setmember (int x, T value) {

memblock[x]=value;

}

template <class T, int N>

T mysequence<T,N>::getmember (int x) {

return memblock[x];

}

int main () {

mysequence <int,5> myints;

mysequence <double,5> myfloats;

myints.setmember (0,100);

myfloats.setmember (3,3.1416);

cout << myints.getmember(0) << '\n';

cout << myfloats.getmember(3) << '\n';

return 0;

}

It is also possible to set default values or types for class template parameters. For example, if the

previous class template definition had been:

template <class T=char, int N=10> class mysequence {..};

We could create objects using the default template parameters by declaring:

mysequence<> myseq;

Which would be equivalent to:

mysequence<char,10> myseq;

Templates and multiple-file projects

From the point of view of the compiler, templates are not normal functions or classes. They are

compiled on demand, meaning that the code of a template function is not compiled until an

instantiation with specific template arguments is required. At that moment, when an instantiation

is required, the compiler generates a function specifically for those arguments from the template.

When projects grow it is usual to split the code of a program in different source code files. In

these cases, the interface and implementation are generally separated. Taking a library of

functions as example, the interface generally consists of declarations of the prototypes of all the

Page 125: OOPS unit -5

125

functions that can be called. These are generally declared in a "header file" with a .h extension,

and the implementation (the definition of these functions) is in an independent file with c++

code.

Because templates are compiled when required, this forces a restriction for multi-file projects:

the implementation (definition) of a template class or function must be in the same file as its

declaration. That means that we cannot separate the interface in a separate header file, and that

we must include both interface and implementation in any file that uses the templates.

Since no code is generated until a template is instantiated when required, compilers are prepared

to allow the inclusion more than once of the same template file with both declarations and

definitions in a project without generating linkage errors.