You are on page 1of 129

Object Oriented Programming Using C++

Object Oriented Programming Using C++

Basic Idea About Languages

WHAT IS LANGUAGE?

You are aware with the term language. It is a system of communication between you and
me. Some of the basic natural languages that we are familiar with are English, Hindi,
Oriya etc. These are the languages used to communicate among various categories of
persons. But how you will communicate with your computer. Your computer will not
understand any of these natural languages for transfer of data and instruction. So there are
programming languages specially developed so that you could pass your data and
instructions to the computer to do specific job. You must have heard names like
FORTRAN, BASIC, COBOL etc. These are programming languages. So instructions or
programs are written in a particular language based on the type of job. As an example, for
scientific application FORTRAN and C languages are used. On the other hand COBOL is
used for business applications.

Programming Languages

There are two major types of programming languages. These are Low Level Languages
and High Level Languages. Low Level languages are further divided in to Machine
language and Assembly language.

Low Level Languages

The term low level means closeness to the way in which the machine has been built. Low
level languages are machine oriented and require extensive knowledge of computer
hardware and its configuration.

(a) Machine Language

Machine Language is the only language that is directly understood by the computer. It
does not needs any translator program. We also call it machine code and it is written as
strings of 1's (one) and 0’s (zero). When this sequence of codes is fed to the computer, it
recognizes the codes and converts it in to electrical signals needed to run it. For example,
a program instruction may look like this:

1011000111101

It is not an easy language for you to learn because of its difficult to understand. It is
efficient for the computer but very inefficient for programmers. It is considered to the
first generation language. It is also difficult to debug the program written in this
language.

1
Object Oriented Programming Using C++

Advantage

The only advantage is that program of machine language run very fast because no
translation program is required for the CPU.

Disadvantages

1. It is very difficult to program in machine language. The programmer has to know


details of hardware to write program.
2. The programmer has to remember a lot of codes to write a program which results
in program errors.
3. It is difficult to debug the program.

(b) Assembly Language

It is the first step to improve the programming structure. You should know that computer
can handle numbers and letter. Therefore some combination of letters can be used to
substitute for number of machine codes.

