C++ Infosystems 1
C++ Infosystems 1
C++ Infosystems 1
UNIT 1
Introduction to OOP 1
UNIT 2
UNIT 3
Templates, Pointers and Graphics 135
UNIT 4
Files and Streams, Polymorphism and Virtual Function 193
BLOCK INTRODUCTION
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.
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.
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
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
As programs grow larger and more complex, the schedule slips, more
programmers are added, complexity increases, costs sky-rocket, the schedule
slips further.
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.
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.
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 :
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.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.
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.
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
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.
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
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.
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.
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.
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 main ()
{
myclass1 a1, b1; a1 and b1 are objects of class
myclass1.
a1.getdata();
b1.getdata();
a1.dispdata();
b1.dispdata();
} // end of 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
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'.
C++
Page 15
Introduction to OOP
Unit 1
/* class employee stores employee information. You use calc() function to
return average salary. */
# include <iostream.h>
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.
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
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.
‘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
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
C++
Page 21
Introduction to OOP
Unit 1
’7’, ’K’, ’,’
Note that the character constant ‘7’ is not the same as the integer 7.
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.
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;
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.
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
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,
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
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.
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].
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;
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
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};
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
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 :
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;
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
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.
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;
CONSTRUCTION OF STRUCTURES
SYNTAX :
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 –
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};
The members of a structure are accessed using the dot operators. Eg.
Std.roll_no.
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.
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.
ARRAYS OF STRUCTURE
defines an array called std, that contains 50 elements. Each element is of the
structure described as student.
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]
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.
Taxonomy of operators
♦ Assignment operators
♦ Arithmetic operators
♦ Relational operators
♦ Logical operators
♦ Increment/decrement operators
♦ Conditional operators
♦ Bitwise operators.
Introduction to OOP unit1
Expressions
int a = 5;
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.
or
Introduction to OOP unit1
'C++' also permits the initialization of more than one variable in one statement
using multiple assignment operation.
a=a+5 or a += 5
b = b - 10 or b -= 10
c = c/2 or c /= 2
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.
division and multiplication is done before addition and subtraction. This is known
as the hierarchy of operators or rule 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
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.4 Casting
This term applies to data conversions by the programmer as opposed to the
automatic data conversions described above.
In this instance, both operands are of int type. Casting one to a higher type, will
cause :
(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.
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.
Example:
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.
++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;
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:
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:
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;
}
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
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:
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.
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:
X = 4; I = I + 1;
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;
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.
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.
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.
SYNTAX:
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.
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
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,
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.
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.
Example:
Introduction to OOP unit1
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;
}
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.
SYNTAX:
Example:
#include <iostream.h>
Introduction to OOP unit1
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;
}
class try
{
private :
int num;
public :
void setdata(d) { num = d; }
};
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.
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++.
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.
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.
void main ()
{
myclass a1; // invokes default constructor
myclass b1 (5); // invokes overloaded constructor
} // end of program.
Introduction to OOP unit1
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.
void main()
{
int no = 1111; float basic = 2500, hra = 250; char name [ ] = "Bill Gates";
Some compilers automatically initialize a static data item, while others do not.
Introduction to OOP unit1
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();
}
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.
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
1. # include <iostream.h>
void main()
{ int num[10],i,j,temp;
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;
}
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.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.
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
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.
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
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();
}
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.
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
{ i -= 12.0; f++; }
void main()
{
distance dist1; distance dist2(11,6.25);
dist1.getdist();
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();
}
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);
#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
// 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);
}
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.
The following example shows how to overload the 'less than' (<) operator.
#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 << "\" "; }
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.
#include <iostream.h>
class distance
Introduction to OOP unit1
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.
x = (x + y) / z;
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.
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.
# include <iostream.h>
# include <string.h>
class string
{ strcpy(str,s);}
void display() { cout << 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;
}
{ 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).
# 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
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.
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
+++++++++++++++++++++++++++++++++++++++++++++
=============================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
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 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
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.
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.
void main( )
{ countdown c1;
cout << "\nc1 = " << c1.getcount( );
c1++; c1++; c1++;
cout << "\nc1 = " << c1.getcount( );
c1--; c1--;
cout << "\nc1 = " << c1.getcount( );
}
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:
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
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
# 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); }
};
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.
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.
# 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.
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();
};
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.
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'.
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.
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.
}
};
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
♦ 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.
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.
# 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();
}
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
# 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
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.
A class can be derived from more than one base class. This is called multiple
inheritance. The syntax is as follows:
The base classes from which C is derived are listed following the colon on C's
specification separated by commas.
CLASS HIERARCHY
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.
Using member functions of the base classes is described through the following
example.
# 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:
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:
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.
# include <iostream.h>
class A
{ public : void show { cout << "\n Class A"; }
};
class B
{ public : void show { cout << "\n Class 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.
{ };
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 :
# 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
2.14 EXERCISE
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.
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.
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);
};
}
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 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
<< setiosflags(ios::showpoint)<<setprecision(2)<<setw(10)<<fees;
}
};
};
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
}
};
void main()
{
book book1; tape tape1;
book1.getdata(); tape1.getdata();
book1.putdata(); tape1.putdata();
}
Introduction to OOP unit1
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:
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.
♦ Understand pointers.
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.
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.
# include <iostream.h>
# define MAX 10
class stack
{
private :
D st[MAX]; int top;
public :
{
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
{
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()
{
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
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.
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 :
};
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;
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.
cout << *p; //This statement prints the integer value stored in the location
pointed to by the integer pointer p.
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.
# include <iostream.h>
# include <string.h >
void main()
{
char *str = “Education is the ability to meet life’s situations”;
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.
# 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();
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.
7 2 1 num
7FD2:0FC2 7FD2:0FC4 0 *next
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;
} *first;
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.
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
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
#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
{
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 *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();
}
# 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
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;
}
}
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.
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.
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.
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
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.
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)
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);
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);
ellipse() FUNCTION
Example : ellipse(50,50,0,90,50,20);
draws an ellipse of given dimensions with 50,50 as the center of the ellipse.
setcolor() FUNCTION
This function sets the current drawing color.
Syntax : setcolor(int color);
Example : setcolor(RED);
Introduction to OOP unit1
circle(250,250,15);
setlinestyle() FUNCTION
This sets the line width and style for drawing subsequent lines.
Syntax : setlinestyle(linestyle, upattern, thickness);
TABLE 3.1
VALUES OF LINESTYLE FOR SETLINESTYLE FUNCTION
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);
setfillstyle() FUNCTION
Introduction to OOP unit1
TABLE 3.2
VALUES FOR PATTERN OF SETFILLSTYLE FUNCTION
moveto() FUNCTION
This function moves the cursor to the specified location in the graphics
screen.
Syntax: moveto(column, row);
Example: moveto(100,100);
settextstyle() FUNCTION
This function is used to specify the font, direction and character size to be used
for subsequent text output in graphics mode.
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);
TABLE 3.5
Constant Value Displays text
LEFT_TEXT 0 Left Aligned (default)
CENTER_TEXT 1 Centered text
RIGHT_TEXT 2 Right Aligned text
getmaxcolor() FUNCTION
cleardevice() FUNCTION
This function clears the graphics screen and positions the cursor at 0, 0.
Syntax : cleardevice();
closegraph() FUNCTION
# 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();
}
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.
class set_para
{
private:
int color; //0..15 for
int fill_pattern; //0..12 setfillstyle
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)
{}
};
Setviewport
The setviewport function sets the current viewport for graphics outputs.
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
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();
}
As a simple example. Let us make a class of molecules that can bounce around
in a closed container.
# include <graphics.h>
# include <conio.h>
# include <stdio.h>
# include <stdlib.h>
const int RAD=5;
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();
}
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.
}
};
void main()
{
a1.disp();
Introduction to OOP unit1
Node() :Link() {}
Node(T& val) {data = val;}
void setdata(T &dat) { data = dat;}
T getdata() { return data;}
};
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
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();
}
# 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();
};
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();
}
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;
}
}
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
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.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.
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.
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.
iostream
istream_withassign iostream_withassign
ostream_withassign
iostream.h fstream.h
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
To see the text in the file you can display it with the DOS TYPE command or
open the file in any editor.
{
infile.getline(buffer,max);
cout << buffer;
}
}
while (text[i])
tstfile.put(text[i++]);
}
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.
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.
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.
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 examples also illustrate the read () and write() member functions which are
usually used for transfer of data block from and to the file.
}
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();
}
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.
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 following example illustrates the use of seekg() function. The seekp()
function is also used in a similar manner whenever necessary.
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');
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.
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.
♦ 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.
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 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);
}
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.
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 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
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.
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
if (!infile)
{
cerr << endl << "Cannot open file " << argv[1];
exit(-1);
}
char ch;
ostream outfile;
To execute this program at the DOS prompt, you can use the command,
4.13 POLYMORPHISM
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.
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.
Below is an example program with a virtual function and exhibits dynamic binding
or polymorphism as it is called.
#include <iostream.h>
class vehicle
{ protected :
int wheels;
float weight;
public :
virtual void message(void) { cout << "Vehicle 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;
}
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.
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.
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 :
// Destructor
mice :: ~mice()
{
delete stock;
}
{
if (nowproducts==maxproducts)
return 0;
++nowproducts;
int i=0;
if (stock[n] != NULL)
{
product *temp=stock[n];
stock[n]=NULL;
--nowproducts;
return temp;
}
else
return NULL;
}
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.
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.
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.
# 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.
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
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.
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();
}