Você está na página 1de 232

Introduction to OOP UNIT I

Object Oriented Programming thr C++

Object Oriented Programming Page 1


Introduction to OOP UNIT I

Object Oriented Programming

UNIT 1
Introduction to OOP 1

UNIT 2

Operator, Overloading and Inheritance 73

UNIT 3
Templates, Pointers and Graphics 135

UNIT 4
Files and Streams, Polymorphism and Virtual Function 193

Object Oriented Programming Page 2


Introduction to OOP UNIT I

BLOCK INTRODUCTION

The chief problem with computer program is complexity. Large programs


are probably the most complicated entities created by humans. Because
of this complexity, programs are prone to error and software errors can be
expensive. Object-Oriented programming offers a new and powerful way
to cope with this complexity. Its goal is clearer, more reliable, more easily
maintained programs.

OOP involves concepts that are new to programmers of traditional language


such as Pascal, Basic and C. These ideas such as date hiding, encapsulation
and polymorphism, lie at the heart of OOP. This block explains OOP with the
C++ programming language.

This book has been split into 4 units.

After completing Unit I, you will under the basic concept of programming in OOP
style. You will also learn to use classes to combine data and function and to
create objects. In this unit, concept of constructors, distracters and overloaded
constructors are also explained.

Unit 2 explains the techniques for designing reusable and extendable classes
and objects. It also explains the basic techniques of redefining functions and
operators, called overloading.

Unit 3 explains how to create templates and use it in programs. You will know
what is a pointer and how to allocate memory dynamically using new operator.
You will learn to design graphics pictures using OOP technique.

Object Oriented Programming Page 3


Introduction to OOP UNIT I

In Unit 4, you will understand the concepts of files and streams, and how to
create binary and ASCII files. You will also learn to define virtual function, friend
functions and Polymorphism.

Object Oriented Programming Page 4


Introduction to OOP UNIT I

UNIT 1 INTRODUCTION TO
OOP

Structure

1.0 Introduction
1.1 Objectives
1.2 What is C++ ?
1.3 Characteristics of Object Oriented Languages
1.3.1 Objects
1.3.2 Classes
1.3.3 Inheritance
1.3.4 Reusability
1.3.5 Creating New Data Types
1.3.6 Polymorphism and Overloading
1.3.7 Overloading Functions
1.4 Starting, Compiling and Executing C++ Programs
1.4.1 Invoking C++
1.4.2 Naming your Program
1.4.3 Compiling
1.4.4 Running the Program
1.5 Inline Functions
1.6 Storage types in C++
1.7 C++ Programming Basic
1.7.1 First C++ Program
1.7.2 White Space
1.7.3 Escape Sequence
1.7.4 Input with cin
1.7.5 Output with cout
1.7.6 Example to develop an Employee class
1.7.7 Manipulators
1.7.8 Example 1.7.1 rewritten to illustrate setw
1.8 Programming Style
1.8.1 Character Set

Object Oriented Programming Page 5


Introduction to OOP UNIT I

1.8.2 Keywords and Identifiers


1.8.3 Variables
1.8.4 Constants
1.8.5 Data Types
1.8.6 Declarations
1.8.7 Arrays
1.8.8 Enumerated Data Types
1.8.9 Structures
1.9 C++ Operators
1.9.1 Assignment Operators
1.9.2 Arithmetic operators
1.9.3 Type conversion
1.9.4 Casting
1.9.5 Relational Operators
1.9.6 Logical Operators
1.9.7 Increment/Decrement Operators
1.9.8 Conditional Operators
1.9.9 Precedence Of Operators
1.10 Decision Statements
1.10.1 One Way Branching
1.10.2 Two Way Branching
1.10.3 Nested if then else
1.10.4 Multi Way Branching
1.10.5 Switch Case
1.11 Programming Control Statements
1.11.1 Goto statement
1.11.2 For loop
1.11.3 Continue Statement
1.11.4 Break Statement
1.11.5 While loop
1.11.6 Do loop
1.12 Objects and Classes
1.12.1 Private and Public
1.12.2 Protected
1.12.3 Example to Illustrate Class Concept
Object Oriented Programming Page 6
Introduction to OOP UNIT I

1.12.4 Class - Declaration and Usage

1.13 Constructors
1.13.1 Example to Illustrate Constructors
1.14 Destructors
1.15 Overloaded Constructors
1.16 Example to illustrate Overloading Constructors and Destructors
1.17 Formatting Decimal Number
1.17.1 To Illustrate Formatting Decimal Numbers
1.18 Static Class Data
1.18.1 To Illustrate Static Class Data and Static Functions
1.19 Exercise
1.20 Summary

1.0 INTRODUCTION
PROCEDURAL LANGUAGES AND ITS DIFFICULTIES

A program in a procedural language is a list of instructions. The programmer


creates the list of instructions, and the computer carries them out. When
programs become larger, a single list of instructions becomes difficult to
understand. Hence 'functions' were adopted for better understanding of the
programs. Functions are called as subroutines, subprograms or procedures in
different languages. Dividing a program into functions and modules is called
structured programming or 'Procedure Oriented Programs' (POP).

As programs grow larger and more complex, the schedule slips, more
programmers are added, complexity increases, costs sky-rocket, the schedule
slips further.

In POP, the emphasis is on doing things, and a subdivision of programs into


functions continues this emphasis. Data is the reason for the program, not the
function that acts on the data. Yet data is given a secondary status, while

Object Oriented Programming Page 7


Introduction to OOP UNIT I

functions primary status. The global variables in such languages are accessible
to all functions. There are chances that it may accidentally be corrupted.

Another problem is that, since many functions access the same data, the way
the data is stored becomes critical. The arrangement of the data cannot be
changed without modifying all the functions that access it. In a large project, it
may also be difficult to find all the functions to modify it correctly.

There are other problems with traditional languages based on POP. One is the
difficulty of creating new data types (extensibility) as traditional languages are
not usually extensible.

THE OBJECT - ORIENTED APPROACH

The fundamental idea behind Object Oriented languages is to combine into a


single unit both data and the functions that operate on the data. Such a unit is
called an ‘object’.

Object Oriented Programming (OOP) is a software development technique that


has gained popularity because of potential gains in programmer productivity over
conventional software development methodologies.

An object is a self contained unit or module of data and code. All data and
procedures related to the object are defined within it. So, procedures (called
'methods' in OOP terminology and 'member functions' in C++) are tied to the
data. A 'message' identifying a method to execute is passed to the object.

The advantages of OOP fall into two broad categories increased programming
productivity and decreased maintenance costs. Well chosen classes and objects
may be re-used in other applications. Re-used code would have already been
tested, so it should need little testing when used in a new program. Objects help
partition complex problems into simpler ones that are easier to implement.

Object Oriented Programming Page 8


Introduction to OOP UNIT I

Application testing is generally shorter because objects are small and contain
independent code and local data segments that are verified with less effort than
in conventional programs. When a bug does occur, a particular object is usually
implicated. This makes isolating and correcting the bug easier.

Data hiding, a feature with all OO languages makes it possible to change the
data structure of an object without affecting the operation of the program.

1.1 OBJECTIVES
At the end of this unit, you will be able to :

♦ Understand the characteristics of Object Oriented Language.


♦ How to start C++, write a simple program, compile and execute C++
programs.
♦ Different storage types in C++, escape sequence.
♦ Taking input using cin and displaying output using cout.
♦ The basic data types in C++.
♦ The different operators.
♦ The decision statements.
♦ The looping statements.
♦ How to write the constructors and destructors and invoke them.

1.2 WHAT IS C++ ?


C++ is a superset of C, that is, C with extensions to support OOP. It was
developed by Bjarne Stroustrup of AT&T Bell Labs in 1986 as a means of
making complex programs easier to write and maintain. The name C++ is a
combination of C and the increment operator '++' indicating an incremental
development of C.

Object Oriented Programming Page 9


Introduction to OOP UNIT I

C++ Version 1.2 was the initial AT&T release. The next AT&T version was 2.1. It
is available both in translator form and compiler form. C++ version 2.1 adds
several features to C++. Some of the primary new features include :
♦ Multiple Inheritance
♦ Explicit support for abstract classes
♦ Pointers to class members
♦ Additional operator overloading
These are significant enhancements over previous C++ standards.

1.3 CHARACTERISTICS OF OBJECT ORIENTED LANGUAGES


The fundamental idea behind Object Oriented languages is to combine into a
single unit both data and the functions that operate on the data. Such a unit is
called an ‘object’.

1.3.1 Object
In an OO language problem you no longer divide the problem into functions, but
into objects. To understand object correctly, you need to understand Class first.

1.3.2 Class
Class describes the data and its behavior or functionality. Objects are said to be
'members' of classes.

This is the very much like what you see in nature, where Animal is a class and
Cat is an object of this class. The basic features of Animals, that is - 2 eyes, 2
ears, legs, etc. are common to all Animals. Thus Cat which is an object of class
Animal inherits these properties. The Cat can then be assigned individual
characteristics like color, their nature etc.

Just as int, a predefined data - type in C++ can have many variables declared of
its type, e.g. int a, count, total, amount, declares 4 variables, all of integer
type. Similarly, you can define many objects of the same class.

Object Oriented Programming Page 10


Introduction to OOP UNIT I

A class is a data type defined by the user describing the data it represents and
the functions to be used to manipulate the data. It serves as a plan / template.
Defining the class does not create any objects. Thus the class Animal can have
objects - Cat, Dog, Lion, Tiger, Crocodile, Frog etc.

Classes and their objects can be defined according to the problem at hand.
Thus in the banking system, ACCOUNT is a class describing number, date
opened, name of customer etc. SB, AC, FD, RD are objects of this class, each
having additional properties - like RD would include number of installments and
installment amount.

WHAT CONSTITUTES AN OBJECT ?


♦ Physical Objects: e.g. Electrical components in a circuit design problem.
♦ Elements of the computer - user environment: Windows, Menus, Mouse,
Keyboard, Graphics - objects (line, circle, etc.)
♦ Programming Constructs: Stacks, Customized Arrays, Linked lists, Binary
trees.
♦ User - defined data types : Angles, Complex numbers, Points on the plane.
♦ Collections of data: Dictionary, an inventory.
♦ Components in Computer games: Positions in a board game (chess,
checkers), Opponents and friends in adventure games.

1.3.3 Inheritance
Classes are divided into subclasses. Like the Animal, described above, can be
divided into subclasses like Land animal, Water Animal etc. Animal in turn may
be a subclass of the Fauna class. Thus Land Animal inherits all or some
properties of the higher classes and can add properties of its own.

The principle here is that each subclass shares common characteristics with the
class from which it has been derived. In addition to the characteristics shared

Object Oriented Programming Page 11


Introduction to OOP UNIT I

with other members of the class, each subclass has its own particular
characteristics.

In C++, the original class that is, the main class is called the 'Base class'. Other
classes can be defined that share the 'Base class' characteristics and add their
own as well. These are called 'Derived Classes'. The derived class can be a
base class of another class.

1.3.4 Reusability
The concept of inheritance provides an important extension to the idea of
reusability. Once a class has been written, created and debugged, it can be
distributed to other programmers for use in their own programs. This is called
reusability.

A programmer can take an existing class, and without modifying it, add
additional features and capabilities to it. This is done by deriving a new class
from the existing one. The new class will inherit the capabilities of the old one,
but is free to add new features of its own.

1.3.5 Creating New Data Types


New data types can be created by using the 'class' definition.

1.3.6 Polymorphism And Overloading


Polymorphism allows you to create multiple definitions for operators and
functions and at run-time depending on the context a particular definition will be
used.

An existing operator like + used with integer values (built-in data type)
constitutes addition. When a new data type is defined, the same + operator can
be made to operate in a particular manner on the new data type. This capability
of an operator to operate on many data types or in a new manner, constitutes
"operator overloading". Overloading is a kind of polymorphism. For e.g. '+' is

Object Oriented Programming Page 12


Introduction to OOP UNIT I

normally used to add numbers. This operator can be overloaded to add strings
(concatenation) or sets (union) and so on. Similarly functions also can be
overloaded as shown in the next section. The terms 'Overloading' and
'Polymorphism' are used interchangeably.

1.3.7 Overloading Functions


An overloaded function appears to perform different activities depending on the
kind of data to be sent to it. A function can be overloaded depending on the
factors like the number of arguments, the kind of arguments etc. The compiler
can also distinguish between overloaded functions with the same number of
arguments, provided their data types are different.

1.4 STARTING, COMPILING AND EXECUTING C++ PROGRAMS


1.4.1 Invoking Turbo C++
To start Turbo C++, type TC at the DOS prompt.
F>TC

Object Oriented Programming Page 13


Introduction to OOP UNIT I

Figure 1 ( C++ Editor screen)


You get the following screen. It will mostly be blank, with the menu bar at the top
and the status line on the bottom.

1.4.2 Naming Your Program


Select New from the FILE menu. An edit window will appear with the filename
NONAME00.CPP. You need to change this name. Select Save As from the FILE
menu to do this. In the text field in the resulting dialog box, enter the name of
your program, e.g., FIRST.CPP. The new name will appear at the top of the Edit
window. Notice that you have changed the filename from NONAME00.CPP to
FIRST.CPP.

1.4.3 Compiling And Executing The Program

Object Oriented Programming Page 14


Introduction to OOP UNIT I

The program that you type into the Edit window constitutes the source file. It is
an ASCII file with .CPP extension. This source file is not an executable program.
First, you must compile the source file into an object file. The object file, has an
extension .OBJ contains machine-language instructions that can be executed by
the computer. However, these instructions are not complete. A second step,
called linking is required. The linking step is necessary because an executable
program almost always consists of more than one object file. Linking combines
the object files into a single executable program.

Compiling: To compile the source file, select Compile from Compile menu. A
window called compiling will appear. An entry called Line Compiled will change
as compiling progresses. When the process if finished, the window will display
Success: Press Any Key. The entries for Warnings and errors will be 0.
Compilation creates an object file which has the extension .OBJ. If there is an
error, go back to the program correct the errors and compile it again.

Linking: To link your object file, Select Link from the COMPILE menu. The OBJ
file will be combined with the one or more library files. The result is an
executable file with extension .EXE.

Object Oriented Programming Page 15


Introduction to OOP UNIT I

1.4.4 Running the Program


To run the .EXE file, select Run from RUN menu (or press CTRL + F9). The
result will be displayed in the screen and control returns to the editing screen. To
see the result, select User Screen from WINDOW menu or ALT + F5.

1.5 INLINE FUNCTIONS


Functions, as you know is a module of code, which occurs repeatedly in the
program. Thus, it saves memory space, as the code is not repeatedly compiled.
When the compiler sees a function call, it normally generates a jump to the
function. At the end of the function, it generates another jump to the statement
after the call. But this takes time as the compiler has to save the variables and
return address on the stack, process the function, unstack all the variables etc.

But, when the function is very small say two or three lines and is not repeated
often or the time taken to transfer control to the function and back is more than
the time for execution of the function body, the functions become a bottleneck to
the program. In such cases, you use an 'inline’ function. This function is written
like a normal function in a source file but is compiled into inline code instead of
into a function.

When you use 'inline functions' there are some restrictions. The compiler must
have seen the function definition before it gets to the first function call so that it
can insert the statements. If there is only 'main function' in the program then the
'inline function' definition must be written before main function. In such cases the
function declaration is unnecessary and can be eliminated.

It is to be noted that 'inline' keyword is actually just a request to the compiler.


Sometimes the compiler will ignore the request and compile the function as a
normal function. These functions will be discussed in detail, later in this book.

Object Oriented Programming Page 16


Introduction to OOP UNIT I

1.6 STORAGE TYPES


C++ provides all the storage types available in C as shown in the table given
below:

TABLE 1.1 : STORAGE TYPES IN C++

Storage Type Automatic Static Automatic External


(Local) (Static) (Global)
Visibility Function Function Function
Lifetime Function Program Program
Initialized Value Not initialized 0 0
Storage Stack Segment Data Segment Data Segment
Purpose Variables used by Same as auto, but Variables used
a single function. must retain value when by several
the function terminates. functions.

1.7 C++ PROGRAMMING BASICS


The execution of every program begins from 'main()'. This function may or may
not take parameters, it always returns void. It indicates the logical beginning of
the program. Other commands and constructs are enclosed in braces as the
body of main().

# include <iostream.h> is not a program statement. It is called a 'preprocessor


directive'. A preprocessor directive is a instruction to the compiler itself. A part of
the compiler called the 'preprocessor' deals with these directives before it begins
the real compilation process.

Just as in C, appropriate headers are included, using the # include command,


depending on the functions to be used in the program. This command is placed
at the beginning of the program, i.e. before any functions are executed.

'iostream.h' is the header file to be included to perform any input - output


operations in C++. Keyword 'cout' is used for output. The following program
displays a message on the screen.
Object Oriented Programming Page 17
Introduction to OOP UNIT I

1.7.1 First C++ Program


Consider the following program - myclass1.cpp. This class contains one integer
num and describes the functionality of this data member. All functionality of this
data member is described through methods (member functions) within the class.
myclass allows the data to be entered (getdata()) and displayed (dispdata()).

Any other functionality required will have to be included within the class
declaration.

// myclass1.cpp
# include <iostream.h> NOTE
class myclass1 The class command starts the
{ declaration of a new class
private :
int num; private and public are two types of
public : accesses. Data members are usually
private while member functions are
void getdata() // to enter the value public.
{
cout << endl << "Enter an integer:"; cout is the keyword used to display
cin >> num; information.
} cin is the keyword to enter data.

void dispdata() //to display the value


{
cout <"Num=" << num<<endl;
}
}; indicates the end of the class command

void main ()
{
myclass1 a1, b1; a1 and b1 are objects of class
myclass1.
a1.getdata();
b1.getdata();
a1.dispdata();
b1.dispdata();
} // end of program.

Object Oriented Programming Page 18


Introduction to OOP
Unit 1
A class as you have defined earlier is a combination of data and its functionality,
that is the data is encapsulated in the class. In the class defined above, you
have one data member - num. It is defined as private. Private access implies
that the member can be accessed only by other members of the class. You see
the value of num being manipulated only within the class, that is, by the member
functions getdata() and dispdata() only.

Member functions - getdata() and dispdata() are declared as public. Public


access implies that the member can be accessed directly by other members of
the class (within the class) and by objects of the class (in main) using the dot (•)
operator e.g. - a1•getdata(); in the above program.

cout is the keyword used to display information on the standard output (the
VDU). It uses the overloaded left-shift operator (<<). Any number of items can
be concatenated using the << operator. endl is used to insert a newline
character in the output. In its place the escape sequence \n can be used as :

cout << '\n' << "Enter an integer :"; or cout << "\nEnter an integer :";

All other escape sequences available in C are available in C++ as shown in the
table given below.

cin is the keyword to enter data from standard input (the keyboard). It uses the
overloaded right-shift (>>) operator

1.7.2 White Space


White Space is defined as spaces, carriage returns, linefeeds, tabs, vertical tabs,
and formfeeds. These are ignored by the compiler. But there are some
exceptions :
♦ The string constant cannot be split.
♦ # include <header file> must be written on a single line.

C++
Page 14
Introduction to OOP
Unit 1
♦ // symbols are used in C++ to indicate comments. This is valid only till the
end of that line. No white space should be used between the slashes.
1.7.3 Escape Sequences
Escape sequences are denoted by a backslash (\) and a character. E.g. : \t is an
Escape sequence because the \ causes an 'escape' from the normal way the
characters are interpreted. In the example given above, it is interpreted as the
'tab' character and not as character 't'.

Escape Sequences can be used in both character and string constants.

TABLE 1.2 : COMMON ESCAPE SEQUENCES

Escape Sequence Character


\a Bell(Beep)
\b Backspace
\f Formfeed
\n New Line
\r Return (Enter key)
\t Tab
\\ Backslash
\’ Single Quotation Mark
\” Double Quotation Mark
\xadd Hexadecimal Representation

1.7.4 Input With Cin


cin is used for input in C++. It is defined as an object in the header file
iostream.h. The >> is the 'extraction' or 'get from' operator.

1.7.5 Output using cout


cout is used for output in C++. It is defined as an object in the header file
iostream.h. The << is the 'insertion' or 'put to' operator.

1.7.6 Example To Develop An Employee Class .

C++
Page 15
Introduction to OOP
Unit 1
/* class employee stores employee information. You use calc() function to
return average salary. */

# include <iostream.h>

# include <string.h> // to use strings


class employee
{
private :
int emp_no;
char name[20];
int basic;
public :
void getdata() // to enter the data
{ cout << "Enter employee no :"; cin >> emp_no; cin.get();
cout << "Enter name :"; cin.getline(name,'\n');
cout << "Enter Salary :"; cin >> basic;
}

void dispdata() // to display the value


{ cout << "Employee no :" << emp_no;
cout << "Name :" << name;
cout << "Salary :" << basic;
} parameter received

float calc(employee x)
{ float temp;
temp = (float(basic) + x.basic)/2; // int basic is casted to float type
return temp;
} basic of object that calls calc()
function -i.e. instance variable
};
void main ()
{ employee a1, b1;
a1.getdata(); b1.getdata();
float average = a1.calc(b1);
/* object a1, invokes function calc(), b1 is passed as the parameter */
cout << endl << "Average salary :"<< average;

C++
Page 16
Introduction to OOP
Unit 1

} // end of program.

1.7.7 Manipulators
The 'endl' manipulator has the same effect as the '\n' escape sequence.

The 'setw' manipulator (setw(n), causes the number (or string) that follows in the
stream to be printed within a field 'n' characters wide, where 'n' is the argument
to setw(n). The setw(n), is defined in iomanip.h.

The number or string variable or constant that follows the setw manipulator is
printed right justified within the width specified as argument. These manipulators
are normally used to format the output obtained from the program.

1.7.8 Example 1.7.1 Rewritten to illustrate manipulator - setw()


# include <iostream.h>
# include <iomanip.h>

class myclass1
{
private :
int num;
public :
void getdata() // to enter the value
{
cout << endl << "Enter an integer :";
cin >> num;
}
void dispdata() // to display the value
{
cout << setw(10) << "Number =" << setw(10) << num<<endl;
}
};
void main ()
{
myclass1 a1;
a1.getdata();
a1.dispdata();

C++
Page 17
Introduction to OOP
Unit 1
} // end of program.

OUTPUT

with setw manipulator without setw manipulator


Enter an integer : 12 Enter an integer : 12
Number= 12 Number = 12

1.8 PROGRAMMING STYLE


1.8.1 Character Set
Obviously the set of legal characters of ‘C++’ can contribute a legal word in
‘C++’. The set of such characters is refered as Character set of ‘C++’. The
characters are grouped as follows:
♦ Letters
♦ Digits
♦ Special Characters
♦ White Spaces

Alphabets :A ... Z a ... z


Numerals : 0 ... 9
Special Characters
, comma & ampersand
. period ^ caret
; semicolon * asterisk
: colon - minus sign
? question mark + plus sign
‘ apostrophe < less than
“ quotation mark > greater than
! exclamation ( left parenthesis
| vertical slash = equal to
/ slash ) right parenthesis

C++
Page 18
Introduction to OOP
Unit 1
\ back slash [ left square bracket
~ tilde ] right square bracket
_ under score { left bracket
$ dollar sign } right bracket
% percent sign # number sign
White Spaces
Blank spaces , Horizontal tab ,Carriage return , New line.

1.8.2 Keywords And Identifiers


The set of ‘C++’ words that can be formed from these characters can be
classified as keywords and identifiers. The keywords are a part of ‘C++’, which
have a predefined meaning and cannot be changed. All keywords must be
written in lower-case. From the character set you could observe that both upper
and lower cases are allowed in ‘C++’.

‘C++’ Keywords
auto do for return typedef
break double goto start union
case else if sizeof unsigned
char enum int static void
continue extern long struct while
default float register switch

Identifiers are user defined names, that refer to variables and function names.

1.8.3 Variables
Variables enable the programmers to assign and manipulate data using symbolic
names. Strings and numeric values can be stored in the memory of the
computer for subsequent recall. Whenever the memory is used for this purpose
the programmer must assign a unique name to each area in memory. In brief, a
variable is a data name that may be used to store a data value, for easy retrieval.
For example, the legal identifier names in ‘C++’ are,

C++
Page 19
Introduction to OOP
Unit 1
totsalary
Counter1
Stdname

The naming conventions of variables has already been discussed. The


maximum length of the variable is machine dependent. Usually 32 is the
maximum number of characters permissible in a variable name.

C++
Page 20
Introduction to OOP
Unit 1
1.8.4 Constants
Constant is one that has a fixed value throughout the program. The constant
can be viewed as a read only memory variable. In a program, the constant
identifier should not be changed by any manifestation of the program
statements.

Constants are broadly classified into numeric constant and character constant.
Pictorially the taxonomy of the constants are given here.

Constant

* Numeric Constant
# Integer Constant
# Real Constant
* Character Constant
# Character Constant
# String Constant
An integer constant is a sequence of digits that may or may not be prefixed with
a minus sign. Some examples are,

14
-32
0
576321

Note that ‘C++’ does not support unary plus hence, +14 is not a valid integer.
A real constant can be represented in 2 forms,
1. Decimal form 2. Exponent form

Eg. 12.75 Eg. 1275E-2


-14E-2

A character constant is a single character enclosed within a pair of single quotes.


Examples are,

C++
Page 21
Introduction to OOP
Unit 1
’7’, ’K’, ’,’
Note that the character constant ‘7’ is not the same as the integer 7.

A string constant is a group of characters enclosed in double quotes. These


characters may be letters, numbers, or any special characters.

Examples are, ”welcome”


”2000”

1.8.5 Data Types


Data type is defining an attribute to the variable. It defines the set of legal that
the variable can store. ‘C++’ is rich data types. The basic data types are int,
char, and float.

Integer
The data type ‘int’ are whole numbers with a range of values supported by a
particular machine. For instance, in a 16 bit word length machine, the integer
values lie between –32768 to 32767.

‘C++’ facilitates some control over the integer data type by providing sub data
types namely short int, int, long int.

Short int represents fairly small integer values and requires half the amount of
storage as a normal int uses.

Similarly a long int represents fairly higher integer values and requires generally
twice the number of bits as a normal int uses. Nevertheless these are highly
machine dependent.

Another option in integer data type is declaring it as unsigned. This unsigned


integer uses all bits for the magnitude of the number and are always positive. For
instance, in a 16 bit machine the range of unsigned integer is 0 to 65,535. Thus
long and unsigned are intended for increasing the range of values.

C++
Page 22
Introduction to OOP
Unit 1
Floating point type
Floating point numbers are numbers that have a decimal point. This data type in
‘C++’, is an attribute for real numbers. The corresponding declaration is,
float a;
which instructs the compiler that the variable ‘a’ belongs to the data type real. If
you want to initialise the variable, then

float a;
a = 14.752;

This can also be achieved through a single statement.


float a = 14.752;

The keyword float defines the floating point number. When more accuracy is
required, another subdata type, double under the float data type can be used.
Obviously this double data type uses twice the storage as that of the float data
type. To display a double value the format specifier %f is used to obtain the
standard floating point notation and %e for scientific or exponential notation.

Character data type

The char keyword defines a character data type. Thus the declaration for this is
char x;
x = a;

The variable x is of type character and is initialised to the character ‘a’. The same
effect could be achieved as,
char x = ’a’;

Table 1.3

Integer type Floating point type Character type

C++
Page 23
Introduction to OOP
Unit 1
Int Float Char
short int Double
long int Long double
Unsigned int

C++
Page 24
Introduction to OOP
Unit 1
Table 1.4
Type Description Format storage
specifier specifier (machine
dependent)
Int integer data type %d or %i 2 Bytes
Short int %hd
Long int %ld
unsigned int %u
float floating point representation %e
Scientific notation(exponent form) 4 Bytes
Otherwise (decimal form) %f
double for better precision of
floating point 8Bytes
scientific notation %e
otherwise %f
long double %le or %lf
char character representation %c 10 Bytes
1Byte
Format specifications of 'C++'data types

1.8.6 Declarations
The modern programming languages clearly separate the data and the control
statements. All the data is declared first. This makes the program more readable
and also provides the information to the compilers to allocate memory spaces.

The data and control are well separated by making the former to precede
textually, in the name of declarations. Such declarations follow the syntax,

type identifier v1,v2,...............vn;


Example: int n1, n2, n3;

Of course, initialisation of the data is also possible.


float x, y, z; int x =72;

Data declaration does two significant tasks for each variable. They are:
♦ tells the compiler what the variable name is.
♦ specifies what type of data the variable will hold.
C++
Page 25
Introduction to OOP
Unit 1

TABLE 1.5 : BASIC C++ VARIABLE TYPES

Keyword Numerical Range Digits of Bytes of


precision memory
Low High
Char -128 127 n/a 1
Int -32,768 32,767 n/a 2
-38 38
Float 3.4x10 3.4x10 7 4
-308 308
Double 1.7x10 1.1x10 15 8
4932 4932
long double 3.4x10 1.1x10 19 10
Unsigned char 0 255 n/a 1
Unsigned int 0 65,535 n/a 2
Unsigned long 0 4,294,967,295 n/a 4

1.8.7 ARRAYS
Apart from the broad spectrum of data types, C++ supports arrays. This data
type is useful when a group of elements are to be represented by a common
name.

An array is a group of elements that share a common name, that are


differentiated from one another by their positions within the array. An array is a
collection of homogeneous data.

For example, 21, 20, 14, 25 and 13 are marks in 5 subjects of a student. To
store these five marks, five variables would be required – test1, test2, test3,
test4 and test5. For such a representation, arrays are useful. This can be
represented as test[5]. The ability of using a single name to represent a
collection of items and to refer to an item by specifying the location number
enables the programmer to develop concise and efficient programs.

Declaring arrays
An array must be declared, since it is basically a variable. The declaration is :

C++
Page 26
Introduction to OOP
Unit 1
Syntax: type variable-name [size];
Example: int marks[5];
This example describes an array of 5 integer elements and the elements are
numbered starting with 0. Each element is accessed by the array name followed
by its position in square brackets. This position is known as the subscript, thus
each array statement is a subscripted variable. Therefore, you would have:
mark[0], mark[1], mark[2], mark[3] and mark[4].

If the array is accessed beyond its limit, C++ does not report it as an error.
Having declared mark[5], accessing mark[5] is not a syntax error. The program
does not terminate abnormally, though it is a logical error as the last legal
element is mark[4].

ONE DIMENSIONAL ARRAY

A list of data items can be given one variable name using one subscript and such
a variable is called a one dimensional array.

Example:

# include <iostream.h>
void main()
{
int num[10];
int i;

cout<<"Enter 10 numbers "<<endl;


for (i=0;i<9;i++)
cin>>num[i];

for (i=0;i<9;i++)
cout<<num[i]<<endl;
}

C++
Page 27
Introduction to OOP
Unit 1
The array storage starts from 0 and hence the loop termination is i < 10. The
second loop is to display the10 integers.

C++
Page 28
Introduction to OOP
Unit 1
INITIALIZATION OF ARRAYS

An array can be initialized along with its declaration.

SYNTAX: static type array-name[size]={val1,val2..};


static int count[3]={0,0,0 };

will declare the variable count as an array of size 3 and will assign zero to each
element. Note that this declares a static variable. The size parameter may be
omitted. In such cases, the compiler allocates enough spaces for all initialized
elements.
static int count[]={0,0,0};

TWO DIMENSIONAL ARRAY

The following table could be considered as a two dimensional array:

56 3 This array stores the score and the


62 2 rank of 3 students.
75 1
Then score[0][0] represents the marks of the first student and score[0][1] the
rank of the first student. C++ allows us to define such a table of items by defining
a two dimensional array. As with the single dimensional array, each element of
the array is indexed from zero to its maximum size minus one, the first index
stands for row and the second index for column. C++ uses the row major
arrangement to access the elements of the array – first number represents the
row and the second number represents the column.

Declaration
int score [3][2]
will declare a table of 3 rows and 2 columns.
Initialization
Similar to the one dimensional arrays, two dimensional arrays can also be
initialized.
C++
Page 29
Introduction to OOP unit1

static int table[2][3]={0,0,0,1,1,1};

initializes the elements of the first row to zero and the second row to one. Note
that initialization is done row by row. For better degree of readability, you can
also write the same initialization in the matrix form, as :

static int table[2][3]={{0,0,0},{1,1,1}};

The inner braces are optional, but it is good practice to use them, as they
improve the readability.

Example:

# include <iostream.h>
void main()
{
int num[3][3];
int i,j;

cout<<"Enter the numbers into the array"<<endl;


for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
cin>>num[i][j];
}

for (i=0;i<3;i++)
{
for (j=0;j<3;j++)
cout<<num[i][j]<<"\t";
cout<<endl;
}
}