The set of symbols and letters forms the Assembly Language and a translator program is
required to translate the Assembly Language to machine language. This translator
program is called `Assembler'. It is considered to be a second-generation language.

Advantages:

1. The symbolic programming of Assembly Language is easier to understand and


saves a lot of time and effort of the programmer.
2. It is easier to correct errors and modify program instructions.
3. Assembly Language has the same efficiency of execution as the machine level
language. Because this is one-to-one translator between assembly language
program and its corresponding machine language program.

Disadvantages:

1. One of the major disadvantages is that assembly language is machine dependent.


A program written for one computer might not run in other computers with
different hardware configuration.

HIGH LEVEL LANGUAGES

You know that assembly language and machine level language require deep knowledge
of computer hardware where as in higher language you have to know only the
instructions in English words and logic of the problem irrespective of the type of
computer you are using.

2
Object Oriented Programming Using C++

Higher level languages are simple languages that use English and mathematical symbols
like +, -, %, / etc. for its program construction.

You should know that any higher level language has to be converted to machine language
for the computer to understand.

Higher level languages are problem-oriented languages because the instructions are
suitable for solving a particular problem. For example COBOL (Common Business
Oriented Language) is mostly suitable for business oriented language where there is very
little processing and huge output. There are mathematical oriented languages like
FORTRAN (Formula Translation) and BASIC (Beginners All-purpose Symbolic
Instruction Code) where very large processing is required.

Thus a problem oriented language designed in such a way that its instruction may be
written more like the language of the problem. For example, businessmen use business
term and scientists use scientific terms in their respective languages.

Advantages of High Level Languages

Higher level languages have a major advantage over machine and assembly languages
that higher level languages are easy to learn and use. It is because that they are similar to
the languages used by us in our day to day life.

COMPILER

It is a program translator that translates the instruction of a higher level language to


machine language. It is called compiler because it compiles machine language
instructions for every program instructions of higher level language. Thus compiler is a
program translator like assembler but more sophisticated. It scans the entire program first
and then translates it into machine code.

The programs written by the programmer in higher level language is called source
program. After this program is converted to machine languages by the compiler it is
called object program.

Higher Level Language --> (Compile) ---> Program --> Machine Language Program

Fig. Compile

A compiler can translate only those source programs, which have been written, in that
language for which the compiler is meant for. For example FORTRAN compiler will not
compile source code written in COBOL language.

3
Object Oriented Programming Using C++

Object program generated by compiler is machine dependent. It means programs


compiled for one type of machine will not run in another type. Therefore every type of
machine must have its personal compiler for a particular language. Machine
independence is achieved by using one higher level language in different machines.

INTERPRETER

An interpreter is another type of program translator used for translating higher level
language into machine language. It takes one statement of higher level languages,
translate it into machine language and immediately execute it. Translation and execution
are carried out for each statement. It differs from compiler, which translate the entire
source program into machine code and does involve in its execution.

The advantage of interpreter compared to compiler is its fast response to changes in


source program. It eliminates the need for a separate compilation after changes to each
program. Interpreters are easy to write and do not require large memory in computer. The
disadvantage of interpreter is that it is time consuming method because each time a
statement in a program is executed then it is first translated. Thus compiled machine
language program runs much faster than an interpreted program.

What is C++

C++ is a general-purpose, platform-neutral programming language that supports object-


oriented programming and other useful programming paradigms, including procedural
programming, object-based programming, generic programming, and functional
programming.

History

• Developed by Dr. Bjarne Stroustrup at AT&T Bell labs in the early 80’s
• Originally called C with Classes
• 1985 First external C++ release
• 1990 first Borland C++ release, The Annotated C++ Reference Manual
• 1995 Initial draft standard released
• 1997 Formally approved international C++ standard is accepted – ISO/ANSI C++

Why C++?

Popular and relevant (used in nearly every application domain):


end-user applications (Word, Excel, PowerPoint, Photoshop, Acrobat, Quicken, games)
operating systems (Windows 9x, NT, XP; IBM’s K42; some Apple OS X)
large-scale web servers/apps (Amazon, Google)
central database control (Israel’s census bureau; Amadeus; Morgan-Stanley financial
modeling)
communications (Alcatel; Nokia; 800 telephone numbers; major transmission nodes in
Germany and France)
numerical computation / graphics (Maya)

4
Object Oriented Programming Using C++

device drivers under real-time constraints


Stable, compatible, scalable

Design goals of C++

Backward compatibility with C


(almost completely – every program in K&R is a C++ program)
Simplicity, elegance
(few built-in data types, e.g., no matrices)
Support for user-defined data types
(act like built-in types; N.B. Standard Template Library (STL))
No compromise in efficiency, run-time or memory
(unless “advanced features” used)
Compilation analysis to prevent accidental corruption of data
(type-checking and data hiding)
Support object-oriented style of programming

Some C++ concepts

constructor / destructor / copy constructor


initialization list
inheritance
exceptions
overloading operators (e.g., assignment operator)
namespace
const
virtual function
pure virtual (abstract) function
friend
template
standard template library (STL)
pass by value, pass by reference
composition versus derivation

Major C++ Enhancements

1. C++ supports object-oriented programming features

e.g., abstract classes, inheritance, & virtual methods

2. C++ supports data abstraction & encapsulation

e.g., the class mechanism & name spaces

5
Object Oriented Programming Using C++

3. C++ supports generic programming

e.g., parameterized types

4. C++ supports sophisticated error handling

e.g., exception handling

5. C++ supports identifying an object’s type at runtime

e.g., Run-Time Type Identification (RTTI)

The C++ Compiler

Translates C++ source code into the machine language for the hardware platform
output of the compiler are object files (.obj) which are partially ready to run
object files must be linked together using the system linker to make an executable file
(.exe)
.exe files are specific for the hardware platform
C++ is portable only at the source level

C++ include statements

indicate to the compiler preprocessor which files (source) to include in the file to be
compiled. Included files are actually copied into the source file and replace the
#include statement.

C++ Application

classes are/can be used by a C++ application; but the application is not itself an
instantiated class (like Java)
main() is the name of the function where the executable file starts execution
C++ classes do not have main() functions
C++ objects are initialized via class constructors, C++ applications are initialized in the
main() function.

6
Object Oriented Programming Using C++

C++ application development

C++ Source
File compiler Object Linker .EXE File
File

C++ Include
Files System
Object
Files

Advantages of C++ for scientific and engineering problems include:

• Availability. C++ can be used on a variety of computers ranging from personal


computers to supercomputers.
• Portability. C++ is in the last stages of standardization, and this process has been
closely followed by compiler vendors, ensuring quick availability of a common
standard language.
• Speed. Even with the speed of modern computers there are problems for which
efficiency of language is of paramount importance. C++ inherits the speed of C.
• Generality. Science and engineering now extends beyond computation and into
realms of graphics and robotics. The C++ language is not only suited for formulas
and computations (FORTRAN's strong suit), it can be used effectively in data
base and business applications (COBOL's strong suit).
• Reusability. Clearly it would be an advantage to use previously written code if it
can be inserted into one's current project. The capability of easy re-use and
modification of existing code to fit new problems is an important feature of the
C++ language.
• Object Orientation. As computers have become larger and faster, they have been
programmed to solve larger and more complex problems. Object Oriented
Programming (OOP) is a strategy for simplifying the programming task, and is
supported by the language features of C++.

Some Disadvantages Include:

• Cryptic Syntax. While having the English-like capability of a high level language,
the speed of execution in C++ is inherited from C, and C++ retains some rather
cryptic syntax to maintain compatibility.
• Black box features. Some features, such as input/output operations, are difficult
for the novice to get a handle on.

7
Object Oriented Programming Using C++

• A large overhead. C++ was designed for large and very large applications.
Learning a language, on the other hand, proceeds by building small programs at
first. It sometimes seems that a programming problem is being attacked with a
meat cleaver when a judicious scalpel might be more appropriate!
• Difficult debugging. Debugging C and C++ programs can be very frustrating.
Errors in a C++ program may be very difficult to find because the compiler may
not catch them until many lines later.

C++ - HelloWorld

#include <iostream.h>

int main()

cout << “Hello World” << “\n”;

Stream Input/Output

Stream Input
Keyboard, Hello, World!
Disk file, etc.

Stream Output
Video display,
Hello, World! Disk file, etc.

Some streams in <iostream>

cout
cin
cerr
Operator <<
Operator >>

8
Object Oriented Programming Using C++

Identifiers:

Identifiers refer to the names of variables, functions, arrays, classes, etc. created by the
programmer. They are the functional requirement of any language. Each language has its
own rules for naming these Identifiers.

The following rules for naming these identifiers are:

• Only alphabetic characters, digits and underscores are permitted.


• The name cannot start with a digit.
• Uppercase and lowercase are distinct.
• A declared keyword cannot be used as variable name.

Keywords:

The Keywords implement specific C++ language features. They are explicitly reserved
identifiers and cannot be used as names for the program variables or other user-defined
program elements.

For eg. Break, double, new, switch, operator, this, char etc.

Constants:

Like variables, constants are data storage locations. But variables can vary; constants, on
the other hand and as you might have guessed, do not vary.

You must initialize a constant when you create it, and you cannot assign a new value
later; after a constant is initialized, its value is, in a word, constant.

Literal Constants

C++ has two types of constants: literal and symbolic.

A literal constant is a value typed directly into your program wherever it is needed. For
example:

int myAge = 39;

myAge is a variable, of type int; 39 is a literal constant. You can't assign a value to 39,
and its value can't be changed.

9
Object Oriented Programming Using C++

Symbolic Constants

A symbolic constant is a constant that is represented by a name, just as a variable is.


Unlike a variable, however, after a constant is initialized, its value can't be changed. If
your program has one integer variable named students and another named classes, you
could compute how many students you have, given a known number of classes, if you
knew there were 15 students per class:

students = classes * 15;

NOTE : * indicates multiplication.

In this example, 15 is a literal constant. Your code would be easier to read and easier to
maintain if you substituted a symbolic constant for this value:

students = classes * studentsPerClass

If you later decided to change the number of students in each class, you could do so
where you define the constant studentsPerClass without having to make a change every
place you used that value.

Defining Constants with #define

To define a constant the old-fashioned, evil, politically incorrect way, you would enter:

#define studentsPerClass 15

Note that studentsPerClass is of no particular type (int, char, and so on). #define does a
simple text substitution. Every time the preprocessor sees the word studentsPerClass, it
puts 15 in the text.

Because the preprocessor runs before the compiler, your compiler never sees your
constant; it sees the number 15.

Defining Constants with const

Although #define works, there is a better, less fattening, and more tasteful way to define
constants in C++:

const unsigned short int studentsPerClass = 15;

This example also declares a symbolic constant named studentsPerClass, but this time
studentsPerClass is typed as an unsigned short int.

10
Object Oriented Programming Using C++

This takes longer to type, but offers several advantages. The biggest difference is that this
constant has a type, and the compiler can enforce that it is used according to its
type.

Characters and Strings

There also exist non-numerical constants, like:

'z'
'p'
"Hello world"
"How do you do?"

The first two expressions represent single characters, and the following two represent
strings of several characters. Notice that to represent a single character we enclose it
between single quotes (') and to express a string of more than one character we enclose
them between double quotes (").

When writing both single characters and strings of characters in a constant way, it is
necessary to put the quotation marks to distinguish them from possible variable
identifiers or reserved words. Notice this:

x
'x'

x refers to variable x, whereas 'x' refers to the character constant 'x'.

Character constants and string constants have certain peculiarities, like the escape codes.
These are special characters that cannot be expressed otherwise in the source code of a
program, like newline (\n) or tab (\t). All of them are preceded by an inverted slash (\).
Here you have a list of such escape codes:

\n Newline
\r carriage return
\t Tabulation
\v vertical tabulation
\b Backspace
\f page feed
\a alert (beep)
\' single quotes (')
\" double quotes (")
\? question (?)
\\ inverted slash (\)

11
Object Oriented Programming Using C++

For example:

'\n'
'\t'
"Left \t Right"
"one\ntwo\nthree"

Additionally, you can express any character by its numerical ASCII code by writing an
inverted slash bar character (\) followed by the ASCII code expressed as an octal (radix-
8) or hexadecimal (radix-16) number. In the first case (octal) the number must
immediately follow the inverted slash (for example \23 or \40), in the second case
(hexadecimal), you must put an x character before the number (for example \x20 or
\x4A).
[Consult the document ASCII Code for more information about this type of escape code].

Constants of string of characters can be extended by more than a single code line if each
code line ends with an inverted slash (\):

"string expressed in \
two lines"

You can also concatenate several string constants separating them by one or several blank
spaces, tabulators, newline or any other valid blank character:

"we form" "a single" "string" "of characters"

User Defined Data Types

User Defined Data Types: Structures and Classes

Struct Type

Struct student
{
char name[20];
int roll_no;
float total_marks;
};

The Keyword struct declares student as a new data type that can hold three fields of
different data type. These fields are known as structure members or elements. The
identifier student, which is referred to as structure name or structure tag, can be used to
create variables of type student.

12
Object Oriented Programming Using C++

Example:
Struct student A; //C declaration

Student A; // C++ declaration

Note:
C++ structures support all the features of structures as defined in ‘C’ , But C++ has
expanded its capabilities further to suit its OOP philosophy.
In C++, the structure can have both variables and functions as members.

Class Type

The class type enables us to create sophisticated user defined types. We provide data
items for the class type and the operations that can be performed on the data. For
example, to create a square class that has a data item for size, and provides draw and
resize operations:

class square {
int size;
public:

square();
~square();
void draw();
bool resize(int newSize);

};

square s;//c++ declaration

Enumeration Type

An enumeration type is a user defined type that enables the user to define the range of
values for the type. Named constants are used to represent the values of an enumeration,
for example:

enum weekday {monday, tuesday, wednesday, thursday, friday, saturday,


sunday};
weekday currentDay = wednesday;
if(currentDay==tuesday){
// do something
}

The default values assigned to the enumeration constants are zero-based, so in our
example above monday == 0, tuesday == 1, and so on.

13
Object Oriented Programming Using C++

The user can assign a different value to one or more of the enumeration constants, and
subsequent values that are not assigned a value will be incremented. For example:

enum fruit {apple=3, banana=7, orange, kiwi};

Here, orange will have the value 8 and kiwi 9.

Derived Data Types

Arrays

An array is a data structure which allows a collective name to be given to a group of


elements which all have the same type. An individual element of an array is identified
by its own unique index (or subscript).

An array can be thought of as a collection of numbered boxes each containing one data
item. The number associated with the box is the index of the item. To access a particular
item the index of the box associated with the item is used to access the appropriate box.
The index must be an integer and indicates the position of the element in the array. Thus
the elements of an array are ordered by the index

Declaration of Arrays

An array declaration is very similar to a variable declaration. First a type is given for the
elements of the array, then an identifier for the array and, within square brackets, the
number of elements in the array. The number of elements must be an integer.

For example data on the average temperature over the year in Britain for each of the last
100 years could be stored in an array declared as follows:

float annual_temp[100];

This declaration will cause the compiler to allocate space for 100 consecutive float
variables in memory. The number of elements in an array must be fixed at compile time.
It is best to make the array size a constant and then, if required, the program can be
changed to handle a different size of array by changing the value of the constant,

const int NE = 100;

float annual_temp[NE];

then if more records come to light it is easy to amend the program to cope with more
values by changing the value of NE. This works because the compiler knows the value of
the constant NE at compile time and can allocate an appropriate amount of space for the
array. It would not work if an ordinary variable was used for the size in the array
declaration since at compile time the compiler would not know a value for it.

14
Object Oriented Programming Using C++

Functions:

Functions are segments of code that allow you to better organize your code. You can
think of a function as a small program, and of a program as a collection of functions. This
is a function for the "Hello World" program:

#include

void print_hello()

{ // This line declares the function

cout << "Hello World!\n"; // This is the body, which defines the function

void main()

print_hello(); // This is how the function is called

The print_hello() function The function is void because it does not return any value once
it has finished.

Pointers:

Pointers are variables that hold addresses in C and C++. They provide much power and
utility for the programmer to access and manipulate data in ways not seen in some other
languages. They are also useful for passing parameters into functions in a manner that
allows a function to modify and return values to the calling routine.

Introduction

As a program is executing all variables are stored in memory, each at its own unique
address or location. Typically, a variable and its associated memory address contain data
values. For instance, when you declare:

int count = 5;

The value "5" is stored in memory and can be accessed by using the variable "count". A
pointer is a special type of variable that contains a memory address rather than a data
value. Just as data is modified when a normal variable is used, the value of the address

15
Object Oriented Programming Using C++

stored in a pointer is modified as a pointer variable is manipulated.

Usually, the address stored in the pointer is the address of some other variable.

int *ptr;
ptr = &count // Stores the address of count in ptr
// The unary operator & returns the address of a variable

To get the value that is stored at the memory location in the pointer it is necessary to
dereference the pointer. Dereferencing is done with the unary operator "*".

int total;
total = *ptr;
// The value in the address stored in ptr is assigned to total

Declaration and Initialization

Declaring and initializing pointers is fairly easy.

int main()
{
int j;
int k;
int l;
int *pt1; // Declares an integer pointer
int *pt2; // Declares an integer pointer/
float values[100];
float results[100];
float *pt3; // Declares a float pointer
float *pt4; // Declares a float pointer
j = 1;
k = 2;
pt1 = &j; // pt1 contains the address of the variable j
pt2 = &k; // pt2 contains the address of variable k
pt3 = values;
// pt3 contains the address of the first element of values
pt3 = &values[0];
// This is the equivalent of the above statement

return 0;
}

16
Object Oriented Programming Using C++

What Is a Variable?

In C++ a variable is a place to store information. A variable is a location in your


computer's memory in which you can store a value and from which you can later retrieve
that value.

Notice that this is temporary storage. When you turn the computer off, these variables are
lost. Permanent storage is a different matter. Typically, variables are permanently stored
either to a database or to a file on disk. Storing to a file on disk is discussed on Day 16,
"Advanced Inheritance."

Declaration of Variables:

Say you want to store data for temporary use in a program. You will have to declare
variables to input the data. Luckily, declaring variables in C++ is very easy. This simple
program gets the user's age as input and displays it back to the screen. Here is the source
code:

#include <iostream>

using namespace std;

int main()

int age;

cout << "My Second C++ Program" <<' endl;

cout << "Please enter your age in years followed by <enter>: ";

cin >> age;

cout << "\nYou are " << age << " years old." << endl;

return 0;

To declare the variable "age," simply type the data type (int) in front of it. Notice that you
can specify the type of data you want the function main to return. This next program uses
a few more variables. It retrieves the user's age, as well as their height, weight, hair color,
and eye color.

17
Object Oriented Programming Using C++

#include <iostream>

#include <string>

int main()

int age, feet, inches, pounds;

string hair, eye;

cout << "My third c++ program.\n\n";

cout << "Please type your answer to each question"

<< "followed by <enter>." << endl;

cout << "What is your age (years)? ";

cin >> age;

cout << "\nHow tall are you (ft in)? ";

cin >> feet >> inches;

cout << "\nHow much do you weigh (lbs)? ";

cin >> pounds;

cout << "\nWhat color is your hair? ";

cin >> hair;

cout << "\nWhat color are your eyes? ";

cin >> eye;

cout << endl << "\nYou are " << age << " years old, "

<< feet << " feet " << inches << " inches tall." << "\nYou

weigh " << pounds << " pounds,

<< " have " << hair << " colored hair and "

<< eye << " colored eyes." << endl;

return 0;

18
Object Oriented Programming Using C++

Notice that it's possible to declare different variables of the same type in one line. Simply
separate them by a comma. The previous code also includes a file called string and uses
strings to store characters.

Unlike C, declarations in C++ are statements. As declarations are statements in C+


+, variables may be declared anywhere within the program. In the following
example, the scope of the variable counter is valid for the duration of the
compound statement, initialized by the counted loop.

for (int counter=0; counter<10; counter++)

cout << counter << endl;

If there is already a declaration of counter, earlier in the function, then it will not
have scope until the compound statement has been completed, whereby it will
retain its original value before the counted loop was executed.

Preprocessor Directives

Preprocessor directives are orders that we include within the code of our programs that
are not instructions for the program itself but for the preprocessor. The preprocessor is
executed automatically by the compiler when we compile a program in C++ and is in
charge of making the first verifications and digestions of the program's code.

All these directives must be specified in a single line of code and they do not have to
include an ending semicolon;.

#define

At the beginning of this tutorial we have already spoken about a preprocessor directive:
#define, that serves to generate what we called defined constantants or macros and
whose form is the following:

#define name value

Its function is to define a macro called name that whenever it is found in some point of
the code is replaced by value. For example:

19
Object Oriented Programming Using C++

#define MAX_WIDTH 100


char str1[MAX_WIDTH];
char str2[MAX_WIDTH];

It defines two strings to store up to 100 characters.

#define can also be used to generate macro functions:

#define getmax(a,b) a>b?a:b


int x=5, y;
y = getmax(x,2);

after the execution of this code y would contain 5.

#undef

#undef fulfills the inverse functionality of #define. It eliminates from the list of defined
constants the one that has the name passed as a parameter to #undef:

#define MAX_WIDTH 100


char str1[MAX_WIDTH];
#undef MAX_WIDTH
#define MAX_WIDTH 200
char str2[MAX_WIDTH];

#ifdef, #ifndef, #if, #endif, #else and #elif

These directives allow to discard part of the code of a program if a certain condition is
not fulfilled.

#ifdef allows that a section of a program is compiled only if the defined constant that is
specified as the parameter has been defined, independently of its value. Its operation is:

#ifdef name
// code here
#endif

For example:

#ifdef MAX_WIDTH
char str[MAX_WIDTH];
#endif

In this case, the line char str[MAX_WIDTH]; is only considered by the compiler if the
defined constant MAX_WIDTH has been previously defined, independently of its value.
If it has not been defined, that line will not be included in the program.

20
Object Oriented Programming Using C++

#ifndef serves for the opposite: the code between the #ifndef directive and the #endif
directive is only compiled if the constant name that is specified has not been defined
previously. For example:

#ifndef MAX_WIDTH
#define MAX_WIDTH 100
#endif
char str[MAX_WIDTH];

In this case, if when arriving at this piece of code the defined constant MAX_WIDTH
has not yet been defined it would be defined with a value of 100. If it already existed it
would maintain the value that it had (because the #define statement won't be executed).

The #if, #else and #elif (elif = else if) directives serve so that the portion of code that
follows is compiled only if the specified condition is met. The condition can only serve to
evaluate constant expressions. For example:

#if MAX_WIDTH>200
#undef MAX_WIDTH
#define MAX_WIDTH 200

#elsif MAX_WIDTH<50
#undef MAX_WIDTH
#define MAX_WIDTH 50

#else
#undef MAX_WIDTH
#define MAX_WIDTH 100
#endif

char str[MAX_WIDTH];

Notice how the structure of chained directives #if, #elsif and #else finishes with #endif.

#line

When we compile a program and errors happen during the compiling process, the
compiler shows the error that happened preceded by the name of the file and the line
within the file where it has taken place.

The #line directive allows us to control both things, the line numbers within the code files
as well as the file name that we want to appear when an error takes place. Its form is the
following one:

#line number "filename"

21
Object Oriented Programming Using C++

Where number is the new line number that will be assigned to the next code line. The line
number of successive lines will be increased one by one from this.

filename is an optional parameter that serves to replace the file name that will be shown
in case of error from this directive until another one changes it again or the end of the file
is reached. For example:

#line 1 "assigning variable"


int a?;

This code will generate an error that will be shown as error in file "assigning variable",
line 1.

#error

This directive aborts the compilation process when it is found returning the error that is
specified as the parameter:

#ifndef __cplusplus
#error A C++ compiler is required
#endif

This example aborts the compilation process if the defined constant __cplusplus is not
defined.

#include

This directive has also been used assiduously in other sections of this tutorial. When the
preprocessor finds an #include directive it replaces it by the whole content of the
specified file. There are two ways to specify a file to be included:

#include "file"
#include <file>

The only difference between both expressions is the directories in which the compiler is
going to look for the file. In the first case where the file is specified between quotes, the
file is looked for in the same directory that includes the file containing the directive. In
case that it is not there, the compiler looks for the file in the default directories where it is
configured to look for the standard header files.

If the file name is enclosed between angle-brackets <> the file is looked for directly
where the compiler is configured to look for the standard header files.

22
Object Oriented Programming Using C++

#pragma

This directive is used to specify diverse options to the compiler. These options are
specific for the platform and the compiler you use. Consult the manual or the reference of
your compiler for more information on the possible parameters that you can define with
#pragma.

Comments

Comments are pieces of source code discarded from the code by the compiler. They do
nothing. Their purpose is only to allow the programmer to insert notes or descriptions
embedded within the source code.

C++ supports two ways to insert comments:

// line comment
/* block comment */

The first of them, the line comment, discards everything from where the pair of slash
signs (//) is found up to the end of that same line. The second one, the block comment,
discards everything between the /* characters and the next appearance of the */
characters, with the possibility of including several lines.

We are going to add comments to our second program:

/* my second program in C++

with more comments */

#include <iostream.h>

int main ()

cout << "Hello World! "; // says Hello World!

cout << "I'm a C++ program"; // says I'm a C++ program

return 0;

23
Object Oriented Programming Using C++

Hello World! I'm a C++ program

If you include comments within the source code of your programs without using the
comment characters combinations //, /* or */, the compiler will take them as if they were
C++ instructions and, most likely causing one or several error messages.

C++ Operators

Operators Introduced to C++

The following operators are introduced in C++.

New Operators
Operator Description
New Used to allocate memory
delete Used to de-allocate memory
:: Scope resolution operator, used to bind a method to a class
->* Class member pointer operator
.* Class member pointer operator

C++ Operator Examples

The following shows how the new operators are used.

// Allocate memory for five integers

iPtr = new int[5];

// Deallocate the memory

delete [] iPtr;

// Define a display function for the class, Rectangle

void Rectangle::display()

// Output a pointer to a data member

cout << x.*ptrToMember;

// Output a pointer to a data member of a class pointer

24
Object Oriented Programming Using C++

cout << xPtr->*ptrToMember;

C++ Arithmetic Operators

The following table shows the basic C++ arithmetic operators.

Arithmetic Operators
Operator Description
~ 1's compliment negation. This operator is overloaded in C++ as a
destructor.
+ Unary plus or addition.
- Unary minus or subtraction.
* Multiplication, or indirection.
/ Division.
% Modulus (remainder of a division).
++ Increment (pre-increment if placed before the variable, post-increment if
placed after).
-- Decrement (pre-decrement if placed before the variable, post-decrement if
placed after).

Arithmetic Operator Examples

The following illustrates how to use the arithmeic operators.

// Negate the value of a

result = ~a;

// Caluclate the sum of a and b

total = a + b;

// Calculate the difference between a and b

difference = a - b;

// Calculate the product of a and b

25
Object Oriented Programming Using C++

product = a * b;

// Calculate the quotient of a and b

quotient = a / b;

// Calculate the remainder when a is divided by b

remainder = a % b;

// Increment the value of a

a++;

// Decrement the value of b

b--;

// The pre-inrecrement version

num = ++a;

// The pre-decrement version

num = --b;

Self Assignment

If an assignment is made that requires the value of the variable being assigned to,
C++ offers a convenient shortcut by placing the operator immediately before the
assignment operator.

total += a; // Equivalent to total = total + a;

difference -= a; // Equivalent to difference = difference - a;

product *= a; // Equivalent to product = product * a;

quotient /= a; // Equivalent to quotient = quotient / a;

remainder %= a; // Equivalent to remainder = remainder % a;

C++ Relational Operators

26
Object Oriented Programming Using C++

The following table shows the basic C++ relational operators.

Relational Operators
Operator Description
< Less than (eg. x < 10).
<= Less than or equal to (eg. x <= 10).
== Equivalence (eg. x == 10).
> Greater than (eg. x > 10).
>= Greater than or equal to (eg. x >= 10).
!= Not equivalent (eg. x != 10).

C++ Logical Operators

The following table shows the basic C++ logical operators.

Logical Operators
Operator Description
! Logical Not. For example, (!x) will evaluate to True if x is zero.
&& Logical And. For example, (x > 4 && y <= 10) will evaluate to true if x is
greater than four and y is less than or equal to ten.
|| Logical Or. For example, (x > 10 || y > 10) will evaluate to true if either x
or y are greater than ten

Type Conversion

When dealing with assignment statements and calculations, data types can sometimes be
converted to other data types through something that is called type conversion.
Conversions that take place without the programmer specifically asking for it are called
implicit conversions. Conversions that are requested by the programmer are called
explicit conversions. Programmers run into problems during implicit conversions because
they can be unaware of what is actually happening during execution of their program
until they examine the code very carefully.

Definition

implicit conversion - conversion that happens without the programmer specifically asking
for it

27
Object Oriented Programming Using C++

It's pretty clear that programmers can run into problems because of implicit conversions.
However, if you fully understand data types and how they are defined for certain
arithmetic operators, you should be able to avoid them. For instance, if y and z are float,
and a is int, when the statement z = a + y is executed, the value of a will be stored in a
temporary memory location as float for use in the rest of the statement. Then, the addition
is done (in float form) and finally, the result stored in z. So what happened? [a was
implicitly converted into float during the execution of the statement]

Another form of implicit conversion may take place during assignment, but not
necessarily from a smaller type to a larger type.

Example:

int a;
float b = 3.5;
float c = 5.0;
int d = 2;
a = b * c / d;
cout << a; --> 8

What conversion took place in the above example? First of all, d was implicitly converted
to 2.0 during b * c / d. The result of that multiplication and division is 8.75, but as it was
declared int, so it was implicitly converted to 8 during assignment.

Definition

explicit conversion - conversion requested by the programmer; sometimes called


typecasting

While programmers are unaware of implicit conversions, they are completely in control
of explicit conversions. Explicit conversions, or typecasting, can come in handy as you
will see in later problems. Typecasting can be easily accomplished and it has a easy to
use form which is: type( variable ) where type is whatever data type you choose and
variable is the variable you are converting. It simply takes the value of variable and
converts in into the type specified.

Example 1:

double d;
int k;
d = 12.78;
k = int(d); --> k = 12
d = double(k); --> d = 12.0

Example 2:

28
Object Oriented Programming Using C++

int m = 10, n = 4, r;
double q;
q = m / n; --> q = 2.0
r = double(m) / n; --> 2

r = m / n; --> 2
q = double(m) / n --> 2.5

Note: q = (double)m / n is equivalent to q = double(m) / n;

Control structures

Although C++ is an object-oriented programming language, it is really a hybrid


language as it still supports structured programming techniques. With an object-
oriented approach, instead of breaking the problem domain up in terms of
functionality, you identify the objects in terms of data and behavior. This section
concentrates on the structured capabilities of C++.

Structured programming is based around three basic constructs: Sequence,


Selection and Iteration. The Sequence construct is the simplest, whereby statements
are executed in the order they're found in the code.

Both the Selection and Iteration constructs require a Logical Test. Logical tests can
be performed on variables, literal values, calculations, and results of functions The
test will evaluate to either true or false.

Selection Constructs

The Selection constructs are used when the flow of execution may flow down two
or more paths.

The if Statement

The if statement is used to control the flow of execution down one of two or more
paths, depending on the result of a logical test. Further conditions may be specified
with else if, should previous conditions be false, and else may be used should none
of the above be true. There is no semicolon at the end of if statement.

if (grade < 40)

cout << "Failed" << endl;

29
Object Oriented Programming Using C++

else if (grade < 75)

cout << "Passed" << endl;

else

cout << "Excellent Pass" << endl;

If statements can be nested, and the combined with logical operators.

If more than one line should be executed should a condition be true, the lines
should be enclosed within curly braces.

if (x == 10)

cout << "That's an excellent result" << endl;

cout << "You should be extremely proud of yourself!" << endl;

Note: A common mistake is to use the assignment operator instead of the equality
operator when checking for equivalence. The following statement will always
evaluate to True as x is assigned the value 10 which is a non-zero number.

if (x = 10)

The switch Statement

When there are many conditions, the switch statement can be used if the values are
discrete. The switch statement is easier to read than multiple if statements when
there are a large number of discrete values.

Iteration Constructs

The Iteration constructs are used when a block of code is required to be executed
continually until a condition is met.

Pre-Condition Loops

30
Object Oriented Programming Using C++

Pre-condition loops allow for a condition to be tested at the start of the loop. This
type of loop is used when you only want to execute the block of code should the
condition be true. If there is more than one line to be included in the iteration, it
should be contained within curly braces.

A semicolon is not added to the end of the while statement. If one is added in error,
then the block of code will be executed exactly once. The following example uses a
pre-condition loop to calculate the factorial of a number (a number that is
multiplied by every integer number below itself down to 1).

factorial.cpp

#include <iostream.h>

int main()

int num;

long int factorial=1;

cout << "Enter a number: ";

cin >> num;

cout << "The factorial of " << num << " is: ";

// Use a pre-condition loop to calculate the factorial

while (num > 1)

factorial *= num--;

cout << factorial << endl;

return 0;

Post-Condition Loops

31
Object Oriented Programming Using C++

Post-condition loops allow for a condition to be tested at the end of the loop. This
type of loop is used when you want to execute the block of code at least once and is
often used for validation. If there is more than one line to be included in the
iteration, it should be contained within curly braces. The following example uses a
post-condition loop to ensure that a number is between 1 and 10.

validate.cpp

#include <iostream.h>

int main()

int num;

// Use a post-condition loop to validate the number entered

do

cout << "Enter a number between 1 and 10: ";

cin >> num;

} while (num < 1 || num > 10);

cout << num << " is between 1 and 10\n";

return 0;

Counted Loops

Counted loops are used when you know how many times you want to execute a
statement or a list of statements. A semicolon is not added to the end of the for
statement. If one is added in error, then the block of code will be executed exactly
once. The following is the general syntax of a counted loop.

for (initialisation_section; condition; increment_section)

32
Object Oriented Programming Using C++

// List of statements

The parameters that the counted loop operates on are in three sections separated by
semicolons. The first section is for initialising any variables, the second section has
the condition, and the third section has any increments required to implement the
loop. If more than one variable is to be used in either the initialisation_section or
the increment_section, then they are separated by commas. As declarations are
statements in C++, control variables may be declared in the initialisation section of
the counted loop. The condition must evaluate to either true or false. Compounded
conditions must be created by using the logical operators. The following counted
loop prints the prime numbers (a number divisible only by itself and 1) between 1
and a number enetered by the user.

prime.cpp

#include <iostream.h>

int main()

int num;

cout << "Enter a number: ";

cin >> num;

for (int counter = 1; counter < num; counter++)

int prime, test;

test = counter;

prime = 1;

while (test-- > 2)

33
Object Oriented Programming Using C++

if ((counter % test) == 0)

prime = 0;

if (prime == 1)

cout << counter << " is a prime number\n";

return 0;

Structures

Structures are a way of storing many different variables of different types under the same
name. This makes it a more modular program, which is easier to modify because its
design makes things more compact. It is also useful for databases.

The format for declaring a structure(in C++, it is different in C) is

struct NAME

VARIABLES;

};

Where NAME is the name of the entire type of structure. To actually create a single
structure the syntax is NAME name_of_single_structure; To access a variable of the
structure it goes name_of_single_structure.name_of_variable;

For example:

struct example

int x;

};

example an_example; //Treating it like a normal variable type

34
Object Oriented Programming Using C++

an_example.x=33; //How to access it

Here is an example program:

struct database

int id_number;

int age;

float salary;

};

int main()

database employee; //There is now an employee variable that has modifiable

//variables inside it.

employee.age=22;

employee.id_number=1;

employee.salary=12000.21;

return 0;

The struct database declares that database has three variables in it, age, id_number, and
salary.

You can use database like a variable type like int. You can create an employee with the
database type as I did above. Then, to modify it you call everything with the 'employee.'
in front of it. You can also return structures from functions by defining their return type
as a structure type. Example:

struct database fn();

I suppose I should explain unions a little bit. They are like structures except that all the
variables share the same memory. When a union is declared the compiler allocates
enough memory for the largest data-type in the union. It’s like a giant storage chest where
you can store one large item, or a bunch of small items, but never the both at the same

35
Object Oriented Programming Using C++

time.

The '.' operator is used to access different variables inside a union also.

As a final note, if you wish to have a pointer to a structure, to actually access the
information stored inside the structure that is pointed to, you use the -> operator in place
of the . operator.

A quick example:

#include <iostream.h>

struct xampl

int x;

};

int main()

xampl structure;

xampl *ptr;

structure.x=12;

ptr=&structure; //Yes, you need the & when dealing with structures

//and using pointers to them

cout<<ptr->x; //The -> acts somewhat like the * when used with pointers

//It says, get whatever is at that memory address

//Not "get what that memory address is"

return 0;

Union

A union is a user-defined data or class type that, at any given time, contains only one
object from its list of members (although that object can be an array or a class type). The

36
Object Oriented Programming Using C++

member-list of a union represents the kinds of data the union can contain. A union
requires enough storage to hold the largest member in its member-list.

Declaring a Union

Begin the declaration of a union with the union keyword, and enclose the member list in
curly braces:

union DATATYPE // Declare union type

char ch;

int i;

long l;

float f;

double d;

} var1; // Optional declaration of union variable

Using a Union

A C++ union is a limited form of the class type. It can contain access specifiers (public,
protected, private), member data, and member functions, including constructors and
destructors. It cannot contain virtual functions or static data members. It cannot be used
as a base class, nor can it have base classes. Default access of members in a union is
public.

A C union type can contain only data members.

In C, you must use the union keyword to declare a union variable. In C++, the union
keyword is unnecessary:

union DATATYPE var2; // C declaration of a union variable

DATATYPE var3; // C++ declaration of a union variable

A variable of a union type can hold one value of any type declared in the union. Use the
member-selection operator (.) to access a member of a union:

var1.i = 6; // Use variable as integer

var2.d = 5.327; // Use variable as double

37
Object Oriented Programming Using C++

You can declare and initialize a union in the same statement by assigning an expression
enclosed in curly braces. The expression is evaluated and assigned to the first field of the
union. For example:

#include <stdio.h>

union NumericType

int iValue;

long lValue;

double dValue;

};

void main()

union NumericType Values = { 10 }; // iValue = 10

printf("\n%d", Values.iValue);

Values.dValue = 3.1416;

printf("\n%f", Values.dValue);

The NumericType union is arranged in memory (conceptually) as shown in Figure 8.1.

Figure: Storage of Data in Numeric Type Union

38
Object Oriented Programming Using C++

Enumerations (enum)

Enumerations serve to create data types to contain something different that is not limited
to either numerical or character constants nor to the constants true and false. Its form is
the following:

enum model_name {

value1,

value2,

value3,

} object_name;

For example, we could create a new type of variable called color to store colors with the
following declaration:

enum colors_t {black, blue, green, cyan, red, purple, yellow, white};

Notice that we do not include any fundamental data type in the declaration. To say it
another way, we have created a new data type without it being based on any existing one:
the type color_t, whose possible values are the colors that we have enclosed within curly
brackets {}. For example, once declared the colors_t enumeration in the following
expressions will be valid:

colors_t mycolor;

mycolor = blue;
if (mycolor == green) mycolor = red;

In fact our enumerated data type is compiled as an integer and its possible values are any
type of integer constant specified. If it is not specified, the integer value equivalent to the
first possible value is 0 and the following ones follow a +1 progression. Thus, in our data
type colors_t that we defined before, black would be equivalent to 0, blue would be
equivalent to 1, green to 2 and so on.

If we explicitly specify an integer value for some of the possible values of our
enumerated type (for example the first one) the following values will be the increases of
this, for example:

enum months_t { january=1, february, march, april,

39
Object Oriented Programming Using C++

may, june, july, august,

september, october, november, december} y2k;

in this case, variable y2k of the enumerated type months_t can contain any of the 12
possible values that go from january to december and that are equivalent to values
between 1 and 12, not between 0 and 11 since we have made january equal to 1.

Functions in C++

Functions allow the programmer to modularise the program. All variables declared
within functions are called local variables, in that they are known only in the
function to which they have been defined. Some functions have a parameter list
that provides a communication method between the function, and the module that
called the function. The parameters are also local variables, in that they are not
available outside of the function. The programs covered so far all have main, which
is a function. The following example uses a function called square which writes the
square (a number multiplied by itself) of the numbers between 1 and 10.

factorial.cpp

#include <iostream.h>

#include <iomanip.h>

// Function prototype

int square(int x);

int main()

for (int counter=1; counter<=10; counter++)

cout << "Square of " << setw(4) << counter << " is "

<< setw(4) << square(counter) << endl;

return 0;

40
Object Oriented Programming Using C++

// Define the function 'square'

int square(int x)

return x * x;

The function prototype, "square", declares a function that takes an integer


parameter and returns an integer. When the compiler reaches the function call to
square in the main program, it is able to check the function call against the
function's definition. When the program reaches the line that calls the function
square, the program jumps to the function and executes that function before
resuming its path through the main program. Programs that do not have a return
type should be declared using void. The Factorial program is an example of a
recursive function, a function that calls itself.

Pass by Value

Parameters to a function may either be pass by value, or pass by reference. If


parameters are passed by value, only a copy of the variable has been passed to the
function. Any changes to the value will not be reflected back to the calling
function. The above function uses pass by value, as the square function doesn't
need to alter the value of the parameter passed to it. The program, Number To
Words, is another example of pass by value functions.

Default Arguments

C++ Allows you to specify default values for the arguments of functions. The
default value is specified in the function prototype and not the function definition,
unless the function definition is also the declaration. It is not necessary to assign a
default value for every argument, but from the point the first default value is
defined, default values will be required for the remaining arguments of the
function. The following are valid function prototypes for functions with three
arguments.

// Three default arguments

41
Object Oriented Programming Using C++

void func1(int first=0, int second=0, int third=0);

// Two default arguments

void func2(int first, int second=0, int third=0);

// One default argument

void func3(int first, int second, int third=0);

// No default arguments

void func4(int first, int second, int third);

If no default argument is provided, then the argument must be provided when the
function is called. Default values are specified from left to right, as shown in the
following example.

default.cpp

#include <iostream.h>

void display(int first=0, int second=0, int third=0);

int main()

display(); // Displays 0 0 0

display(23); // Displays 23 0 0

display(12, 50); // Displays 12 50 0

display(20, 1, 1964); // Displays 20 1 1964

return 0;

void display(int first, int second, int third)

42
Object Oriented Programming Using C++

cout << first << " "

<< second << " "

<< third << endl;

Pass by Reference

A function that uses call-by-reference arguments reflects any changes to the values
of the arguments to the calling function. In traditional C, this is achieved by
passing the address of the variable, and using pointers to de-reference the
arguments. C++ introduces a reference operator (&), that allows true call-by-
reference functions, eliminating the need to dereference arguments passed to the
function. The reference operator is placed before the variable name of arguments in
the parameter list of the function. The function can then be called without passing
the address, and without dereferencing within the function. The following example
contains a function to swap two values. As the values require changing in the
calling function, the values are passed by reference.

swap.cpp

#include <iostream.h>

// The arguments x, and y are passed by reference

// Therefore changes made to these variables will

// be reflected to where they were called.

void swap(int &x, int &y);

int main()

int x=6, y=9;

cout << "Before the swap:\n";

cout << "X: " << x << endl;

43
Object Oriented Programming Using C++

cout << "Y: " << y << endl;

swap(x, y);

cout << "\nAfter the swap:\n";

cout << "X: " << x << endl;

cout << "Y: " << y << endl;

return 0;

void swap(int &x, int &y)

int temp = x;

x = y;

y = temp;

Function Overloading

C++ allows both functions and operators to be overloaded. An overloaded function,


is a function with the same name as another function, but with different parameter
types. This promotes programming flexibility. Overloaded functions allow the
following

• Use the same function name


• Carry out operations using different data types
• The programmer using the function need not be concerned with how
the function has been implemented.

For example, suppose we were required to find the product of two numbers, either
of which may be of type int or double. All we would have to do is write four
functions, each with the same name and defined to ensure that we get the correct

44
Object Oriented Programming Using C++

result, regardless of the types of the arguments we use in the function call. The
appropriate function is selected depending on the data types of the parameters.

The following shows you the function prototypes.

int product(int x, int y);

double product(int x, double y);

double product(double x, int y);

double product(double x, double y);

The compiler will then choose the appropriate function. From a readability point of
view, function overloading should only be used when the functionality is the same.
Overloaded functions must adhere to the following two rules:

1. The compiler does not use the return type of the function to distinguish
between function instances.
2. The argument list of each of the function instances must be different.

The following example overloads a swap function for integers, and floating point
numbers.

overload.cpp

#include <iostream.h>

// Overload the swap function for int and float

void swap(int &a, int &b);

void swap(float &a, float &b);

int main()

int i1 = 3, i2 = 5;

float f1 = 3.14159f, f2 = 1.23f;

45
Object Oriented Programming Using C++

cout << "Integers before swap:" << endl;

cout << i1 << ", " << i2 << endl;

swap(i1, i2);

cout << "Integers after swap:" << endl;

cout << i1 << ", " << i2 << endl;

cout << "Floating points before swap:" << endl;

cout << f1 << ", " << f2 << endl;

swap(f1, f2);

cout << "Floating points after swap:" << endl;

cout << f1 << ", " << f2 << endl;

return 0;

// An integer swap function

void swap(int &a, int &b)

int temp = a;

a = b;

b = temp;

// An overloaded float swap function

void swap(float &a, float &b)

46
Object Oriented Programming Using C++

float temp = a;

a = b;

b = temp;

Inline functions

An inline function is a request to the compiler to optimise the function call by


substituting the function called at the point where the function call is made. If the
request is successful, the overhead associated with a normal function call is
eliminated. To make an inline function, the keyword, "inline" precedes the function
prototype and function definition. As it's just a request, there is no guarantee that
the function will be called inline.

Functions containing the following would not be suitable for an inline function:

• Static Variables
• Iteration Constructs
• A switch Statement
• Arrays
• Recursive calls to istelf

The following example uses an inline function to determine if a given year is a leap
year. If the request is successful, the function definition will be expanded in the
main part of the program, eliminating the need for a function call.

leap.cpp

#include <iostream.h>

// Prototype declaration

inline int leap(int year);

int main()

47
Object Oriented Programming Using C++

int year;

cout << "Enter a year: ";

cin >> year;

if (leap(year))

cout << "The year " << year << " is a leap year" << endl;

else

cout << "The year " << year << " is not a leap year" << endl;

return 0;

// Definition of leap

inline int leap(int year)

if (((year % 4) == 0) && (((year % 100) != 0) || ((year%400) == 0)))

return 1;

return 0;

An array is a set of variables, represented by a single name. The individual


variables are called elements and are identified by index numbers. The following
example declares an array with ten elements.

int x[10];

The first element in the array has an index number of zero. Therefore, the above
array has ten elements, indexed from zero to nine.

Accessing the Elements

48
Object Oriented Programming Using C++

To access an individual element in the array, the index number follows the variable
name in square brackets. The variable can then be treated like any other variable in
C++. The following example assigns a value to the first element in the array.

x[0] = 16;

The following example reads a value from the keyboard into the last element of an
The following example prints the value of the third element in an array.

cout << x[2] << endl;

array with ten elements.

cin >> x[9];

Initialising Array Elements

Arrays can be initialised like any other variables by assignment. As an array


contains more than one value, the individual values are placed in curly braces, and
seperated with commas. The following example initialeses a ten dimensional array
with the first ten values of the three times table.

int x[10] = {3, 6, 9, 12, 15, 18, 21, 24, 27, 30};

This saves assigning the values individually as in the following example.

int x[10];

x[0] = 3;

x[1] = 6;

x[2] = 9;

x[3] = 12;

x[4] = 15;

x[5] = 18;

x[6] = 21;

49
Object Oriented Programming Using C++

x[7] = 24;

x[8] = 27;

x[9] = 30;

Looping through an Array

As the array is indexed sequentially, we can use the for loop to display all the
values of an array. The following example displays all the values of an array. It
then sorts the array into ascending order, and displays the sorted array.

sort.cpp

#include <iostream.h>

#include <iomanip.h>

int main()

int x[10] = {1, 37, 3, 7, 4, 9, 2, 33, 19, 5};

int counter;

cout << "Before Sorting:\n\n";

cout << "Element" << setw(10) << "Content" << endl;

// Display the contents of the initial array

for (counter=0; counter<10; counter++)

cout << setw(7) << counter << setw(10) << x[counter] << endl;

// Sort the array

for (int outer=0; outer<10; outer++)

for (int inner=outer+1; inner<10; inner++)

if (x[inner] < x[outer])

50
Object Oriented Programming Using C++

// Swap the values

int temp = x[inner];

x[inner] = x[outer];

x[outer] = temp;

cout << "After Sorting:\n\n";

cout << "Element" << setw(10) << "Content" << endl;

// Display the contents of the sorted array

for (counter=0; counter<10; counter++)

cout << setw(7) << counter << setw(10) << x[counter] << endl;

return 0;

Multidimensional Arrays

An array can have more than one dimension. By allowing the array to have more
than one dimension provides greater flexibility. For example, spreadsheets are built
on a two dimensional array; an array for the rows, and an array for the columns.
The following example uses a two dimensional array with two rows, each
containing five columns.

multi.cpp

#include <iostream.h>

#include <iomanip.h>

int main()

51
Object Oriented Programming Using C++

// Declare a 2 x 5 multidimensional array

int x[2][5] = { {1, 2, 3, 4, 5},

{2, 4, 6, 8, 10} };

// Display the rows

for (int row=0; row<2; row++)

// Display the columns

for (int column=0; column<5; column++)

cout << setw(6) << x[row][column];

cout << endl;

return 0;

We have already seen how variables are memory cells that we can access by an identifier.
But these variables are stored in concrete places of the computer memory. For our
programs, the computer memory is only a succession of 1 byte cells (the minimum size
for a datum), each one with a unique address.

A good simile for the computer memory can be a street in a city. On a street all houses
are consecutively numbered with an unique identifier so if we talk about 27th of Sesame
Street we will be able to find that place without trouble, since there must be only one
house with that number and, in addition, we know that the house will be between houses
26 and 28.

In the same way in which houses in a street are numbered, the operating system organizes
the memory with unique and consecutive numbers, so if we talk about location 1776 in
the memory, we know that there is only one location with that address and also that is
between addresses 1775 and 1777.

POINTERS

52
Object Oriented Programming Using C++

A pointer is a variable that represents the location (rather than the value) of a data item,
such as a variable or an array element.

Suppose v is a variable that represents some particular data item. The compiler will
automatically assign memory cells for this data item. The data item can then be accessed
if we know the location (i.e. the address) of the first memory cell. The address v’s
memory location can be determined by the expression &v, where & is a unary operator,
called the address operator, that evaluates the address of its operand.

pv = &v
This new variable pv is called pointer to v, since it “point” to the location where v is
stored in memory. As pv represents v’s address not its value, it is referred to as a pointer
variable.

Value of v

Address of pv
pv v
The data item represented by v (ie the data item stored in v’s memory cells) can be
accessed by the expression *pv, where * is a unary operator, called the indirection
operator, that operates only on a pointer variable. Therefore, *pv and v both represent the
sane data item,(ie the contents of the same memory cells). If we write pv = &v and
u=*pv, then u and v will both represent the same value; ie, the value of v will indirectly
be assigned to u.

void main()
{
int u =3, v;
int *pu, *pv;
pu = &u; // pointer to an integer
v = *pu; // assign value of u to v
pv = &v; // assign address of v to pv
cout << “u = “<< u;
cout <<”&u = “ << &u;
cout <<”pu = “<<pu;
cout <<”*pu= “<<*pu;
cout <<”v = “<<v;
cout <<”&v = “<<&v;
cout <<”pv = “<< pv;
cout <<”*pv = “<<*pv;
}
pu is a pointer to u, and pv is a pointer to v. Therefore pu represents the address of u, and
pv represents the address of v.
u =3 &u=F8E pu=F8E *pu=3
v =3 &v=F8C pv = F8C *pv=3

53
Object Oriented Programming Using C++

Pointer Declarations

All pointer variables must be declared before they may be used. The interpretation of a
pointer declaration differs, however, from the interpretation of other variable
declarations. Pointer variable must be preceded by an asterisk(*). This identifies the fact
that the variable is a pointer.
data-type *ptvar;
where ptvar is the name of the pointer variable, and data-type refers to the data type of
the pointer’s object.

Passing Pointers To A Function

Pointers are often passed to a function as arguments. This allows data items within the
calling portion of the program to be accessed by the function, altered within the function,
and then returned to the calling portion of the program in altered form. WE refer to this
use of pointers as passing arguments by reference (or by address or by location).

When an item is passed by reference, however (i.e., when a pointer is passed to a


function), the address of a data or within the calling function. The contents of that address
can be accessed freely, either within the function or within the calling routine. Any
change made to the data item (i.e., to the contents of the address) will be recognized in
both the function and the calling routine.

When pointers are used as arguments to a function, each formal pointer arguments must
be preceded by an asterisk. Function prototypes are written in the same manner. If a
function declaration does not include variable names, the data type of each pointer
argument must be followed by an asterisk.

Eg.
void main()
{
void funct1(int u, int v);
void funct2(int *pu, int *pv);

int u = 1, v = 3;

cout <<”Before calling funct1 : u = “<<u<<” v = “ <<v;


funct1(u,v);
cout <<”After calling funct1 : u = “<<u<<” v = “ <<v;

cout <<”Before calling funct2 : u = “<<u<<” v = “ <<v;


funct2(&u,&v);
cout <<”After calling funct2 : u = “<<u<<” v = “ <<v;
}// end of main

54
Object Oriented Programming Using C++

void funct1(int u, int v)


{
u=0, v=0;
cout << “within funct1 : u = “<<u <<”v = “<<v;
}

void funct2(int *pu, int *pv)


{
*pu=0, *pv=0;
cout << “within funct2 : *pu = “<<*pu <<”*pv = “<<*pv;
}

Pointers And One Dimensional Arrays

An array name is really a pointer to the first element in the array. Therefore, if x is a one
dimensional array, then the address of the first array element can be expressed as either
&x[0] or simply as x. The address of the second array element can be written as either
&x[1] or as (x+1), and so on. In general, the address of array element (i+1) can be
expressed as either &x[i] or as (x + i). So we can write the actual array element, preceded
by an ampersand; or we can write an expression in which the subscript is added to the
array name.

In the expression (x + i), for example, x represents an address, whereas i represents an


integer quantity. Moreover, x is the name of an array whose elements may be characters,
integers, floating point quantities etc. Hence the expression (x + i) is a symbolic
representation for an address specification rather than an arithmetic expression.

When writing the address of an array element in the form (x + i), however, you need not
be concerned with the number of memory cells associated with each type of array
element; the C++ compiler adjusts for this automatically. You must specify only the
address of the first array element (i.e., the name of the array) and the number of array
elements beyond the first (i.e., a value for the subscript). The value of I is sometimes
referred to as an offset when used in this manner.

Since &x[i] and (x + i) both represent the address of the ith element of x, it would seem
reasonable that x[i] and *(x + i) both represent the contents of that address, i.e, the value
of the ith element of x. The two terms are interchangeable. Hence, either term can be
used in any particular application.
Eg.
void main()
{
int x[10] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
int i;
for (i=0; i< = 9; i++)
{

55
Object Oriented Programming Using C++

// display an array element


cout << “ i = “ << i << “ x[i] = “ << x[i] << “ *(x + i) = “ << *(x + i);

// display the corresponding array address


cout << “ &x[i] = “<< &x[i] << “ (x + i) = “ << (x + i);
}
} // end of main

Operations On Pointers

In arrays, an integer value can be added to an array name in order to access an individual
array element. The integer value is interpreted as an array subscript; it represents the
location of the desired array element relative to the first element in the array. This works
because all of the array elements are of the same data type, and therefore each array
element occupies the same number of memory cells (i.e., the same number of bytes or
words). The actual number of memory cells that separate the two array elements will
depend on the data type of the array.

This concept can be extended to pointer variables in general. Thus, an integer value can
be added to or subtracted from a pointer variable, though the resulting expression must be
interpreted very carefully. Suppose, for example, that px is a pointer variable that
represents the address of some variable x. We can write expressions such as ++px, --px,
(px + 3), (px + i) and (px – i), where i is an integer variable. Each expression will
represent an address that is located some distance from the original address represented
by px. The exact distance will be the product of the integer quantity and the number of
bytes or words associated with the data item to which px points. Suppose, for example,
that px points to an integer quantity, and each integer quantity requires two bytes of
memory. Then the expression (px + 3) will result in an address that is six bytes beyond
the integer to which px points. This new address will not necessarily represent the
address of another data item, particularly if the data items stored between the two
addresses involve different data types.

Px |2bytes|

(px+3)

Eg.
void main()
{
int *px; // pointer to an integer
int i =1;
float = 0.3;

56
Object Oriented Programming Using C++

double d = 0.005;
char c = ‘*’;

px = &i;
cout <<”Values : i = “<< i <<”f = “<<f << “d = “<<d<<”c = “<<c;
cout <<”Addresses : &i =“ <<&i<<”&f =“<<&f<<”&d = “<<&d<<”&c =”<<&c;
cout <<”Pointer values : px = “<<px<< ”px+1=”<<px+1<< ”px+2=”<<px+2<<
”px+3=”<<px+3;
}

This program displays the values and addresses associated with four different types of
variables: i, an integer variable; f, a floating-point variable; d, a double-precision
variable; and c, a character variable. The program also makes use of a pointer variable,
px, which represents the address of i. The values of px, px + 1, px + 2 and px + 3 are also
displayed, so that they may be compared with the addresses of the different variables.

OUTPUT :

Values : i =1 f=0.300000 d =0.005000 c = *


Addresses : &i=117E &f=1180 &d=1186 &c=118E
Pointer Values : px =117E px+1=1180 px+2=1182 px+3=1184

If px is defined as a pointer to a different type of object(eg, a character or a floating-point


quantity), then any integer constant that is added to or subtracted from the pointer will be
interpreted differently. In particular, each integer value will represent an equivalent
number of individual bytes if px points to a character, or a corresponding number of four-
byte multiples if px points to a floating-point quantity.

One pointer variable can be subtracted from another provided both variables point to
elements of the same array. The resulting value indicates the number or bytes separating
the corresponding array elements.

57
Object Oriented Programming Using C++

eg.
void main()
{
int *px, *py; //interger pointers
static int a[6] = {1,2,3,4,5,6};
px = &a[0];
py = &a[5];
cout <<”px = “<<px << “py = “<<py;
cout <<”py-px = “<<py-px ;
}
In particular, the pointer cariable px points to a[0], and py points to a[5]. The difference
py-px, should be 5, since a[5] is the fifth element beyond a[0].
Execution of the program results in the following output
px = 52 py = 5c
py-px = 5
The first line indicates that the address of a[0] is 52, and the address of a[5] is 5c. The
difference between these two hexadecimal numbers is 10 (when converted to decimal).
Thus, a[5] is stored at an address which is 10 bytes beyond the address of a[0]. Since
each integer quantity occupies two bytes, we would expect the difference between py an
px to be 10/2=5. the second line of output confirms this value.

Pointer variables can be compared provided both variables are of the same data type.
Such comparisons can be useful when both pointer variables point to the same array. The
comparisons can test for either equality or inequality. Moreover, a pointer variable can be
compared with zero (which is usually NULL when used in this manner).

Eg.
Suppose px and py are pointer variables that point to elements of the same array. Several
logical expressions involving these two variables are shown below. All of the expressions
are syntactically correct.
(px < py)
(px >= py)
(px == py)
(px != py)
(px == NULL)
These expressions can be used as any other logical expression. For example,
if (px < py)
cout << “px < py”;
else
cout << ”px >= py”;

Expressions such as (px < py) indicate whether or not the element associated with
px is ranked ahead of the element associated with py (i.e., whether or not the subscript
associated with *px is less than the subscript associated witj *py).

58
Object Oriented Programming Using C++

The operations discussed previously are the only operations that can be carried out on
pointers. These permissible operations are summarized below.

1. A pointer variable can be assigned the address of an ordinary variable (e.g., pv =


&v).
2. A pointer variable can be assigned the value of another pointer variable (e.g., pv =
px) provided both pointers point to objects of the same data type.
3. A pointer variable can be assigned a null(zero) value (e.g., pv = NULL, where
NULL is a symbolic constant that represents the value 0).
4. An integer quantity can be added to or subtracted from a pointer variable (e.g., pv
+ 3, ++pv, etc.)
5. One pointer variable can be subtracted from another provided both pointers point
to elements of the same array.
6. Two pointer variables can be compared provided both pointers point to objects of
the same data type.

Other arithmetic operations on pointers are not allowed. Thus, a pointer variable cannot
be multiplied by a constant; two pointer variables cannot be added; and so on. An
ordinary variables cannot be assigned an arbitrary address (i.e., an expression such as &x
cannot appear on the left side of an assignment statement).

Pointers And Multidimensional Arrays

A two dimensional array, for example, is actually a collection of one-dimensional arrays.


Therefore, we can define a two-dimensional array as a pointer to a group of contiguous
one-dimensional arrays. Thus a two-dimensional array declaration can be written as
data-type (*ptvar) [expression2];
rather than
data-type array[expression1][expression2];
This concept can be generalized to higher-dimensional arrays; that is;
data-type (*ptvar)[expression2][expression3]………..[expression n];
replaces
data-type array[expression1][expression2]………..[expression n];

In this declarations data-type refers to the data type of the array, ptvar is the name of the
pointer variable, array is the corresponding array name, and expression1, expression2,
……expression n are poisitve-valued integer expression that indicate the maximum
number of array elements associated with each subscript.

Notice that parentheses that surround the array name and the preceding asterisk in the
pointer version of each declaration. These parentheses must be present. Without them we
would be defining an array of pointers rather than a pointer to group of arrays, since these
particular symbols (i.e., the square brackets and the asterisk) would normally be
evaluated right to left.

59
Object Oriented Programming Using C++

Eg1. Suppose x is a two-dimensional integer having 10 rows and 20 columns. We can


declare x as
int (* x) [20];
rather than
int x[10][20];
In the first declaration, x is defined to be a pointer to a group of contiguous, one-
dimensional, 20-element integer arrays. Thus, x points to the first 20-element arrays,
which is actually the first row (i.e., row 0) of the original two-dimensional array.
Similarly, (x + 1) points to the second 20-element array, which is the second row (row 1)
of the original two-dimensional array, and so on.

x
1st one-dimensional aray

(x + 1)
2nd one dimensional array

………………….

(x + 9)

10th one-dimensional array

Eg. 2 Consider a three dimensional floating point array t. This array can be defined as
float (*t)[20][30];
rather than
float t[10][20][30];
In the first declaration, t is defined as a pointer to a group of contiguous two-dimenional,
20 * 30 floating-point arrays. Hence t points to the first 20 * 30 array, (t + 1) points to the
second 20 * 30 array, and so on.

An individual array element within a multidimensional array can be accessed by the


repeated use of the indirection operator. Usually, however, this procedure is more
awkward than the conventional method for accessing an array element.

Eg. Suppose x is a 2-d integer array having 10 rows and 20 columns. The item in row 2,
column 5 can be accessed by writing either
x[2][5] or *(*(x + 2) + 5)

In the second form (x + 2) is a pointer to row 2. Therefore the object of this pointer. *(x +
2), refers the entire row. Since row 2 is a one-dimensional array, *(x + 2) is actually a
pointer to the first element in row 2. The object of this pointer, *(*(x + 2) + 5), therefore
refers to the item in column 5 of row 2, which is x[2][5].

60
Object Oriented Programming Using C++

x
1st one dimensional array

(x + 1)
2nd one dimensional array

(x + 2)
3rd one dimensional array

*(x+2) *(x+2)+5

*(*(x+2)+5)

Programs that make use of multidimensional arrays can be written in several different
ways. In particular, there are different ways to define the arrays, and different ways to
process the individual array elements.

Arrays Of Pointers

A multidimensional array can be expressed in terms of an array of pointers rather than a


pointer to a group of contiguous arrays. Each pointer will indicate the beginning of a
separate (n-1)-dimensional array.
In general terms, a two-dimensional array can be defined as a one-dimensional array of
pointers by writing
data-type *array[expression 1];
rather than the conventional array definition.
data-type array[expression1][expression2];
similarly, an n-dimensional array can be defined as an (n-1)-dimensional array of pointers
by writing
data-type *array[expression1][expression2]….[expression n-1];
rather than
data-type array[expression1][expression2]….[expression n];

In these declarations data-type refers to the data type of the original n-dimensional array,
array is the array name, and expression 1, expression 2,………expression n are positive
valued integer expressions that indicate the maximum number of elements associated
with each subscript.

61
Object Oriented Programming Using C++

Notice that the array name and its proceeding asterisk are not in closed in parentheses in
this type of declaration. Thus, a right to left rule first associates the pairs of square
brackets with array defining the named object as an array. The preceding asterisk than
establishes that the array will contain pointers.

Moreover, the last (i.e. the leftmost) expression is omitted when defining an array of
pointers, whereas the first (i.e. leftmost) expression is omitted when defining a pointer to
a group of arrays.

When an n-dimensional arrays is expressed in this manner, an individual array element


within the n-dimensional array can be accessed by a single use of the indirection
operator.

e.g. Suppose x is a two dimensional integer array having 10 rows and 20 columns, we can
define x as a one dimensional array of pointers of writing.
i n t * x [10]
Hence x [0] points to the beginning of the first row, x[1] points to the beginning of the
second row and so on .note that the number of elements within each is not explicitly
specified.

X [0] 1st one-dimensional array

X [1] 2nd one -dimensional array

X [2] 3rd one -dimensional array

(X [2]+ 5)
*(X [2] + 5)

X [9] 10th one -dimensional array

An individual array element, such as x [2][5] can be accessed by writing


*(X [2] + 5)

In this expression x[2] is a pointer to the first element in a row 2, so that (x[2]+5) points
to element 5 (actually , the sixth element ) within row 2. The object of this pointer
*(x[2]+5) therefore refers to x[2][5].

62
Object Oriented Programming Using C++

Now consider a three dimensional floating point array t. Suppose the dimensionality of t
is 10 * 20 * 30. This array can be expressed as a two dimensional array of pointers by
writing
float *t [10][20];

Therefore we have 200 pointer (10 rows, 20columns), each pointing to one-dimensional
array.
An individual array element such as t[2][3][5], can be accessed by writing
*(t [2][3] +5)

In this expression t[2][3] is a pointer to the first element in the one dimensional array
represented t[2][3]. Hence (t[2][3] +5) points to element 5 (the sixth element) within this
array. The object of this pointer, *(t[2][3] +5), therefore represented t[2][3][5].

Passing Functions To Other Functions

A pointer to a function can be passed to another function as an argument. This allows one
function to be transferred to another, as though the first function were a variable. Let us
refer to the first function as the guest function, and the second function as the host
function. Thus, the guest is passed to the host, where it can be accessed. Successive calls
to the host function can pass different pointers (i.e., different guest functions) to the host.

When a host function accepts the name of a guest function as an argument, the formal
argument declaration must identify that argument as a pointer to the guest function. In its
simplest form, the formal argument declaration can be written as
data-type (*function-name)()
where data-type refers to the data type of the quantity returned by the guest and function-
name is the name of the guest. The formal argument declaration can also be written as
data-type (*function-name)(type1, type2,…….)
or as
data-type (*function-name)(type1 arg1, type2 arg2,…….)
where type1, type2,….. refer to the data types of the arguments associated with the guest,
and arg1, arg2,…refers to the name of the arguments associated with the guest.

The guest function can be accessed within the host by means of the indirection operator.
To do so, the indirection operator must precede the guest function name (i.e., the formal
argument). Both the indirection operator and the guest function name must be enclosed in
parentheses; i.e.,
(*function-name)(argument1, argument2, …., argument n);
Where argument1, argument 2, ………, argument n refer to the arguments that are
required in the function call.

Now consider the function declaration for the host function. It may be written as
funct-data-type funct-name(arg-data-type (*)(type1, type2,….), data types of other funct
|-----pointer to guest function -----|

63
Object Oriented Programming Using C++

args);
where funct-data-type refers to the data type of the quantity returned by the host function;
funct-name refers to the name of the host function; arg-data-type refers to the data type of
the quantity returned by the guest function, and type1, type2,….. refer to the data types of
guest function’s arguments. Notice that the indirection operator appears in parentheses, to
indicate that they are function arguments.
When full function prototyping is used, the host function declaration is expanded as
follows:
funct-data-type funct-name(arg-data-type (*ptr-var)(type1 arg1, type2 arg2,…..….),
|-----pointer to guest function -----|
data types of other funct args);

The notation is the same as above, except that pt-var refers to the pointer variables
pointing to the guest function, and type1 arg1, type2 arg2,…. refer to the data types and
the corresponding names of the guest function’s argument.

More About Pointer Declarations

One difficulty is the dual use of parentheses. In particular, parentheses are used to
indicate functions, and they are used for nesting purposes (to establish precedence) within
more complicated declarations. Thus, the declaration
int *p(int a);
indicates a function that accepts an integer argument, and returns a pointer to an integer.
On the other hand, the declaration
int *p(int a);
indicates a pointer to a function that accepts an integer argument and returns an integer.
In this last declaration, the first pair of parentheses is used for nesting, and the second
pair is used to indicate a function.
The interpretation of more complex declarations can be increasingly troublesome. For
example, consider the declaration
int *(*p)(int (*a)[]);
In this declaration, (*p)(…..) indicates a pointer to a function. Hence int *(*p) (…….)
indicates a pointer to a function that returns a pointer to an integer within the last pair of
parentheses (the functions argument specification ), (*a) [] indicates a pointer to an array.
Therefore, int(*a)[] represents a pointer to an array of integers. Putting the pieces
together, (*p) (int (*a)[]) represents a pointer to a function whose argument is a pointer to
an array of integers. And finally, the entire declaration
int *(*p) (iunt (*a)[]);
represents a pointer to a function that accepts a pointer to an array of integers as an
argument, and returns a pointer to an integer.

Remember that a left parenthesis immediately following an identifier name indicates that
the identifier represents a function. Similarly, a left square bracket immediately following
an identifier name indicates that the identifier represents an array. Parentheses that
identify functions and square brackets that identify arrays have a higher precedence than

64
Object Oriented Programming Using C++

the unary indirection operation. Therefore, additional parentheses are required when
declaring a pointer to a function or a pointer to an array.

Several declarations involving pointer are shown below.

int *p; // p is a pointer to an integer quantity

int *p[10]; // p is a 10 element array of pointer to integer quantities

int (*p)[10]; // p is a pointer to a 10 element integer array

int *p(void); // p is a function that returns a pointer to an integer quantity

int p(char *a); /* p is a function that accepts an argument which is a pointer to a


character and returns an integer quantity */

int *p(char a*); /* p is a function that accepts an argument which is a pointer to a


character returns a pointer to an integer quantity */

int (*p) (char *a); /* p is a function that accepts an argument which is a pointer to a
character and returns an integer quantity */

int (*p(char *a))[10]; /* p is a function that accepts an argument which is a pointer to a


character and returns a pointer to a 10-element integer array */

int p(char (*a)[]); /* p is a function that accepts an argument which is an array of


pointers to characters returns an integer quantity */

int *p (char a []); /*p is a function that accept an argument which is a character array
returns a pointer to an integer quantity */

int *p (char (*a) []); /*p is a function that accepts an argument which is a pointer to a
character array returns a pointer to an integer quantity */

int *p (char *a []); /*p is a function that accepts an argument which is an array of
pointers to characters returns a pointer to an integer quantity */

int (*p)(char(*a)[]); /*p is a pointer to a function that accepts an argument which is a


pointer to a character array returns an integer quantity */

int *(*p) (char (*a) []); /*p is a pointer to a function that accepts an argument which is a
pointer to a character array returns a pointer to an integer quantity */

int *(*p)(char *a[]); /*p is a pointer to a function that accepts an argument which is an
array of pointers to characters returns a pointer to an integer
quantity */

65
Object Oriented Programming Using C++

int (*p[10])(void); / * p is a 10 element array of pointers to functions; each function


returns an integer quantity */

int (*p[10])(char a); / * p is a 10 element array of pointers to functions; each function


accepts an argument which is a character, and returns an integer
quantity */

int *(*p[10])(char a); /* p is a 10 element array of pointers to functions; each function


accepts an argument which is a character, and returns a pointer to
an integer quantity */

int *(*p[10])(char *a); /* p is a 10 element array of pointers to functions; each


function
accepts an argument which is a pointer to a character, and returns a
pointer to an integer quantity */

Operators new and new[ ]

In order to request dynamic memory, the operator new exists. new is followed by a data
type and optionally the number of elements required within brackets []. It returns a
pointer to the beginning of the new block of assigned memory. Its form is:

pointer = new type

or

pointer = new type [elements]

The first expression is used to assign memory to contain one single element of type. The
second one is used to assign a block (an array) of elements of type.
For example:

int * bobby;
bobby = new int [5];

in this case, the operating system has assigned space for 5 elements of type int in a heap
and it has returned a pointer to its beginning that has been assigned to bobby. Therefore,
now, bobby points to a valid block of memory with space for 5 int elements.

66
Object Oriented Programming Using C++

You could ask what is the difference between declaring a normal array and assigning
memory to a pointer as we have just done. The most important one is that the size of an
array must be a constant value, which limits its size to what we decide at the moment of
designing the program before its execution, whereas the dynamic memory allocation
allows assigning memory during the execution of the program using any variable,
constant or combination of both as size.

The dynamic memory is generally managed by the operating system, and in multitask
interfaces it can be shared between several applications, so there is a possibility that the
memory exhausts. If this happens and the operating system cannot assign the memory
that we request with the operator new, a null pointer will be returned. For that reason it is
recommended to always check to see if the returned pointer is null after a call to new.

int * bobby;
bobby = new int [5];
if (bobby == NULL) {
// error assigning memory. Take measures.
};

Operator delete.

Since the necessity of dynamic memory is usually limited to concrete moments within a
program, once it is no longer needed it should be freed so that it becomes available for
future requests of dynamic memory. The operator delete exists for this purpose, whose
form is:

delete pointer;

or

delete [] pointer;

The first expression should be used to delete memory alloccated for a single element, and
the second one for memory allocated for multiple elements (arrays). In most compilers
both expressions are equivalent and can be used without distinction, although indeed they
are two different operators and so must be considered for operator overloading (we will
see that on section 4.2).
How many numbers do you want to type
// rememb-o-matic in? 5
Enter number : 75
#include <iostream.h> Enter number : 436
Enter number : 1067
#include <stdlib.h> Enter number : 8
Enter number : 32
You have entered: 75, 436, 1067, 8, 32,

67
Object Oriented Programming Using C++

int main ()

char input [100];

int i,n;

long * l;

cout << "How many numbers do you


want to type in? ";

cin.getline (input,100); i=atoi (input);

l= new long[i];

if (l == NULL) exit (1);

for (n=0; n<i; n++)

cout << "Enter number: ";

cin.getline (input,100); l[n]=atol


(input);

cout << "You have entered: ";

for (n=0; n<i; n++)

cout << l[n] << ", ";

delete[] l;

return 0;

This simple example that memorizes numbers does not have a limited amount of numbers
that can be introduced, thanks to us requesting to the system to provide as much space as
is necessary to store all the numbers that the user wishes to introduce.

68
Object Oriented Programming Using C++

NULL is a constant value defined in manyfold C++ libraries specially designed to


indicate null pointers. In case that this constant is not defined you can do it yourself by
defining it to 0:

#define NULL 0

It is indifferent to put 0 or NULL when checking pointers, but the use of NULL with
pointers is widely extended and it is recommended for greater legibility. The reason is
that a pointer is rarely compared or set directly to a numerical literal constant except
precisely number 0, and this way this action is symbolically masked

Dynamic Memory Allocation in C++

C++ provides the new and delete operators for memory allocation, instead of using
C's malloc and free functions. They cannot be interchanged with each other. For
example, it's not possible to free memory allocated by malloc with delete, and it's
not possible to delete memory allocated by new with the free function.

Allocating Memory

Memory allocation is achieved using the new operator. The following allocates
memory for one an integer, and sets the initial value to 42.

newint.cpp

#include <iostream.h>

int main()

int *iPtr;

iPtr = new int(42);

cout << *iPtr << endl;

// Free the memory

delete iPtr;

return 0;

69
Object Oriented Programming Using C++

The memory allocated with new is released using the delete keyword.

Allocating Memory for Arrays

When allocating memory for an array, the size of the array is specified within
square brackets using the new operator. The next example allocates memory for
five integers.

fiveint.cpp

#include <iostream.h>

int main()

int *iPtr;

iPtr = new int[5];

// Initialise the array

for (int counter=0; counter<5; counter++)

iPtr[counter] = 0;

// Free the memory

delete [] iPtr;

return 0;

When deleting an array, the [] token must prefix the array name to delete. When
allocating arrays, it's a good idea to check that it was successful. If the memory is
unable to be allocated, new returns a NULL value.

70
Object Oriented Programming Using C++

checkmem.cpp

#include <iostream.h>

int main()

double *dPtr;

if ((dPtr = new double[5000000]) == NULL)

cout << "Not enough memory!\n";

else

cout << "Memory allocated successfully\n";

delete [] dPtr;

return 0;

CLASSES

Classes
A class in C++ is a collection of some functions and the data on which they operate. In C,
as structure is a collection of various types of data, in C++ a class is a collection of data
and member functions required for their input, processing and output. The functions and
the data on which they operate are grouped together and given a name. This is known as a
class. It allows the data (and functions) to be hidden, if necessary, from external use.
When defining a class, we are creating a new abstract data type that can be treated like
any other built-in data type.
Declration Of A Class

A class can be declared as given below:


class cl_name
{
private :

71
Object Oriented Programming Using C++

data_type var1;
data_type var2;
……………..
……………..
public :
data_type m_function1();
data_type m_function2();
…………………………
…………………………
};
Where
cl_name – is the name of the class
data_type – is the type of data
var_1, var2 are the names of the variables
m_function1(), m_function2() are the member functions

The class declaration starts with the keyword class followed by the class name. Then are
declared the variable which form the data and the data type for each. The member
functions for processing the data are also declared along with return type for each. The
class declaration ends with the closing brace (}) followed by the semi-colon. There are
two more key words inside the class declaration – private and public. The data or the
member functions which follow the keyword private (with a colon(:) thereafter) cannot
be accessed from outside the class. They can be accessed by some member functions
from within the class. Data or member functions declared as public (with a colon(:)
thereafter) can however be accessed from outside the class. By default data is always
private and member functions are public. Even then it is recommended to explicitly
specify the private and public members in a class. This is a result of how classes are used.
The data is hidden so it will be safe from accidental manipulation, while the functions
that operate on the data are public so they can be accessed from outside the class.
However, there is no rule that data must be private and functions public; in some
circumstances there is a need to use private functions and public data.

Eg. Suppose we want to read the side of a triangle, evaluate it’s area and display the
result. We can declare a class as given below
class triangle
{
private:

72
Object Oriented Programming Using C++

float side1;
float side2;
float side3;
float area;
public:
void read_data();
void area_triangle();
void display();
};

It declares a class named triangle. The data consists of side1, side2, side3, the side of the
triangle and its area, all declared private. The member function include read_data() to
read information, area_tringle() to evaluate it’s area and display() to show any
information. Note that we can not assign value to variables side1, side2, side3 by means
other than the function read_data(). Member function area_triangle() has been planned
to evaluate area assign value to variable area. The information about the triangle can be
obtained only through member function display().

Objects in C++
Object represents the basic run – time entity in an object-oriented system; they occupy
space in memory that keeps its state and is operated on by the defined operations on the
object. Each object when created gets a private copy of the instance variables, and when
an operation defined on the class is performed on the object, it is performed on the state
of the particular object.
When program is executed, the objects interact by sending message passing to one
another. Each object contains data, and code to manipulate the data. Objects can interact
without having to know details of each other’s data or code. The figure below shows the
notation of object oriented analysis and design.

Object: Account

DATA
side1
side2
side3
area

FUNCTION
read_data ()
area_triangle()
display()

In the above section we declared a class named triangle. Each member of this class will
consist of four real number to store three sides and the area of the triangle. In addition to

73
Object Oriented Programming Using C++

data we will declare three member function of process the data. Declaration of a class, as
in case of declaration of a structure does not allocate any memory for storing data. It just
defines a combination of a data and member function, which will be grouped together.
An object in C++ define combination of data and member function which conform to the
definition of a class. We have defined above a class named triangle. Suppose ABC and
PQR are two triangles. Each of them will have three sides and an area. They will be using
member function read _data(), area _triangle() and display() declared in the class
definition. Both ABC and PQR are objects belonging to class triangle. The syntax of
declaring objects is as under:

class cl _name obj1, obj_2,…………


Where
cl _name is the of the class
obj_1,obj_2 are the names of the objects

The following is valid declaration of object


class triangle ABC, PQR;

Definition of Member Functions in a Class


Eg. Suppose it is required to assign the values of 10 and 13 to the X and Y coordinates of
a point and display the same.
class point
{
private:
int x;
int y;
public:
void getxy (int x_cord, int y_cord);
void showxy();
};
Here the member functions getxy() and shoxy() have been incorporated as member
functions of the class.
The member functions can be declared in two ways:
i) outside the class definition
ii) inside the class definition
Irrespective of the place of definition, the function should perform the same task.
Therefore, the code for the function body would be identical in both the cases.

74
Object Oriented Programming Using C++

Outside the Class Definition


Member functions that are declared inside a class have to be defined separately outside
the class. Their definitions are very much like the normal functions. They should have a
function header and a function body.
An important difference between a member function and a normal function is that a
member function incorporates a membership ‘identity label’ in the header. This ‘label’
tells the compiler which class the function belongs to. The general form of a member
function definition is :
return-type class-name :: function-name (argument declaration)
{
Function body
}
The membership label class-name :: tells the compiler that the function function-name
belongs to the class class-name. That is, the scope of the function is restricted to the
class-name specified in the header line. The symbol :: is called the scope resolution
operator.

Eg.
class point
{
private:
int x;
int y;
public:
void getxy (int x_cord, int y_cord);
void showxy();
};
// member functions defined outside the class definition
void point :: getxy (int x_cord, int y_cord)
{
x = x_cord;
y = y_cord;
}

75
Object Oriented Programming Using C++

void point :: showxy()


{
cout << “ X coordinate – “ << x << endl;
cout << “ Y coordinate – “ << y << endl;
}
Since these functions do not return any value, their return type is void.
The member functions have some special characteristics that are often used in the
program development. These characteristics are:
• Several different classes can use the same function name. The ‘membership label’
will resolve their scope.
• Member functions can access the private data of the class. A non-member
function cannot do so. (However, an exception to this rule is a friend function).
• A member function can call another member function directly, without using the
dot operator.
Inside the Class Definition
Another method of defining a member function is to replace the function declaration by
the actual function definition inside the class. Small functions may be defined inside the
class definition.
Eg.
class point
{
private:
int x;
int y;
public:
void getxy (int x_cord, int y_cord)
{
x = x_cord;
y = y_cord;
}
void showxy()
{

76
Object Oriented Programming Using C++

cout << “ X coordinate – “ << x << endl;


cout << “ Y coordinate – “ << y << endl;
}
};
Note that as the member functions are defined inside the class definition, there are no
semicolons after the function definitions.
When a function is defined inside a class, it is treated as an inline function.
Eg.
#include <iostream.h>
class point
{
private:
int x;
int y;
public:
void getxy (int x_cord, int y_cord)
{
x = x_cord;
y = y_cord;
}
void showxy();
}; // end of class
void point :: showxy()
{
cout << “ X coordinate – “ << x << endl;
cout << “ Y coordinate – “ << y << endl;
}
void main()
{
point p;

77
Object Oriented Programming Using C++

point q;
p.getxy(10,12);
p.showxy();
q.getxy(15,25);
q.showxy();
} //end of main
This program features the class point. This class contains two private variables and two
public functions. The member function getxy() has been defined inside the class and
therefore behaves like an inline function. This function supplies values to both the
variables.
x = x_cord;
in the function definition of getxy(). This shows that the member functions can have
direct access to private data items. The member function showxy() displays the values of
the private variables x and y.
The program creates two objects, p and q in two different statements. This can be
combined in one statement.
point p, q;

Here is the output of program


Object p
X coordinate – 10
Y coordinate – 12

Object q
X coordinate – 15
Y coordinate – 25
Making an Outside Function Inline
We can define a member function outside the class definition and still make it inline by
just using the qualifier inline in the header line of function definition. Example:
class point
{
……………….

78
Object Oriented Programming Using C++

………………
public :
void getxy(int x_cord, int y_cord); //declaration
};

inline void point :: getxy(int x_cord, int y_cord) //definition


{
x = x_cord;
y = y_cord;
}

Constructors

Suppose it is required to read a number and test if it is a prime number. Suppose there is a
class to store integer numbers n (number to be tested) and prime (to be assigned the
value of 1 if n is prime and 0 otherwise). Lets initialize prime with 1 which will be
updated to 0 if number n happens to be divisible by any other than 1 and n.

class anynumber
{
private :
int n;
int prime = 1; //this is illegal
public :
void getno(int k)
{ n = k; }
void isprime();
void display();
};

The above declaration is illegal. You cannot initialize a data member of a class inside the
class declaration. The declaration int prime = 1 is illegal. Data members in a class can be
initialized through a special type of function known as constructor.

C++ provides a special member function called the constructor which enables an object
to initialize itself when it is created. This is known as automatic initialization of objects.
It also provides another member function called the destructor that destroys the objects
when they are no longer required.

A constructor is a ‘special’ member function whose task is to initialize the objects of its
class. It is special because its anme is the same as the class name. The constructor is

79
Object Oriented Programming Using C++

invoked whenever an object of its associated class is created. It is called constructor


because it constructs the values of data members of the class. The only restriction on a
constructor is that it cannot return a value.

//class with a constructor


class point
{
private :
int x, y;
public :
point (void); // constructor declared
…………..
………….
};
point :: point (void) // constructor defined
{
x = 0;
y = 0;
}

When a class contains a constructor like the one defined above, it is guaranteed that an
object created by the class will be initialized automatically. For example
point p1; //object p1 created
not only creates the object p1 of type point but also initializes its data members x and y
to zero. There is no need to write to any statement to invoke the constructor function (as
we do with the normal functions). If a ‘normal’ member function is defined for zero
initialization, we would need to invoke this function for each of the objects separately.

A constructor that accepts no parameters is called default constructor. The default


constructor for class A is A::A() .

The constructor functions have some special characteristics. These are :


• They should be declared in public section.
• They are invoked automatically when the objects are created.
• They do not have return types, not even void and therefore, and they cannot return
values.
• They cannot be inherited, though a derived class can call the base class
constructor.
• Like other C++ functions, they can have default arguments.
• Constructors cannot be virtual.
• We cannot refer to their addresses.
• An object with a constructor (or destructor) cannot be used as a member of a
union.
• They make ‘implicit calls’ to the operators new and delete when memory
allocation is required.

80
Object Oriented Programming Using C++

Constructors With Arguments

The constructors that can take arguments are called parameterized constructors.

Example :

class student
{
private:
int roll_no;
char name[30];
int age;
public :
student (int x, int y); // constructor declared
};
student :: student (int x, int y)
{
roll_no = x;
age = y;
}

Objects of such classes having parameterized constructors can be created with an


implicit/explicit call to constructors.

Eg..
student s1 = student(3, 17); // explicit call
student s1(3, 17); // implicit call

Remember, when the constructor is parameterized, we must provide appropriate


arguments for the constructor.

Multiple Constructors in A Class

C++ allows us to declare multiple constructors inside a class.


point (); // no arguments
point(int, int) // two arguments

In the first case, the constructor itself supplies the data values and no values are passed by
the calling program. In the second case, the function call passes the appropriate values
from main(). C++ permits us to use both these constructors in the same class. For
example,

class num
{
private :
int m, n;

81
Object Oriented Programming Using C++

public :
num() // constructor1
{
m = 0;
n = 0;
}
num (int a, int b) // constructor 2
{
m =a;
n =b;
}
num (num &i) // constructor 3
{
m = i.m; // passing object as an argument
n = i.n;
}
};

The process of sharing the same name by two or more functions is referred to as function
overloading. Similarly, defining more than one constructor is known as constructor
overloading. Either of these constructors may be called explicitly/implicitly when
creating an object.

Example:
num n1; // will call constructor1
num n2 (5,6); // will call constructor 2
num n3(n2); // will call constructor 3

Constructor 3 copies the values of n2 into n3. In other words, it sets the value of every
data element of n3 to the value of the corresponding data element of n2. Such a
constructor is called copy constructor.
When defining multiple constructors in a class, we must also define the “do-nothing”
implicit constructor such as
Num() { };
This constructor will do nothing and is defined just to satisfy the compiler.

Constructors with Default Arguments

It is possible to define constructors with default arguments. For example, the constructor
point() can be declared as follows:
point (int x, int y = 0);
The default value of the argument y is zero. Then the statement
point P(7);
assigns the value 7 to the x variable and 0 to y (by default). However, the statement
point P(5 , 7);

82
Object Oriented Programming Using C++

assigns 5 to x and 7 to the y. The actual parameter, when specified, overrides the default
value.

It is important to distinguish between the default constructor A::A() and the default
argument constructor A::A(int x = 0). The default argument constructor can be called
with either one argument or no arguments. When called with no arguments, it becomes a
default constructor.

Copy Constructor

We used the copy constructor


num(int &i);
as one of the overloaded constructors.

A copy constructor is used to declare and initialize an object from another object. For
example, the statement
num n2(n1);
would define the object n2 and at the same time initialize it to the value of n1. Another
form of this statement is
num n2 = n1;
The process of initializing through a copy constructor is known as copy initialization.
Statement
n2 = n1;
will not invoke the copy constructor. If n1 and n2 are objects, this statement is legal and
simply assigns the values of n1 to n2, member by member. This is the task of the
overloaded assignment operator.

Example:
#include<iostream.h>
class code
{
private :
int id;
public :
code() { };
code (int a) { id = a}
code (code &x) { id = x.id}

void display()
{ cout << id; }
};
void main()
{
code A(100); // object A is created and initialized
code B(A); // copy constructor called
code C = A; // copy constructor called again

83
Object Oriented Programming Using C++

code D; // D is created but not initialized


D = A; // A is copied over D but constructor is not called

cout << “\n id of A = “;


A.display();
cout << “\n id of B = “;
B.display();
cout << “\n id of C = “;
C.display();
cout << “\n id of D = “;
D.display();
}

Destructors

A destructor is used to destroy the objects that have been created by a constructor. Like a
constructor, the destructor is a member function whose name is the same as the class
name but is preceded by a tilde(~).

Eg.
classname :: ~classname(){ }

A destructor never takes any argument nor does it return any value. It will be invoked
implicitly by the compiler upon exit from the program to clear up the storage that is no
longer accessible. If new is used to allocate memory in the constructor then we should
use delete to free that memory.

Example
matrix :: ~ matrix()
{
for( int i = 0; i < n; i++)
delete p[i];
delete p;
}

If you don’t do so, your program may fail to call the destructor.

Friend Function

Private data can be accessed by member functions of a class. However, some times it is
required that a function which is not a member of the class should have access to private
data. This is possible by defining the non-member function as a friend function. A friend
function will have access to all private and protected members of the class of which it is
a friend. To declare a friend function it is required to write the prototype of the function
within the class with the keyword friend preceding the function prototype.

84
Object Oriented Programming Using C++

class ABC
{
private:
…………..
…………..
public:
…………..
…………..
friend void xyz(); // declaation
};

The function declaration should be preceded by the keyword friend. The function is
defined elsewhere in the program like a normal C++ function. The function definition
does not use either the keyword friend or the scope resolution ::. The functions that are
declared with the keyword friend are known as friend functions. A function can be
declared as a friend in any number of classes. A friend function, although not a member
function, has full access rights to the private members of the class.

A friend function possesses certain special characteristics:


• It is not in the scope of the class to which it has been declared as friend.
• Since it is not in the scope of the class, it cannot be called using the object of that
class.
• It can be invoked like a normal function without the help of any object.
• Unlike member functions, it cannot access the member names directly and has to
use an object name and dot membership operator with each member name (e.g.
A.x).
• It can be declared either in the public or the private part of a class without
affecting its meaning.
• Usually, it has the object as arguments.

Example:
#include<iostream.h>
class sample
{
private:
int a, b;
public:
void setvalue()
{ a = 25;
b = 40; }

friend float mean(sample s);


};

float mean(sample s)
{

85
Object Oriented Programming Using C++

return float(s.a + s.b)/2.0;


}

Void main()
{
sample X;
X.setvalue();
cout << “Mean value = “ << mean(X) ;
}

Output

Mean value = 32.5

The friend function accesses the class variable a and b by using the dot operator and the
object passed to it. The function call mean(X) passes the object X by value to the friend
function.

Forward reference for declaration of friend function

Suppose a rectangular field measures 15 * 12 m2 with a circle of radius 5 m at its center.


It is required to find the area of the field outside the circle.

Suppose there are two classes rectangle and circle to evaluate the area of the figures. We
have to define a friend function (rest()) which will have access to the areas of both the
figures.

class circle
{
private:
float r, ar;
public :
circle (float x)
{
r = x;
ar = PIE * r * r;
}
friend float rest(rectangle R, circle C);
};

class rectangle
{
private:
float l, b, ar;
public:
rectangle(float x, float y)

86
Object Oriented Programming Using C++

{
l = x;
b = y;
ar = I * b;
}
friend float rest (rectangle R, circle C);
};

The program will fail to compile as, in class circle we have defined friend function as :
friend float rest (rectangle R, circle C);
We have, as yet, not defined class rectangle. This leads to an error. The problem will not
be solved by declaring rectangle before circle as the friend function needs to be declared
in both the classes. The problem is solved by what is known as foreward reference in
C++.

#include <iostreamh>
#define PIE 3.14159
class rectangle; //forward reference

class circle
{
private:
float r, ar;
public :
circle (float x)
{
r = x;
ar = PIE * r * r;
}
friend float rest(rectangle R, circle C);
};

class rectangle
{
private:
float l, b, ar;
public:
rectangle(float x, float y)
{
l = x;
b = y;
ar = I * b;
}
friend float rest (rectangle R, circle C);
};
float rest (rectangle R, circle C)

87
Object Oriented Programming Using C++

{
float a;
a=R.ar – C.ar;
return(a);
}

void main()
{
Float a;
Circle C(5);
Rectangle R(12, 15);
a = rest(R, C);
cout << “Area of the lawn = “ <<a;
}

Member function of one class as friend of another

Member function of one class can be friend functions of another class. In such cases they
are defined using the scope resolution operator as shown below:

class X
{
………………
………………
int fun1(); // member function of X
………………
};
class Y
{
………………
………………
friend int x :: fun1(); // fun1() of X is friend of Y
………………
};

The function fun1() is a member of class X and a friend of class Y.

Example
#include <iostreamh>
#define PIE 3.14159
class rectangle; //forward reference

class circle
{
private:
float r, ar;

88
Object Oriented Programming Using C++

public :
circle (float x)
{
r = x;
ar = PIE * r * r;
}
float rest(rectangle R, circle C);
};

class rectangle
{
private:
float l, b, ar;
public:
rectangle(float x, float y)
{
l = x;
b = y;
ar = I * b;
}
friend float circle :: rest(rectangle R);
};
float circle :: rest (rectangle R)
{
float a;
a=R.ar – ar;
return(a);
}

void main()
{
float a;
circle C(5);
rectangle R(12, 15);
a = C.rest(R);
cout << “Area of the lawn = “ <<a;
}

Friend Class

A class itself may be a friend of another class. In that case any function of the friend
class will have access to the private members if the other class.

In such cases, the class is called a friend class. This can be specified as follows:

89
Object Oriented Programming Using C++

class Z
{
………………
friend class X; // all member functions of X are friends to Z
};

Example:
#include <iostreamh>
#define PIE 3.14159
class circle
{
private:
float r, ar;
public :
circle (float x)
{
r = x;
ar = PIE * r * r;
}
friend class rectangle; // friend class declaration
};
class rectangle
{
private:
float l, b, ar;
public:
rectangle(float x, float y)
{
l = x;
b = y;
ar = l * b;
}
float diff(circle C)
{
float a;
a = ar – C.ar;
return(a);
}
};

void main()
{
float left;
circle C(5);
rectangle R(12, 15);
left = R.diff ( C );

90
Object Oriented Programming Using C++

cout << “Area of the lawn = “ <<left;;


}

Static Class Members

The data members and member functions in a class can also be declared as static.
Normally each object of a class have separate copies of all data members. But when a
variable is declared static, only one copy of the variable will be stored and all the objects
of the class will share the variable. When any statement is made to the static variable of
any object, the change is effective for all the objects of the class.

Example:

#include<iostream.h>
class twonos
{
private:
static int p;
int q;
public:
void setdata(int i, int j)
{
p = i;
q = j;
};
void show()
{
cout << “static int p = “ <<p<<endl;
cout <<”int q = “ << q;
}
};
void main()
{
twonos X, Y;
X.setdata(5, 6);
cout <<”In object X “ ;
X.show();
Y.setdata(8, 10);
cout <<”In object X “ ;
X.show();
cout <<”In object Y “ ;
Y.show();
}
A class twonos has two integer numbers as the data members, one of them name p is
declared static. Objects X and Y are two objects of this class. Numbers p and q in object

91
Object Oriented Programming Using C++

X are assigned values of 5 and 6 respectively. In object Y they are assigned respective
values of 8 and 10.

Output :

In object X
Static int p = 5
int q = 6

In object X
Static int p = 8
int q = 6

In object Y
Static int p = 8
int q = 10

Operator Overloading

C++ allows us to specify some new jobs for an already existing C++ operators. The
mechanism of giving some extra jobs to an operator is known as operator overloading.
Operator overloading provides a flexible option for the creation of new definitions for
most of the C++ operators. Almost all the operators can be overloaded in C++, except the
following:
i) Class member access operators (., .*)
ii) Scope resolution operator (::)
iii) Size operator (sizeof)
iv) Conditional operator (? :)

When an operator is overloaded, its original meaning is not lost. Although the semantics
of an operator can be extended, we cannot change its syntax, the grammatical rules that
govern its use such as the number of operands, precedence and associativity.

Defining Operator Overloading

The additional task of an operator can be specified with the help of a special function,
called operator function. The operator function must be a member of a class so that the
additional task of the operator is limited by the concerned class. The general form of an
operator function is :

return type classname :: operator op(arglist)


{
Function body // task defined
}

92
Object Oriented Programming Using C++

return type : is the type of value returned by the specified operation


op : is the operator being overloaded

The op is preceded by the keyword operator. Operator op is the function name.

Operator function must be either a non static member function or a friend function. The
two functions will be treated differently. A friend function will have one argument for
unary operators and two for binary operators, while a member function has no arguments
for unary operators. This is because the object used to invoke the member function is
passed implicitly and therefore is available for the member function. This is not the case
with friend function. Arguments may be passed either by value or by reference. Operator
functions are declared in the class using prototypes as follows:

vector operator+(vector); // vector addition


vector operator-(vector); // unary minus
friend vector operator+(vector, vector); // vector addition
friend vector operator-(vector); // vector minus
int operator ==(vector); // comparison
friend int operator==(vector, vector) // comparison

Vector is a data type of class and may represent both magnitude and direction.

The process of overloading involves the following steps:


1. Create a class that defines the data type that is to be used in overloading
operation.
2. Declare the operator function operator op() in the public part of the class. It may
be either a member function of a friend function
3. Define the operator function to implement the required operations.

Overloaded operator functions can be invoked by expressions such as


op x or x op
for unary operators and
x op y
for binary operators. op x (or x op) would be interpreted as
operator op (x)
for friend functions. Similarly, the expression x op y would be interpreted as either
x.operator op(y)
in case of member functions, or
operator op(x, y)
in case of friend functions. When both the forms are declared, standard argument
matching is applied to resolve any ambiguity.

93
Object Oriented Programming Using C++

Overloading Unary Operators

A unary operator is one which operates on a single operand.

Example : overloading unary minus

#include <iostream.h>

class space
{
private:
int x, y, z;
public:
void getdata(int a, int b, int c);
void display();
void operator–(); //overload unary minus
};
void space :: getdata(int a, int b, int c)
{
x = a;
y = b;
z = c;
}
void space :: display()
{
cout << x ;
cout << y;
cout << z;
}

void space :: operator–()


{
x = -x;
y = -y;
z = -z;
}

void main()
{
space S;
S.getdata(10, -20, 30);
cout << “S : “;
S.display();

-S; // activates operator-() function

94
Object Oriented Programming Using C++

cout << “S : “;
S.display();
}

Output :

S : 10 -20 30
S : -10 20 -30

The function operator –() takes no argument. It changes the sign of data members of the
object S. Since this function is a member function of the same class, it can directly access
the members of the object which activated it.

Statement S2 = -S1 will not work, the function operator –() does not return any
value. It can work if the function is modified to return an object.

Using friend function

friend void operator –(space &s); // declaration

void operator –(space &s) // definition


{
s.x = -s.x;
s.y = -s.y;
s.z = -s.z;
}

Here the argument is passed by reference. It will not work if we pass argument by value
because only a copy of the object that activated the call is passed to operator –().
Therefore, the changes made inside the operator function will not reflect in the called
object.

Overloading Binary Operaotrs

Binary operators can be used to add (+), subtract (-), multiply (*) and divide (/) the
objects. When we use binary operator for overloading it takes first argument (A)
internally, and passes second argument (B) as an argument and return a value to store in
C, where C may be object as well as a data member/ variable. If we use binary operator
function as friend function; it takes two arguments.

Example : overload + operator

#include<iostream.h>
class complex
{
private:

95
Object Oriented Programming Using C++

float x, y;
public:
complex() { }; //constructor 1
complex(float real, float imag) // constructor 2
{
x = real;
y = imag;
}
complex operator +(complex);
void display();
};

complex complex :: operator +(complex c)


{
complex temp; // temporary
temp.x = x + c.x; // these are
temp.y = y + c.y; // float additions
return(temp);
}
void complex :: display ()
{
cout << x << + j” << y ;
}

void main()
{
complex c1, c2, c3;
c1 = complex(2.5, 3.5);
c2 = complex(1.6, 2.7);
c3 = c1 + c2;

cout << “ C1 = “<<c1.display();


cout << “ C2 = “<<c2.display();
cout << “ C3 = “<<c3.display();
}

Output :

C1 : 2.5 + j3.5
C2 : 1.6 + j2.7
C3 : 4.1 + j6.2

Features of the overloaded function


1. It receives only one complex type argument explicitly.
2. It returns a complex type value.

96
Object Oriented Programming Using C++

3. It is a member function of complex.

The function is expected to add two complex values and return a complex value as the
result but receives only one value as argument. Where does the other value come from?
C3 = C1 + C2; // invokes operator +() function

INHERITANCE

Inheritance is one of the most powerful features of objected oriented programming. It


promotes software reusability by creating new base classes from existing classes. The
new classes created, in addition to some additional features over and above the
capabilities of the base class from which they are derived, posses all the attributes of the
base class.

When you derive a new class, it inherits all the attributes of the base class. You may
incorporate additional attributes into the new class. But you do not have to touch the
member functions of the base class. Each derived class itself becomes the base class for
creation of further derived classes. Thus it is possible to create class libraries. Software
groups can develop their own libraries and can use class libraries used by other groups.

The C++ classes can be reused in several ways. Once a class has been written and tested,
it can be adapted by other programmers to suit their requirements. This is basically done
by creating new classes, reusing the properties of the existing ones. The mechanism of
deriving a new class from an old one is called inheritance (or derivation). The old class
is referred to as the base class and the new one is called the derived class or subclass.

The derived class inherits some or all of the traits from the base class. A class can also
inherit properties from more than one class or from more than one level. A derived class
with only one base class, is called single inheritance and one with several base classes is
called multiple inheritance. The traits of one class may be inherited by more than one
class. This process is known as hierarchical inheritance. The mechanism of deriving a
class from another ‘derived class’ is known as multilevel inheritance.

97
Object Oriented Programming Using C++

A A B

Multiple Inheritance
B

Single Inheritance

A
A

B
B C D

Hierarchical Inheritance
C

Multileverl Inheritance

B C

Hybrid Inheritance

98
Object Oriented Programming Using C++

A derived class can be defined by specifying its relationship with the base class in
addition to its own details. The general form of defining a derived class is :

class derived-class-name : visibility-mode base-class-name


{
……………….. //
………………. . // members of derived class
……………….. //
};

The colon indicates that the derived-class-name is derived from the base-class-name. The
visibility mode is optional and, if present, may be either private or public. The default
visibility-mode is private. Visibility mode specifies whether the features of the base class
are privately derived or publicly derived.

Examples
class ABC : private XYZ // private derivation
{
Members of ABC
};

class ABC : public XYZ // public derivation


{
Members of ABC
};

class ABC : XYZ // [private derivation by default


{
Members of ABC
};

Points to Remember :

1. In private derivation, public members of base class becomes the private


members of the derived class.
class B class D : private B
{ {
int a; int d;
public : public:
int b, c; display();
getdata(); };
mul();
};

99
Object Oriented Programming Using C++

Class D

private :
int d;

int b, c;
getdata();
mul();

public:
display();

In public derivation, public members of a base class becomes the public members of the
derived class.
Class D

private :
int d;

public:
int b, c;
getdata();
mul();

display();

2. In each case, no private members of a base class is accessible to the derived class.

Example of Single Inheritance

#include <iostream.h>

class B
{
int a; // private : not inheritable
public : // public : ready for inheritance
int b;
void get_ab();
int get_a();
void show_a();

100
Object Oriented Programming Using C++

};

class D : public B
{
int c;
public :
void mul();
void display();
};

void B :: get_ab()
{ a = 5; b = 10; }

int B :: get_a()
{ return a; }

void B :: show_a()
{ cout << “a = “ << a; }

void D :: mul()
{ c = b * get_a(); }

void D :: display()
{
cout <<” a = “ << get_a;
cout <<” b = “ << b;
cout <<” c = “ << c;
}

void main()
{
D d;
d.get_ab();
d.mul();
d.show_a();
d.display();

d.b = 20;
d.mul();
d.display();
}

Output :

A=5 a=5 b = 10 c = 50
A=5 b = 20 c = 100

101
Object Oriented Programming Using C++

The class D is a public derivation of the base class B. Therefore, D inherits all the
public members of B and retians their visibility. Thus a public member of the base
class B is also a public member of the derived class D. The private members of B
cannot be inherited by D. The class D, in effect, will have more members than what
it contains at the time of declaration

Class D

private :
int c;

public:
int b;
get_ab();
get_a()
show_a();

mul();
display();

NOTE : Although the data member a is private in B and cannot be inherited, pbjects
of D are able to access it through an inherited member function of B.

Example : Single Inheritance : Private


#include <iostream.h>

class B
{
int a; // private : not inheritable
public : // public : ready for inheritance
int b;
void get_ab();
int get_a();
void show_a();
};

class D : private B // private derivation


{
int c;
public :
void mul();

102
Object Oriented Programming Using C++

void display();
};

void B :: get_ab()
{ cout << “Enter values for a and b : “;
cin >> a >> b; }

int B :: get_a()
{ return (a); }

void B :: show_a()
{ cout << “a = “ << a; }

void D :: mul() // ‘a’ cannot be used directly


{ c = b * get_a(); }

void D :: display()
{
show_a(); // outputs value of ‘a’
cout <<” b = “ << b;
cout <<” c = “ << c;
}

void main()
{
D d;
// d.getab() ; wont work
d.mul();
// d.show_a(); it wont work
d.display()’
// d.b = 20; it wont work, b has become private
d.mul();
d.display();
}

Output :
Enter values for a and b : 5 10
A=5 b = 10 c = 50
Enter values for a and b : 12 20
A = 12 b = 20 c = 240

Being private members of D, the members of B, get_ab() and show_a() can not be
accessed directly through main().

103
Object Oriented Programming Using C++

Class D

private :
int c;

int b;
get_ab();
get_a()
show_a();

public:
mul();
display();

Making a Private Member Inheritable

A private member of a base class can be inherited when declared as protected. A


private member of a class when declared protected, it becomes accessible by the
member functions within its class and any class immediately derived from it. It
cannot be accessed by the functions outside these two classes. A class can now use all
the three visibility modes:

class alpha
{
private : //optional
………. // visible to member functions
………. // within its class
protected :
………. // visible to member functions
………. // of its own and derived class
public :
………. // visible to all functions
………. // in the program
};

When a protected member is inherited in public mode, it becomes protected in the


derived class too and therefore is accessible by the member functions of the derived
class. A protected member, inherited in the private mode derivation, becomes
private in the derived class. Although it is available to the member functions of the
derived class, it is not available for further inheritance (since private members
cannot be inherited).

104
Object Oriented Programming Using C++

Class B
not inheritable X X not inheritable
Private

Protected

Public
Class D2 : private B
Class D1 : public B Private
Private
Protected
Protected
Public
Public

Class X : public D1 : protected D2

Private

Protected

Public

The keywords private, protected, and public may appear in any order and any
number of times in the declaration of a class. For example

class beta
{
protected :
………….
public :
…………..
private :
………….
public :
…………..
};
is a valid class definition.

105
Object Oriented Programming Using C++

It is possible to inherit a base class in protected mode (known as protected


declaration). In protected derivation, both the public and protected members of the
base class become protected members of the derived class.

What are the various functions that can have access to these members? They could
be:
1. A function that is a friend of the class.
2. A member function of a class that is a friend of the class.
3. A member function of a derived class.

While the friend functions and the member functions of a friend class can have direct
access to both the private and protected data, the member functions of a derived class
can directly access only the protected data. However, they can access the private data
through the member functions of the base class.

Visibility of inherited members

Base Class Derived Class Visibility


Visibility
Public Private Protected
Derivation Derivation Derivation

Private Not inherited Not Inherited Not Inherited

Protected Protected Private Protected

Public public Private Protected

Multilevel Inheritance

Base Class A Grandfather

Intermediate B Father
Base Class

Derived Class C Child

106
Object Oriented Programming Using C++

In the above figure class A servers as a base class for the derived class B, which in turn
serves as a base class for the derived class C. The class B is known as intermediate
base class since it provides a link for the inheritance between A and C. The chain ABC is
known as inheritance path.

A derived class with multilevel inheritance is declared as follows:

class A { …………………. }; // Base class


class B : public A { ……….}; // B derived from A
class C : public B { ……….}; // C derived from B

This process can be extended to any number of levels;


Example
class student
{
protected:
int roll_number;
public :
void get_number(int);
void put_number();
};
void student :: get_number(int a)
{ roll_number = a; }
void student :: put_number()
{ cout << “roll number : “ << roll_number ; }

class test : public student // first level derivation


{
protected:
float sub1, sub2;
public :
void get_marks(float, float);
void put_marks();
}
void test :: get_marks(float x, float y)
{ sub1 = x ; sub2 = y ; }
void test :: put_marks()
{ cout << “Marks in sub1 = “ << sub1;
cout << “Marks in sub2 = “ << sub2; }

class result : public test // second level derivation


{ float total;
public :
void display();
};

107
Object Oriented Programming Using C++

Polymorphism

Before getting into this section, it is recommended that you have a proper understanding
of pointers and class inheritance. If any of the following statements seem strange to you,
you should review the indicated sections:

Statement: Explained in:


Int a::b(c) {}; Classes
a->b Pointers
class a: public b; Friendship and inheritance

Pointers to base class


One of the key features of derived classes is that a pointer to a derived class is type-
compatible with a pointer to its base class. Polymorphism is the art of taking advantage of
this simple but powerful and versatile feature, that brings Object Oriented Methodologies
to its full potential.

We are going to start by rewriting our program about the rectangle and the triangle of the
previous section taking into consideration this pointer compatibility property:

// pointers to base class 20

#include <iostream> 10

using namespace std;

class CPolygon {

protected:

int width, height;

public:

void set_values (int a, int b)

{ width=a; height=b; }

};

class CRectangle: public CPolygon {

108
Object Oriented Programming Using C++

public:

int area ()

{ return (width * height); }

};

class CTriangle: public CPolygon {

public:

int area ()

{ return (width * height / 2); }

};

int main () {

CRectangle rect;

CTriangle trgl;

CPolygon * ppoly1 = &rect;

CPolygon * ppoly2 = &trgl;

ppoly1->set_values (4,5);

ppoly2->set_values (4,5);

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

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

return 0;

In function main, we create two pointers that point to objects of class CPolygon (ppoly1
and ppoly2). Then we assign references to rect and trgl to these pointers, and because
both are objects of classes derived from CPolygon, both are valid assignations.

109
Object Oriented Programming Using C++

The only limitation in using *ppoly1 and *ppoly2 instead of rect and trgl is that both
*ppoly1 and *ppoly2 are of type CPolygon* and therefore we can only use these pointers
to refer to the members that CRectangle and CTriangle inherit from CPolygon. For that
reason when we call the area() members at the end of the program we have had to use
directly the objects rect and trgl instead of the pointers *ppoly1 and *ppoly2.

In order to use area() with the pointers to class CPolygon, this member should also have
been declared in the class CPolygon, and not only in its derived classes, but the problem
is that CRectangle and CTriangle implement different versions of area, therefore we
cannot implement it in the base class. This is when virtual members become handy:

Virtual members
A member of a class that can be redefined in its derived classes is known as a virtual
member. In order to declare a member of a class as virtual, we must precede its
declaration with the keyword virtual:

// virtual members 20

#include <iostream> 10

using namespace std; 0

class CPolygon {

protected:

int width, height;

public:

void set_values (int a, int b)

{ width=a; height=b; }

virtual int area ()

{ return (0); }

};

class CRectangle: public CPolygon {

public:

110
Object Oriented Programming Using C++

int area ()

{ return (width * height); }

};

class CTriangle: public CPolygon {

public:

int area ()

{ return (width * height / 2); }

};

int main () {

CRectangle rect;

CTriangle trgl;

CPolygon poly;

CPolygon * ppoly1 = &rect;

CPolygon * ppoly2 = &trgl;

CPolygon * ppoly3 = &poly;

ppoly1->set_values (4,5);

ppoly2->set_values (4,5);

ppoly3->set_values (4,5);

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

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

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

return 0;

111
Object Oriented Programming Using C++

Now the three classes (CPolygon, CRectangle and CTriangle) have all the same
members: width, height, set_values() and area().

The member function area() has been declared as virtual in the base class because it is
later redefined in each derived class. You can verify if you want that if you remove this
virtual keyword from the declaration of area() within CPolygon, and then you run the
program the result will be 0 for the three polygons instead of 20, 10 and 0. That is
because instead of calling the corresponding area() function for each object
(CRectangle::area(), CTriangle::area() and CPolygon::area(), respectively),
CPolygon::area() will be called in all cases since the calls are via a pointer whose type is
CPolygon*.

Therefore, what the virtual keyword does is to allow a member of a derived class with the
same name as one in the base class to be appropriately called from a pointer, and more
precisely when the type of the pointer is a pointer to the base class but is pointing to an
object of the derived class, as in the above example.

A class that declares or inherits a virtual function is called a polymorphic class.

Note that despite of its virtuality, we have also been able to declare an object of type
CPolygon and to call its own area() function, which always returns 0.

Abstract base classes


Abstract base classes are something very similar to our CPolygon class of our previous
example. The only difference is that in our previous example we have defined a valid
area() function with a minimal functionality for objects that were of class CPolygon (like
the object poly), whereas in an abstract base classes we could leave that area() member
function without implementation at all. This is done by appending =0 (equal to zero) to
the function declaration.

An abstract base CPolygon class could look like this:

// abstract class CPolygon

class CPolygon {

protected:

int width, height;

112
Object Oriented Programming Using C++

public:

void set_values (int a, int b)

{ width=a; height=b; }

virtual int area () =0;

};

Notice how we appended =0 to virtual int area () instead of specifying an implementation


for the function. This type of function is called a pure virtual function, and all classes that
contain at least one pure virtual function are abstract base classes.

The main difference between an abstract base class and a regular polymorphic class is
that because in abstract base classes at least one of its members lacks implementation we
cannot create instances (objects) of it.

But a class that cannot instantiate objects is not totally useless; We can create pointers to
it and take advantage of all its polymorphic abilities. Therefore a declaration like:

CPolygon poly;

would not be valid for the abstract base class we have just declared, because tries to
instantiate an object. Nevertheless, the following pointers:

CPolygon * ppoly1;

CPolygon * ppoly2;

would be perfectly valid.

This is so for as long as CPolygon includes a pure virtual function and therefore it's an
abstract base class. However, pointers to this abstract base class can be used to point to
objects of derived classes.

Here you have the complete example:

// abstract base class 20

113
Object Oriented Programming Using C++

#include <iostream> 10

using namespace std;

class CPolygon {

protected:

int width, height;

public:

void set_values (int a, int b)

{ width=a; height=b; }

virtual int area (void) =0;

};

class CRectangle: public CPolygon {

public:

int area (void)

{ return (width * height); }

};

class CTriangle: public CPolygon {

public:

int area (void)

{ return (width * height / 2); }

};

114
Object Oriented Programming Using C++

int main () {

CRectangle rect;

CTriangle trgl;

CPolygon * ppoly1 = &rect;

CPolygon * ppoly2 = &trgl;

ppoly1->set_values (4,5);

ppoly2->set_values (4,5);

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

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

return 0;

If you review the program you will notice that we refer to objects of different but related
classes using a unique type of pointer (CPolygon*). This can be tremendously useful. For
example, now we can create a function member of the abstract base class CPolygon that
is able to print on screen the result of the area() function even though CPolygon itself has
no implementation for this function:

// pure virtual members can be called 20

// from the abstract base class 10

#include <iostream>

using namespace std;

class CPolygon {

protected:

int width, height;

public:

115
Object Oriented Programming Using C++

void set_values (int a, int b)

{ width=a; height=b; }

virtual int area (void) =0;

void printarea (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 () {

CRectangle rect;

CTriangle trgl;

CPolygon * ppoly1 = &rect;

CPolygon * ppoly2 = &trgl;

116
Object Oriented Programming Using C++

ppoly1->set_values (4,5);

ppoly2->set_values (4,5);

ppoly1->printarea();

ppoly2->printarea();

return 0;

Virtual members and abstract classes grant C++ the polymorphic characteristics that
make object-oriented programming such a useful instrument in big projects. Of course,
we have seen very simple uses of these features, but these features can be applied to
arrays of objects or dynamically allocated objects.

Let's end with the same example again, but this time with objects that are dynamically
allocated:

// dynamic allocation and 20


polymorphism
10
#include <iostream>

using namespace std;

class CPolygon {

protected:

int width, height;

public:

void set_values (int a, int b)

{ width=a; height=b; }

virtual int area (void) =0;

void printarea (void)

117
Object Oriented Programming Using C++

{ 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 () {

CPolygon * ppoly1 = new


CRectangle;

CPolygon * ppoly2 = new CTriangle;

ppoly1->set_values (4,5);

ppoly2->set_values (4,5);

ppoly1->printarea();

ppoly2->printarea();

delete ppoly1;

delete ppoly2;

118
Object Oriented Programming Using C++

return 0;

Notice that the ppoly pointers:

CPolygon * ppoly1 = new CRectangle;

CPolygon * ppoly2 = new CTriangle;

are declared being of type pointer to CPolygon but the objects dynamically allocated
have been declared having the derived class type directly.

Input/Output with Files

C++ provides the following classes to perform output and input of characters to/from
files:

• ofstream: Stream class to write on files


• ifstream: Stream class to read from files
• fstream: Stream class to both read and write from/to files.

These classes are derived directly or indirectly from the classes istream, and ostream. We
have already used objects whose types were these classes: cin is an object of class istream
and cout is an object of class ostream. Therfore, we have already been using classes that
are related to our file streams. And in fact, we can use our file streams the same way we
are already used to use cin and cout, with the only difference that we have to associate
these streams with physical files. Let's see an example:

// basic file operations [file example.txt]

#include <iostream> Writing this to a file

#include <fstream>

using namespace std;

int main () {

119
Object Oriented Programming Using C++

ofstream myfile;

myfile.open ("example.txt");

myfile << "Writing this to a file.\n";

myfile.close();

return 0;

This code creates a file called example.txt and inserts a sentence into it in the same way
we are used to do with cout, but using the file stream myfile instead.

But let's go step by step:

Open a file

The first operation generally performed on an object of one of these classes is to associate
it to a real file. This procedure is known as to open a file. An open file is represented
within a program by a stream object (an instantiation of one of these classes, in the
previous example this was myfile) and any input or output operation performed on this
stream object will be applied to the physical file associated to it.

In order to open a file with a stream object we use its member function open():

open (filename, mode);

Where filename is a null-terminated character sequence of type const char * (the same
type that string literals have) representing the name of the file to be opened, and mode is
an optional parameter with a combination of the following flags:

ios::in Open for input operations.


ios::out Open for output operations.
ios::binary Open in binary mode.
Set the initial position at the end of the file.
ios::ate If this flag is not set to any value, the initial position is the beginning of the
file.
All output operations are performed at the end of the file, appending the
ios::app content to the current content of the file. This flag can only be used in streams
open for output-only operations.
If the file opened for output operations already existed before, its previous
ios::trunc
content is deleted and replaced by the new one.

120
Object Oriented Programming Using C++

All these flags can be combined using the bitwise operator OR (|). For example, if we
want to open the file example.bin in binary mode to add data we could do it by the
following call to member function open():

ofstream myfile;

myfile.open ("example.bin", ios::out | ios::app | ios::binary);

Each one of the open() member functions of the classes ofstream, ifstream and fstream
has a default mode that is used if the file is opened without a second argument:

class default mode parameter


ofstream ios::out
ifstream ios::in
fstream ios::in | ios::out

For ifstream and ofstream classes, ios::in and ios::out are automatically and respectivelly
assumed, even if a mode that does not include them is passed as second argument to the
open() member function.

The default value is only applied if the function is called without specifying any value for
the mode parameter. If the function is called with any value in that parameter the default
mode is overridden, not combined.

File streams opened in binary mode, perform input and output operations independently
of any format considerations. Non-binary files are known as text files, and some
translations may occur due to formatting of some special characters (like newline and
carriage return characters)

Since the first task that is performed on a file stream object is generally to open a file,
these three classes include a constructor that automatically calls the open() member
function and has the exact same parameters as this member. Therefor, we could also have
declared the previous myfile object and conducted the same opening operation in our
previous example by writing:

ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);

Combining object construction and stream opening in a single statement. Both forms to
open a file are valid and equivalent.

To check if a file stream was successful opening a file, you can do it by calling to
member is_open() with no arguments. This member function returns a bool value of true

121
Object Oriented Programming Using C++

in the case that indeed the stream object is associated with an open file, or false
otherwise:

if (myfile.is_open()) { /* ok, proceed with output */ }

Closing a file
When we are finished with our input and output operations on a file we shall close it so
that its resources become available again. In order to do that we have to call the stream's
member function close(). This member function takes no parameters, and what it does is
to flush the associated buffers and close the file:

myfile.close();

Once this member function is called, the stream object can be used to open another file,
and the file is available again to be opened by other processes.

In case that an object is destructed while still associated with an open file, the destructor
automatically calls the member function close().

Text files
Text file streams are those where we do not include the ios::binary flag in their opening
mode. These files are designed to store text and thus all values that we input or output
from/to them can suffer some formatting transformations, which do not necessarily
correspond to their literal binary value.

Data output operations on text files are performed in the same way we operated with
cout:

// writing on a text file [file example.txt]

#include <iostream> This is a line.

#include <fstream> This is another line.

using namespace std;

int main () {

ofstream myfile ("example.txt");

122
Object Oriented Programming Using C++

if (myfile.is_open())

myfile << "This is a line.\n";

myfile << "This is another line.\n";

myfile.close();

else cout << "Unable to open file";

return 0;

Data input from a file can also be performed in the same way that we did with cin:

// reading a text file This is a line.

#include <iostream> This is another line.

#include <fstream>

#include <string>

using namespace std;

int main () {

string line;

ifstream myfile ("example.txt");

if (myfile.is_open())

while (! myfile.eof() )

123
Object Oriented Programming Using C++

getline (myfile,line);

cout << line << endl;

myfile.close();

else cout << "Unable to open file";

return 0;

This last example reads a text file and prints out its content on the screen. Notice how we
have used a new member function, called eof() that returns true in the case that the end of
the file has been reached. We have created a while loop that finishes when indeed
myfile.eof() becomes true (i.e., the end of the file has been reached).

Checking state flags


In addition to eof(), which checks if the end of file has been reached, other member
functions exist to check the state of a stream (all of them return a bool value):
bad()
Returns true if a reading or writing operation fails. For example in the case that
we try to write to a file that is not open for writing or if the device where we try to
write has no space left.
fail()
Returns true in the same cases as bad(), but also in the case that a format error
happens, like when an alphabetical character is extracted when we are trying to
read an integer number.
eof()
Returns true if a file open for reading has reached the end.
good()
It is the most generic state flag: it returns false in the same cases in which calling
any of the previous functions would return true.

124
Object Oriented Programming Using C++

In order to reset the state flags checked by any of these member functions we have just
seen we can use the member function clear(), which takes no parameters.

get and put stream pointers


All i/o streams objects have, at least, one internal stream pointer:

ifstream, like istream, has a pointer known as the get pointer that points to the element to
be read in the next input operation.

ofstream, like ostream, has a pointer known as the put pointer that points to the location
where the next element has to be written.

Finally, fstream, inherits both, the get and the put pointers, from iostream (which is itself
derived from both istream and ostream).

These internal stream pointers that point to the reading or writing locations within a
stream can be manipulated using the following member functions:

tellg() and tellp()

These two member functions have no parameters and return a value of the member type
pos_type, which is an integer data type representing the current position of the get stream
pointer (in the case of tellg) or the put stream pointer (in the case of tellp).

seekg() and seekp()

These functions allow us to change the position of the get and put stream pointers. Both
functions are overloaded with two different prototypes. The first prototype is:

seekg ( position );
seekp ( position );

Using this prototype the stream pointer is changed to the absolute position position
(counting from the beginning of the file). The type for this parameter is the same as the
one returned by functions tellg and tellp: the member type pos_type, which is an integer
value.

The other prototype for these functions is:

seekg ( offset, direction );


seekp ( offset, direction );

Using this prototype, the position of the get or put pointer is set to an offset value relative
to some specific point determined by the parameter direction. offset is of the member
type off_type, which is also an integer type. And direction is of type seekdir, which is an

125
Object Oriented Programming Using C++

enumerated type (enum) that determines the point from where offset is counted from, and
that can take any of the following values:

ios::beg offset counted from the beginning of the stream


offset counted from the current position of the stream
ios::cur
pointer
ios::end offset counted from the end of the stream

The following example uses the member functions we have just seen to obtain the size of
a file:

// obtaining file size size is: 40 bytes.

#include <iostream>

#include <fstream>

using namespace std;

int main () {

long begin,end;

ifstream myfile ("example.txt");

begin = myfile.tellg();

myfile.seekg (0, ios::end);

end = myfile.tellg();

myfile.close();

cout << "size is: " << (end-begin) << "


bytes.\n";

return 0;

Binary files
In binary files, to input and output data with the extraction and insertion operators (<<
and ]>>) and functions like getline is not efficient, since we do not need to format any

126
Object Oriented Programming Using C++

data, and data may not use the separation codes used by text files to separate elements
(like space, newline, etc...).

File streams include two member functions specifically designed to input and output
binary data sequentially: write and read. The first one (write) is a member function of
ostream inherited by ofstream. And read is a member function of istream that is inherited
by ifstream. Objects of class fstream have both members. Their prototypes are:

write ( memory_block, size );


read ( memory_block, size );

Where memory_block is of type "pointer to char" (char*), and represents the address of
an array of bytes where the read data elements are stored or from where the data elements
to be written are taken. The size parameter is an integer value that specifies the number of
characters to be read or written from/to the memory block.

// reading a complete binary file the complete file content is in memory

#include <iostream>

#include <fstream>

using namespace std;

ifstream::pos_type size;

char * memblock;

int main () {

ifstream file ("example.txt", ios::in|


ios::binary|ios::ate);

if (file.is_open())

size = file.tellg();

memblock = new char [size];

file.seekg (0, ios::beg);

127
Object Oriented Programming Using C++

file.read (memblock, size);

file.close();

cout << "the complete file content is


in memory";

delete[] memblock;

else cout << "Unable to open file";

return 0;

In this example the entire file is read and stored in a memory block. Let's examine how
this is done:

First, the file is open with the ios::ate flag, which means that the get pointer will be
positioned at the end of the file. This way, when we call to member tellg(), we will
directly obtain the size of the file. Notice the type we have used to declare variable size:

ifstream::pos_type size;

This is the correct way of declaring size since ifstream::pos_type is the type returned by
file.tellg(). But since this type is an integer type, it can be converted to an int. Therefore,
we could also declare size as a variable of type int or some other integer type capable of
holding the size of a file and call tellg as:

int size;

size = (int) file.tellg();

Once we have obtained the size of the file, we request the allocation of a memory block
large enough to hold the entire file:

128
Object Oriented Programming Using C++

memblock = new char[size];

Right after that, we proceed to set the get pointer at the beginning of the file (remember
that we opened the file with this pointer at the end), then read the entire file, and finally
close it:

file.seekg (0, ios::beg);

file.read (memblock, size);

file.close();

At this point we could operate with the data obtained from the file. Our programs simply
announces that the content of the file is in memory and then terminates.

Buffers and Synchronization

When we operate with file streams, these are associated to an internal buffer of type
streambuf. This buffer is a memory block that acts as an intermediary between the stream
and the physical file. For example, with an ofstream, each time the member function put
(which writes a single character) is called, the character is not written directly to the
physical file with which the stream is associated. Instead of that, the character is inserted
in that stream's intermediate buffer.

When the buffer is flushed, all the data contained in it is written to the physical medium
(if it is an output stream) or simply freed (if it is an input stream). This process is called
synchronization and takes place under any of the following circumstances:

• When the file is closed: before closing a file all buffers that have not yet been
flushed are synchronized and all pending data is written or read to the physical
medium.
• When the buffer is full: Buffers have a certain size. When the buffer is full it is
automatically synchronized.
• Explicitly, with manipulators: When certain manipulators are used on streams,
an explicit synchronization takes place. These manipulators are: flush and endl.
• Explicitly, with member function sync(): Calling stream's member function
sync(), which takes no parameters, causes an immediate synchronization. This
function returns an int value equal to -1 if the stream has no associated buffer or
in case of failure. Otherwise (if the stream buffer was successfully synchronized)
it returns 0.

129

You might also like