MULTIDIMENTIONAL ARRAYS

C++ permits arrays of more than two dimensions. The maximum number of
dimensions depends on the compiler.
Introduction to OOP unit1

SYNTAX : type array-name[s1][s2][s3]…[sm];

1.8.8 ENUMERATED DATA TYPES


This is used when you know in advance the finite number of values a variable
can take in a program. E.g. The days of the week can only take values from
Sunday to Saturday.

An 'enum' specifier defines the set of all names that will be permissible values of
the type. These values are called 'members' of the data variable. 'Enumerated'
means that all values are listed.

These data types are treated internally as integers. The first member gets
value 0, the second 1, and so on. Changes can be done by assigning it in the
declaration. The values can be set by initializing the first value.

In example 1.3 below, Sunday is initialized the value 1. Thus Monday gets the
value 2 and so on. If the difference between the first and second value is more
than 1, the values must be specified explicitly while declaring the data type.

E.g. Sun = 10, Mon = 20, and so on.

Example:

# include <iostream.h>
enum days_of_week {Sun = 1,Mon,Tue,Wed,Thu,Fri,Sat};
void main()
{
days_of_week day1,day2;
day1 = Mon; day2 = Thu;

int diff = day2 - day1;

cout << "Days between = " << diff <<endl;


if (day1 < day2)
cout << "day1 comes before day2 \n";
}
1.8.9 Structure
Introduction to OOP unit1

A ‘structure’ is a data type, which is used to define a heterogeneous set of data


types or a set of data items belonging to different data types.

CONSTRUCTION OF STRUCTURES

A structure construction creates a format or a template that may be used to


declare structure variables.

SYNTAX :

struct tag-name { data-type member1;


data-type member2;
...;
...;
};

The keyword struct declares a structure to hold the template. Each variable
declared in the template is called a field or member of the structure. Each
member is a data item that can belong to any data type. Each structure has a
name, called tag-name. Also note that a structure does not declare any
variables, it describes a format or template.

e.g:

struct std_info
{
char name[20];
int roll_no;
float marks;
};

Here, std_info is the tag name, which declares a format that can store a name,
roll_no and marks. The structure variables are declared after describing the
structure given above as –

struct std_info std1, std2, std3;


or, while describing the structure, as :
Introduction to OOP unit1

struct std_info { char name[20];


int roll_no;
float marks;
} std1, std2, std3;

or struct { char name[20];


int roll_no;
float marks;
} std1, std2, std3;

Here tag name is not used.

Each of the variables std1, std2 and std3 has the format described in the
template. i.e., Name, roll_no. and marks.

Note:
♦ The template is terminated with a semicolon.
♦ The tag-name can be used to declare structure variables. A structure
variable can be initialized during declaration. However, it must be static (like
an array).
♦ Structure members cannot be initialized inside the template.
static struct std_info { char name[20];
int roll_no;
float marks;
} std1 = {”mahe”, 1000, 90.00};

ACCESSING STRUCTURE MEMBERS

The members of a structure are accessed using the dot operators. Eg.
Std.roll_no.

INITIALISING STRUCTURE MEMBERS


Members of a structure can be accessed using the period (.) operator.
e.g : std1.roll_no = 108;
Introduction to OOP unit1

Thus, 108 is stored in roll_no, a member of std1. std1 has been declared as a
variable of structure std_info. std_info is a structure of three members - name,
roll_no, marks. All I/O operations can be carried out with structure members.

e.g : cin>>std1.marks; cout<<"student 1 scored :”<<std1.marks<<endl);

The structure variable can be initialized by specifying the values of each member
within curly braces (the values are separated by commas) and assigning this to
the variable.

SYNTAX : variable = {value1, value2, ...};

e.g. : std1 = { ”smith”,105, 91};

Here Smith is assigned to std1.name, 105 to std1.roll_no and 91 to std1.marks.

ARRAYS OF STRUCTURE

When a number of variables have to be assigned the same structure, an array


may be used instead of using number of variables, that is, the variable being
assigned the structure template, could be an array.

e.g. : struct student std[50];

defines an array called std, that contains 50 elements. Each element is of the
structure described as student.

ARRAYS WITHIN STRUCTURES

Any member of a structure can be an array. In the above examples two integer
variable mark1 and mark2 have been described to store marks in two subjects.
This could be redefined as an array of two elements,
struct student
{ char name[20], grade;
int rollno; int mark[2];
};
To access the members :
std.name
std.grade
Introduction to OOP unit1

std.rollno
std.mark[0]
std.mark[1]

STRUCTURE INSIDE STRUCTURES

A structure may be defined inside a structure. Nesting of structure to any depth


is allowed in C++. e.g :

struct student
{ int rollno;
struct
{ char firstname[10], lastname[20], middlename[10];
} name;
} std;

The structure student defines a template containing rollno and the structure
name. name defines a template containing firstname, lastname and
middlename. Hence, rollno would be referred to as std.rollno and firstname as
std.name.firstname.

1.9 C++ OPERATORS


'C++' supports a rich set of operators. An operator can be defined as just a
symbol that tells the compiler to perform certain mathematical or logical
manipulations.

Taxonomy of operators

♦ Assignment operators
♦ Arithmetic operators
♦ Relational operators
♦ Logical operators
♦ Increment/decrement operators
♦ Conditional operators
♦ Bitwise operators.
Introduction to OOP unit1

Expressions

The following are the rules regarding expressions:

♦ A signed or unsigned variable name or constant is an expression.


♦ An expression connected by an arithmetic operator to an unsigned variable
name or an unsigned constant is an expression.
♦ An expression enclosed in parenthesis is an expression
♦ Two expressions connected by an arithmetic operator is an expression
♦ Two arithmetic operators should not occur in succession in an expression.

1.9.1 Assignment Operators


Values need to be assigned to variables. The '=' operator is used for
assignment.

int a = 5;

The syntax of an assignment is,


Variable-name = expression;
For example,

sum = a + b;
Assigns the total of contents of a and b to a variable named, sum. The variable
sum appears to the left of the equal sign, which is called the assignment
operator. On the left of this operator only a single variable can occur,
expressions and constants are strictly not allowed.

The assignment statement is called a dynamic statement because the value of


the expression on the right of assigned operator is assigned during the time of
execution, not during the time of execution, not during compilation.

The declaration of a variable and its initial assignment is possible, as a single


line. This takes the form,

[qualifer] Type identifier = constant

or
Introduction to OOP unit1

[qualifer] Type identifier = predefined variable

example : auto into no = 100;

'C++' also permits the initialization of more than one variable in one statement
using multiple assignment operation.

Similarly, compound assignment operators can be used

Eg: +=, -=, /=, *= , %=

a=a+5 or a += 5

b = b - 10 or b -= 10

c = c/2 or c /= 2

prod = prod * no or prod *= no

year = year % 4 or year %= 4

1.9.2 Arithmetic Operators


The arithmetic operators are given below.

Operator Meaning
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus
These operators can operate on any built-in data types such as, int, char, float.
But for modulus operator, operand must not be float. Note that in 'C++' a char
data type is promoted to int data type. Integer division truncates any fractional
part. You have already written many programs using this. This modulus operator
is discussed later.

Hierarchy of Arithmetic operators

When an arithmetic expression involves two or more arithmetic operators, the


hierarchy or the order of precedence of the operator is important. In 'C++',
Introduction to OOP unit1

division and multiplication is done before addition and subtraction. This is known
as the hierarchy of operators or rule of precedence.

Multiplication and division have the same precedence, so do addition and


subtraction. Operators of the same precedence if appearing in one expression,
then the order in which they appear in one expression, the order in which they
are evaluated depends on their association. But using parentheses this
precedence can be overridden. That is, (a+b)/c will make the computer to
evaluate addition first and then division. But whatever is within the parenthesis
will be evaluated in the order of precedence.

Modulus Operator

The modulus operator is represented by the % (percent symbol). This returns the
remainder of the division, hence 11 mod 2 is represented in 'C++' as, 11%2 and
the result is 1, the remainder of the division. 10 % 5 is 0 as there is no remainder
after this division.

Symbolic Constant

When a numeric value or a constant is to be used in the program, then, it can be


given a symbolic definition or preprocessor directives which means, before
compilation every occurrence of the symbolic-name in the program is substituted
by the value-of-constant as given in the syntax.

SYNTAX: #define symbolic-name value-of-constant

This name is usually written in upper case to distinguish it from an ordinary


variable.

Mixed Mode

Having known the basic two types int and float, the next logical question is
whether mixing of these two types is allowed. That is, an arithmetic expression
containing an operand of type int and another of type float. This is allowed. The
integer value is automatically converted to type float for the calculation. Such
automatic conversions are known as implicit conversion.
Introduction to OOP unit1

1.9.3 Type Conversions


When two operands of different types are encountered in the same expression,
the lower type variable is converted to the type of the higher type variable. These
conversions take place invisible to the user.

TABLE 1.6 : HIERARCHY OF DATA TYPES

Long double (highest order)


Double E.g.: Int is converted to float,
Float double is converted to long
Long double.
Int
Char (lowest order)

1.9.4 Casting
This term applies to data conversions by the programmer as opposed to the
automatic data conversions described above.

e.g. : int marks_eng, marks_kan;


float avg = (float(marks_eng) + marks_kan)/2;
In the above example, variable marks_eng is cast to float. When an arithmetic
expression is on the right hand side of the assignment, value returned is the
same type as the operands.

In this instance, both operands are of int type. Casting one to a higher type, will
cause :

♦ return type to be of the higher type (float, in this instance.)


♦ all operands to be implicitly cast to the higher type (in this instance,
marks_kan is implicitly casted to float.)

1.9.5 Relational Operators


The relational operators are symbols that are used to test the relationship
between variables or between a variable and a constant. For example,

(salary == 4000)
Introduction to OOP unit1

(a > b)

Here, == is the operator used to test quality. A table of such relational operators
are listed below.

TABLE 1.7 RELATIONAL OPERATORS

Operator Meaning
== equal to
> greater than
< less than
!= not equal to
>= greater than or equal to
<= less than or equal to

Notice that some of the relational operators consist of two characters. There
should not be any space between those two characters.

1.9.6 Logical Operators


Logical operators are symbols that are used to combine expressions containing
relational operators. This circumstances will arise when you want to perform a
statement block on a combined condition, like x > 7 and x < 14. Then you code
this using an AND operator. The AND operator is represented as &&.

Example:

((x > 7) && (x < 14))


(salary >=4000 && salary <=5000)

The other logical operators are tabulated below:

TABLE 1.8 LOGICAL OPERATORS


Operation Operator
AND &&
OR ||
NOT !

1.9.7 Increment/Decrement Operator


Introduction to OOP unit1

Apart from + and – ‘C++’ provides two very useful operators. They are ++ and --
defined as increment and decrement respectively. The ++ operator adds 1 to the
operand and -- operators decrements 1 from the operand.

Both are unary operators.

These operators can be used in two ways:


♦ pre-operator (before the variable) and
♦ post-operator (after the variable)

SYNTAX : ++ variable; --variable; (Pre-operator)


Variable++; variable--; (Post operator)

++variable is equivalent to
variable = variable + 1; or variable += 1;

--variable is equivalent to
variable = variable –1; or variable-=1;

A prefix operator first adds 1 to the operand and then the result is assigned to
the variable on left. In contrast, a postfix operator first assigns the value to the
variable on the left and then increments the operand.

Example :
int i = 5;
a = i++; a = ++I;
a will be 5 a will be 6
i will be 6 i will be 6
1.9.8 Conditional Operator
This is a compressed version of the if - else statement. The syntax of this
statement is : c = (a > b) ? a : b;

Where : a and b are operands,


?: is the conditional operator,
> is the relational operator.

If the condition is true then value a is assigned to c otherwise b is assigned to c.


Introduction to OOP unit1

1.9.9 Precedence Of Operators


In an expression, operators with higher precedence are evaluated before those
of lower precedence. Operators on the same row have equal precedence and
are evaluated left to right.

TABLE 1.9 PRECEDENCE SUMMARY

Operator Type Operators Precedence


Parentheses () Highest Precedence
Unary ! , ++ , -- , -
Arithmetic
Multiplicative *,/,%
Additive +,-
Relational
Inequality < , > , <= , >=
Equality == , !=
Logical
And &&
Or ||
Conditional ?:
Assignment = , += , -= , *= , /= , %= Lowest Precedence

1.10 DECISION STATEMENTS


You have seen that C++ programs are a collection of functions each having a
declaration part and a computational part which are executed sequentially, that is
statement by statement.

In practice, it becomes necessary to make some changes in the order of


execution and you need the in-built decision making mechanism. This is
accomplished by a set of control constructs. In accordance with the decision,
control will be transferred to another part of the computational structure, inside
the function. This decision may be,
1. One way branching.
2. Two way branching.

Boolean variables in C++

There is no datatype called boolean variable in C++. A boolean variable is one


that could take either TRUE or FALSE and nothing else.
Introduction to OOP unit1

For example there can be a test,

Say, if code==0 then declare pass, if not fail.

Now the condition is code being 0 or not. That is, this expression is true only if
the code is zero. If it is not zero, then the expression fails. Now C++ achieves
this effect of boolean variable as follows:

TRUE : if the expression evaluates to a non-zero value.

FALSE : if the expression evaluates to zero.

Decision making and branching

To override the sequential flow of execution, branching is a must. At the same


time arbitrary unconditional branches are not healthy for programming.
Branching must be done based on a test. Given below are the various constructs
that achieve this effect.

1.10.1 One way branching


One way branching means evaluating a condition and then branching. In
accordance with the test advocated, set of statements are executed. This type of
decision making technique takes the form:

If (test expression)
{
statement-block
}
statement-n;

This syntax is for a simple if statement. That is, the decision is made based on a
condition,

Braces { and } are used to group declarations and statement together into a
compound statement. This set of compound statement together enclosed within
parenthesis is called a block.

If (condition)
{
Introduction to OOP unit1

Block of statements
}
Statement-n;

Example:

If (code ==0) printf("student has passed");


or
if (code ==0)
printf("student has passed");

The statement block can be a single statement or a group of statements. If the


logical expression is true then the statement block is executed, otherwise the
statement block will be skipped and statement-n will be executed. When the
condition is TRUE, that is when the logical expression evaluates to true then
both the statement and the statement-n are executed. The test expression is
made up of relational and logical operators.
Introduction to OOP unit1

Example:

If (salary == 4000)
hra = salary *.1;
If ((x > 7) && (x < 14))
{
statement-block
}
if (salary >=4000 && salary <=5000)
{
statement-block
}

Example:
# include <iostream.h>
void main()
{
int n1,n2;
cout <<"Enter 2 random numbers \t";
cin>>n1;
cin>>n2;
if (n1 == n2)
cout <<"Numbers are equal "<<endl;
}

1.10.2 Two way branching


Two way branching is used in situations, wherein you need to trace two mutually
exclusive sets of actions.

This is accomplished by if ..then ..else construct of C++, which takes the form:
If (test expression)
{
statement(s) for the condition being true
}
else
{
Introduction to OOP unit1

statement(s) for the condition being false


}
statement-n;

If the test expression is true then the block of statement, immediately following
the if statement is executed; otherwise the second block of statement is
executed. Note that, in either case, either the true-block of statements or the
false-block of the statement alone is executed and not both.

Example:

// Program to detect larger number


# include <iostream.h>
void main()
{
int n1,n2;
cout <<"Enter 2 random numbers \t";
cin>>n1;
cin>>n2;
if (n1 == n2)
cout <<"Numbers are equal "<<endl;
} // end of program
It is important that the else clause and if clause match with each other.

1.10.3 Nested if-then-else


The else clause, like the if clause, may contain a compound statement. This is a
more flexible control construct. Further, a clause of if statement may itself
contain another if statement. This is known as nested if statement.

The following example illustrates the nested if construct.


Introduction to OOP unit1

Example:

If (x == 3)
{
if (x > 5)
cout << “the numbers lies between 3 and 5 << endl;
}
else
cout << "the number does not lie between 3 and 5" <<endl;

The alternate way is by using the logical operators (AND, OR) and providing a
concise code.

Observe that an AND (&&) operation can be replaced with an if statement nested
within an if clause. Similarly an OR (II) operation can be replaced with an if
statement nested within an else clause.

1.10.4 Multi-way branching


The multiway branching can be achieved by a nested if-then-else clause.
Thereby any number of mutually exclusive statement blocks can be
accommodated.

Example:
if (marks > 80)
grade = ’A’;
else if (marks > 60)
grade = ’B’;
else if (marks > 50)
grade = ’C’;
else
grade = ’F’;
1.10.5 Switch-case
The construct switch(), which is an extension of the if..else.. statement, is used
for efficient multiway branching. The switch statement tests the value of the
expression or variable, which is of type int or int compatible, against a list of case
Introduction to OOP unit1

values and when a match is found, a block of statements associated with that
case is executed. The syntax is as below:

switch (expression)
{
case value-1:
block-1;
break;
case value-2:
block-2;
break;
case value-3:
block-3;
break;
default :
default-block;
break;
}
statement-n;
When the switch is executed, the value of the expression is successfully
compared against the values, value-1, value-2, etc. If a case is found where
values matches with the value of the expression, then the block of statements
that follows the case is executed. If there exists no match then the default block
is executed. The default is optional. The break statement at the end of each
block indicates the end of a particular block and the execution resumes at
statement-n. If a break is not included in the end of each block, then all the
blocks following the block executed will also be executed.

To illustrate the usage of the switch construct, consider the following piece of
code:
Introduction to OOP unit1

Example:

/* To check if given character is a vowel */


#include <iostream.h>
void main()
{ char x;
cout << "\n enter any char : ";
cin>>x;
switch(x)
{
case 'A':
case 'a': cout<<x<<" is a vowel "<<endl;
break;
case 'E':
case 'e': cout<<x<<" is a vowel "<<endl;
break;
case 'I':
case 'i': cout<<x<<" is a vowel "<<endl;
break;
case 'O':
case 'o': cout<<x<<" is a vowel "<<endl;
break;
case 'U':
case 'u': cout<<x<<" is a vowel "<<endl;
break;
default : cout<<x<<" is not a vowel"<<endl;
}
}
1.11 PROGRAMMING CONTROL STATEMENTS
STATEMENTS AND BLOCKS
The basic format of a program in most structured programming languages is:
data <- Declaration portion
action <- control portion
All the computational part, that is the action and the data onto which the action is
performed are well separated in the modern programming languages for
Introduction to OOP unit1

reliability reasons. The action part is going to be a collection of computational


structures. The primitive structure is statements. For example

X = 4; I = I + 1;

The ; operates as a statement terminator. It is not necessary that a line should


have an assignment. For example, there can also be a statement just having a
semicolon. Such a statement is called as empty (null) statement. A line need not
always map to a legal ‘C++’ statement.

That is, line can also have more than one statement. This is logical because of
the fact that semicolon acts as a statement terminator. For example,

i = i + 1; I = 5;

There can also be a multiple statement. Note that = operates as an assignment


operator. That is the variable at the left hand side is assigned after the evaluation
of the expression at the right hand side and the result is stored in that variable at
the left hand side and hence this operator is called as assignment operator.
There can also be a multiple assignment statement. e.g p = q = r = 0;

This statement in one stroke assigns zero to all the three memory variables. This
is basically an initialization of three variables.

Brackets { and } are used to group declarations and statements together into a
compound statement. This set of compound statements enclosed within
parenthesis is called a block.

if (condition)
{
Block of statements
}
statement;

You have seen how to declare variables. It is also possible to declare variables
inside the block. The visibility of the variable is restricted to that block only.
Introduction to OOP unit1

In other words that variable whose scope is localised to a block is called a local
variable.
Example : void main()
{ int temp=20, x;
x = tem * 5;
}
The variables, temp and x, have been declared exclusively for this block and is
not accessible by a statement outside the block.

1.11.1 Goto Statement


Statements are executed as independent entities and they can be grouped as a
block. However, inside a block the execution is statement by statement. Then the
control is said to be sequential. This could be overridden by a goto construct. All
languages provide this feature. This takes the form

SYNTAX: goto <label>;

A label is any valid variable name and must be followed by a colon.


goto mahe; mahe:statement1:
mahe; statement1: goto mahe:

The label can be anywhere in the program either before or after the goto
statement. Note that such control transfer occurs unconditionally. It is obvious
that the goto breaks the normal sequential execution of the program.

This is basically a control jump, which could be either forward or backward.


Consider the following code,
Introduction to OOP unit1

Example:

# include <iostream.h>
void main()
{
char c;
take :
cout <<"Input the character (z to exit) :";
cin >> c;
if (c=='z')
cout << "You have typed the right character to exit";
else
{ cout<<endl<<"Entered character is "<<c<<endl;
goto take;
}
}
This program uses an unconditional transfer. Until the user enters z the control
will not come out of the loop.

1.11.2 For Loop


The looping computational structures can be achieved through many control
structures in ‘C++’. The for construct is one way of doing so. Loops can be
classified as entry controlled and exit controlled loops.

The for loop given below is an entry controlled loop.

SYNTAX:

for(initialization; test condition; modifier expression)

{ body of the loop }


The initialization part that controls the loop through a variable is called loop index
or control variable.

Initialization: The control variable is initialized first with a simple assignment


statement, c=0.
Introduction to OOP unit1

Test condition: The value of the control variable is tested using this test
condition. For each iteration this is performed. This is a relational expression,
such as i <10 which could determine the exit from the loop. If this relational
expression is true then the loop is executed again, otherwise control exits.

Modifier expression: At the end of the loop the control variable is transferred
back to the for statement. The control variable is modified, and the update value
of the control variable is again tested. If the condition is satisfied, the loop
continues, if not control exits.

Example:
#include <iostream.h>
//Program to print the first 100 natural numbers
void main()
{
cout <<endl<< "The first 100 natural numbers are "<<endl;
for (int i=1;i<=100;i++)
cout <<i<<"\t";
cout<<endl;
}

You could also write a program to display all the numbers from 100 to 1, using a
decrement (negative increment), as follows:

Example:

#include <iostream.h>
//Program to print the numbers from 100 to 1
void main()
{
cout <<endl<< "The first 100 natural numbers are "<<endl;
for (int i=100;i>0;i--)
cout <<i<<"\t";
cout<<endl;
}
Introduction to OOP unit1

One of the interesting points of this loop is that it is concise. All the three
operators – the initialization, the iterative test and the increment are stated in the
for statement.

1.11.3 The Continue Statement


This statement is used to go to the top of the loop from anywhere within the loop
during its execution.

Example:

# include <iostream.h>
void main()
{
long dividend,divisor; char ch;
do { cout << "Dividend :"; cin >> dividend;
cout << "Divisor :"; cin >> divisor;
if (divisor == 0)
{ cout << "Illegal Divisor \n";
continue; // Goto the top of the 'do' loop.
}
cout << "quotient" << dividend/divisor;
cout << "Remainder"<< dividend % divisor;
cout << "Repeat ? (y/n) :"; cin >> ch;
} while (ch!='n');

} // end of main

1.11.4 The Break Statement


In contrast to continue, break terminates the loop. It is usually used with for,
do..while, while loops and in the switch statement.
Introduction to OOP unit1

Nesting of the for loop

Nesting of the for loop is permissible in C++, i.e. a body of a for loop can also
have a for structure. To pictorially visualize this circumstance, look at the
following figure,

for (x=10;x>0;x--) x=10 y 1


//outer for loop begins 2
{ 3
for (y=1;y<=5;y++) 4
{ 5
…… x=9 y 1
2
} 3
…. 4
} // outer loop ends 5

In nested loops the inner loops are executed first and then the outer loops. The
nesting is permissible to any depth. For better degree of readability the loops are
to be indented properly.

Skipping a part of loop


It may be necessary to skip a part of the body of the loop. That is, when loop is
in execution, on certain condition the rest of the execution of the loop concerned
is to be ignored and the loop should continue for the next iteration.

The control statement called continue is used to achieve this. This function
causes the loop to be continued, with the next iteration after updating the control
variable, without executing the rest of the statements in the loop. The continue
statement can be used only inside a loop.

for (initialization; test condition; increment)


{
If (condition)
continue;
}

Example:
Introduction to OOP unit1

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


{
if (i==3)
continue;
cout << i;
}

For the above example, only i=1, 2, 4, 5 will be printed. When i is equal to 3,
control is returned to the beginning of the loop.

Comma operator

When the execution of the loop depends on two variables or two conditions the
for statement can be set up with two variables separated by a comma.

for (i=0,,j=n;i<=n;i++,,j--)

Note that the comma is included along with the usual semicolons. This is called
the comma operator.

Example:

#include <iostream.h>
//Program to print ascending and descending numbers
void main()
{
int n;
cout <<endl<< "Enter a number "<<endl;
cin>>n;
cout <<endl;
for (int i=0,j=n;i<=n;i++,j--)
cout <<i<<"\t"<<j<<endl;
cout<<endl;
}

Decision making and looping


Introduction to OOP unit1

You have seen the constructs for different types of decision making. Upon
testing or evaluating a conditional expression the decision to branch was made.

For example, in two way decision making, two distinct blocks of statements are
executed, depending upon the value returned by the test condition. Similarly,
instead of branching the control to either of these two blocks, you can also make
it to loop. Unlike the for loop, in this construct the number of times the block is
executed is not predetermined. Looping is based on a condition. The loop
termination is only by asserting the status, say true or false of the condition. The
while, do .. while construct allows this.

1.11.5 While loop


Looping on a condition can be achieved by the while construct of C++. This is
the simplest of all control structures.

SYNTAX:

while (test condition)


{
body of the loop
}
♦ This is an entry restricted loop
♦ That is, only on the condition being true the body of the loop is executed. In
other words, if the condition returns 0, the body of the loop is not executed
even once.
♦ This process of repeated execution, called iteration, continues until the test
condition returns false.
♦ On exiting from the loop, the control is transferred to the first statement
outside the loop.

Example:
#include <iostream.h>
Introduction to OOP unit1

//Program to print natural numbers 1.. 100 using while loop


void main()
{
int n=1;
cout <<endl<<"The numbers are ;"<<endl;
while (n<=100)
{
cout <<n<<"\t";
n++;
}
cout<<endl;
}

1.11.6 do Loop
An alternate to the while construct is the do control structure. This is also a
decision dependent looping. But the difference here is that the condition is
evaluated at the end, i.e. after executing the body of the loop once.

while basically was entry controlled. Therefore, the body of the loop may not be
executed even once. There are occasions in programming, wherein the
execution may have to be done at least once. This effect is achieved through the
do statement.

SYNTAX:

do
{
body of the loop
} while (condition);

On reaching the do statement, the control proceeds to execute the body of the
loop. When the while statement is reached, the condition is evaluated. If the
condition is true, control is transferred to the beginning of the do loop and the
program continues to execute the body of the loop. Otherwise control is
transferred out of the loop. This loop is an exit controlled loop because, the test
condition is evaluated at the bottom of the do while loop.
Introduction to OOP unit1

Example:

# include <iostream.h>
//Program to print natural numbers 1.. 100 using do .. while loop
void main()
{
int n=1;
cout <<endl<<"The numbers are ;"<<endl;
do
{
cout <<n<<"\t";
n++;
} while (n<=100);
cout<<endl;
}

1.12 OBJECTS AND CLASSES


A class is an abstract idea that can be represented with data structures and
functions. Functions associated with a class are called methods. An object is
said to be an instance of a class.

A class combines data and functions (procedures) into a single programming


unit. This is 'Encapsulation'. Data and procedures are tied together logically. The
parts that make up a class can be protected from the rest of the program to
varying degrees. The programmer has control over the protection of individual
entries in the class definition.
Introduction to OOP unit1

SYNTAX of the CLASS specifier


The class specifier starts with the keyword class, followed by class name. Like
a structure, the body of the class is delimited by braces and terminated by a
semicolon.

class try
{
private :
int num;
public :
void setdata(d) { num = d; }
};

1.12.1 Private And Public


A key feature of object - oriented programming is 'data - hiding' i.e., the data is
concealed within a class, so that it cannot be accessed mistakenly by functions
outside the class. 'private' and 'public' are two types of protection available within
a class.

Items marked with 'private' can only be accessed by methods defined as part of
the class. Data is most often defined as private. The private data 'num' is set to
a value 'd' by using the function setdata. Private members can be accessed by
members of the class.

Public items can be accessed from anywhere in the program without restrictions.
Class methods are usually public. As a general rule, data should not be declared
public. Public members can be accessed by members and objects of the
class.

1.12.2 Protected
This is another type of protection available within a class. Items declared as
protected are private within a class and are available for private access in the
derived class. The derived class concept is dealt with later in this book. The
protected access will be discussed again.
Introduction to OOP unit1

Consider a class 'smallobj' which has 'somedata' as its private member and
'setdata' and 'showdata' as its member functions which are public. These
functions provide the only access to the data item from outside the class. The
class is usually defined before main. Instances of the class are created and
used within main.

1.12.3 Example To Illustrate Class Concept


# include <iostream.h>
class smallobj
{ Class smallobj with 1 data member
private : and 2 methods, is declared.
int somedata;
public :
void setdata(int d) { somedata = d; }
void showdata()
{ cout << "\n Data is " << somedata; }
};
void main()
{
smallobj s1, s2;
s1.setdata(1066); s2.setdata(1776);
s1.showdata(); s2.showdata();
}

1.12.4 Class - Declaration And Usage


♦ Declare the class using the syntax given earlier.
♦ Defining Objects : Example – 1.12.3 defines two objects s1 and s2 of class
smallobj. Specification of the class does not create objects. It only describes
how they will look when they are created. It is the definition that actually
creates objects that can be used by the program and sets aside space for it
in memory.
♦ Calling Member Functions The member functions must always be called by
an object of it's class.
Introduction to OOP unit1

To use a member function the dot operator is used. The dot operator
connects the object name and the member function. The dot operator is
called the 'class member access operator'
SYNTAX is : objectname.functionname(arguments)
E.g.: s1.setdata(1066) in Example 1.12.3.

MESSAGES
Some object - oriented languages refer to calls to member functions as
'messages'. The term 'message' is not a part of the vocabulary of C++.

STRUCTURES AND CLASSES


The only formal difference between a class and structure is that in a class the
members are private by default, while in a structure they are public by default.
Structures can include functions but the commonly practiced way is to use the
structures for data structures and classes for member functions.

EXAMPLE: TO ILLUSTRATE CLASS V/S STRUCTURE


class try struct try
{ {
int data1 ; void func();
public : private :
void func(); int data1;
} }
In the class specification 'private' has been omitted as it is the default option. But
in structure 'public' has been omitted.

1.13 CONSTRUCTORS
Automatic Initialization is carried out using a special member function called the
'constructor'. It is a convenient way to initialize an object when it is first created
without the need to make a separate call to a member function. Thus, a
constructor is a member function that is executed automatically whenever an
object is created. Constructors may or may not take arguments, depending on
how the object is to be constructed. There is no return value from the
constructors.
Introduction to OOP unit1

A constructor always has the same name as the class itself. Every class has an
implicit constructor which need not be defined. It is called automatically for the
object as it is created. Constructors being functions, can be overloaded.

1.13.1 Example To Illustrate Constructors


# include <iostream.h>
class counter
{
private :
unsigned int count;
public :
counter() { count = 0; } // constructor
void inc_count () { count++; }
int getcount() { return count; }
};

void main()
{ counter c1,c2; // Here the constructor is activated twice , once for each object.
:
:program statements
:
}
1.14 DESTRUCTORS
This is activated when the object is destroyed automatically when the program
ends or when the program control passes to a statement outside the scope of
the object. A destructor has the same name as the class preceded by a tilde (~)
e.g. ~counter. Destructors also have no return value. They take no arguments.
The use of these functions is to free memory allocated for the object by the
constructor.

For e.g.: If an object is used as a local variable in a function, the destructor is


invoked when the compiler returns to the calling procedure.

1.15 OVERLOADED CONSTRUCTORS


Introduction to OOP unit1

Objects need to be initialized differently, thus the constructors can be overloaded


in the same way as overloading functions described earlier. However, note that
when there are constructors with arguments in the class an implicit constructor
also has to be written.

1.16 EXAMPLE TO ILLUSTRATE OVERLOADING CONSTRUCTORS


AND DESTRUCTORS
// myclass1.cpp
# include <iostream.h>
class myclass
{
private :
int num;
public :
myclass() { num = 0; } // default constructor
myclass(int n) { num = n; } // overloaded constructor
~myclass() { cout << "\nObject destroyed !"; } //default destructor
void getdata() // to enter the value
{
cout << endl << "Enter an integer :";
cin >> num;
}
void dispdata() // to display the value
{
cout << endl << "Num :" << num;
}
};

void main ()
{
myclass a1; // invokes default constructor
myclass b1 (5); // invokes overloaded constructor

a1.dispdata(); b1.dispdata(); // displays instantiated values


a1.getdata(); b1.getdata(); // enter new values
a1.dispdata(); b1.dispdata(); // displays new values

} // end of program.
Introduction to OOP unit1

1.17 FORMATTING DECIMAL NUMBERS


Formatting decimal numbers require manipulators other than setw().
Manipulators like setiosflags(ios ::fixed) are employed. A group of one-bit flags in
a long int in the 'ios' class determines how formatting will be carried out. To set
the concerned flags, you use the manipulator 'setiosflags' with the name of the
flag as an argument. The name must be preceded by the class name 'ios' and
the scope resolution operator(::).

The 'fixed' flag prevents numbers from being printed in exponential format. The
'showpoint' flag specifies that there will always be a decimal point, even if the
number has no fractional part. To set the precision to two digits to the right of the
decimal place, you use the 'setprecision' manipulator with the number of digits as
an argument. Once all these manipulators have been sent to cout, you can send
the number itself which will be displayed in the required format.

Formats set using the manipulators setiosflags and setprecision remain set till
another command is issued or you exit the program.

1.17.1 Example To Illustrates Formatting Decimal Numbers


# include <iostream.h>
# include <iomanip.h>
/* This program counts the number of instances i.e., the number of objects of
class try*/

void main()
{
int no = 1111; float basic = 2500, hra = 250; char name [ ] = "Bill Gates";

cout << "Formatted number output " ;


cout << endl << "No : " << no << endl << "Name : " << name;
cout << endl << "Basic :" << setiosflags(ios ::fixed)
<< setiosflags(ios::showpoint) << setprecision(2)
<< setw(10) << basic;
cout << endl << "HRA :" << setw(10) << hra;
cout << endl << "Total :" << setw(10) << basic + hra;
} // end of program
Introduction to OOP unit1

The output of this program is :


No : 1111
Name : Bill Gates
Basic : 2500.00
HRA : 250.00
Total : 2750.00

1.18 STATIC CLASS DATA


In the previous examples you saw that each object in a class had its own
separate data. Now if all the objects were to share one data, a slight change in
the class specification would be sufficient. The modification required would be to
give a keyword static for the data which is to be shared. If a data item in a class
is defined as static, then only one such item is created for the entire class, no
matter how many objects there are. A member variable defined as 'static' has
similar characteristics to a normal static variable. It is visible only within the class,
but its lifetime is the entire program.

Some compilers automatically initialize a static data item, while others do not.
Introduction to OOP unit1

1.18.1 TO ILLUSTRATE STATIC CLASS DATA and STATIC


FUNCTION
/* This program counts the number of instances
i.e. the number of objects of class try */
# include <iostream.h>
class try
{
private :
int id;
static int tot;
public :
try () { tot++; id=tot; } // incremented each time an object is created
void print() { cout << " Id is :" << id << endl; }
static void printcount()
{cout << "\nNumber of instances are "<< tot<< endl; }
};
int try::tot = 0; // some compilers may require this initialization

void main()
{
try f1; cout << endl<< "f1:"; f1.print();
try f2; cout << endl<< "f2:"; f2.print();
try f3; cout << endl<< "f3:"; f3.print();
try :: printcount();
}

OUTPUT OF EXAMPLE 1.18.1

f1 : Id is : 1
f2 : Id is : 2
f3 : Id is : 3
Number of instances are 3
Introduction to OOP unit1

Note If a static variable was not used, count for each object would be 1.
printcount is a static function and therefore can be called directly from
main without associating it to an object, try :: printcount();

1.19 EXERCISE
1. Write a program to sort an array of numbers.
2. Write a program to display the reverse of an input string.
3. Write a program to count the number of vowels in the input string and plot it
in the form of a horizontal histogram.
E.g. MAHE E.g. MANIPAL
A # A ##
E # E
I I #
O O
U U
4. Write a program to display the alphabet set along with its ASCII values in a
neat format.
5. Construct a distance class. It consists of two data members - feet (int) and
inches (float). The class must take care of the following :
Objects of the class can be initialized (instantiated)
User can enter data for the object - (if inches exceed 12; increment feet by 1
and reduce inches by 12)
User can display the object
Display the message - "Object destroyed" when the program ends.
6. Create a class to store a string. Include member functions to input and output
the data member. Also include the constructors and the destructors.
7. Create a class called time that has separate int member for hours, minutes
and seconds. The class should contain member functions to initialise the int
values to 0 or any other values. A member function should display the time in
hr:mm:ss format. The final member function should add 2 objects of type
time passed as arguments.
Introduction to OOP unit1

1.20 SUMMARY
Object Oriented Programming is a way of organizing programs. The emphasis is
on the way programs are designed, not on the individual operators. OOP
programs are organized around objects, which contains both data and functions
that act on that data. A class is a template for number of objects.

C++ is a superset of C. It adds to the C language the capability to implement


OOP. It also adds a variety of other features .

A major building block of C++ programs is the function. A function named main( )
is always the first one executed when a program is executed. A function is
composed of statement which tells the computer to do something. Each
statement ends with a semicolon. A statement may contain one or more
expressions, which are sequences of variables and operators that usually
evaluate to a specific value.

Output is most commonly handled in C++ with cout object and << insertion
operator, which together cause variables or constants to be sent to the standard
output device – usually the screen. Input is handled with cin and the extraction
operator >> which causes values to be received from the standard input device –
usually the keyboard.

The built – in data types in C++ are: Char, int and long, float, double, double
long. C++ employs the arithmetic operators +, -, *, / and %. The assignment
operators +=, -=, /*, *=, %=. The increment and decrement operators ++ and –
increase or decrease a variable by 1.
Introduction to OOP unit1

Answers to EXERCISE 1.19

1. # include <iostream.h>
void main()
{ int num[10],i,j,temp;

cout << "Enter 10 numbers"<<endl;


for (i=0;i<10;i++)
cin >> num[i];
for (i=0;i<9;i++)
{ for (j=i+1;j<10;j++)
{
if (num[i]>num[j])
{ temp = num[i];
num[i] = num[j];
num[j] = temp; } } }
cout << "Numbers in ascending order "<<endl;

for (i=0;i<10;i++)
cout << num[i]<<"\t";
cout<<endl;
}

2. // reverse a string
# include <iostream.h>
# include <string.h>
void main()
{ char name[50];
cout<<"input a string"<<endl;
cin.getline(name,'\n');
int n=strlen(name);
for (int i=n-1;i>=0;i--)
cout<<name[i]<<endl;
}

3. # include<iostream.h>
Introduction to OOP unit1

void main()
{ char s[80],row[5];
int a[]= {0,0,0,0,0};
int i,j;
row[0]='a';
row[1]='e';
row[2]='i';
row[3]='o';
row[4]='u';
cout<<"enter a string:";
cin.getline(s,'\n');
for (i=0;s[i]!='\0';i++)
{
switch(s[i])
{ case 'A':
case 'a': a[0]++;
break;
case 'E':
case 'e': a[1]++;
break;
case 'I':
case 'i': a[2]++;
break;
case 'O':
case 'o': a[3]++;
break;
case 'U':
case 'u': a[4]++;
break;
default : break;
}
}
for (i=0;i<5;i++)
{ cout<<row[i]<<"\t";
for (j=1;j<=a[i];j++)
Introduction to OOP unit1

cout<<"#";
cout<<endl;
}
}
4. //program to display the alphabet set
# include<iostream.h>
void main()
{ int c;
for (c=65;c<=122;c++)
{ if (c>90 && c<97)
continue;
cout<<c<<"="<<(char)c<<"\t";
}
}

5. #include<iostream.h>
class distance
{ private : int feet;
float inches;
public :
distance() {feet=0;inches=0.0;}
distance(int f,float i){feet=f; inches=i;}
void getdist()
{ cout<< "Enter the feet";cin>>feet;
cout<< "enter the inches";cin>>inches;
while(inches>=12)
{ feet++;
inches-=12;
}
}
void showdist()
{ cout<<feet<< "\'-"<< inches<< "\"";}
~distance()
{cout<<"Object destroyed"<<endl;}
};
Introduction to OOP unit1

void main()
{ distance d1,d2(5,40.0);
d2.showdist();
d1.getdist();
d1.showdist();
}

6. # include <iostream.h>
# include <string.h>
class string
{
private : char *str;
public : string() {str= new char[1]; strcpy(str,"\0");}
string(char *s) {str=new char[strlen(s)+1];strcpy(str,s);}
void getdata()
{ cout <<"enter a string";
cin.getline(str,'\n');
}
void dispdata()
{ cout <<"String entered is "<<str<<endl;}
~string() {delete str;cout<<"\n Destroy"; }
};
void main()
{
string s1("welcome"),s2;
s1.dispdata();
s2.getdata();
s2.dispdata();
}
7. #include <iostream.h>
class time
{private : int hrs,mins,secs;
public :
time() { hrs=0;mins=0;secs=0;}
time(int h, int m, int s) { hrs=h;
mins=m;
Introduction to OOP unit1

secs=s;}
void getdata()
{ cout<< "Enter hours";cin>>hrs;
cout<< "Enter minutes";cin>>mins;
cout<< "Enter seconds";cin>>secs;
while(secs>=60)
{ secs-=60;
mins++;}
while(mins>59)
{ mins-=60;
hrs++;}
}
void dispdata()
{ cout<<hrs<<":"<<mins<<":"<<secs<<endl;
}

void add_time(time t1,time t2)


{ secs=t1.secs+t2.secs;
mins=t1.mins+t2.mins;
hrs=t1.hrs+t2.hrs;
if (secs>=60)
{ secs-=60; mins++;}
if (mins>=60)
{mins-=60; hrs++;}
}
};
void main()
{ time time1,time2,time3;
time1.getdata();
time2.getdata();
time1.dispdata();
time2.dispdata();
time3.add_time(time1,time2);
time3.dispdata();
}
Introduction to OOP unit1

UNIT 2 OPERATOR OVERLOADING, INHERITANCE

Structure
2.0 Introduction
2.1 Objectives
2.2 Operator Overloading
2.3 Overloading Unary Operators
2.3.1 Nameless Temporary Objects
2.3.2 Limitation of Increment Operators
2.4 Overloading Binary Operator
2.4.1 Overloading Arithmetic Operators
2.4.2 Concatenating String's using '+'
2.4.3 Copy Constructor
2.4.4 Exercise to implement the String class
2.5 Multiple Overloading
2.5.1 Overloading Comparison Operators
2.5.2 Overloading Assignment Operators
2.6 Data Conversion
2.6.1 Conversions between Basic types
2.6.2 Conversions between Objects and Basic types
2.6.3 Conversions between Objects of different classes
2.7 Function Overloading
2.8 Exercise to store Employee information
2.9 Inheritance
2.9.1 Derived Class and Base Class
2.9.2 Derived Class Constructors
2.9.3 Overriding Member Functions
2.9.4 Private and Public Inheritance
2.9.5 Access Specifiers - When to use what?
2.9.6 Class Hierarchies
2.9.7 Abstract Base Class
2.10 Levels of Inheritance

2.11 Multiple Inheritance


2.11.1 Member functions in Multiple Inheritance
Introduction to OOP unit1

2.11.2 Constructors in Multiple Inheritance


2.11.3 Ambiguity in Multiple Inheritance
2.12 Containership: Classes within classes
2.13 Inheritance and Program Development
2.14 Exercise
2.15 Summary

2.0 INTRODUCTION
Operator Overloading is one of the most exciting features of OOP.
Operator Overloading gives you the opportunity to redefine the C++
language within a class. By using classes to create new kinds of variables,
and operator overloading to create new definition for operator, you can
extend C++ to be a new language of your own design. Another kind of
operation, data type conversion, is closely connected with Operator
Overloading in C++. C++ handles the conversion of simple types like int
and float automatically, but conversions involving user-defined types
require some work on the programmers part.
OOP uses a method called Inheritance to modify a class to set ones
need. Modifying a class library does not require compilation. There is no
modifying of any class from the library. Inheritance means deriving new
classes from the base class from the existing class. The existing class is
called as base class and the class, which is derived, is called the derived
class. Deriving a new class from an existing one allows redefining a
member function of the base class and also adding new members to the
derived class.

2.1 OBJECTIVES
At the end of this unit you will be able to,
♦ Overload the unary and binary operators.
♦ Convert basic data type to user-defined data type and visa – versa.
♦ Overload functions
♦ Create new classes from existing classes.

2.2 OPERATOR OVERLOADING


C++ programs can overload existing operators with some other
operations. If the operator is not used in the context as defined by the
Introduction to OOP unit1

language, then the overloaded operator if defined will be executed.


Overloaded operators are those that have been redefined within a C++
class using the keyword 'operator' followed by an operator symbol. All
operators can be overloaded except . , .* , :: , ?= and preprocessor
symbols #, ##. So, the term operator overloading refers to giving the
primitive C++ operator additional functionality when they are applied to
user-defined data types.

2.3 OVERLOADING UNARY OPERATORS


Unary operators as discussed earlier are +, -, ++ and --. The syntax of
overloading is:

return type operator unary operator (arguments) { function body }

Example 2.1: Overloading The Unary Operator ++


# include <iostream.h>

class counter
{
private : unsigned int count;
public : counter() {count = 0;}
int get_count () {return count;}
void operator ++ () { count++;} ++ overloaded
};

void main()
{
counter c1,c2;
cout << "\nc1 = " << c1.get_count();
cout << "\tc2 = " << c2.get_count();
c1++; c2++; ++c2; // Using overloaded ++ operator.
cout << "\nc1 = " << c1.get_count();
Introduction to OOP unit1

cout << "\tc2 = " << c2.get_count();


}

Output of Example 2.1


c1 = 0 c2 = 0
c1 = 1 c2 = 2

The operator is applied once to c1 and twice to c2. Both prefix and postfix
notation is used on c2.

The function declaration void operator ++ () tells the compiler to call this member
function whenever the ++ operator is encountered, provided the operand is of
type counter. Since member functions can always access the particular object
for which they have been called, this operator requires no arguments. So, if the
operand is a basic type like an int, the compiler will use its built-in routine to
increment it.

Notice that the return type of the operator is void. Therefore, it does not return
any value. Hence, it cannot be used in assignment statements as in c1 = c2++;
To rectify this, you have to specify the return type as the name of the object,
create a temporary object and return it. This is shown in Example 2.2.

In this program, operator overloading is done as follows:

1. member data count is incremented


2. a new item temp is created of counter type
3. the incremented value is assigned to this variable - temp

4. temp is returned.

Expressions like c1++ now return a value, so they can be used in other
expressions such as c2 = c1++; and c2++.get_count();
Example 2.2: Illustrates Operator Return Values
# include <iostream.h>
class counter
{
Introduction to OOP unit1

private : unsigned int count;


public : counter() { count = 0; }
counter(int x) { count = x; }
int get_count() {return count;}
counter operator ++ ()
{ count ++;
counter temp;
temp.count = count;
return temp;
}
};

void main()
{
counter c1,c2;
cout << "\nc1 = " << c1.get_count() << "\nc2 = " << c2.get_count();
c1++; c2 = c1++;
cout << "\nc1 = " << c1.get_count() << "\nc2 = " << c2++.get_count();
}

2.3.1 Nameless Temporary Objects


In Example 2.2, a temporary object of type counter was created for the
exclusive purpose of providing a return value for the ++ operator. The next
example shows another approach to the same problem without using a
temporary object.
Example 2.3: Illustrates Nameless Temporary Objects
# include <iostream.h>
class counter
{
private : unsigned int count;
Introduction to OOP unit1

public : counter () {count = 0;}


counter (int c) { count = c; }
int get_count() { return count; }
counter operator ++ ()
{
count++;
return (*this);
}
};

void main()

{
counter c1,c2;

cout << "\nc1 = " << c1.get_count() << "\nc2 = " << c2.get_count();

c1++; c2 = c1++;

cout << "\nc1 = " << c1.get_count() << "\nc2 = " << c2++.get_count();
}

this is a special pointer that points to the current object. It has been used here
to return the incremented value without creating a new object.

2.3.2 Limitation Of Increment Operators

When applied to basic data types prefix and postfix operators are two
different operators. But when they are overloaded there is no distinction
between prefix and postfix notation. The expression c2 = c1++ has
exactly the same effect as c2 = ++c1; In both cases c1 is assigned to c2.
If you need the basic data type implementation for the overloaded
function, then it requires two overloaded operators, one for prefix and one
for postfix.
operator ++ (); // prefix. operator ++ (int); // postfix.
Introduction to OOP unit1

The second declaration uses a dummy int argument, which is set to 0


automatically by the postfix ++ operator. This extra argument allows the
compiler to distinguish the two forms.
2.4 OVERLOADING BINARY OPERATORS

This is very similar to overloading unary operators. This section is divided


into two parts: overloading arithmetic operators, overloading comparison
operators.
2.4.1 Overloading Arithmetic Operators
The first example in this section illustrates overloading arithmetic operator
'+' to add objects of class distance. The second example illustrates
overloading '+' to add polar co-ordinates.
EXAMPLE 2.4 Illustrates Overloading '+' To Add Objects Of Class Distance
# include <iostream.h>
class distance
{ private : int feet;
float inches;

public : distance () { feet = 0; inches = 0.0; }


distance (int ft, float in) { feet = ft; inches = in; }
void getdist()
{ cout << "\nEnter feet : "; cin >> feet;
cout << "\nEnter inches : "; cin >> inches; }
void showdist()
{ cout << feet << "\'-" << inches << '\"'; }
distance operator + (distance); };

distance distance :: operator + (distance d2)


{
int f = feet + d2.feet;

float i = inches + d2.inches;

while (i >= 12.0)


Introduction to OOP unit1

{ i -= 12.0; f++; }

return distance (f,i);

/* temporary variable is not created, the overloaded constructor is called to


create distance(f, i) this is automatically returned. */ }

void main()

{
distance dist1; distance dist2(11,6.25);
dist1.getdist();

distance dist3 = dist1 + dist2;


distance dist4 = dist1 + dist2 + dist3;
cout << "\ndist1 = "; dist1.showdist();
cout << "\ndist2 = "; dist2.showdist();
cout << "\ndist3 = "; dist3.showdist();
cout << "\ndist4 = "; dist4.showdist();

In class 'distance' the declaration for the operator + () function looks


like distance operator + (distance); the function returns a value of type
'distance' and takes one argument of type 'distance'.

When the compiler encounters an expression like distance dist3 = dist1 +


dist2; and finding only distance argument types, it uses the member
function operator + (). Note that though '+' operator needs two operators,
only one is supplied to the function. The answer lies in the fact that the
argument on the left of the operator (here, dist1) is the object of which the
operator is a member function and the object on the right of the operator
(dist2) is furnished as an argument to the operator.

In operator + () function, the left operand is accessed directly - since this


is the object of which the function is a member - using feet and inches.
The right operand is accessed as function's argument, as d2.feet and
d2.inches. The operator returns a value, which can be assigned or used in
other ways; in this case, it is assigned to dist3.
Introduction to OOP unit1

Generalizing this, an overloaded operator always requires one less


argument than its number of operands, since one operand is the object of
which the operator is a member function. Hence unary operators require
no arguments (See Example 2.1).
Adding Polar Coordinates By Overloading '+'Operator

The formula to convert from polar to rectangular co-ordinates are :


x = radius * cos(angle); y = radius * sin(angle);

To convert from rectangular to polar, you use :

angle = atan (y/x); radius = sqrt (x * x + y * y);

EXAMPLE 2.5 Illustrates Adding Polar Coordinates


# include <stdio.h>
# include <math.h>
class polar
{ private : double radius;
double angle;
double getx() { return radius * cos(angle); }
double gety() { return radius * sin(angle); }
public :
polar () { radius = 0.0; angle = 0.0; }
polar (float r, float a)
{ radius = r; angle = a; }
void display()
{ cout << "(" << radius << "," << angle << ")"; }
polar operator + (polar p2)
{ double x = getx() + p2.getx();
double y = gety() + p2.gety();
double r = sqrt (x * x + y * y);
double a = atan(y/x);
return polar(r,a); } };
Introduction to OOP unit1

void main()
{
polar p1(10.0,0.0);
polar p2(10.0,1.570796325);
polar p3;
p3 = p1 + p2;
cout << "\np1 = "; p1.display();
cout << "\np2 = "; p2.display();
cout << "\np3 = "; p3.display();
}

2.4.2 Concatenating Strings Using '+'


Concatenation is the process of joining 2 strings into one. This is
achieved using the function strcpy or strcat, prototyped in string.h. The '+'
operator can be overloaded to concatenate two strings.
2.4.3 Copy Constructor
When a class is being designed, the designer normally supplies the default
constructor and the overloaded constructor. For example, to instantiate an
object of class, class1,

class1 cl1; default constructor will be called.


class1 cl1(100); default constructor will be called.
Suppose,
class1 cl1; default constructor will be called.
class1 cl2(cl1) ; A memberwise copy takes place.
or
class1 cl2=cl1; A memberwise copy takes place.

To prevent this memberwise copy, it is necessary to provide the copy


constructor.
The memberwise copy which the compiler does is dangerous if the object
contains a pointer. For example,
class class1
{ private : char *name;
Introduction to OOP unit1

public :
class1() { strcpy(name,"\0");}
};

class1 cl1;

creates object cl1, with a pointer named, name pointing at a memory location x,
initialized to NULL.

class1 cl2(cl1);

creates object cl2, with a pointer named name pointing at memory x,


which is copied from cl1.
Due to the memberwise copy, both objects have pointers pointing at the
same memory location, resulting in one object being dependent on the
other. Therefore, it is necessary to provide a copy constructor in this
class. The use of the copy constructor is demonstrated in the exercise
that follows.

2.4.4 Exercise To Implement The String Class.

Create a string class. Provide default constructor, overloaded constructor


and copy constructor.
#include <iostream.h>

#include <string.h>

#include <conio.h>

class string
{
private :
char *str;
public :
string() {str=new char[1];strcpy(str,"\0");}
string(char *s) {str = new char[strlen(s)+1]; strcpy(str,s);}
string(string &s) {str=strdup(s.str);cout<<"\ncopy called";}
Introduction to OOP unit1

show() {cout << endl<< str;}


change(char *ss) {strcpy(str,ss);}

// Overloading the assignment operator so that memberwise copy does not take
place.
string& operator = (string &s)
{
str= strdup(s.str);
cout << "\n assignment called";
return (*this);
}

// destructor to free the memory


~string() { delete str; cout<< "\n destroy";}
};
main()
{
clrscr();
string s1("welcome"); // Calls overloaded constructor
string s2=s1; //Calls copy constructor
string s3(s2); //Calls copy constructor
string s4;
s4=s1; //Calls overloaded assignment
s1.show();
s2.show();
s3.show();
s4.show();
s1.change("\t changed");
s1.show();
s2.show();
s3.show();
s4.show();
Introduction to OOP unit1

getch();}
2.5 MULTIPLE OVERLOADING

Overloading '+' operator to add objects of class distance, to add polar co-
ordinates and to concatenate two strings can be done in the same
program. The procedure is known as multiple overloading. The compiler
selects the correct function to carry out the "addition" based on the type of
the operand.

2.5.1 Overloading Comparison Operators


Just as the arithmetic operators have been overloaded, the relational
operators can also be overloaded.

The following example shows how to overload the 'less than' (<) operator.

EXAMPLE 2.6 OVERLOADING COMPARISON OPERATORS

#include <iostream.h>
enum boolean {false,true};
class distance
{ private : int feet;
float inches;
public : distance ()
{ feet=0, inches=0.0; }
distance (int ft, float in)
{ feet=ft; inches=in; }
void getdist()
{ cout<<" \nEnter feet :"; cin >> feet;
cout<<" \nEnter inches :"; cin >> inches; }
void showdist()
{ cout<< feet<< "\'-" << inches << "\" "; }

boolean operator <(distance d2)


Introduction to OOP unit1

{ float bf1 = feet + inches/12;


float bf2 = d2.feet+ d2.inches/12;
return (bf1<bf2)? true:false; }
};
void main()
{ distance dist1, dist2;
dist1.getdist(); dist2.getdist();
cout<<"\n dist1= " ; dist1.showdist();
cout<<"\n dist2= " ; dist2.showdist();
if (dist1<dist2) cout << "\ndist1 is less than dist2";
else cout << "\ndist1 is greater than dist2";
}

The approach used in the operator < () function in example 2.6 is similar to
overloading the + operator in example 2.4 except that here the overloaded
function operator < ( ) has a return type of boolean (defined in the enum
statement at the beginning of the program). The return value is true or false,
depending on the comparison of the two distances. The comparison is made by
converting both distances to floating point feet and comparing them using the
normal < operator.

2.5.2 Overloading Assignment Operator

In the following example, you shall overload the += operator. This


operator combines the addition and assignment into one step.

x+=y is the same as x=x+y

EXAMPLE 2.7 OVERLOADING += OPERATOR

#include <iostream.h>
class distance
Introduction to OOP unit1

{ private : int feet ;


float inches;
public : distance () { feet = 0 ; inches = 0.0;}
distance (int ft, float in) { feet =ft; inches = in; }
void get_dist()
{ cout << " \n Enter feet:"; cin>> feet;
cout << "\n Enter Inches:"; cin >> inches; }
void show_dist()
{ cout << feet << "\'-" <<inches << ‘\"'; }
void operator += (distance); // function prototype
};
void distance :: operator += (distance d2) // function declared externally
{ feet += d2.feet; inches += d2.inches;
if (inches >=12.0) { inches -= 12.0; feet++; }
}

void main()
{ distance dist1; distance dist2(11,6.25);
dist1.get_dist(); cout<< "\ndist1="; dist1.show_dist();
cout << "\ndist2 = "; dist2.showdist();
dist1 += dist2; cout << "\n After addition";
cout << "\ndist1 = "; dist1.showdist();
}

In the operator += () function in the above example, the object that takes on the
value of the sum is the object of which the function is a member. Thus, it is feet
and inches that are given values, not temporary variables used only to return an
object.

2.6 DATA CONVERSION

The = operator will assign a value from one variable to another in


statements like i1 = i2; where i1 and i2 are integer variables or user
defined objects. Thus, assignments between types - Basic or
userdefined, are handled by the compiler without any special instructions.
Introduction to OOP unit1

2.6.1 Conversions Between Basic Types


To convert between basic types you use 'casting'. Casting provides
explicit conversion between datatypes. Implicit conversion occurs during
evaluation of mixed expressions.
Example
int x,y;
float z;

x = (x + y) / z;

Since z is a float datatype, (x+y) is converted to float implicitly by the


compiler. The result is stored in x by implicit conversion to int.
2.6.2 Conversions Between Objects And Basic Types
The conversion between object and Basic data types needs a separate
routine to define the conversion. The following example shows how to
convert between a basic data type and a user defined data type.
Example 2.8 Illustrates Conversions Between Objects And Basic
Types
// converts distance to meters and vice-versa.
# include <iostream.h>
const float MTF = 3.280833;

class distance
{ private : int feet; float inches;
public : distance() {feet = 0; inches = 0.0;}
distance (int ft, float in) { feet = ft; inches = in;}
distance(float meters)
{ float fltfeet = MTF * meters;
feet = int (fltfeet);
inches = 12 * (fltfeet - feet); }
Introduction to OOP unit1

void getdist()
{ cout <<"\n Enter feet :"; cin >> feet;
cout <<"\n Enter inches :"; cin >> inches; }
void showdist() { cout << feet << "\'-" << inches << '\"';}

operator float ()
{ float f = inches / 12;
f= f+float (feet);
return f/MTF;
}
};
void main() {
Distance dist1 = 2.35;
cout << "\ndist1 = "; dist1.showdist();
dist1 = 0.0; cout << "\ndist1 = "; dist1.showdist();
distance dist2(5,10.25);
float meters = float (dist2); // uses conversion function to convert
cout << "\ndist2 = " << meters << "meters";
meters = dist1; cout << "\ndist1 = " << meters << "meters ";
}
Example 2.8 illustrates both types of conversions - basic to
userdefined and vice-versa.
From Basic To User-Defined
The constructor, distance (float meters) converts a basic data type (float) to
user defined data type (distance). This function is called when an object of type
distance is created with a single argument. The function assumes this argument
represents meters. It converts the argument to feet and inches, and assigns the
resulting values to the objects data members.

From User-Defined To Basic


Introduction to OOP unit1

Here, you overload the cast operator, thus creating a conversion function. The
function in example 2.8 which achieves this is the operator float() function. This
operator takes the value of the distance object of which it is a member, converts
this value to a float value representing meters and returns this value. This
operator is called by the statement, meters = float (dist2);

The statement meters = dist1 also has the same effect. Here, the
compiler starts by looking for an overloaded = operator. But, when it
doesn't find one and it sees the conversion function, it uses that instead.

EXAMPLE 2.9 Conversion Between Strings And String Objects

// Convert between ordinary strings and class string.

# include <iostream.h>
# include <string.h>

const int sz = 80;

class string

{ private : char str[sz];


public : string() {str[0] = '\0';}
string(char s[]) // Convert string to class string object.

{ strcpy(str,s);}
void display() { cout << str; }

operator char * () { return str; }


};

void main()
{ string s1; char xstr[50] = "\nManipal Institute";
s1 = xstr; // uses 1-argument constructor.
Introduction to OOP unit1

s1.display();
string s2 = " Of Computer Education.\n";
strcpy(xstr,s2); //uses conversion function.
cout << xstr;
}

Output of Example 2.9

Manipal Institute Of Computer Education.

2.6.3 Conversions Between Objects Of Different Classes

Conversions between objects of different classes can be done in the


same way as the conversion between basic and user-defined types. This
topic can be studied under two sections:
♦ Conversion routine in source object.
♦ Conversion routine in destination object.

Routine In Source Object

When the conversion routine is in the source class, it is implemented as a


conversion function. Example 2.10 shows the conversion between class rec and
class polar.

Example 2.10 Conversion From Polar To Class Rec Using Routine In


Polar (Source Object).
# include <iostream.h>
# include <math.h>
class rec
{ private: double xco, yco;
public : rec() { xco = 0.0; yco = 0.0;}
rec(double x, double y)
{ xco = x; yco = y;}
void display()
Introduction to OOP unit1

{ cout <<"(" << xco << "," << yco << ")";}
}; // end of rec class declaration
class polar
{ private: double radius,angle;
public : polar() { radius = 0.0; angle = 0.0; }
polar(double r, double a)
{ radius = r; angle = a;}
void display()
{ cout <<"(" << radius << "," << angle << ")";}
operator rec()
{ double x = radius * cos(angle);
double y = radius * sin (angle);
return rec(x,y);
}
}; // end of polar class declaration
void main()
{ rec rec1; polar pol1(10.0,0.785398);
rec1 = pol1;
cout << "\npol1 = "; pol1.display(); cout << "\nrec1 = "; rec1.display();
}
In example 2.10 the statement rec1 = pol1; needs conversion as rec and pol are
objects of two different classes. The conversion function is written as a member
function of the polar class (i.e. source object).

Routine In Destination Object


In example 2.10 you defined the conversion routine in the source object
as its member function. The following example illustrates how to define
the routine in the destination object. For this, you use a constructor with
one argument.
Example 2.11 Converts From Polar To Rec Using Routine In Class
Rec Destination).
Introduction to OOP unit1

# include <iostream.h>
# include <math.h>
class polar
{ private : double radius, angle;
public : polar() { radius = 0.0; angle = 0.0;}
polar (double r, double a) { radius = r; angle = a; }
void display() { cout << "(" << radius << "," << angle << ")"; }
double getr() { return radius; }
double geta() { return angle; }
};

class rec
{ private : double xco, yco;
public : rec() { xco = 0.0; yco = 0.0; }
rec(double x, double y) { xco = x; yco = y; }
void display()
{cout << "(" << xco << "," << yco << ")"; }
rec(polar p)
{
float r = p.getr(); float a = p.geta();
xco = r * cos(a); yco = r * sin(a);
}
};

void main()
{ rec rec1; polar pol1(10.0,0.785398);
rec1 = pol1;
cout << "\npol1 = "; pol1.display(); cout << "\nrec1 = "; rec1.display();
}
Introduction to OOP unit1

The conversion routine is a one-argument constructor, from the rec class


rec(polar p). The function sets the object of which it is a member to the
rectangular coordinates that correspond to the polar coordinates of the
object received as an argument.

To perform the conversion, this constructor must be able to access the data
values of the polar object sent as an argument. The polar class contains the two
routines to allow this double getr(); and double geta();.

The statement rec1 = pol1 in main() of example 2.11 invokes the one -
argument constructor and the conversion is done.

Table 2.1 Conversions - When To Use What ?

Conversion Type Routine in Destination Routine in Source

Basic to Basic (Built - in Conversion Functions)

Basic to Class Constructor NA

Class to Basic Not available Conversion function

Class to Class Constructor Conversion function

Precautions While Overloading


Use similar meaning : Do not overload '+' operator for subtraction. It can
be confusing to the user.
♦ Use similar syntax : For better readability and reusability, try to use syntax
similar to the existing usage of the operator.
♦ Restrict the number : Too many overloaded operators causes the listing to
be less readable instead of more.
♦ Avoid ambiguity : Avoid doing the same conversion in more than one way
as the compiler will not know which function to use.
♦ Not all operators can be overloaded : Operators that cannot be overloaded
are :
Introduction to OOP unit1

:: - Scope resolution operator ?: - Conditional operator


.* - Pointer to member operator . - Dot operator

2.7 Function Overloading

The following example illustrates overloading of functions. The function cout


used in the example is an output function, provided in iostream.h. It displays the
message/value on standard output (normally the VDU.)

In this example, a function 'repchar' is overloaded to print a sequence of


characters. What should be the output if there are no arguments or if there is
one character as argument or if there is one character and one integer as the
argument depends on the function body of the respective functions.

The function definition for each function is written according to the data it
receives. Thus, there will be three different functions with the same name but
with a different set of arguments and a different function definition for each.

Example 2.12

# include <iostream.h>
void repchar();
void repchar(char);
void repchar(char, int);
void main()
{
repchar(); // prints + 45 times.
repchar('='); // prints = 45 times.
repchar('>',30); // prints > 30 times.
} // end of main

void repchar() {
for (int j = 0; j<45; j++)
cout << '+';
Introduction to OOP unit1

cout << endl;


}
void repchar(char ch) {
for (int j = 0; j<45; j++)
cout << ch;
cout << endl;
}

void repchar (char ch, int n)


{
for (int j = 0; j < n; j++)
cout << ch;
cout << endl;
}
Output for the above example will be as follows:

+++++++++++++++++++++++++++++++++++++++++++++
=============================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2.8 EXERCISE TO STORE EMPLOYEE INFORMATION

/* class employee stores employee information. You can use calc() function to
return average salary */
# include <istream.h>
#include <string.h> // to use strings
class employee
{
private :
int eno;
char name[20];
int basic;
Introduction to OOP unit1

public:
void getdata() // to enter the data
{ cout << “Enter employee no:”; cin>> eno; cin.get();
cout <<“Enter name :”; cin.getline(name,’\n’);
cout <<“Enter Salary :”; cin>>basic;
}

void dispdata() // to display the value


{ cout << “Employee no:” <<eno;
cout << “Name :”<<name;
cout << “Salary :”<<basic;
Parameter received
}
float calc(employee x)
{ float temp;
temp= (float(basic)+x.basic)/2; // int basic is casted to float type
return temp; basic of object that calls calc()
function -i.e. instance varible
};

void main()
{ employee a1, b1;
a1.getdata(); b1.getdata();
float average =a1.calc(b1); /* object a1, invoke function calc(), b1 is passed
as parameter */
cout << endl<<“Average salary: “<< average;
} // end of program

2.9 INHERITANCE

Inheritance is the process of creating new classes, called derived classes,


from existing classes, the existing class is the base class. The derived
class inherits all the capabilities of the base class but can add properties
Introduction to OOP unit1

of its own. The base class is unchanged by this process. Inheritance has
two important advantages.
♦ Code reusability : it permits code reusability. Once a base class is written and
debugged, it need not be checked again, but can nevertheless be adapted to
work in different situations. Reusing code saves time and money and
increases a program's reliability. A programmer can use a class created by
another person or company, and without modifying it, derive other classes
from it that are suited to particular situations.

♦ The derived class can add data and function members to the class without
affecting the base class behavior. This is data abstraction.

♦ The protection can be increased in derived classes, but cannot be


decreased, that is - a class item declared as protected in a class cannot be
made public later in the derived classes. Making a public item protected or
private in a derived class is allowed.

2.9.1 Derived Class And Base Class


To derive from another class, the class declaration is modified. The base class
name is linked with the new class name, when the class is declared as :

class derived_class_name : public base_class_name

Access specifiers public or private can be used while deriving from the base
class. This determines the availability of the base class members to derived
class.

Example 2.14 Illustrates Derived And Base Classes

// Inheritance with counter class


# include <iostream.h>
class counter // base class

{ protected : unsigned int count; // Note : not private

public : counter ( ) {count = 0;}


Introduction to OOP unit1

counter (int c) {count = c;}


int getcount( ) {return count;}
counter operator ++ ( ) { count++; return counter(count); }
};
class countdown : public counter // Derived class
{ public : counter operator -- ( )

{ count--; return counter(count); }


};

void main( )
{ countdown c1;
cout << "\nc1 = " << c1.getcount( );
c1++; c1++; c1++;
cout << "\nc1 = " << c1.getcount( );
c1--; c1--;
cout << "\nc1 = " << c1.getcount( );
}

The statement class countdown : public counter specifies that countdown is


derived from counter. Thus counter is the base class and countdown is the
derived class.

Accessing Base Class Members

A member function in the base class can be used by objects of the derived class.
This is called 'accessibility'. This can be done by:

♦ Substituting base class constructors

♦ Substituting base class member functions.

In Example 2.14, the statement countdown c1; causes an object of class


countdown to be created and initialized to zero. This is possible because,
Introduction to OOP unit1

when a constructor is not specified in the derived class, the compiler will
choose an appropriate constructor from the base class.
The object of countdown class also uses the operator ++() and getcount()
functions from the counter class to increment and to display the count
respectively. These are from the base class.
The Protected Access Specifier

Protected, is another type of protection available within a class. Items


declared as protected are private within a class and available for private
access in the derived class. The data count is declared as a protected
member for the class counter because private members cannot be
accessed outside the class. Protected member can be accessed by the
classes derived from the base class. The following table gives the
difference between the three access specifiers - private, public and
protected.
TABLE 2.2 Access Specifiers

Access Accessible from Accessible from Accessible from


Specifiers own class derived class objects outside class
Public Yes Yes Yes
Protected Yes Yes No
Private Yes No No

Base Class Unchanged !

Even if other classes have been derived from it, the base class remains
unchanged. It is to be noted that the base class objects cannot use any
data members or member functions of the derived class.
2.9.2 Derived Class Constructors
In example 2.14 you saw that when an object of class countdown was declared,
it called the constructor of the base class counter. But, to initialize a value to the
object of class countdown, the base class constructor is not used by the
compiler. Only those base class constructors which take no arguments, are
available to the derived class. So, you must write a new set of constructors for
the derived class to allow initialization of the derived class objects.
Introduction to OOP unit1

Example 2.15 Constructors In Derived Class

# include <iostream.h>
class counter
{ protected : unsigned int count;
public : counter( ) { count = 0; }
counter(int c) { count = c;}
int getcount( ) { return count; }
counter operator ++ () { count++; return counter(count); }
};

class countdown : public counter


{ public : countdown ( ) : counter( ) { } ;
countdown (int c) : counter (c) { };
/* the base class constructors are called in the derived class constructor */
countdown operator -- ( ) { count --; return
countdown(count); }
};

void main() {
countdown c1; countdown c2(100);
cout << "c1 = " << c1.getcount( );
cout << "c2 = " << c2.getcount( );
c1++; c1++; c1++;
c2--; c2--;
countdown c3 = c2--;
cout << "c1 = " << c1.getcount() << endl ;
cout << "c2 = " << c2.getcount() << endl;
cout << "c3 = " << c3.getcount() << endl;
}
In example 2.15, you see that the declaration of a constructor in the derived
class is as countdown( ) : counter( ) { } and countdown(int x ) : counter(x ) { }
Introduction to OOP unit1

The derived class constructors call the base class constructors. Any additional
statements can be written inside the braces. In this example, the derived class
constructors do nothing additional, so there are no statements within the braces.

In this case, the value of count is passed to the derived class constructor which
in turn passes it to the base class constructor which does the actual initialization.
The one argument is also used in the assignment statements like countdown c3
= c2--;

Dangers of Protected

You should know that there is a disadvantage of making class protected. Say
you have written a class library, which you are distributing, to the public. Any
programmer who buys this library can access protected members of your
classes by simply deriving other classes from them. To avoid corrupted data, it is
often safer to force derived classes to access data in the base class using only
public functions in the base class, just as ordinary main() programs must do. You
will need to weigh the advantages of protected against its disadvantages in your
own programs.

2.9.3 Overriding Member Functions


The derived class can have member functions, which has the same name as the
member functions of the base class.

The example 2.16 shows the manipulation of data storage object called stack.
The stack is basically an array of integers. The restriction here is that the data is
stored and removed from the same end. Hence, the last data stored is the first to
be removed. Hence, you say that it follows LIFO (Last in first out) logic. You use
the function push( ) for storing values into the stack and pop( ) to remove data
values from the stack.

In the example, the base class has two functions - push( ) to store values into
the stack and pop( ) to remove values from the stack. Since the stack is an array
of integers, an erroneous result is obtained if you try to push values into a full
stack (add values to the array after the maximum index) or pop values from an
Introduction to OOP unit1

empty stack (No values have been stored in the stack) . Hence top must have
values in the range 0 to MAX.

But, you do not check the value of top in the base class. Hence, a second class
stack2 is derived from the class stack. So, stack is the base class and stack2 is
the derived class.

Example 2.16 Overriding Base Class Member Functions

# include <iostream.h>
# include <process.h>
const int MAX = 10;
class stack // Does not check for the range of variable top.
{ protected : int st[MAX]; int top;
public : stack() { top = -1; }
void push (int var) { st [++ top] = var; }
int pop() { return st[top--]; }
/* For a right answer the top value must be < MAX. */
};
class stack2 : public stack // Checks for the range of top .
{
public :
void push(int var) // Function name same as base class function
{ if (top +1< MAX)
stack :: push(var);
else
{ cout << "\n Error : Stack full "; exit (1); }
}
int pop() // Function name same as base class function
{
if (top > =0) return stack :: pop();
else
{ cout << "\n Error : Stack Empty "; // top < 0
Introduction to OOP unit1

exit (1);
}
}
}; // end of class

void main()
{
stack2 s1;
s1.push(11); s1.push(22); s1.push(33);
cout << endl << s1.pop(); cout << endl << s1.pop();
cout << endl << s1.pop(); cout << endl << s1.pop();
}

The derived class stack2 has the same functions as the base class. When the
push() function is called by an object of the derived class, the function described
in the derived class is executed. Hence, you say the derived class member
functions override the base class member functions. The range of top is checked
in the member function of the derived class and hence the correct values can be
obtained. If the value of top is out of range, an error message is given and the
program is terminated. Note that the derived class functions call the base class
functions through the statements stack :: push(var) and return stack :: pop();

The scope resolution operator (::) is used for this purpose. Using this operator
allows us to specify exactly what class the called function is a member of.

Inheritance In The Distance Class


Consider the class distance (see example 2.4). It does not have a method to tell
the user whether the distance is in the positive or the negative direction. i.e., the
distance class assumes that the distances to be represented would always be
positive. In order to add the facility for giving negative distances, you will derive a
new class from 'distance'. This is illustrated in Example 2.17.
Introduction to OOP unit1

Example 2.17 Inheritance In Class Distance

//DISTSIGN class derived from DISTANCE adding the use of signs


# include <iostream.h>
# include <conio.h>
enum positive_negative {negative,positive};
class distance
{
int feet;
float inches;
public :
distance() { feet = 0; inches = 0.0; }
distance ( int ft, float in)
void getdist() ;
void showdist() { cout << end1<< "Distance is : ";
cout << feet << "feet " << inches << "inches";
}
void operator += (distance d2);
}

void distance :: operator += (distance d2)


{feet=feet+d2.feet;
inches =inches +d2.inches;
while (inches >=12)
{
feet++; inches =inches -12.0;
}
}
distance:: distance (int ft, float in) { feet=ft; inches=in;
while (inches >= 12)
{ feet ++; inches = inches -12;}
}
Introduction to OOP unit1

void distance :: getdist () { cout<<end1<< "Enter feet :";


cin >> feet ;
cout << "Enter inches :";
cin >> inches;
while (inches >= 12)
{
feet++;
inches = inches - 12;
}
}
class distsign : public distance
{
private :
positive_negative sign;
public :
distsign() : distance () { sign = positive;}
distsign(int ft,float in,positive_negative sg=positive) : distance(ft,in)
{sign=sg;}

void getdist()
{ distance::getdist();
char ch;
cout << "enter sign +/- "; cin >> ch;
sign = ((ch=='+') ?positive:negative);
}
void showdist()
{
distance :: showdist();
cout << ((sign == positive) ? '+': '-');
Introduction to OOP unit1

}
};
void main()
{
clrscr();
distsign d1;
d1.getdist();
d1.showdist();
getch();
};

Output of Example 2.17


Enter feet :10
Enter inches :6.25
Enter sign (+ or -):-
a = (-)10'6.25"
b = (+)11'6.25"
c = (-)100'5.5"

They reflect the constructors in the distance class. There are two constructors.
The first takes no arguments. The second takes two/three arguments since the
third argument is optional. If no argument is given the sign is set to pos (+). The
setting of values to feet and inches is done by the base class constructor which
is invoked from the derived class.

Member Functions In Distsign

The getdist() function in distsign allows a 'sign' to be entered in addition to the


feet and inches. The showdist() function displays this sign alongwith feet and
inches. This is illustrated in the output of Example 2.17. All member functions of
the derived class call the respective function from the base class and perform
some additional functions. Only the additional features are written in the member
Introduction to OOP unit1

functions of the derived class. Thus, you are using the base class code in the
derived class. This is a good example for 'code reusability'.

2.9.4 Private And Public Inheritance


In the above examples, the derived classes were specified as :

class derived_class_name : public base_class_name.

Here the keyword public specifies that the objects of the derived class are
able to access the public member functions of the base class.
In contrast to this, if the keyword private is used, the objects of the derived class
cannot access public member functions of the base class. Since objects can
never access private or protected members of a class, the result is that no
member of the base class is accessible to objects of the derived class.

The following example shows the various valid and invalid access of the
variables.

Example 2.18 Access Combinations

class A // Base Class


{
private : int privdataA;
protected : int protdataA;
public : int pubdataA;
};
class B : public A // publicly derived class
{
public : void funct()
{
int a;
a = privdataA; // Error
Introduction to OOP unit1

a = protdataA; // O.K.
a = pubdataA; // O.K.
}
};
class C : private A // privately derived class
{
public : void funct()
{ int a;
a = privdataA; // Error
a = protdataA; // O.K.
a = pubdataA; // O.K.
}
};

void main( ) // main function


{ int a; B objB;
a = objB.privdataA; // Error
a = objB.protdataA; // Error
a = objB.pubdataA; // O.K. since B is public.
C objC;
a = objC.privdataA; // Error
a = objC.protdataA; // Error
a = objC.pubdataA; // Error since C is private.
}

Example 2.18 specifies a base class A with private, protected, and public
data items. Two classes B and C are derived from A. B is publicly derived
and C is privately derived. Objects of the publicly derived class B can
access public members of the base class A, while objects of the privately
derived class C cannot. If any access specifier is not supplied when
creating a class, private is assumed.
Introduction to OOP unit1

2.9.5 Access Specifiers : When To Use What ?


Suppose, there is a function in the base class that works fine with the objects of
the base class but gives erroneous results with objects of the derived classes
and there is no function of the same name in the derived class to override the
base class. To prevent the objects of the derived class calling this function two
methods can be employed.

♦ Make a dummy function with the same name for the derived class and print
an error message.

Or

♦ Make the derived class private. Now, the function will not be accessible to
objects of the derived class, although it will still be accessible to objects of
the base class.

2.9.6 Class Hierarchies


In all the previous examples, inheritance has been used to add functionality to an
existing class. Inheritance can also be used as a part of the original design of a
program. Then the base class has the highest level in the class hierarchies. The
classes derived from the base class get the second level of hierarchy. The
classes derived from the derived classes get the third level and so on.

The next example illustrates this. Here the employee is the base class and is at
the first level of hierarchy. The division of employees as manager, scientist, and
labourer are derived from 'employee' and form the second level.

EXAMPLE 2.19 Models Employee Database Using Inheritance

# include <iostream.h>
class employee // Contains name and number of the employee.
{
private : char name[80];
unsigned long number;
Introduction to OOP unit1

public :
void getdata()
{
cout << "\n Enter last name "; cin.getline(name,80);
cout << "\n Enter number "; cin >> number;
}
void dispdata()
{ cout <<"\n Name :" << name ;cout << "\n Number : " << number;
}
};
class manager : public employee
{ private : char title [80];
public : void getdata()
{ employee :: getdata( );// Call base class member function
cout << "Enter title : "; cin.getline(title,80);
}
void dispdata()
{ employee :: dispdata( );//Call base class member function
cout << "\n Title :" << title << endl;
}
};
class scientist : public employee
{ private : int papers;
public : void getdata()
{ employee :: getdata();
cout << "Enter papers published :"; cin >> papers;
}
void dispdata()
{ employee :: dispdata();
cout << "\n Number of publications :" << papers;
}
Introduction to OOP unit1

};

void main()
{
manager m1;
scientist s1;
cout<<endl << "Manager "; m1.getdata(); cout << "\nData "; m1.dispdata();
cout << endl << "Scientist "; s1.getdata(); cout << "\nData "; s1.dispdata();
}

2.9.7 "Abstract" Base Class


Classes used only for deriving other classes (e.g. : employee in example
2.19) are called abstract classes, meaning that no actual objects of this
class are created. Note that no objects of the base class employee are
defined. It is used as a general class, which acts as a base from which
other classes are derived.
Assume a labourer class. Though a labourer is an employee, there is no
unique identification for the class and hence the labourer class operates
identically to the base class. Deriving a separate class for the labourer
may seem unnecessary, but by making it a separate class the fact that all
classes are descended from the same source employee is emphasized.
2.10 LEVELS OF INHERITANCE

Classes can be derived from derived classes also. The following segment
illustrates this.

class A
{ };
class B : public A // First level of inheritance
{ };
class C : public B // Second level of inheritance
{ };
Hence B is derived from A and C is derived from B. Now, you have two levels of
inheritance.
Introduction to OOP unit1

EXAMPLE 2.20 Models Student Database

# include <iostream.h>
# include <string.h>
class student
{
private : int id; char name[20];
public : student()
{ id = 0; strcpy(name,"\0");
student(int i, char *n)
{ id = i; strcpy(name, n);
void getdata()
{cout << "\n Roll Number "; cin >> id;
cout << "\n Name :";cin.get(); cin.getline(name,20);
}
void dispdata()
{cout << "\nId = " << id << "\nName = " << name;}
};
class marks : public student // First level of inheritance
{
protected : int mks[3];
public : marks() : student() { mks[0]=mks[1]=mks[2] = 0;}
marks(int i, char *n, int a, int b, int c) : student(i,n)
{ mks[0] = a; mks[1] = b; mks[2] = c; }
void getdata() {
student :: getdata();
for (int i=0; i<3; i++)
{ cout << "\n Enter marks " << i+1; cin >> mks[i]; }
}
void dispdata() {
student :: dispdata();
Introduction to OOP unit1

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


{ cout << "\n Marks in subject " << i+1 <<" is ";
cout << mks[i]; }
}
};

class report : public marks // Second Level of Inheritance.


{
private : int tot;
public : report () { tot = 0; }
report (int i, char *n, int a, int b, int c) : marks (i,n,a,b,c)
{ tot = a + b + c; }
void getdata()
{
marks :: getdata(); tot = mks[0] + mks[1] + mks[2];
}
void dispdata()
{
float avg = tot / 3.0; marks :: dispdata();
cout << "\n Total = " << tot;
cout << "\n Average = " << avg;
}
};
void main( )
{ report r1(9701, "Poornima", 76, 87, 90);
r1.getdata( );
r1.dispdata( );
}
In the above example, the student class is the base class. The marks class is
derived from student and forms the first level of inheritance. The report class is
derived from marks class. This forms the second level of inheritance as the
Introduction to OOP unit1

report class is derived from marks, which is derived from student. The data
members of marks class is specified as protected because the total is calculated
in the reports class.

2.11 MULTIPLE INHERITANCE

A class can be derived from more than one base class. This is called multiple
inheritance. The syntax is as follows:

class A { }; // Base Class A


class B { }; // Base Class B
class C : public A, public B // C is derived from A and B
{ };

The base classes from which C is derived are listed following the colon on C's
specification separated by commas.

Multiple Inheritance can be illustrated by the following diagram.

CLASS HIERARCHY

BASE CLASS 1 BASE CLASS 2

Derived Class 1 Derived Class 2 Derived Class 3

Figure 1

In the above diagram, the base classes are at a higher level of hierarchy than
the derived classes. The arrow gives the relation ‘derived from’ . Here, all the
derived classes have been derived from both base classes. This is called
multiple inheritance.

2.11.1 Member Functions In Multiple Inheritance


Introduction to OOP unit1

Using member functions of the base classes is described through the following
example.

EXAMPLE 2.21 Illustrates Multiple Inheritance

# include <iostream.h>
# include <string.h>
class student
{
private : int id; char name[20];
public : student()
{ id = 0; strcpy(name,"\0");
student(int i, char *n)
{ id = i; strcpy(name, n);
void getdata()
{cout << "\n Roll Number "; cin >> id;
cout << "\n Name :";cin.get(); cin.getline(name,20);
}
void dispdata()
{cout << "\nId = " << id << "\nName = " << name;}
};
class marks {
protected : int mks[3];
public : marks() { mks[0]=mks[1]=mks[2] = 0;}
marks(int a, int b, int c)
{ mks[0] = a; mks[1] = b; mks[2] = c; }
void getdata() {
for (int i=0; i<3; i++)
{ cout << "\n Enter marks " << i+1; cin >> mks[i]; }
}
void dispdata() {
for (int i=0; i<3; i++)
Introduction to OOP unit1

{ cout << "\n Marks in subject " << i+1 <<" is ";
cout << mks[i]; }
}
};
class report : private student, private marks // Multiple Inheritance.
{
private : int tot;
public : report() : student () , marks() { tot = 0; }
report (int i, char *n, int a, int b, int c)
: student(i, n), marks(a, b, c)
{ tot = a + b + c; }
void getdata()
{
student :: getdata();
marks :: getdata(); tot = mks[0] + mks[1] + mks[2];
}
void dispdata()
{
float avg = tot / 3.0;
student :: dispdata(); marks :: dispdata();
cout << "\n Total = " << tot;
cout << "\n Average = " << avg;
}
};
void main( )
{
report r1(9701, "Poornima", 76, 87, 90);
r1.getdata( ); r1.dispdata( );
}

The getdata() and the dispdata() functions in report class will include a call
to functions in the student class by the statements student :: getdata();
Introduction to OOP unit1

and student :: dispdata(); and the marks class by the statements marks ::
getdata() and marks :: dispdata(); . Since the objects of the derived
classes never call the routines of the base classes, the derivation is made
private instead of public.
2.11.2 Constructors In Multiple Inheritance
The statements are written similar to those of example 2.17. The two base
classes are separated by commas. The syntax for this:

dcname () : bcname1() , bcname2()


{ extra statements needed }

where dcname is the derived class name; bcname1 and bcname2 are the
names of the base classes.
If there are arguments passed, the modified syntax is:

dcname (dcarg + bcarg1 + bcarg2) : bcname1 (bcarg1) , bcname2 (bcarg2)

{ extra statements needed }

where dcname is the derived class name; bcname1 and bcname2 are the
names of the base classes. dcarg are the arguments required for the derived
class constructor bcarg1 and bcarg2 are the arguments for constructors of the
base classes.

This has been illustrated in the example 2.21 in the report class.

2.11.3 Ambiguity In Multiple Inheritance


The most common ambiguity is shown in the example below. When both the
base classes have a function with the same name and you call the function with
the object of the derived class, the compiler will not know which function to use.
Hence, it should be specified clearly by writing the base class name in the calling
statement.

Example 2.22 Ambiguity In Multiple Inheritance


Introduction to OOP unit1

# include <iostream.h>
class A
{ public : void show { cout << "\n Class A"; }
};

class B
{ public : void show { cout << "\n Class B"; }
};

class C : public A, public B { };

void main()
{
C objc; objc.show(); // Error : ambiguous function call
objc.A::show(); // Call the member function of A
objc.B::show(); // Call the member function of B
}
Thus, the scope - resolution operator is used to resolve ambiguity.

2.12 CONTAINERSHIP : CLASSES WITHIN CLASSES

In Inheritance, if a class B is derived from class A, B has all characteristics


of A in addition to its own. Hence you can say that "B is a kind of A". So,
inheritance is sometimes called as a "kind of" relationship. There is
another kind of relationship called a "has a" relationship, or containership.
In OOP, this relation occurs when you have an object of class A in class B
as shown.
class A

{ };

class B
{ A a; // A is contained in B. };
This relation can be used instead of inheritance. Thus, the employee database
problem gives the following relationships :

Example 2.23 Containership With Student And Marks


Introduction to OOP unit1

# include <iostream.h>
# include <string.h>

class student
{
private : int id; char name[20];
public : student()
{ id = 0; strcpy(name,"\0");
student(int i, char *n)
{ id = i; strcpy(name, n);
void getdata()
{cout << "\n Roll Number "; cin >> id;
cout << "\n Name :";cin.get(); cin.getline(name,20);
}
void dispdata()
{cout << "\nId = " << id << "\nName = " << name;}
};

class marks {
private : int mks[3]; student s;
public : marks() { mks[0]=mks[1]=mks[2] = 0;}
marks(int a, int b, int c) { mks[0] = a; mks[1] = b; mks[2] = c; }
void getdata() { s.getdata();
for (int i=0; i<3; i++)
{ cout << "\n Enter marks " << i+1; cin >> mks[i]; }
}
void dispdata()
{
s.dispdata();
for (int i=0; i<3; i++)
{ cout << "\n Marks in subject " << i+1 <<" is ";
Introduction to OOP unit1

cout << mks[i]; }


}
};
void main( )
{
marks m1;
m1.getdata( ); m1.dispdata( );
}
2.13 INHERITANCE AND PROGRAM DEVELOPMENT

Inheritance is a very useful concept when it comes to program development.


Thus, if programmer A creates a class, it can be improved by programmer B and
used by programmer C and D. This is possible only due to the software
reusability feature of C++. Thus, OOP makes programming more flexible, but
more complex.

2.14 EXERCISE

1. Overload the == operator to compare the two string objects.

2. Overload the + operator to add two distance objects.

3. Overload the -= operator to subtract two distance objects.

4. Create a student class which stores the id, name and fees of the student.
Derive a class to store the marks in three subjects of the student. Give the
necessary interface to it.

5. Modify the time class from Exercise 7 in Unit 1 so that instead of a function to
add time it uses the overloaded operator + to add 2 times.

6. A publishing company markets both books and audio cassette version of its
work. Create a class publication that stores the title and price of a
publication. From this class derive 2 classes book which adds a page count
Introduction to OOP unit1

and tape which adds a playing time in minutes. Each of these 3 classes
should have a getdata() function to get its data from the user at the
keyboard, and a putdata() function to display its data.

2.15 SUMMARY

This unit covers the concept of OOP – Polymorphism. Polymorphism means one
thing having many forms. It is a very powerful concept, which gives C++
language a facility to redefine itself into a new language. There are 2 types of
polymorphism – operator overloading and function overloading.

An operator can be overloaded to perform different operations on different data


types in different content. All forms of operators can be overloaded to perform a
set of distinct operations on objects. These instructions are to be given in
member functions called operation function. Arithmetic operators, comparison
operators and most other operators can be overloaded. Even the cast operators
can be overloaded to perform conversion between objects and basic data types
and between objects of different classes.

Inheritance is the most powerful use of a class and the most important concept
of OOP. It is the mechanism using which reusability of code is achieved.
Libraries of classes can be distributed like libraries of functions. A new class can
be derived from an existing one having all the properties of the old one in
addition to new members and enhancements.

ANSWER TO EXCERISE 2.14


1. //Overload the == operator to compare the 2 strings
#include <iostream.h>
#include <string.h>
class string
{
private : char * str;
Introduction to OOP unit1

public :
string() {str=new char[1];strcpy(str,"\0");}
string(char *s) {str=new char [strlen(s)+1]; strcpy(str,s);}
~string() {delete str; cout<<"\n Destroy";}
int operator==(string &st)
{ int a;
if (stricmp(str,st.str)==0)
return 1;
else
return 0;
}
void display() {cout <<endl <<str;}
void getdata() { cout <<"Enter a string"<<endl;
cin.getline(str,'\n');}
};

void main()
{ string s1,s2;
s1.getdata();
s2.getdata();
s1.display();
s2.display();
if (s1==s2)
cout<< "Both strings are equal"<<endl;
else
cout<< "Strings are not equal"<<endl;
}
Introduction to OOP unit1

2. // Overloading + operator
# include<iostream.h>
class distance
{ private : int feet;
float inches;
public : distance() {feet=0;inches=0.0;}
distance(int f,float i) {feet=f;inches=i;}
void getdist()
{ cout<< "Enter the feet";cin>>feet;
cout<< "enter the inches";cin>>inches;
while(inches>=12)
{ feet++;
inches-=12;
}
}

void showdist()
{ cout<<feet<< "\'-"<<inches<<"\""<<endl;}
~distance()
{cout<<"Object destroyed"<<endl;}
distance operator + (distance);
};

distance distance :: operator + (distance d)


{ distance d1;
d1.feet=feet+d.feet;
d1.inches=inches+d.inches;
if (d1.inches>=12.0)
{ d1.inches-=12.0;
d1.feet++;
Introduction to OOP unit1

}
return d1;}
void main()
{ distance dist1,dist2,dist3;
dist1.getdist();
dist2.getdist();
dist3 = dist1 + dist2;
dist1.showdist();
dist2.showdist();
dist3.showdist();
}

3.
#include<iostream.h>
class distance
{ private : int feet;
float inches;
public : distance() {feet=0;inches=0.0;}
distance(int f,float i) {feet=f;inches=i;}
void getdist()
{ cout<< "Enter the feet";cin>>feet;
cout<< "enter the inches";cin>>inches;
while(inches>=12)
{ feet++;
inches-=12;
}
}
Introduction to OOP unit1

void showdist()
{ cout<<feet<< "\'-"<<inches<<"\""<<endl;}
~distance()
{cout<<"Object destroyed"<<endl;}
void operator -= (distance);
};

void distance :: operator -= (distance d)


{ distance d1;
feet -= d.feet;
inches -= d.inches;
if (inches>=12.0)
{ inches-=12.0; feet++; }
}

void main() {
distance dist1,dist2;
dist1.getdist();
dist2.getdist();
dist1.showdist();
dist1 -= dist2;
dist1.showdist();
dist2.showdist();

4.
# include<iostream.h>
# include <string.h>
# include <iomanip.h>
class student {
private : int id; char name[20]; float fees;
public : student(){id=0;strcpy(name,"\0");fees=0.0;}
Introduction to OOP unit1

student (int i,char *n,float f) { id=i; strcpy(name,n); fees=f;}


void getdata() {
cout <<"Enter id";cin>>id;cin.get();
cout <<"Enter name"; cin.getline(name,'\n');
cout<<"Enter fees"; cin>>fees;
}
void dispdata() {
cout<<"id is "<<id<<endl <<"name is"<<name<<endl;
cout<<"fees is"<< setiosflags(ios::fixed)

<< setiosflags(ios::showpoint)<<setprecision(2)<<setw(10)<<fees;
}
};

class marks : private student


{ private : int marks[3];
public : marks():student() {marks[0]=marks[1]=marks[2]=0;}
marks(int i,char *n,float f,int a,int b,int c):student(i,n,f)
{ marks[0]=a;
marks[1]=b;
marks[2]=c;}
void getdata()
{
student ::getdata();
for (int i=0;i<3;i++)
{ cout<<"\n enter marks"<<i+1;cin>>marks[i];}
}
void dispdata()
{ student ::dispdata();
for (int i=0;i<3;i++)
{cout<<"\n marks in subject"<<i+1<<"is";cout<<marks[i];}
}
Introduction to OOP unit1

};
void main()
{ marks m1(9901,"Asha",4000,60,70,80);
m1.getdata();
m1.dispdata();
}

5.
#include <iostream.h>
class time
{private : int hrs,mins,secs;
public :
time() { hrs=0;mins=0;secs=0;}
time(int h, int m, int s) { hrs=h; mins=m; secs=s;}
void getdata() {
cout<< "Enter hours";cin>>hrs;
cout<< "Enter minutes";cin>>mins;
cout<< "Enter seconds";cin>>secs;
while(secs>=60)
{ secs-=60;
mins++;}
while(mins>59)
{ mins-=60; hrs++;}
}
void dispdata() {
cout<<hrs<<":"<<mins<<":"<<secs<<endl;
Introduction to OOP unit1

}
time operator + (time t1)
{ time t2;
t2.secs=secs+t1.secs;
t2.mins=mins+t1.mins;
t2.hrs =hrs +t1.hrs;
if (t2.secs>=60) { t2.secs-=60; t2.mins++;}
if (t2.mins>=60) {t2.mins-=60; t2.hrs++;}
return t2;
}
};
void main()
{
time time1,time2,time3;
time1.getdata();
time2.getdata();
time1.dispdata();
time2.dispdata();
time3=time1+time2;
time3.dispdata();
}

6.
//publication class & derived class
#include<iostream.h>
const int LEN=80;
class publication
{
private : char title[LEN];
float price;
public : void getdata()
Introduction to OOP unit1

{ cout<<"\n enter title:";cin>>title;


cout<<"enter price";cin>>price;
}
void putdata()
{ cout<<"\n title:"<<title;
cout<<"\n price:"<<price;
}
};

class book : private publication


{ private : int pages;
public : void getdata()
{ publication ::getdata();
cout<<"enter number of pages:";
cin>>pages; }
void putdata()
{ publication :: putdata();
cout<<"\n pages:"<<pages;
}
};
class tape : private publication
{ private : float time;
public :
void getdata()
{ publication ::putdata();
cout<<"\nenter playing time :";cin>>time;
}
void putdata()
{ publication :: putdata();
cout<<"playing time:"<<time;
Introduction to OOP unit1

}
};
void main()
{
book book1; tape tape1;
book1.getdata(); tape1.getdata();
book1.putdata(); tape1.putdata();
}
Introduction to OOP unit1

UNIT 3 TEMPLATES, POINTERS AND GRAPHICS

Structure
3.0 Introduction
3.1 Objectives
3.2 Template
3.2.1 Generalized Stack Header File
3.2.2 Using The Stack Header file to Create Integer Stack
3.2.3 Using The Stack Header file to Create Character Stack
3.2.4 Creating Stack Header file Using Templates
3.2.5 Using the Template To Create Stack
3.2.6 Inheritance of Class Stack Using Templates
3.2.7 Using the Class Stack
3.3 Address And Pointers
3.4 Memory Management In C++
3.4.1 The new Operator
3.4.2 The delete Operator
3.5 Linked Lists for storing Data
3.5.1 Create And Display Contents of a Linked List
3.5.2 Inserting a Node into the List
3.6 An Array of Pointers to Objects
3.7 Pointers to Pointers
3.8 Debugging Pointers
3.9 Graphics IN C++
3.10 Text Mode Graphics Functions
3.11 Graphics Mode Graphics Functions
3.11.1 Setting Up Graphics Mode
3.11.2 Position Functions
3.11.3 Drawing Shapes
3.11.4 Miscellaneous Functions
3.11.5 Filling Patterns
3.11.6 Cursor Control
3.11.7 Text Output
3.11.8 Clearing Graphics Screen
3.11.9 Ending Graphics Mode
3.11.10 Illustrates Some Graphics Functions
3.12 Inheritance in Graphics
3.12.1 Illustrates Inheritance In Graphics
3.13 Simulating Moving Objects
3.14 Using cout with Graphics
3.15 Exercise
3.16 Summary
Introduction to OOP unit1

3.0 INTRODUCTION
The Stack class that was created in Unit 2 could be used with a specific type of
data, i.e. int. But if this class has to be used with any type of data, then the class
has to be generalized.

Pointer is variable that holds the address of a data item. Pointers are commonly
used in the following areas while programming:

♦ Accessing array elements.

♦ Passing arguments to a function when the function needs to modify the


original arguments.

♦ Passing arrays and strings to functions.

♦ Obtaining memory from the system – Dynamic memory allocation.

♦ Creating data structures such as linked lists.

C++ includes an extensive collection of graphics oriented library functions.


Using these functions you can create an image on the screen. Graphics
and OOP work together particularly well because objects can represent
specific images, such as balls or text boxes. Graphics provides a visual
way to see objects in action.
Turbo C++ graphics functions fall into two categories:

♦ those that work in the text mode

♦ those that work in the graphics mode

The text mode graphic functions are concerned with placing the text in
certain areas of the screen. The graphics – mode functions allow you to
draw dots, lines, and shapes (like circles, rectangles, and ellipse etc.), add
color to lines and areas, and perform many other graphics – related
activities. Graphics mode functions require a graphics monitor and
adapter card such as CGA, EGA or VGA.
Introduction to OOP unit1

3.1 OBJECTIVES
♦ Create templates or Parameterized data types that defines a general class.

♦ Usage of Templates with different types of data.

♦ Understand pointers.

♦ Creating linked list for storing datas.

♦ Creating graphics images using Object Oriented techniques.

3.2 TEMPLATES
In the previous unit, you have created classes which includes variables of
different data types as its private data members. For e.g.: Consider the
stack class described in Unit 2 (see example 2.16). It has an array of
integers as its private members to store values. It also has an integer
variable top to keep track of the index.
This stack has a disadvantage and that is, it can store only integer values.
If you need a stack to store float or character data, you have to define a
second class for float data and a third class for character data. If you
could generalize the stack class, this difficulty would not arise.
If the class stack is generalized, you can use it in many programs. So it
would be helpful if you create a header file with this class. The header
files have an extension of '.h'. E.g. iostream.h is a system defined header
file containing the classes required for standard input and output. As you
include iostream.h in any of our programs, you can also include the user
defined header files in various programs. This is another example for the
code reusability feature of C++.

Note : To include a user defined header file, you use " " instead of < > to
specify the header file name.

E.g. # include "newhead.h"

where newhead.h is a user defined header file.


The following example illustrates how to create a generalized stack without using
templates.

Here, the data type of the stack required is denoted by a variable name. In the
program, which requires the stack header file, the stack file is included after
Introduction to OOP unit1

defining what the variable stands for. This can be done using the typedef
statement.

3.2.1 Example To Generalized Stack Header File


Create the file and save it under the name stack_h.h. (Do not compile this file)

# include <iostream.h>
# define MAX 10

class stack
{

private :
D st[MAX]; int top;
public :

stack() { top = -1;}


void push (D var)

{
st[++top] = var;
}
D pop()
{
return(st[top--]);
}
};
In the above example, a header file is created for the class stack. When this file
is to be included in a program, the name of the file has to be enclosed in double
quotes. This signifies that the included header file is a user defined header file.
The following example uses the stack defined in example 3.1.1

3.2.2 Using The Stack Header File To Create Integer Stack

typedef int D; // Defining the data type of the stack.


# include “stack_h.h” // Filename of the stack header
main()
Introduction to OOP unit1

{
int s; stack s1;
s1.push(50); s1.push(60);
s = s1.pop(); cout << s;
}

The following example shows how to use the same header file to create a
stack of characters.
3.2.3 Using The Stack Header File To Create Character Stack
typedef char D; // Defining the data type of the class
# include “stack_h.h” // Filename of the stack header
main()
{

char s; stack s1;


s1.push(‘a’); s1.push(‘b’);
s = s1.pop(); cout << s;

So, from examples 3.1.2 and 3.1.3, it is evident that you can create a
general stack class, which can be used in more than one program. This
facilitates code reusability. (The above method can also be used in C
programs.)

Note : The header file <iostream.h> has not been included in examples
1.2.2 and 1.2.3 because it has already been included in stack.h.

In C++ , you have a structure that defines such general classes. This
structure is called 'template' or 'Parameterised data types'.
The statement that declares such classes is

template <class T>

where template is a keyword , class indicates that a datatype is the


parameter and T is the name given instead of the datatype for declaring
Introduction to OOP unit1

the private variables of the class. If you have any other arguments it can
be specified by using comma as the separator. After this statement you
give the class specifier using the datatype as T. The template is stored in
a separate header file to promote code reusability.
In the example given below, the statements # ifndef and # endif indicates
to the compiler that if the file has already been compiled once, it is not
necessary to do it again for the same program.
3.2.4 Creating Stack Header File Using Templates
Create this file and name it stack_h.h. Do not compile this file.
# include <iostream.h>
template <class T, int MAX>
class stack
{
private :
T st[MAX];
int top; // Since top is a index, it is always a integer.
public :
stack() { top = -1; }
void push(T var) { st[++top] = var; }
T pop() { return (st[top--]); }
};

Note: T is the template defined. The parameters for the stack to be created has
to be passed to it when creating an object of the class. If the parameter is
a datatype then it is indicated by the word class. If the parameter is a
value of a particular data type then the data type is to be specified in the
template statement. E.g. integer for MAX in Example 3.1.4. The header
file has to be included in the program file and should not to be compiled
on its own.

The following example illustrates how to use the declared template.

3.2.5 Using Templates To Create Stack


# include "stack_h.h" // Include header file.
main()
Introduction to OOP unit1

{ stack <int, 3> s1; // Declares a stack for maximum 3 integers.


stack <char, 5> s2; // Declares a stack for maximum 5 characters.
s1.push(50); s2.push(‘a’);
int x1 = s1.pop();
char x2 = s2.pop();
cout << x1 << x2 << endl;

Note that in the above example you did not use the typedef statement to declare
the stack. Instead, you sent the datatype and the size as parameters
enclosed in < > when you declared a object of the class stack.

The following two examples give illustrate the use of templates. Here you
will use inheritance in the header file. Two templates have been defined -
one for the base class and the other for the derived class.
Writing the template for the base class follows the same procedure as the
previous program. When this class derives another class, a separate
template statement is to be written for the derived class as shown in the
syntax below :

template <arguments for derived class>

class derivedclass : public baseclass<values for arguments of baseclass>


{
// Class specification for derived class.

};

3.2.6 Inheritance Of Class Stack Using Templates

(create file named, stackt_h.h. Do not compile)


# include <iostream.h>

const int MAX = 3;

template <class T>


Introduction to OOP unit1

class stack
{
protected :
T st[MAX]; int top;
public :
stack() {top = -1;}
void push(T var)
{st[++top] = var;}
T pop()
{ return st[top--];}
};
template <class X>
class stack1 : public stack<X>
{
public :
void push(X var)
{
if (top+1 < MAX) stack<X>::push(var);
else
cout<< "\n Error! Stack full!\n";
}
X pop()
{
if (top >= 0) stack<X>::pop();
else
cout << "\n Error! Stack Empty\n";
}
};
Introduction to OOP unit1

To include the header file in our program, you have to give the statement
#include “stackt_h.h” where stackt_h.h contains the specifier for class
stack. The program, which uses the class stack defined in Example 3.1.6,
is shown below.
3.2.7 Using The Class Stack
# include <conio.h>
# include "stackt_h.h" // Include the header file.
main()
{
stack1<char> s1;
stack1<int> s2;

char x; int x1;


clrscr();

s1.push('a'); s1.push('b'); s1.push('c');


s1.push('d'); // Gives Error as output

x = s1.pop(); cout << x << endl;


x = s1.pop(); cout << x << endl;
x = s1.pop(); cout << x << endl;
x= s1.pop(); // Gives Error as output

getch(); // Press any key to continue.

s2.push(50); s2.push(60); s2.push(70);


s2.push(80); // Gives Error as output

x1 = s2.pop(); cout << x1 << endl;


x1 = s2.pop(); cout << x1 << endl;
x1 = s2.pop(); cout << x1 << endl;

x1 = s2.pop(); // Gives Error as output


getch(); } // Press any key to continue.
Introduction to OOP unit1

3.3 ADDRESSES AND POINTERS


Every byte in the computer's memory has an address. Addresses are
basically numbers that start at 0 and end at the highest address, which
will vary according to the amount of memory available in the computer.
For e.g. the highest address for 640K of memory is 65535.
Note that the address of a variable is not the same as its contents. The address
is the memory location, which is used to store the variable contents. The
address of a variable can be got by using the address of (&) operator.

E.g. cout << &var1;

This statement prints the address of the variable var1. The output will be a
number like 0x8f4ffff4, which is a hexadecimal number.
Variables can also be defined as pointers in the program.

For e.g. int *p;

Here p is a pointer variable which stores an address of the location where


the integer variable is stored.
cout << p; //This statement prints the value in p which is a address.

cout << *p; //This statement prints the integer value stored in the location
pointed to by the integer pointer p.

3.4 MEMORY MANAGEMENT IN C++


When an array is defined, the compiler sets aside memory for the array
data. Arrays are a useful source of data storage, but they have a serious
drawback because you have to know in advance how much data will be
stored and declare an array of that size. This is because the compiler
requires the array size to be a constant. In such cases you can define
large arrays. But there will be wastage of space. To overcome this, C++
has two operators. They are
♦ new This operator allocates the memory.

♦ delete This operator deallocates the memory.

3.4.1 The New Operator


Introduction to OOP unit1

This operator obtains memory from the operating system and returns a pointer to
its starting point.

The new operator has the same operation as the malloc function of C. But, this
operator is superior in that it returns a pointer to the appropriate data type, while
malloc’s pointer must be cast to the appropriate type.

3.4.2 The delete Operator


This operator deallocates the memory allocated to the pointer variable. If the
program reserves many chunks of memory using new operator, eventually all the
available memory will be reserved and the system will crash. To ensure safe and
efficient use of memory, the new operator is matched by a corresponding delete
operator that returns memory to the operating system.

Example 3.1 Illustrates both new and delete operators.

# include <iostream.h>
# include <string.h >
void main()

{
char *str = “Education is the ability to meet life’s situations”;

int len = strlen(str);


char * ptr;

ptr = new char[len + 1]; // set aside memory : string + ‘\0’.


strcpy(ptr,str);

cout << endl << “ptr = “ << ptr;


delete ptr ; // release ptr’s memory.

In the above example the statement


Introduction to OOP unit1

delete ptr;
returns to the system whatever memory was pointed to by ptr.

Deleting the memory does not delete the pointer that points to it and does
not change the address value in the pointer. However, this address is no
longer valid; the memory it points to may be now filled with something
entirely different.
new AND delete OPERATORS IN CLASSES

The next example illustrates how to use the new and delete operators in classes.
The new operator is used in the constructor so that the memory is allocated
when the object is created. The delete operator is usually used in the destructor
to return the memory to the operating system when the object is destroyed.

Example 3.2 String Class Using new And delete Operators

# include <iostream.h>
# include <string.h>
class string
{
private :
char * str;
public :
string (char *s)
{ int length = strlen(s);
str = new char[length + 1]; // Allocates memory to string.
strcpy(str, s);
}
~string()
{ delete str; // Deallocates the memory.
}
void display()
{ cout << str; }
};
Introduction to OOP unit1

void main() {
string s1 = “Manipal Institute of Computer Education.”;
cout << endl << “s1 = “; s1.display();

3.5 LINKED LISTS FOR STORING DATA


C++ has memory data structures like arrays, files and structure. Though these
allow for quite flexible storage, some applications may require the data to be
structured differently. This can be achieved using linked lists.

Data structures have two levels – the physical level and logical level.

At the physical level, the data structure is concerned with the actual storage
location of data and the relationship of the different data items.

At the logical level, the data structure is concerned with the defined data
relationships, their physical locations as such are not considered, i.e., the next
data to be read is maintained logically. A linked list is one such logical data
structure.

A linked list is a data structure such that there is one starting data item, and each
data item (including the start data) contains a pointer to the next data in
sequence. The last data item in the list stores a special value that marks the end
of the list. Each data item in the list is known as a node. The building block for a
linked list is the structure data type of C++.

The linked list provides a more flexible storage system in that it does not use
arrays at all. Instead, space for each data item is obtained as and when needed
with new and each item is connected or linked to the next data item using a
pointer. Hence, the individual items do not need to be located contiguously in
memory the way the array elements are; they can be scattered anywhere. It is
basically a chain of pointers. These are also called as non - linear lists.

The advantage of using a list is that,


Introduction to OOP unit1

♦ We can preserve the logical order even though we have a random


physical order.
♦ Memory is used efficiently (optimum use of memory)
♦ New nodes can be inserted at any points.
♦ Any node can be deleted.

The following figure illustrates a list with 3 nodes.

7 2 1 num
7FD2:0FC2 7FD2:0FC4 0 *next

7FD2:0FDE 7FD2:0FC2 7FD2:0FC4 Addres


s

The above picture represents a structure containing num (an int data) and *next (
a pointer to the next data item). Each data-pointer pair is a node of the linked list
or data list.

struct node {

int num;

struct node *next;

} *first;

In the above example, first is a pointer to a structure with two members,


an integer num and a pointer next. To connect the pointer to the structure
members, the arrow operator ( ->) is used.
Example : first -> num

Creation of a linked list has been illustrated in example 3.4.1. The individual data
items, or links, are represented by structures of type link. Each structure contains
an integer - representing the object’s single data item - and a pointer to the next
link. The list itself stores a pointer to the link at the head of the list.

The linklist class has only one member data item : the pointer to the start of the
list. When the list is first entered, the constructor initializes this pointer, first, to
Introduction to OOP unit1

NULL. The NULL constant is defined in the MEM.H header file (which is included
in the IOSTREAM.H file) to be 0. This value serves as a signal that a pointer
does not hold a valid address. In example 3.4.1 a link whose next number has a
value of NULL is assumed to be at the end of the list.

3.5.1 Create And Display Contents Of A Linked List


# include <iostream.h>
# include <conio.h>
struct node
{
int data;
node * next;
};
class linklist
{
private :
node* first; // Points to the first node in the list.
node* last; // Points to the last node in the list.
public :
linklist()
{
first = NULL;
}
void additem (int d); // Appends a node to the list.
void display(); // Displays the list contents.
};
Introduction to OOP unit1

void linklist :: additem(int d)


{
node * newlink = new node;
newlink-> data = d;
newlink-> next = NULL;
if (first == NULL)
{
first = newlink;
last = first;
}
else
{
last -> next = newlink;
last = newlink;
}
}
void linklist :: display()
{
node* current = first;
while (current != NULL) {
cout << endl << current->data;
current = current->next;
}
}

void main() {

linklist l1;

clrscr();

l1.additem(25); l1.additem(36);

l1.additem(49); l1.additem(64);

l1.display();

getch();
}
Introduction to OOP unit1

The function additem() adds an item to the linked list. A new node is inserted at
the end of the list. A new structure is created of type node by the statement

node * newlink = new node;

This creates memory for the new node structure with new and saves the pointer
to it in the newlink variable. The structure is then inserted at the end of the list.

The function display() displays the contents of the list. A temporary variable is
used to traverse the list and simultaneously print the values on the screen until
you find a next that is NULL, denoting the end of the list.

Note: The link structure in example 3.4.1 contained a pointer to the same kind
of structure. This could also be done using classes as shown below,
Class c1
{
c1 *ptr;
};
However, while a class can contain a pointer to an object of its own
type, it cannot contain an object of its own type.
class c1
{ c1 obj; // Not allowed.
};
This is true of structures as well as classes.
Introduction to OOP unit1

3.5.2 Example For Inserting A Node Into The List


// Link list class with INSERT interface

#include<iostream.h>
#include<conio.h>
struct list
{
int data;
list *next;
};
class linklist
{
private :
list *head;
list *last;
public:
linklist() { head=NULL;}
void additem(int d);
void insert();
list * search(int n);
void display();
void remove();
~linklist();
};
Introduction to OOP unit1

// To add a new item to the list


void linklist :: additem(int d)
{
list *newitem = new list;
newitem -> data = d;
newitem -> next = NULL;
if (head==NULL)
{
head=newitem;
last=head;
}
else
{
last->next = newitem;
last=newitem;
}
}
// To display the entire list
void linklist :: display()
{
list *disp = head;
cout << endl<<"Contents of the list :" <<endl;
while (disp)
{
cout << " "<< disp->data;
disp=disp->next;
}
}

// To insert data into the list


void linklist :: insert()
Introduction to OOP unit1

{
int n1,n2;
linklist::display();
cout << "\nEnter number before which to insert ";
cin >> n1;
cout << "Enter number to insert ";
cin >> n2;
if (head->data == n1) // Data at the head
{
list * newlink = new list;
newlink->data = n2;
newlink->next = head;
head=newlink;
}
else
{
list * temp=search(n1);
if (temp==NULL)
{
cout << "Number not found in the list ";
return;
}
list *newlink = new list;
newlink -> data = n2;
newlink -> next= temp->next;
temp->next = newlink;
}
}
// To search for a particular Data and return the address of the previous node

list * linklist :: search (int d)


{
Introduction to OOP unit1

list *ptr=head;
while (ptr) {
if (ptr->next->data==d)
return ptr;
ptr=ptr->next;
}
return NULL;
}

void linklist::remove()
{
int r;
display();
cout << "\n Enter number to delete ";
cin >> r;
if (head->data==r)
{
list *temp = new list;
temp=head;
head=head->next;
delete temp;
}
else
{
list *temp=new list;
temp=search(r);

if (temp==NULL)
{
cout << "Number not found in the list ";
return;
}
Introduction to OOP unit1

list *rem=temp->next;
temp->next=temp->next->next;
delete rem;
}
display();
}

// destructor
linklist::~linklist()
{
list *temp,*hold;
temp=head;
while(temp != NULL)
{
hold = temp->next;
delete temp;
temp=hold;
}
}
void main() {
linklist l1;
clrscr();
l1.additem(5); l1.additem(15); l1.additem(25); l1.additem(35);
l1.display();
l1.insert();
l1.display();
l1.remove();
getch();
}

3.6 AN ARRAY OF POINTERS TO OBJECTS


A common programming construction is an array of pointers to objects.
This arrangement is more flexible than placing the objects themselves in
an array.
Example 3.3 An array of pointers to objects
Introduction to OOP unit1

# include <iostream.h>
class person
{
protected: char name[40];
public: void setname(void) { cout<<"Enter name"; cin>>name; }
void printname(void) { cout<<"\n Name is :"<<name; }
};
void main(void)
{ person* persptr[100];
int n=0;
char choice;
do
{
persptr[n]=new person;
persptr[n]->setname();
n++;
cout<<"Enter another (y/n)?";
cin>>choice;
} while(choice=='y');
for(int j=0;j<n;j++) {
cout<<"\nPerson number"<<j+1;
persptr[j]->printname();
}
} // end of main

The main ( ) function defines an array, Persprt, of 100 pointers to type person. In
a do loop it then asks the user to enter a name. With this name it creates a
person object using new, and stores a pointer to this object in the array persptr.
Introduction to OOP unit1

3.7 POINTERS TO POINTERS


Your next example demonstrates an array of pointers to objects, and shows how
to sort these pointers based on data in the object. This involves the idea of
pointers to pointers.

Example 3.4

# include<iostream.h>
# include <string.h>
class person
{
protected: char name[40];
public: void setname(void) { cout<<"Enter name:";cin>>name; }
void printname(void) { cout<<"\n"<<name; }
char* getname() { return name; }
};

void main(void)
{
void bsort(person**, int);
person* persptr[100];
int n=0;
char choice;

do
{ persptr[n]=new person;
persptr[n]->setname();
n++;
cout<<"Enter another (y/n)?";
Introduction to OOP unit1

cin>>choice;
} while(choice=='y');
cout<<"\nUnsorted list:";
for (int j=0;j<n;j++) { persptr[j]->printname(); }
bsort(persptr,n);
cout<<"\nSorted list";
for(j=0;j<n;j++) { persptr[j]->printname(); }
}
void bsort(person** pp,int n)
{
void order(person**,person**);
int j,k;
for (j=0;j<n-1;j++)
for (k=j+1;k<n;k++)
order(pp+j,pp+k);
}
void order(person** pp1,person** pp2)
{
if(strcmp((*pp1)->getname(),(*pp2)->getname())>0)
{
person* temp=*pp1;
*pp1=*pp2;
*pp2=temp;
}
}

Actually, when we sort person objects, we do not move the objects


themselves; we move the pointers to the objects.
You will notice that the first argument to the bsort ( ) function, and both the
arguments to order ( ) have the type person**. What do these two
asterisks mean?. These arguments are used to pass the address of the
array persptr, or – in the case of order ( ) – the addresses of the elements
of the array. If this were an array of type person, then the address of the
Introduction to OOP unit1

array would be type person* . However the array is of type pointers to


person, or person* so its address is type person**. The address of a
pointer is a pointer to a pointer.

3.8 DEBUGGING POINTERS


Pointers can be the source of mysterious or catastrophic program bugs.
The most common problem is that the programmer has failed to place a
valid address in a pointer variable. When this happens, the pointer can
end up pointing anywhere in the memory. It could be pointing to the
program code, or to the operating system. If the programmer then inserts
a value into the memory using the pointer, the value will write over the
program or operating instructions, and the computer will crash.
Example:
gotoxy(1,10);
cout<<"speed"<<speed;
//Debugging pointers
int *intptr;
void main()
{
*intptr=37;
}

When intptr is defined it is given the value 0, since it is external. The


single program statement will attempt to insert value 37 into the address
at 0. However the runtime error – checking unit, built into the program by
the compiler will display the message:’ Null pointer assignment’ indicating
that you have failed to initialize a pointer properly.
One way to localise the program is to set a Watch window on the contents of 0
address, waiting for any change in the value pointed to by 0. When it changes
you have found the offending program statement.

3.9 GRAPHICS IN C++


Graphics provide a visual way to see objects in action. Turbo C++
graphics functions fall into two categories:
Introduction to OOP unit1

♦ those that work in the text mode


♦ those that work in the graphics mode

The text mode graphic functions are concerned with placing text in certain
areas of the screen. The graphics-mode functions allow you to draw dots,
lines, and shapes (like circles, rectangles, and ellipse etc.), add colour to
lines and areas, and perform many other graphics-related activities.

3.10 TEXT - MODE GRAPHICS FUNCTIONS


The text mode graphics functions need no preparation before use. You can start
using the functions without any prior initialization.

THE window ( ) FUNCTION

This function takes four integer arguments that determine the left, top,
right, bottom coordinates of the window. Text written by certain functions
will appear inside the window, starting at the top left corner. Text too long
for the width is automatically wrapped at the right edge. Text that goes
beyond the bottom of the window causes the contents of the window to
scroll upward.
Syntax: window (int left, int top, int right, int bottom);

This function does not draw a border around the window, it only confines text to
a rectangular area. So, you cannot see the window unless you start typing in it,
The default coordinates for this function are the entire screen.

THE cputs( ) FUNCTION

This function writes a string of text to a window.


Syntax : cputs (string);

A peculiarity of cputs( ) is that it does not translate a newline character


(‘\n’) into the carriage-return-plus-linefeed combination. This must be done
by the user by inserting both a linefeed (represented by ‘\n’ character) and
a carriage-return (represented by the ‘\r’ character) whenever you want to
start a new-line.
THE clrscr( ) FUNCTION
This function erases the text window.
Syntax : clrscr( );
Introduction to OOP unit1

When a window is not initialized, this function can be used to erase the
entire screen.
THE gotoxy( ) FUNCTION

This library function positions the cursor within a text window. Since text is
usually written starting at the cursor position, this allows us to position text where
you want it.

Syntax : gotoxy (int x, int y);

where x is the column number

y is the row number

for the position where the text is to be placed on the screen.

THE putch( ) FUNCTION

This library function displays a single character at the cursor position.

Syntax : putch(char ch);

Its parameter is the character to be displayed.

3.11 GRAPHICS - MODE GRAPHICS FUNCTIONS


In graphics mode the basic element is a pixel. Pixel is a abbreviation for picture
element. The number of pixels (resolution) on the screen depends on the
hardware. Each pixel displays a single dot on the screen. Any pixel can be
suppressed or illuminated.

Graphics-mode programs use a completely different set of functions from text-


mode programs to put images on the screen. A graphics program must also
perform some preliminary work to set the appropriate graphics mode.

3.11.1 Setting Up Graphics Mode

detectgraph() FUNCTION
This function checks the system and returns two integer parameters : a
value representing the system's graphics driver and a value for the
recommended graphics mode if an adapter is installed. If a negative driver
Introduction to OOP unit1

value is returned, it indicates the absence of a graphics adapter. The


mode value is the highest resolution possible with that adapter.
Syntax : detectgraph(int *driver, int *mode);

Example 3.5 Illustrates Detectgraph Function


# include <graphics.h>
# include <iostream.h>
main()
{
int g_dr, g_mode; detectgraph(&g_dr,&g_mode);
if (g_dr < 0) cout << "No graphics Adapter\n";
}

The function detectgraph can be called directly or indirectly. The function


given above makes a direct call to the function. The constant DETECT
makes an indirect call to the function. The above program could be
rewritten as illustrated in Example 3.15.

Example 3.6 Illustrates Detect Constant


# include <graphics.h>
# include <iostream.h>
main()
{
int g_dr, g_mode;
g_dr = DETECT;
if (g_dr < 0) cout << "No graphics Adapter\n";
}
initgraph( ) FUNCTION
This library function must be executed before any other graphics mode
functions can be used. This requires the GRAPHICS.H header file.
Syntax : initgraph(int *driver, int *mode, char *path);

where *driver is the graphics driver, given by an integer.


Introduction to OOP unit1

*mode is the graphics mode, given by an integer.

*path is a string indicating where the driver is available.

Note : The driver is a file with the extension BGI. Each type of hardware
requires a different driver. A null string (“”) indicates driver is in the
current directory.

3.11.2 Position Functions

getmaxx() and getmaxy() FUNCTIONS


These functions return the maximum pixels in each row (number of
columns) and each column (number of rows) of the screen. The values
depend on the resolution of the screen. On a 640 X 200 resolution screen,
getmaxx() returns 639 and getmaxy() returns 199.
Syntax : int getmaxx();
int getmaxy();

Example : int x = getmaxx();


int y = getmaxy();

getx() and gety() FUNCTIONS


The functions getx() and gety() return the current x and y coordinates.
Syntax : int getx();
int gety();

Example : int x = getx();


int y = gety();

3.11.3 Drawing Shapes


The functions described in this section, helps us to draw different shapes like
line, circle, etc. on the screen.
Introduction to OOP unit1

line() FUNCTION
This function is used to draw a line, it requires the starting coordinates
and the ending coordinates of the line.
Syntax : line(start_col, start_row, end_col, end_row)

Example : line(0, 0, getmaxx(), getmaxy() );

will draw a diagonal line from the top left corner to the bottom right corner.

circle() FUNCTION
This function requires three parameters - the x and the y values of the
center and the radius.
Syntax : circle(center_col, center_row, radius);

Example : circle(getmaxx()/2, getmaxy()/2, 50);

draws a circle at the center of the screen with a radius of 50 pixels.


arc() FUNCTION

This function draws a circular arc using that specified center, start and
end angles and radius.
Syntax : arc(column, row, st_angle, end_angle, radius);

Example : arc(50,50,0,90, 50);

draws an arc of radius 50 with center at 50,50.

ellipse() FUNCTION

This function draws an ellipse or an elliptical arc using the specified


center, start and end angles and horizontal and vertical radius.
Syntax: ellipse(cen_col, cen_row, st_angle, end_angle, hor_rad, ver_rad);

Example : ellipse(50,50,0,90,50,20);

draws an ellipse of given dimensions with 50,50 as the center of the ellipse.

3.11.4 Miscellaneous Functions

setcolor() FUNCTION
This function sets the current drawing color.
Syntax : setcolor(int color);

Example : setcolor(RED);
Introduction to OOP unit1

circle(250,250,15);

will draw a circle with border red.

setlinestyle() FUNCTION
This sets the line width and style for drawing subsequent lines.
Syntax : setlinestyle(linestyle, upattern, thickness);

where linestyle could be any one of the values in Table - 3.1

TABLE 3.1
VALUES OF LINESTYLE FOR SETLINESTYLE FUNCTION

Constant Value Draws a


SOLID_LINE 0 solid line
DOTTED_LINE 1 dotted line
CENTER_LINE 2 center line
DASHED_LINE 3 line of hyphens
USERBIT_LINE 4 user defined style

upattern Should contain a sequence of on and off bits


representing a pattern for drawing the line. If linestyle is
not USERBIT_LINE the value of upattern is ignored.
thickness Could be NORM_WIDTH, value 1(normal width) or THICK_WIDTH, value 3
(three times as thick).
3.11.5 Filling Enclosed Regions

In this section, the functions useful for filling the shapes have been
introduced.
floodfill() FUNCTION
This function fills a bounded region with colour.
Syntax : floodfill(column, row, border);

where column, row is a point inside the area to be filled,

border is the color of the border of the area to be filled.

setfillstyle() FUNCTION
Introduction to OOP unit1

This function sets the fill pattern and color.


Syntax : setfillstyle(pattern, color);

where pattern could be any of the values in Table 3.2

TABLE 3.2
VALUES FOR PATTERN OF SETFILLSTYLE FUNCTION

Constant Pattern Value


EMPTY_FILL Background colour 0
SOLID_FILL Foreground colour 1
LINE_FILL Horizontal lines 2
LTSLASH_FILL /// Pattern (Thin lines) 3
SLASH_FILL /// Pattern (Thick lines) 4
BKSLASH_FILL \\\ Pattern (Thick lines) 5
LTBKSLASH_FILL \\\ Pattern (Thin lines) 6
HATCH_FILL Light cross Hatch 7
XHATCH_FILL Heavy cross Hatch 8
INTERLEAVE_FILL Interleaving lines 9
WIDE_DOT_FILL Sparse dots 10
CLOSE_DOT_FILL Densely packed dots 11
USER_FILL User defined pattern 12

3.11.6 Cursor Control

moveto() FUNCTION
This function moves the cursor to the specified location in the graphics
screen.
Syntax: moveto(column, row);

Example: moveto(100,100);

positions the cursor at location 100,100 on the screen.

3.11.7 Text Output


Introduction to OOP unit1

outtext() and outtextxy() FUNCTIONS


Both these functions are used to display text on the screen in the graphics
mode. The function outtext() displays the text at current cursor position
while the outtextxy() function positions the cursor and displays the given
text.
Syntax : outtext(text_string);

This function is usually used after the moveto() function.

Syntax : outtextxy(column, row, text_string);

Example : outtextxy(50,50,”MICE”); prints MICE at 50, 50.

settextstyle() FUNCTION

This function is used to specify the font, direction and character size to be used
for subsequent text output in graphics mode.

Syntax : settextstyle(font, direction, char_size);


where font can be any of the values from Table 3.3. All these fonts are read from special
files, with extension .CHR, during run time.
TABLE 3.3
VALID FONT VALUES

Constant Value Displays


DEFAULT_FONT 0 Letters in default font
TRIPLEX_FONT 1 Stroked triplex letters
SMALL_FONT 2 Stroked small letters
SANS_SERIF_FONT 3 Stroked sans serif letters
GOTHIC_FONT 4 Stroked gothic letters

direction can be any of the values from the table 3.4


TABLE 3.4

VALUES FOR DIRECTION


Constant Value Displays text
HORIZ_DIR 0 horizontally, left aligned
VERT_DIR 1 vertically, top aligned
Introduction to OOP unit1

char_size magnifies all stroked letters specified number of times (unless it is 0) i.e.
if char_size is 2, magnification is 2 times. Maximum magnification is 10.

settextjustify() FUNCTION
This function is used to change the default alignment of horizontal and
vertical output.
Syntax : settextjustify(horiz, vert);

where horiz can be any of the values from Table 3.5

TABLE 3.5
Constant Value Displays text
LEFT_TEXT 0 Left Aligned (default)
CENTER_TEXT 1 Centered text
RIGHT_TEXT 2 Right Aligned text

vert can be any of the values from Table 3.6


TABLE 3.6

Constant Value Displays text


BOTTOM_TEXT 0 Bottom Aligned
CENTER_TEXT 1 Centered
TOP_TEXT 2 Top Aligned (Default)

getmaxcolor() FUNCTION

This function returns an integer to represent the maximum number of


colours supported by the current driver.

getpixel() and putpixel() FUNCTIONS

The getpixel() function returns an integer to represent the colour of the


pixel at the co-ordinates specified.
Syntax : getpixel(column, row);
Example : int i = getpixel(100, 100); stores in the variable i, the value of the
pixel representing its colour.
Introduction to OOP unit1

The putpixel() function plots the pixel at the specified location.


Syntax : putpixel(column, row, colour);
Example : putpixel(100,100, RED); displays a red coloured point at 100,100.

3.11.8 Clearing Graphics Screen

cleardevice() FUNCTION

This function clears the graphics screen and positions the cursor at 0, 0.
Syntax : cleardevice();

3.11.9 Ending Graphics Mode

closegraph() FUNCTION

This function must be used when no more graphics routines are to be


used. It releases the memory reserved by graphics system and restores
the screen to the video mode that was active before initgraph().
Syntax : closegraph();

3.11.10 Illustrates Some Graphics Functions

# include <iostream.h>
# include <graphics.h>
main()
{
int g_dr, g_mode; int x,y;
g_dr = DETECT;
initgraph(&g_dr, &g_mode, "");
x = getmaxx()/2;
Introduction to OOP unit1

y = getmaxy()/2;
setcolor(RED);
setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
rectangle(0, 5, 635, 165); circle(x, y, 100);
setfillstyle(WIDE_DOT_FILL, 1); floodfill(50, 50, RED);
setfillstyle(SLASH_FILL, 3); floodfill(x,y,RED);
settextstyle(GOTHIC_FONT , HORIZ_DIR, 6);
outtextxy(50, 50, "HELLO!" );
settextstyle(SANS_SERIF_FONT, VERT_DIR, 5);
outtext("MICE");
getch();
cleardevice();
moveto(getmaxx()/2, getmaxy()/2);
settextjustify(CENTER_TEXT, CENTER_TEXT);
setcolor(YELLOW);
outtext("MANIPAL INSTITUTE OF COMPUTER EDUCATION");
getch();
closegraph();
}

3.12 INHERITANCE IN GRAPHICS


This section illustrates inheritance in graphics. The program draws a
triangle, rectangle and a circle by taking as input the center point
coordinates and the radius.
For the triangle and the rectangle the required points are calculated using the
input obtained.

The base class is set_para. This is used to set the parameters for the linestyle,
fillstyle etc. with which the figure is to be drawn. The classes circle1, rectangle1,
triangle1 etc. are all derived from setpara. These classes draw the respective
figure.

The problem has been solved in Example 3.11.1


Introduction to OOP unit1

3.12.1 Example To Illustrates Inheritance In Graphics


# include <iostream.h>
# include <conio.h>
# include <graphics.h>
int gd = DETECT,gm;

class set_para
{
private:
int color; //0..15 for
int fill_pattern; //0..12 setfillstyle

int line_width; //1&3 for


int line_style; //0..4 setting
int upat; //0&1 line style

public :
int xc, yc, radius;

void draw() {
setfillstyle(fill_pattern,color);
setlinestyle(line_style,upat,line_width);
}
set_para(int c,int fp,int lw,int ls,int up) {
xc = getmaxx()/2; yc = getmaxy()/2;
color = c; fill_pattern = fp;
line_width = lw; line_style = ls;
upat = up;
}
};
class triangle1 : public set_para
{
private:
Introduction to OOP unit1

int pts[8];
public:
void tria(int r)
{
set_para::draw();
radius = r;
pts[0]=xc; pts[1]=yc-radius;
pts[2]=xc-radius; pts[3]=yc+radius;
pts[4]=xc+radius; pts[5]=yc+radius;
pts[6]=xc; pts[7]= yc-radius;
fillpoly(4,pts);
}
triangle1(int c,int fp,int lw,int ls,int up):set_para(c,fp,lw,ls,up)
{}
};

class circle1 : public set_para


{
public:
void circl(int r) {
set_para::draw(); radius = r;
circle(xc,yc,radius); floodfill(xc,yc,getmaxcolor());
}
circle1(int c,int fp,int lw,int ls,int up):set_para(c,fp,lw,ls,up) {
}
};
class rectangle1 : public set_para
{
public :
void rect(int r) {
set_para::draw(); radius = r;
Introduction to OOP unit1

rectangle(xc-radius, yc-radius, xc+radius, yc+radius);


floodfill(xc,yc,getmaxcolor());
}
rectangle1(int c,int fp,int lw,int ls,int up):set_para(c,fp,lw,ls,up) {
}
};
void main() {
initgraph(&gd,&gm,""); cleardevice();
setbkcolor(6);
rectangle1 r(6,9,1,0,1); r.rect(125);
circle1 c(7,9,1,1,0); c.circl(100);
triangle1 t(15,11,1,1,1); t.tria(80);
getch();
closegraph();
}

Setviewport

The setviewport function sets the current viewport for graphics outputs.

The viewports arguments are given in absolute screen cordinates.

void setviewport(left, top, right, bottom, clip);

The clip argument is 0 or non-zero. If the value is non-zero all drawings will be
clipped to the current viewport.

Clearviewport
The clearviewport function clears the current viewport.

clearviewport();

Fillellipse
Fillellipse draws and fills an ellipse.
Introduction to OOP unit1

Void fillellipse (int x, int y, int xradius, int yradius);


x,y - refer to the center of ellipse
xradius - refers to the horizontal axis
yradius - refers to the vertical axis

EXAMPLE 3.7
#include <graphics.h>
#include <conio.h>
#include <dos.h>
void plane(int x,int y)
{ line (x,y,x+10,y-3);
line (x+10,y-3,x+25,y-2);
line (x+25,y-2,x+29,y-7);
line (x+29,y-7,x+27,y);
line (x+27,y,x,y);
line (x+11,y-1,x+15,y-1);
}
main()
{
int gm,gd,i,w;
detectgraph(&gd,&gm);
initgraph(&gd,&gm,"");
setviewport(300,100,500,200,0);
setbkcolor(WHITE);
setfillstyle(SOLID_FILL,RED);
bar(0,0,200,100);
for(i=100;i+200 > 0;i = i-5)
{
delay(100);
setfillstyle(SOLID_FILL,RED);
bar(0,0,200,100);
setfillstyle(SOLID_FILL,YELLOW);
Introduction to OOP unit1

fillellipse(88,3,12,9);
plane(i,10);
plane(i+15,30);
plane(i+50,13);
plane(i+70,70);
outtextxy(i,50,"Let us hope they are Birds and not war planes");
}
getch();
clearviewport(); closegraph();
}

3.13 simulating moving objects


When connected with a graphics display, a whole world of Object – Oriented
animation opens up to the C++ programmer.

As a simple example. Let us make a class of molecules that can bounce around
in a closed container.

Member functions of molecule erase the molecule at its old position,


calculate the new position, and draw the molecule at the new position.
This is how the animation effect – an object moving on the screen – is
achieved, by continually erasing and redrawing the object. Here’s the
listing for MOLECULE.
Example 3.8 Simulating moving objects

# include <graphics.h>
# include <conio.h>
# include <stdio.h>
# include <stdlib.h>
const int RAD=5;
Introduction to OOP unit1

const int MAX=6;


const int DIST=(RAD+MAX);
const int LEFT=0;
const int TOP=0;
const int RIGHT=639;
const int BOTTOM=479;
enum hdir { hSTOP=0,hRIGHT,hLEFT};
enum vdir { vSTOP=0,vDOWN,vUP};
class molecule
{
private: int xco,yco;
int oldx,oldy;
int speed;
hdir horz;
vdir vert;
COLORS color;
public:
molecule (int x,int y,int s,hdir h,vdir v,COLORS c)
{xco=x;yco=y;speed=s;horz=h;vert=v;color=c;}
void erase();
void calculate();
void draw();
};
void molecule::erase()
{
setcolor(DARKGRAY);
circle(oldx,oldy,RAD);
setfillstyle(SOLID_FILL,BLACK);
floodfill(oldx,oldy,DARKGRAY);
setcolor(BLACK);
circle(oldx,oldy,RAD);
Introduction to OOP unit1

}
void molecule::calculate()
{
oldx=xco;
oldy=yco;
switch(horz)
{
case hSTOP:break;
case hRIGHT:xco +=speed;break;
case hLEFT:xco-=speed;break;
}

if (xco<=LEFT+DIST)
horz=hRIGHT;
else if (xco>=RIGHT-DIST)
horz=hLEFT;
switch(vert)
{
case vSTOP:break;
case vDOWN:yco+=speed;break;
case vUP:yco-=speed;break;
}
if(yco<=TOP+DIST)
vert=vDOWN;
else if(yco>=BOTTOM-DIST)
vert=vUP;
}
void molecule :: draw()
{
setcolor (color);
circle (xco,yco,RAD);
Introduction to OOP unit1

setfillstyle(SOLID_FILL,color);
floodfill(xco,yco,color);
}
void main()
{
/* initialize graphics mode */
initgraph(&gdriver, &gmode, "\\tc3\\bgi");
errorcode = graphresult();

if (errorcode != grOk)
{
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1);
}
molecule m1(100,120,2,hRIGHT,vUP,BLUE);
molecule m2(150,220,2,hLEFT,vUP,GREEN);
molecule m3(200,140,3,hRIGHT,vDOWN,CYAN);
molecule m4(250,240,3,hLEFT,vDOWN,RED);
molecule m5(300,160,3,hRIGHT,vUP,MAGENTA);
molecule m6(150,350,4,hLEFT,vUP,LIGHTGREEN);
molecule m7(150,350,4,hLEFT,vSTOP,LIGHTGRAY);
molecule m8(150,350,4,hSTOP,vUP,BROWN);

rectangle(LEFT,TOP,RIGHT,BOTTOM);
while(!kbhit() )
{
m1.calculate();m1.erase();m1.draw();
m2.calculate();m2.erase();m2.draw();
Introduction to OOP unit1

m3.calculate();m3.erase();m3.draw();
m4.calculate();m4.erase();m4.draw();
m5.calculate();m5.erase();m5.draw();
m6.calculate();m6.erase();m6.draw();
m7.calculate();m7.erase();m7.draw();
m8.calculate();m8.erase();m8.draw();
}
closegraph();
}

A molecules’ direction has two components: x and y. To calculate its new


position, you either add or subtract the speed to the x position, depending
on the angle. You do the same for the y position. If either of these
generations brings the molecule to the edge of the screen, we change the
appropriate component of the direction, so that the molecule appears to
bounce off the wall. To draw the molecule, you draw the outline of a circle
and fill it with the same color. To erase it you draw over it with a dark gray
circle, then fill it with black and erase it.

3.14 Using Cout With Graphics


You can fall back on ordinary character – based output with Cout. This works in
graphics mode, and although the text appears rather crude in the graphics
environment, it does not provide a quick and dirty way to generate text output.
This approach is sometimes helpful in debugging, when you want to check the
values of variables but do not want to go to the trouble of using outtext ( ) or the
debugger.

3.15 EXERCISE
1. Create a template for arrays.
2. Create a template for singly linked list.
3. Create a class to create and display strings of a linked list.
4. Create a class for creating a double linked list.
Introduction to OOP unit1

3.16 Summary
Pointers are variables that hold address values. Pointers are defined
using an asterisk (*). A data type is always included in pointer definitions,
since the compiler must know what is being pointed to, so that it can
perform arithmetic correctly on the pointer. The address operator & is
used to store the address of a variable. You can access the thing pointed
to using the asterisk in a different way, as the indirection operator,
meaning contents of the variable pointed to by.
Array elements can be accessed using pointer notation. Like other address, the
address of an array is a constant, which can be assigned to a variable, can be
incremented and changed in other ways.

The new operator obtains a specified amount of memory from the system and
returns a pointer to the memory. This operator is used to create variable and
data structures during program execution. The delete operator releases memory
obtained with new.

Classes and structures may contain data members that are pointers to their own
type. This permits the creation of complex data structures like linked lists.

Turbo C++ has 2 kinds of functions called graphics functions. The first works
only with text displays and is concerned with displaying text in a rectangular area
of the screen called a window. The key function in this mode is window(), which
defines the rectangular area.

The second kind of graphics function requires a graphics display. Programs that
uses these functions must initialize the display system to a graphics mode using
the initgraph() function, and terminates with the closegraph( ) function.

Library function can write lines, squares, and polygons on the screen, use
different line widths, and fill shapes with color. Text in a variety of fonts can be
displayed, and its size, color and positions can be manipulated.

ANSWERS FOR EXERCISE 3.15


1.
# include<iostream.h>
Introduction to OOP unit1

const int MAX=5;


template<class t>
class array
{ protected : t arr[MAX];int i;
public :
array(){i=-1;}
void store(t var)
{ arr[++i]=var;}
void disp()
{ int k;
for (k=0;k<MAX;k++)
cout<<arr[k]<<endl;}
};
template <class x>
class array1 : public array<x>
{ public :
void store(x var)
{ if (i+1<MAX)
array<x>::store(var);
else
cout<<"\n error array full\n";

}
};

void main()
{

array1 <int> a1;


a1.store(10); a1.store(20); a1.store(30);

a1.disp();
Introduction to OOP unit1

array1 <char> a2;


a2.store('a'); a2.store('b'); a2.disp();
}
2. #include <conio.h>
#include <iostream.h>
#define NULL 0
enum bool {FALSE,TRUE};
template <class T>
class Data
{
public :
virtual void setdata(T&) =0;
virtual T getdata() = 0;
};
class Link
{
Link *prev;
Link *next;
public:
Link() { next=NULL;prev=NULL;}
linkto(Link *l) { next=l; if (l) l->prev=this;}
Link * nextlink() {return next;}
Link * prevlink() {return prev;}
};
template <class T>
class Node : public Data<T>, public Link
{
private :
T data;
public :
Introduction to OOP unit1

Node() :Link() {}
Node(T& val) {data = val;}
void setdata(T &dat) { data = dat;}
T getdata() { return data;}
};

template <class T>


class list
{

private :
Node <T> *head;
Node <T> *tail;
public:

list() {head=tail=NULL;}
bool isempty() {if (head==NULL) return FALSE;
else return TRUE;
}

void display_list();
void add_data(T data) { Node <T> * temp= new Node<T>;
temp->setdata(data);
if (head==NULL)
{
head=tail=temp;}
else
{
tail->linkto(temp);
tail=temp;
}
}

};
Introduction to OOP unit1

template <class T>


void list <T> :: display_list()
{
Node <T> *tmp= head;
cout << endl << "Data in the list ";
while (tmp)
{
cout << endl << tmp->getdata();
tmp=(Node <T> *) tmp->nextlink();
}
}

void main()
{
list <int> l1;
l1.add_data(100);
l1.add_data(200);
l1.add_data(300);
l1.add_data(300);
l1.add_data(300);
l1.display_list();
list <char> l2;
l2.add_data('z');
l2.add_data('j');
l2.add_data('k');
l2.add_data('v');
l2.add_data('b');
l2.display_list();
getch();
}

3. //strings of linked list


Introduction to OOP unit1

# include<iostream.h>
# include<string.h>
# include <conio.h>
struct node
{ char name[20];
node *next;
};
class linklist
{ private : node *first;
node *last;
public : linklist(){first=NULL;}
void additem(char *s);
void display();
};

void linklist :: additem(char *s)


{ node *newline=new node;
strcpy(newline->name,s);
newline->next=NULL;
if (first==NULL)
{ first=newline;
last=first;
}
else
{ last->next=newline;
last=newline;
}
};

void linklist ::display()


{ node *current=first;
Introduction to OOP unit1

while (current!=NULL)
{ cout<<endl<<current->name;
current=current->next;
}
}
void main()
{
linklist l1;
clrscr();
l1.additem("niki");
l1.additem("asha");
l1.additem("shaila");
l1.additem("usha");
l1.display();
getch();
}

4. //double linked list


#include <iostream.h>
struct node
{ int data;
node *next;
node *prev;
};

class linklist
{ private :
node *first;
Introduction to OOP unit1

node *last;
public :
linklist()
{ first=NULL; }
void additem(int d);
void disp_forward();
void disp_backward();
};
void linklist ::additem(int d)
{ node *newlink=new node;
node *temp=new node;
newlink->data=d;
newlink->next=NULL;
if (first==NULL)
{ first=newlink;
first->prev=NULL;
last=first;
}
else
{ temp=newlink;
temp->prev=last;
last->next=temp;
last=newlink;
}
}

void linklist ::disp_forward()


{ node *current=first;
while(current!=NULL)
{ cout<<endl<<current->data;
Introduction to OOP unit1

current=current->next;
}
}
void linklist ::disp_backward()
{ node *current=last;
while(current!=NULL)
{ cout<<endl<<current->data;
current=current->prev;
}
}
void main()
{
linklist l1;
l1.additem(10);
l1.additem(20);
l1.additem(30);
cout <<"Elements in forward direction"<<endl;
l1.disp_forward();
cout <<endl<<"Elements in backward direction"<<endl;
l1.disp_backward();
}
Introduction to OOP unit1

UNIT 4 FILES & STREAMS,POLYMORPHISM & VIRTUAL


FUNCTIONS
Structure

4.0 Introduction
4.1 Objectives
4.2 Files And Streams
4.2.1 Stream Class Hierarchy
4.3 Files
4.4 Manipulating ASCII Files
4.4.1 Creating An ASCII String File
4.4.2 Reading An ASCII String File
4.4.3 Character Input/Output
4.4.4 Creating a File using put()
4.4.5 Creating a File using get()
4.4.6 Detecting End of File
4.5 The fstream Class
4.6 Manipulating binary Files
4.6.1 Creating a Student File
4.6.2 Displaying Student File
4.7 Positioning the stream pointer
4.7.1 Functions to Move the File Pointer
4.7.2 Illustrates seekg() function
4.8 Objects that Reads and writes themselves
4.9 The ios Flags
4.10 Friend Functions and Classes
4.10.1 Illustrates Friend Functions
4.10.2 Friend Classes
4.10.3 Exercise
4.10.4 Disadvantages of Friend Class/Functions
4.10.5 Advantages of Friend Functions
4.10.6 Example for Overload >> and << for Class Marks
Introduction to OOP unit1

4.11 Command Line Parameters


4.11.1 Use of Command Line Parameters To Add Numbers given as
Command Line Parameters
4.12 Redirection in C++
4.12.1 Output Redirected to Printer
4.13 Polymorphism
4.14 The C++ Pointer Rule
4.15 Virtual Function
4.15.1 Illustrates Virtual Functions
4.16 Example to Demonstrate Polymorphism
4.17 Pure Virtual Functions and Abstract Class
4.17.1 Example for Virtual Functions in Graphics
4.18 Exception
4.18.1 Example for Exception
4.19 Exercise
4.20 Summary

4.0 INTRODUCTION
Most programs need to read and write data to disk files. In this unit you will learn
how to perform these activities using C++ streams. A stream is a general name
given to a flow of data. Different streams are used to represent different kinds of
data flow. Each stream is associated with a particular class, which contains
member functions and definitions for dealing with that particular kind of data flow.
Each file in C++ is an object of a particular stream class.

You can read and write to files using cout and cin. These predefined objects
normally represent the display and the keyboard, but they can be redirected by
the user to represent disk files. Redirection is a technique that allows the user
considerable flexibles in the way programs are used.

The concepts of encapsulation and data hiding ensure that nonmember


functions should not be able to access an object’s private or protected data i.e. if
Introduction to OOP unit1

you are not a member, you cannot get it. But this can be achieved by using
friend functions.

Virtual means existing in effect but not in reality. A virtual function is one that
does not really exist but nevertheless appears real to some parts of a program.

Command line arguments are used when invoking a program for DOS. They are
used to pass the name of a data file to an application.

4.1 OBJECTIVES
At the end of this unit, you will be able to:
♦ Understand the stream class Hierarchy.
♦ Stores the contents into a data file.
♦ Retrieves the contents from a data file.
♦ How to use friend functions in a class.
♦ Pass arguments to a program from the operating system i.e. command line
arguments.
♦ Redirection in C++.
♦ Polymorphism and virtual functions.

4.2 STREAM
A Stream is a general name given to a flow of data. Each stream is associated
with a particular class, which contains member functions and definitions for
dealing with that particular kind of data flow.

4.2.1 Stream Class Hierarchy


The ios class is the base class. It contains many constants and member
functions common to input and output operations. E.g. showpoint and fixed flags
used for numeric output. The ios class derives two classes - istream and
ostream.

The istream class includes all functions for input of data. It includes member
functions like get(), getline(), read(). The overloaded extraction operator >> is a
Introduction to OOP unit1

member of the istream class. The cin object, representing the standard input
stream, usually directed from the keyboard, is a predefined object of the
istream_withassign class, which is derived from the istream class.

The ostream class includes all functions for output of data. It includes member
functions like put(), putline() and write(). The overloaded insertion operator << is
a member of the ostream class. The cout object, representing the standard
output stream, usually directed to the video display, is a predefined object of the
ostream_withassign class, which is derived from the ostream class.

The iostream class is derived from both istream and ostream class by multiple
inheritance. The iostream_withassign class is derived from iostream class. The
<baseclass>_withassign classes add assignment perators to their base classes.

The classes used for input and output to the video display and keyboard are
declared in the header file iostream.h. The classes used for disk I/O are included
in the file fstream.h.

fstream.h incorporates iostream.h. Therefore, you need not explicitly open


iostream.h. The hierarchy of the classes included in the iostream and fstream
classes is shown in the form of a diagram.
Introduction to OOP unit1

ios pointer streambuf

istream fstreambase ostream filebuf

iostream

ifstream fstream ofstream

istream_withassign iostream_withassign
ostream_withassign

iostream.h fstream.h

Figure 4.1 : Stream Class Hierarchy.

4.3 FILES
Files are of two types
♦ ASCII files
♦ binary files.

ASCII files are those files created by storing each character. They can also be
called as text files.

Binary files are those files created by storing a block of memory (array or
structure or class) . These are also called non-ASCII files.
Introduction to OOP unit1

4.4 MANIPULATING ASCII FILES


To transfer a string to the file, you declare an object to be a member of the
ofstream class and initialize it to the filename that you want to use. This
initialization sets aside various resources for the file and accesses the file of that
name on the disk. You can use the insertion operator << to output text to the
file.

As in C, there is no need to open or close the file. This is automatically done by


the constructors and the destructors of the ostream class.

To see the text in the file you can display it with the DOS TYPE command or
open the file in any editor.

4.4.1 Example To Creating An Ascii String File


# include <fstream.h>
void main()
{
ofstream outfile ("out.txt"); // Open file for output.
outfile << "Creating an ASCII file" << endl;
outfile << "C++ is said to be the superset of C" << endl;
outfile << "We are using the Turbo C++ 3.0 Version" << endl;
}

To obtain a string to the file, you declare an object to be a member of the


ifstream class and initialize it to the filename that you want to use. To read a
string, you can use the istream member function getline(variable, length); This is
illustrated in the example given below.

4.4.2 Example For Reading An Ascii String File.


# include <fstream.h>
void main()
{
const int max = 80; char buffer[80];
ifstream infile ("out.txt"); // Declare file for input.
while (infile) // Check for End of File.
Introduction to OOP unit1

{
infile.getline(buffer,max);
cout << buffer;
}
}

4.4.3 Character Input /Output


To manipulate a file character by character, you use the member functions put()
for output to file or get() for input from file.

4.4.4 Example For Creating A File Using put()


# include <fstream.h>
void main()
{
ofstream tstfile ("out.dat");

char text[ ] = "This is a text line";


int i=0;

while (text[i])
tstfile.put(text[i++]);
}

4.4.5 Example For Reading A File Using get().


# include <fstream.h>
void main()
{ ifstream tstfile ("out.dat");

char ch;
int i=0;
while (tstfile)
{
ch = tstfile.get( );
cout << ch;
}
}
4.4.6 Detecting End-Of-File
Introduction to OOP unit1

The ifstream objects have values that can be tested for various error conditions.
If a condition is true, the object returns a zero value, otherwise it returns nonzero
value. One of these conditions is the end of file (EOF). The above program
checks for the end of file in a while loop.

4.6 THE FSTREAM CLASS


Till now, you created an object for either reading from or writing to the file. You
can also create a file for operating in more than one modes. The advantage of
using more than one mode is that you can read and write from the file without
having to close and open the file each time in either read or write mode.

If you want to use the file for both input and output simultaneously, you declare
the a stream to be an object of fstream class. To associate the file with the
stream, you have to open the file using the open() member function in the
required modes.

In the open() function you include several mode bits to specify certain aspects of
the file object you are opening. The options are given in the table.

TABLE 4.1 - MODES FOR OPENING FILES


DESCRIPTION
in Open for reading (default for ifstream).
out Open for writing (default for ofstream).
app start reading or writing at the end of the file (append).
ate erase file before reading or writing (truncate).
nocreate error when opening if file does not already exist.
noreplace error when opening for output if file already exists, unless
ate or app is set.
binary open file in binary (not text) mode.
Introduction to OOP unit1

E.g. open("data.dat",ios::in | ios::out | ios::app);


will open the file, data.dat for input or output or append modes. The in and out
modes are included because you want to use the file for both reading and
writing. The app mode is used to retain the previous contents of the file.

The vertical bar between the flags cause the bits representing these flags to be
ORed together bitwise, so that several flags can apply simultaneously.

After opening the file, the necessary manipulations can be done. Finally, the file
has to be closed using the close() member function.

4.6 MANIPULATING BINARY FILES


The binary files can be used to store or retrieve objects to and from the file.

To write to the file, you use the function, write() which takes two arguments - a
pointer to the block and the size of the block.

Similarly to get the contents from the file, you use the function, read() which
takes two arguments - a pointer to the block and the size of the block.

The following example creates a student file by declaring an object of fstream


class. Though the file can be opened in many modes, in the following two
examples, it has been opened in only one mode (read [in] / write [out] ).

The examples also illustrate the read () and write() member functions which are
usually used for transfer of data block from and to the file.

4.6.1 Example For Creating A Student File


# include <fstream.h>
class student
{
private : int rno; char name[10]; float fees;
public : void getdata()
{
cout << "Roll Number: "; cin >> rno;
cout << endl << "name :"; cin.get(); cin >> name;
cout << endl << "fees :"; cin >> fees;
Introduction to OOP unit1

}
void dispdata()
{
cout << "Roll Number = " << rno <<endl;
cout << "Name = " << name << endl;
cout << "Fees = " << fees << endl;
}
};
void main()
{
student s1;
fstream stdfile;
stdfile.open ("std.dat", ios::out|ios::binary); // Open file for output.
char wish;
// Writing to the file.
do
{
s1.getdata();
stdfile.write( (char *)&s1, sizeof(student));
cout << "Continue ? y/n"; cin >> wish;
}
while (wish == 'y' || wish == 'Y');
stdfile.close(); // Close the file.
}
4.6.2 Example For Displaying A Student File
# include <fstream.h>
class student
{
private : int rno; char name[10]; float fees;
public : void getdata()
{
cout << "Roll Number: "; cin >> rno;
cout << endl << "name :"; cin.get(); cin >> name;
cout << endl << "fees :"; cin >> fees;
}
Introduction to OOP unit1

void dispdata()
{
cout << "Roll Number = " << rno <<endl;
cout << "Name = " << name << endl;
cout << "Fees = " << fees << endl;
}
};
void main()
{
student s1;
fstream stdfile;

stdfile.open("std.dat",ios::in|ios::binary);
stdfile.read( (char *)&s1,sizeof(student));
while (stdfile)
{
s1.dispdata();
stdfile.read( (char *)&s1,sizeof(student));
}
stdfile.close();
}

4.7 POSITIONING FILE POINTERS


When you can open a file in more than one mode using the fstream class, it is
not necessary to close the file and open it again when you need to switch from
one mode to the other. But if you are writing and reading in different positions of
the file then, the stream pointers have to be positioned appropriately.

Each file object has associated with it two integer values called the get pointer
and the put pointer. These are also called the current get position and the
current put position, or simply the current position. These values specify the byte
number in the file where reading or writing will take place.

4.7.1 Functions To Move The File Pointer


seekg( ) and seekp( )
seekg () - for get pointer
seekp () - for put pointer
Introduction to OOP unit1

These functions take two arguments.


The first argument is the relative offset i.e. the number of bytes the file pointer
has to be moved. (+ for forward and - for backward. )

The second argument is the position of the file pointer from where the offset is to
be considered. The default argument for this is the beg (beginning of the file). It
can take values ios::beg (beginning), ios::end (end of file), and ios::cur (current
pointer position).

E.g. : seekg(-5, ios::end); moves the get pointer 5 bytes backward from the end
of the file.

THE tellg () or tellp() FUNCTION


These functions return the current position of the get or put pointer in bytes.

The following example illustrates the use of seekg() function. The seekp()
function is also used in a similar manner whenever necessary.

4.7.2 Example To Illustrate seekg() Function


# include <fstream.h>
# include <io.h>
# include <string.h>
class student
{
private : int rno; char name[10]; float fees;
public : void getdata()
{
cout << "Roll Number: "; cin >> rno; cin.get();
cout << endl << "name :"; cin >> name;
cout << endl << "fees :"; cin >> fees;
}
void dispdata()
{
cout << "Roll Number = " << rno <<endl;
cout << "Name = " << name << endl;
cout << "Fees = " << fees << endl;
}
};
Introduction to OOP unit1

void main()
{
student s1; fstream stdfile; char wish;
stdfile.open ("std.dat",ios::app | ios::out | ios::in|ios::binary);
do // Writing to the file.
{
s1.getdata();
stdfile.write( (char *)&s1, sizeof(student));
cout << "continue ? ( y / n )" << endl; cin >> wish;
}while (wish == 'y' || wish== 'Y');

stdfile.seekg (0); // moves the file pointer to beginning of the file.


stdfile.read( (char *)&s1,sizeof(student));
while (!stdfile.eof()) // Reading from file.
{
s1.dispdata();
stdfile.read( (char *)&s1,sizeof(student));
}
stdfile.close();
}

4.8 OBJECTS THAT READ AND WRITE THEMSELVES


Sometimes it makes sense to let each member of a class read and write itself to
a file. In this example you can add member functions – diskout ( ) and diskin ( ) –
to the person class. These functions allow a person object to write itself to a disk
and read itself back in.
Introduction to OOP unit1

4.8.1 Example For Objects that Read and Write Themselves


# include<fstream.h>
class person
{
protected:
char name[40];
int age;
public:
void getdata(void)
{
cout<<"\nEnter name";cin>>name;
cout<<"\nEnter age";cin>>age;
}
void showdata(void)
{
cout<<"\nName:"<<name;
cout<<"\nAge:"<<age;
}
};
void main(void)
{
person pers;char ch;
fstream infile;
infile.open("Person.dat",ios::binary|ios::out|ios::in);
do
{
cout<<"\nEnter persons data";
pers.getdata();
infile.write((char*)&pers,sizeof(pers));
cout<<"\nEnter another person(y/n)";
cin>>ch;
} while(ch=='y');
infile.seekg(0,ios::end);
int endposition=infile.tellg();
int n=endposition/sizeof(person);
cout<<"\nThere are"<<n<<"persons in file";
Introduction to OOP unit1

cout<<"\nEnter person number";


cin>>n;
int position=(n-1)*sizeof(person);
infile.seekg(position);
infile.read((char*)&pers,sizeof(pers));
pers.showdata();
}

4.9 THE ios FLAGS


Till now, you have been using the ios flags for various reasons like formatting
decimal output, setting the appropriate flags and so on. A list of all the flags and
its use is given in the table below :

TABLE 4.2
THE ios FLAGS
Flag Purpose
skipws Skip whitespace on input.
left Left - justify output.
right Right - justify output.
internal Use padding after sign or base indicator.
dec Decimal Conversion.
oct Octal Conversion.
hex Hexadecimal Conversion.
showbase Use base indicator on output.
showpoint Use decimal point in floating - point output..
uppercase Uppercase hex output.
showpos Preface positive integers with '+'.
scientific Floating - point notation with E (E.g. : 6.4575E2).
fixed Fixed floating - point notation (645.75).
unitbuf Flush all streams after insertion.
stdio Flush stdout and stderr after insertion.

4.10 FRIEND FUNCTIONS AND CLASSES


These are used when you want to override the security provided by the classes.
Introduction to OOP unit1

For e.g. When the data of two objects is to be added and they are members of
different classes, the addition function cannot be an individual member function
of either class because it must be possible to access the private members of
both the classes. You can then declare a function to be a friend of both the
classes and use it to do the necessary calculations.

When a class B is declared to be a friend of another class A then, the members


of class A (private and public) can be accessed withi class B.

♦ The friend function can be declared anywhere, that is, as private or as public.
It is not governed by the access specifiers.
♦ Friend functions are not transitive. That is, if X is a friend of Y and Y is a
friend of Z, it does not imply that X is a friend of Z.
♦ Friendship, however, can be inherited.

4.10.1 Example To Illustrates Friend Functions


# include <iostream.h>
class newclass; // Forward declaration.

class myclass
{
private : int mydata;
public : myclass( ) { mydata = 0; }
myclass (int n ) { mydata = n; }
friend int addclass (myclass, newclass); // Friend Function.
};
class newclass
{
private : int newdata;
public : newclass ( ) {newdata = 0; }
newclass (int n ) { newdata = n; }
friend int addclass (myclass, newclass);
};

int addclass (myclass mc, newclass nc)


{
Introduction to OOP unit1

int tot;
tot = mc.mydata + nc.newdata;
return (tot);
}
void main( )
{
myclass m1(100); newclass n1(200);
cout << "\nThe sum of the data of the two classes is " << addclass(m1,n1);
}

4.10.2 Friend Classes


The member functions of a class can all be made friends at the same time when
you make the entire class a friend.

4.10.3 Example of Friend Classes


# include<iostream.h>
class alpha
{
private:
int data1;
public:
alpha(){ data1=99; }
friend class beta;
};
class beta
{
public:
void func1(alpha a) {cout<<"\ndata1:"<<a.data1;}
void func2(alpha a) {cout<<"\ndata1:"<<a.data1;}
void func3(alpha a) {cout<<"\ndata1:"<<a.data1;}
};
void main()
{
alpha a;
beta b;
b.func1(a);
b.func2(a);
Introduction to OOP unit1

b.func3(a);
}
In the alpha the entire class beta is proclaimed a friend. Now all the member
functions of beta can access the private data of alpha.

4.10.4 Disadvantage Of Friend Class/Functions


The aim of using object oriented programming is to protect the data members
from accidental or deliberate modifications. The data is to be accessed only
through the member functions of that class. By declaring a friend, the private
variables can be accessed by the friend which defeats the purpose of OOP.

4.10.5 Advantage Of Friend Functions


The istream and ostream classes overload the >> and << operators for system
defined data types. These overloaded functions can be used in any user defined
class to give a better interface to the data type defined. To overload >> and <<
for any userdefined data type, the functions have to be declared as a friend of
the user defined class.

This creates similarity between the objects of system defined data types and
user-defined data types, i.e. user-defined objects can be input or output using
the cin or cout statements without a member function in that class.

Note : The prototype of the overloaded >> operator in the istream class is as
follows :
istream& operator >> (istream& , datatype& );

The prototype of the overloaded << operator in the ostream class is as


follows :
ostream& operator << (ostream& , datatype& );

The following example illustrates how to overload >> and << operators for the
class marks.

4.10.6 Example For Overloaded >> And << For Class Marks
# include <iostream.h>
class marks
{
Introduction to OOP unit1

private : int roll; int mks;

public : marks( ) // Default Constructor


{ roll = -1; mks = 0; }
marks( int m, int n) // Overloaded Constructor
{ roll = m; mks = n; }

friend ostream& operator << (ostream& ostrm, marks& m);

friend istream& operator >> (istream& istrm, marks& m);


};

ostream& operator << (ostream& ostrm, marks& m)


{
ostrm <<endl << "Roll No : " << m.roll << endl << "Marks : " << m.mks;
return ostrm;
}
istream& operator >> (istream& istrm, marks& m)
{
cout << endl << "Enter Roll number : " ; istrm >> m.roll;
cout << endl << "Enter marks : "; istrm >> m.mks;
return istrm;
}
void main( )
{
marks m1;
cin >> m1; // input is done using the friend function
cout << endl << "The record is .......";
cout << m1; // output is done using friend function
}
4.11 COMMAND - LINE ARGUMENTS
The arguments that are passed to a program from the operating system along
with a command as it begins to execute are known as command - line
arguments.

The exe version of any program can be used like a command to execute the
program at the command line. To receive the command - line arguments,
usually two parameters are passed.
Introduction to OOP unit1

The two command line parameters used by a C++ program are argc (argument
count) and argv (argument value). The argc is an integer which is the number of
words in the command. The argv is an array of character pointers which stores
the words in the command.

E.g. copy file1 file2


For this DOS command,
argc = 3. argv[0] = "copy" argv[1] = "file1" argv[2] = "file2"

4.11.1 EXAMPLE FOR USE OF COMMAND LINE PARAMETERS TO


ADD NUMBERS GIVEN AS COMMAND - LINE PARAMETERS.
// add.cpp - program file.
# include <iostream.h>
# include <stdlib.h>
# include <process.h>
void main(int argc, char *argv[ ])
{
int i, sum = 0;
if (argc < 3)
{ cout << "Enter atleast two integers to add "; exit (-1); }
else
{
for (i = 1; i < argc; I++) sum = sum + atoi (argv[ i ]);
cout << "Sum of the numbers is : " << sum << endl;
}
}
Note : This program can be executed at the DOS prompt as :
A > add 10 20 30 40 50
where 'add' is the name of the file where the program is typed.
Output
Sum of the numbers is : 150
A>
To go to the DOS prompt directly from the compiler choose File, DOS
Shell option. After executing the program, type exit at the DOS prompt to
return to the compiler.
Introduction to OOP unit1

A second method to execute any C++ program having command line


arguments is as follows :
In the Run menu of the compiler, there is an option for Arguments. When
the option is chosen, type the arguments in the box provided. (Do not write
the filename in the box.) The program can then be executed in the usual
manner without having to go to the DOS prompt.

4.12 REDIRECTION IN C++


Redirection is a technique, that allows the user considerable flexibility in the way
the programs are used. Output from a program is normally to the standard
output file and this output can be redirected to a secondary storage file or to the
printer. Similarly, input redirection can be used to read data from a secondary
storage file instead of the standard input file, the keyboard.

The following example implements the DOS TYPE command with the output
being redirected to the printer.

Note :The type command is used to display the contents of any ASCII file. To
redirect the output to the printer, the command would be

type filename > prn

To implement this using C++, open an object of ostream for printer.

4.12.1 Example For Output Redirected To Printer.


// Filename : outprn.cpp
# include <fstream.h>
# include <process.h>
void main( int argc, char *argv[ ])
{
if (argc <= 1)
{
cerr << "Enter a file name"; exit(-1);
}
ifstream infile(argv[1]);
Introduction to OOP unit1

if (!infile)
{
cerr << endl << "Cannot open file " << argv[1];
exit(-1);
}

char ch;

ostream outfile;

outfile.open("PRN"); // open file for printer.


while (infile)
{
infile.get(ch); outfile << ch;
}
outfile.close();
}

To execute this program at the DOS prompt, you can use the command,

A > outprn out.txt


outprn - name of the C++ program file.
out.txt - file to be printed.

4.13 POLYMORPHISM

Polymorphism means "many forms". In C++, the meaning of polymorphism is


the ability to access different implementations of a function using the same
name.

There are two levels at which polymorphism operates. Compile-time


polymorphism and run-time polymorphism. Compile-time polymorphism has
already been demonstrated through operator overloading and function
overloading. Both are a subtle form of polymorphism since in both cases a
single entity is used to refer to two or more things.
Introduction to OOP unit1

Run-time polymorphism is based on virtual functions, derived classes and base


class pointers.

4.14 THE C++ POINTER RULE.

The rule as given in C++ terms is as follows. A Pointer declared as pointing to


base class can be used to point to an object of a derived class of that base
class, but a pointer to a derived class cannot be used to point to an object of the
base class or to any of the derived classes of the base class.

In the program given below, there is a base class named, vehicle. You are
allowed to declare a pointer to the vehicle class which is the base class and use
that pointer to refer to object of either the base class or any of the derived
classes.

This is exactly what you do in the main program. You declare a single pointer
which points to the vehicle class and use it to point to objects of each of the
classes - car, truck and boat.

4.15 VIRTUAL FUNCTION


Virtual functions are functions which are declared with the key word virtual in the
base class.

Example,

virtual void dispdata() { cout << " This is the base class";}

These virtual functions may or may not be implemented again in the derived
classes. If it is implemented, the declaration must be identical to that of the base
class except for the word, virtual.

void dispdata() { cout << "Roll number "<< roll; }

Below is an example program with a virtual function and exhibits dynamic binding
or polymorphism as it is called.

4.15.1 Example to Illustrate Virtual Function


Introduction to OOP unit1

#include <iostream.h>
class vehicle
{ protected :
int wheels;
float weight;
public :
virtual void message(void) { cout << "Vehicle message\n "; }
};

class car : public vehicle


{
int passenger_load;
public :
void message(void ) { cout << "Car message\n";}
};

class truck : public vehicle


{
int passenger_load;
float payload;
public :
int passengers(void) { return passenger_load;}
};
class boat : public vehicle
{
int passenger_load;
public :
int passengers(void) { return passenger_load;}
void message( void) { cout << "Boat message\n ";}
};

main()
{
vehicle *vc;
vc =new vehicle;
vc message () ;
vc=new car;
vc message () ;
Introduction to OOP unit1

vc=new truck;
vc message () ;
vc=new boat;
vc message () ;
delete vc;
}

The output will be,


Vehicle message
Car message
Vehicle message
boat message

Note : The keyword virtual only appears in the base class. All classes that
derive this class will have the corresponding method automatically
declared virtual by the system.

Since the method named message() is declared to be virtual method in its


declaration in the base class, anytime you refer to this method with a pointer to
the base class, you actually execute the method associated with one of the
derived classes if there is a method available in the derived class and if the
pointer is actually pointing to that derived class.

1. The decision of which method to call is not made during the time when the
code is compiled, but, when the code is executed. This dynamic binding and
can be very useful in some programming situations. In fact , there are only
three different calls made, because the class named truck does not have a
method message(), so the system simply uses the method from the base
class to satisfy the message passed. For this reason a virtual function must
have an implementation available in the base class which will be used if there
is not one available in one or more of the derived classes.
2. The structure of the virtual function in the base class and each of the derived
classes is identical. The return type and the number and the types of the
Introduction to OOP unit1

parameters must be identical for all, since a single statement can be used to
call any one of them.
3. If the keyword VIRTUAL is used the system will use late binding, which is
done at runtime, but if the keyword is not included, early binding will be
used. What these words actually mean is that with late binding the compiler
does not know which method will actually respond to the message because
the type of the pointer is not known at compile time. With early binding ,
however, the compiler decides at compile time, what method will respond to
the message sent to the pointer.

4.16 EXAMPLE TO DEMOSTRATE POLYMORPHISM

A class named, mice, keeps track of the products being sold and added to stock.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream.h>
#include <conio.h>
// Base class Product
class product
{
protected : char *name;
public :

product() { name = NULL;}


product(char *n) { name=strdup(n);}
~product() {delete name;}
virtual void which_product() { cout << "Just a product";}
};
class soap : public product
{
public : soap() : product() {}
soap(char *n) : product (n) {}
void which_product() { cout << "Soap named "<<name;}
};
Introduction to OOP unit1

class paste : public product


{
public : paste() : product() {}
paste(char *n) : product (n) {}
void which_product() { cout << "Tothpaste named "<<name;}
};
class mice
{
private : int maxproducts;
int nowproducts;
product **stock;
public:
mice(int n);
~mice();
int accept(product *d);
product* sell(int n);
void listproducts();
};
// Constructor
mice :: mice(int n)
{
maxproducts=n;
nowproducts=0;

stock = new product *[maxproducts];

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


stock[i]=NULL;
}

// Destructor
mice :: ~mice()
{
delete stock;
}

// ACCEPT member function


int mice :: accept(product *d)
Introduction to OOP unit1

{
if (nowproducts==maxproducts)
return 0;
++nowproducts;
int i=0;

while (stock[i] != NULL)


++i;
stock[i]=d;
return i+1;
}
// SELL member function
product* mice :: sell(int n)
{
if (n > nowproducts)
return NULL;
--n;

if (stock[n] != NULL)
{
product *temp=stock[n];
stock[n]=NULL;
--nowproducts;
return temp;
}
else
return NULL;
}

// LISTPRODUCTS member function


void mice :: listproducts()
{
if (nowproducts==0)
return;
for (int i=0;i<nowproducts;++i)
{
Introduction to OOP unit1

if (stock[i]==NULL)
continue;
cout << "\n Product " << i <<" ";
stock[i]->which_product();
}
}
void main()
{
clrscr();
mice m(10);
soap s1("rexona");
soap s2("lux");
soap s3("lifebuoy");
paste p1("colgate");
paste p2("close-up");
m.accept(&s1);
m.accept(&s2);
m.accept(&s3);
m.accept(&p1);
m.accept(&p2);
product *p =m.sell(2);
cout << "Product sold :"; p->which_product();
m.listproducts();
getch();
}

Output will be :
Product sold : soap named Lux.
And a list of the other products.

4.17 PURE VIRTUAL FUNCTIONS AND ABSTRACT CLASSES


A class that contains a pure virtual function is called an abstract class. Objects
of an abstract class cannot be defined but they are used to derive child classes.
A pointer to abstract class can be defined.
Introduction to OOP unit1

A pure virtual function is one, which is declared with the keyword virtual and
initialized to 0. That is, there in no implementation of the function. The functions
will be implemented in the derived classes.

virtual void showdata() = 0;

Pure virtual functions must be implemented or declared in the derived classes.

Pure Virtual Function

A pure virtual function is a virtual function with no body. In the notation =0, the
equal sign has nothing to do with assignment; the value 0 is assigned to
anything. The =0 syntax is simply how we tell the compiler that a function will be
pure – that is, have no body.

4.17.1 Example for Virtual Functions in a Graphics


In main ( ), you setup an array, ptrarr, of pointers to shapes. Next we create
three objects, one of each class, and place their addresses in an array. Now it is
easy to draw all 3 shapes. The statement ptrarr [ j ] draw ( ); does all this as the
loop variable j changes.This is a powerful approach to combining graphics
elements, especially when a large number of objects need to be grouped
together and drawn as a unit.

# include<graphics.h>
# include<conio.h>
const int w=50;
class shape
{
protected:
int xco,yco;
int linecolor;
int fillcolor;
public:
shape()
{ xco=0;yco=0;linecolor=WHITE;fillcolor=WHITE;}
void set(int x,int y,int lc,int fc)
Introduction to OOP unit1

{ xco=x;yco=y;linecolor=lc;fillcolor=fc;}
void colorize()
{
setcolor(linecolor);
setlinestyle(SOLID_LINE,0,THICK_WIDTH);
setfillstyle(SOLID_FILL,fillcolor);
}
virtual void draw()=0;
};
class ball:public shape
{
public:
ball(): shape()
{}
void set(int x,int y,int lc,int fc)
{
shape::set(x,y,lc,fc);
}
void draw()
{
shape::colorize();
circle(xco,yco,w);
floodfill(xco,yco,linecolor);
}
};
class rect:public shape
{
public:
rect():shape()
{}
void set(int x,int y,int lc,int fc)
{
shape::set(x,y,lc,fc);
}
void draw()
{
shape::colorize();
rectangle(xco-w,yco-w,xco+w,yco+w);
floodfill(xco,yco,linecolor);
Introduction to OOP unit1

moveto(xco-w,yco+w);
lineto(xco+w,yco-w);
}
};
class tria:public shape
{
public:
tria():shape()
{}
void set(int x,int y,int lc,int fc)
{
shape::set(x,y,lc,fc);
}
void draw()
{
shape::colorize();
int triarray[]={xco,yco-w,
xco+w,yco+w,
xco-w,yco+w};
fillpoly(3,triarray);
}
};
void main()
{
int driver,mode;
driver=DETECT;
initgraph(&driver,&mode,"x:\tc3\bgi");
shape* ptrarr[3];
ball b1;
rect r1;
tria t1;
b1.set(100,100,WHITE,BLUE);
r1.set(100,200,WHITE,RED);
t1.set(100,300,WHITE,GREEN);
ptrarr[0]=&b1;
ptrarr[1]=&r1;
ptrarr[2]=&t1;
for (int j=0;j<3;j++)
Introduction to OOP unit1

ptrarr[j]->draw();
getche();
closegraph();
}
4.18 EXCEPTIONS
Exceptions provide a systematic, object – oriented approach to handling runtime
errors generated by C++ classes. For example a constructor in a user – written
string class might generate an exception if the application tries to initialize an
object with a string that is too long.

Not all errors can be handled by exception. For example, some errors are
detected, not by the program but by the OS, which then terminates the
application.

When exceptions are used, this is called ‘throwing an exception’. In the


application we install a separate section of code to handle the error. This is
called ‘Exception handler’ or ‘catch block’. Any code in the application that uses
objects of the class is enclosed in a ‘try block’. So the exception mechanism
uses 3 new C++ keywords: throw, catch and try.

4.18.1 A Simple Exception Example


# include<iostream.h>
const int MAX=3;
class stack
{
private:
int st[MAX];int top;
public:
class range
{
};
stack(){top=-1;}
void push(int var)
{
if(top>=MAX-1)
throw range();
Introduction to OOP unit1

st[++top]=var;
}
int pop()
{
if(top<0)
throw range();
return st[top--];
}
};
void main()
{
stack s1;
{
try
s1.push(11);
s1.push(22);
s1.push(33);

cout<<"1"<<s1.pop()<<endl;
cout<<"2"<<s1.pop()<<endl;
cout<<"3"<<s1.pop()<<endl;
cout<<"4"<<s1.pop()<<endl;
}
catch(stack::range)
{
cout<<"stack full or empty"<<endl;
}
cout<<"Arrive here after catch"<<endl;
}

Sequence of Events

1. Code is executing normally outside a try block.


2. Control enters the try block.
3. A statement in the try block causes an error in a member function.
4. The member function throws an exception.
Introduction to OOP unit1

5. Control transfers to the exception handler ( catch block ) following the try
block.

4.18 EXERCISE
1. Write a program that copies the contents of a character file to another
file. Invoke the program with two command line arguments - the source
file and the destination file.
2. Create a student class which reads and display the roll number, name and
marks in 3 subject of the student. Store the details in student data file.
3. Modify the above problem to read the data from data file and display the total
marks, average and grade (i.e., average < 50 fail otherwise pass) on the
screen.

4.19 SUMMARY
In this unit, you have seen the hierarchy of stream classes, you have also seen
how to perform disk I/O in different ways. Files in C++ are objects of various
classes, ofstream for output, istream for input, ifstream for input and output.
Member function of these or base classes are used to perform I/O operation.
Functions such as put () and write () are used for output, while get () and read ()
are used for input.

The read() and write () functions work in binary mode, so that entire objects can
be saved to disk no matter what sort of data they contain.

A check for error conditions should be made after each file operation. The object
itself takes on a value of 0 if an error occurred or nonzero otherwise. Several
member functions can be used to determine specific kinds of errors.

Redirection provides an approach to file I/O, using input and output to cin and
cout. Sending output to the printer involves outputting to a file usually called
PRN. The extraction operator >> and the insertion operator << can be
overloaded so that they work with programmed – defined data types.
Introduction to OOP unit1

Virtual functions provide a way for a program to decide, when it is running, what
function to call. Ordinarily such decisions are made at compile time. Virtual
functions make possible greater flexibility in performing the same kind of action
on different kinds of objects. In particular, they allow the use of functions called
from an array of type pointer– to–base that actually holds a variety of derived
types. Typically a function is declared virtual in the base class and other
functions with the same name are declared in derived class. A pure virtual
function has no body in the base class.

A friend function can access a class’s private data, even though it is not a
member function of the class. This is useful when one function must have
access to two or more unrelated classes and when overloading operator must
use, on its left side, a value of a class other than the one of which it is a member.
Friends are also used to facilitate functional notation.

ANSWERS TO EXERCISE 4.19


1.
#include<fstream.h>
#include<process.h>
void main(int argc,char * argv[])
{ if (argc!=3)
{ cerr<<"\n syntax : fcopy sourcefile destination file";exit(-1);}
char ch;
ifstream infile;
infile.open(argv[1]);
if (!infile)
{
cerr<<"\n cannot open"<<argv[1];
exit(-1);
}
ofstream outfile;
outfile.open (argv[2],ios ::noreplace);
if (!outfile)
{ cerr<<"\n cannot open"<<argv[2];
Introduction to OOP unit1

exit(-1);
}
while(infile)
{ infile.get(ch);
outfile.put(ch);
}
}

2.
# include <fstream.h>
class student
{
private : int rno;
char name[20];
int marks[3];
public : void getdata()
{ cout << "Enter Roll No";
cin>>rno;cin.get();
cout << "Enter Name ";
cin.getline(name,'\n');
cout << "Enter Marks";
for (int i=0;i<3;i++)
cin>>marks[i];
}
void dispdata()
{ cout <<"Roll Number :"<<rno<<endl;
cout <<"Name :"<<name<<endl;
for (int i=0;i<3;i++)
cout<<endl<<marks[i];
}
};
void main()
{
student s1;
fstream stdfile;
Introduction to OOP unit1

stdfile.open("std.dat",ios::out|ios::binary);
char wish;
do
{ s1.getdata();
s1.dispdata();
stdfile.write((char *)&s1,sizeof(student));
cout <<"Continue (Y/N)?";
cin>>wish;
} while (wish=='y'|| wish=='Y');
stdfile.close();
}

3.
# include <fstream.h>
class student
{
private : int rno;
char name[20];
int marks[3];
public : void getdata()
{ cout << "Enter Roll No";
cin>>rno;cin.get();
cout << "Enter Name ";
cin.getline(name,'\n');
cout << "Enter Marks";
for (int i=0;i<3;i++)
cin>>marks[i];
}
void dispdata()
{ int tot = 0;
cout <<"Roll Number :"<<rno<<endl;
cout <<"Name :"<<name<<endl;
for (int i=0;i<3;i++)
{ cout<<marks[i]<<endl;
tot += marks[i];
Introduction to OOP unit1

}
float avg=tot/3.0;
if (avg<50)
cout<<"Grade : Fail"<<endl;
else
cout<<"Grade : Pass"<<endl;
}
};

void main()
{
student s1;
fstream stdfile;
stdfile.open("std.dat",ios::in|ios::binary);
stdfile.read((char *)&s1,sizeof(student));
while(stdfile)
{ s1.dispdata();
stdfile.read((char *)&s1,sizeof(student));
}
stdfile.close();
}

Você também pode gostar