Object Oriented Programming IOE
Object Oriented Programming IOE
Notes
Pravin Sangroula
May, 2025
Contents
Chapter 1: Introduction to OOP 4
1.1 History of programming languages . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Need of Object Oriented programming . . . . . . . . . . . . . . . . . . . 5
1.2.1 Problems with Procedural Languages . . . . . . . . . . . . . . . . 5
1.2.2 The Object-Oriented Approach . . . . . . . . . . . . . . . . . . . 7
1.3 Object Oriented programming vs procedure oriented programming . . . . 7
1.4 Concepts of object oriented programming . . . . . . . . . . . . . . . . . . 9
1.4.1 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.4.2 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.4.3 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.4.4 Reusability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4.5 Creating New Data Types . . . . . . . . . . . . . . . . . . . . . . 11
1.4.6 Polymorphism and Overloading . . . . . . . . . . . . . . . . . . . 11
1.5 Popular object oriented languages . . . . . . . . . . . . . . . . . . . . . . 12
1.6 Advantages of OOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.7 Disadvantages of OOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1
CONTENTS Object Oriented Programming
2
CONTENTS Object Oriented Programming
References 194
3
Chapter 1: Introduction to OOP Object Oriented Programming
4
Chapter 1: Introduction to OOP Object Oriented Programming
5
Chapter 1: Introduction to OOP Object Oriented Programming
large number of connections causes problems in several ways. First, it makes a pro-
gram’s structure difficult to conceptualize. Second, it makes the program difficult
to modify. A change made in a global data item may necessitate rewriting all the
functions that access that item. For example, in an inventory management pro-
gram, someone may decide that the product codes for the inventory items should
be changed from 5 digits to 12 digits. This may necessitate a change from a short to
a long data type. Now all the functions that operate on the data must be modified
to deal with a long instead of a short.
When data items are modified in a large program it may not be easy to tell which
functions access the data, and even when you figure this out, modifications to the
functions may cause them to work incorrectly with other global data items. Ev-
erything is related to everything else, so a modification anywhere has far-reaching,
and often unintended, consequences.
6
Chapter 1: Introduction to OOP Object Oriented Programming
poor job of modeling things in the real world. In the physical world we deal with
objects such as people and cars. Such objects aren’t like data and they aren’t like
functions. Complex real-world objects have both attributes and behavior.
Note: So neither data nor functions, by themselves, model real-world objects effec-
tively.
7
Chapter 1: Introduction to OOP Object Oriented Programming
8
Chapter 1: Introduction to OOP Object Oriented Programming
1.4.1 Objects
When you approach a programming problem in an object-oriented language, you no
longer ask how the problem will be divided into functions, but how it will be divided into
objects. Thinking in terms of objects, rather than functions, has a surprisingly helpful
effect on how easily programs can be designed. This results from the close match between
objects in the programming sense and objects in the real world. What kinds of things
become objects in object-oriented programs? The answer to this is limited only by your
imagination, but here are some typical categories to start you thinking:
The match between programming objects and real-world objects is the happy result of
combining data and functions: The resulting objects offer a revolution in program design.
1.4.2 Classes
In OOP we say that objects are members of classes. Almost all computer languages have
built-in data types. For instance, a data type int, meaning integer, is predefined in C++.
You can declare as many variables of type int as you need in your program. In a similar
way, you can define many objects of the same class, as shown in Figure 4. A class serves
as a plan, or blueprint. It specifies what data and what functions will be included in
objects of that class.
A class is thus a description of a number of similar objects. This fits our non-technical
understanding of the word class. Prince, Sting, and Madonna are members of the rock
musician class. There is no one person called “rock musician,” but specific people with
specific names are members of this class if they possess certain characteristics. An object
is often called an “instance” of a class.
1.4.3 Inheritance
The idea of classes leads to the idea of inheritance. In our daily lives, we use the concept of
classes divided into subclasses. We know that the animal class is divided into mammals,
amphibians, insects, birds, and so on. The vehicle class is divided into cars, trucks, buses,
motorcycles, and so on.
The principle in this sort of division is that each subclass shares common characteris-
tics with the class from which it’s derived. Cars, trucks, buses, and motorcycles all have
wheels and a motor; these are the defining characteristics of vehicles. In addition to the
characteristics shared with other members of the class, each subclass also has its own
particular characteristics: Buses, for instance, have seats for many people, while trucks
have space for hauling heavy loads. This idea is shown in Figure 59. Notice in the figure
9
Chapter 1: Introduction to OOP Object Oriented Programming
Figure 5: Inheritance.
10
Chapter 1: Introduction to OOP Object Oriented Programming
that features A and B, which are part of the base class, are common to all the derived
classes, but that each derived class also has features of its own.
In a similar way, an OOP class can become a parent of several subclasses. In C++
the original class is called the base class; other classes can be defined that share its
characteristics, but add their own as well. These are called derived classes.
1.4.4 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. It is similar to
the way a library of functions in a procedural language can be incorporated into different
programs.
However, in OOP, the concept of inheritance provides an important extension to the
idea of 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.
For example, you might have written (or purchased from someone else) a class that
creates a menu system, such as that used in Windows or other Graphic User Interfaces
(GUIs). This class works fine, and you don’t want to change it, but you want to add
the capability to make some menu entries flash on and off. To do this, you simply create
a new class that inherits all the capabilities of the existing one but adds flashing menu
entries. The ease with which existing software can be reused is an important benefit of
OOP.
where the variables position1, position2, and origin each represent a pair of independent
numerical quantities. By creating a class that incorporates these two values, and declaring
position1, position2, and origin to be objects of this class, we can, in effect, create a new
data type. Many features of C++ are intended to facilitate the creation of new data
types in this manner.
11
Chapter 1: Introduction to OOP Object Oriented Programming
• Python – Commonly used for web development, data science, automation, and
artificial intelligence (e.g., Django, TensorFlow).
• C# – Popular for Windows applications and game development using Unity (e.g.,
enterprise software, .NET applications).
• Ruby – Used in web application development with Rails framework (e.g., GitHub,
Shopify).
• Swift – Primarily used for developing iOS and macOS applications (e.g., iPhone
apps).
12
Chapter 1: Introduction to OOP Object Oriented Programming
codebases, which could be considered inefficient for simple tasks. Lastly, for small-scale
or procedural problems, using OOP might be unnecessary and lead to over-engineered
solutions.
13
Chapter 2: Basics of c++ Programming Object Oriented Programming
Documentation Section
Linking Section
Class Declaration/definition
Member function definition
Main Function
• Documentation Section: This section is used to document the logic of the pro-
gram that the programmer going to code, Whatever written in the documentation
section is the comment and is not compiled by the compiler.
Listing 1: Comments in C++
// This is a C ++ program to find the Area of the circle
• Linking Section:
In the above snippets, namespace std contains declarations for cout, cin, endl,
etc. statements.
14
Chapter 2: Basics of c++ Programming Object Oriented Programming
• Main Function: The main function tells the compiler where to start the execution
of the program.
Listing 6: Main Function
int main ()
{
printMax () ;
return 0;
}
15
Chapter 2: Basics of c++ Programming Object Oriented Programming
– Arithmetic: +, -, *, /, %
– Relational: ==, !=, <, >, <=, >=
– Logical: &&, ||, !
– Assignment: =, +=, -=, *=, /=
• Comments:
C++ Keywords:
16
Chapter 2: Basics of c++ Programming Object Oriented Programming
The statement define two integer variables, var1 and var2. The keyword int signals the
type of variable. These statements, which are called declarations, must terminate with
a semicolon, like other program statements. You must declare a variable before using it.
However, you can place variable declarations anywhere in a program. It’s not necessary to
declare variables before the first executable statement (as was necessary in C). However,
it’s probably more readable if commonly-used variables are located at the beginning of
the program.
The combination of operands and operators is known as expression. For example in
the expression: x = a + b;. x,a,b are operands and +,= are operator.
The above statement causes the phrase in quotation marks to be displayed on the screen.
The identifier cout (pronounced “C out”) is actually an object. It is predefined in C++
to correspond to the standard output stream. A stream is an abstraction that refers to
a flow of data. The operator << is called the insertion or put to operator. It directs the
contents of the variable on its right to the object on its left. In above statement it directs
the string constant “Every age has a language of its own\n” to cout, which sends it to
the display.
The above statement causes the program to wait for the user to type in a number.The
resulting number is placed in the variable a. The keyword cin (pronounced “C in”) is
17
Chapter 2: Basics of c++ Programming Object Oriented Programming
an object, predefined in C++ to correspond to the standard input stream. This stream
represents data coming from the keyboard (unless it has been redirected). The >> is the
extraction or get from operator. It takes the value from the stream object on its left and
places it in the variable on its right.
The endl Manipulator: endl causes a linefeed to be inserted into the stream,
so that subsequent text is displayed on the next line. It has the same effect as sending
the ‘\n’ character, but is somewhat clearer. Manipulators are instructions to the output
stream that modify the output in various ways; we’ll see more of them as we go along.
Strictly speaking, endl (unlike ‘\n’) also causes the output buffer to be flushed, but this
happens invisibly so for most purposes the two are equivalent.
Cascading << and >>: The extraction operator >> can be cascaded with cin allowing
the user to enter a series of values. We can do same for the insertion operator as well.
• Integer: Integer variables represent integer numbers like 1, 30,000, and –27.
Integer variables exist in several sizes, but the most commonly used is type int.
The amount of memory occupied by the integer types is system dependent. On
a 32-bit system such as Windows, an int occupies 4 bytes (which is 32 bits) of
18
Chapter 2: Basics of c++ Programming Object Oriented Programming
memory. This allows an int to hold numbers in the range from –2,147,483,648
to 2,147,483,647. C++ allows the use of modifiers to alter the size or sign of an
integer type. Type long always occupies four bytes, which is the same as type int
on 32-bit Windows systems. On all systems type short occupies two bytes, giving
it a range of –32,768 to 32,767. These are shown in Table 5:
• Character Variables: Type char stores integers that range in value from –128 to
127. Variables of this type occupy only 1 byte (eight bits) of memory. As you may
already know, the ASCII character set is a way of representing characters such as ‘a’,
‘B’, ‘$’, ‘3’, and so on, as numbers. These numbers range from 0 to 127. Standard
C++ provides a larger character type called wchar t to handle foreign languages.
This is important if you’re writing programs for international distribution.
19
Chapter 2: Basics of c++ Programming Object Oriented Programming
Notes:
• Bool: Variables of type bool can have only two possible values: true and false.
In theory a bool type requires only one bit (not byte) of storage, but in practice
compilers often store them as bytes because a byte can be quickly accessed, while
an individual bit must be extracted from a byte, which requires additional time.
• The setw Manipulator: We have already seen the use of the endl manipulator.
Now, let us explore another manipulator: setw, which changes the field width of
output. Each value displayed by cout can be thought of as occupying a field: an
imaginary box with a certain width. By default, this width is just enough to hold
the value. For example: The integer 567 occupies a field three characters wide.
The string "pajamas" occupies a field seven characters wide. However, this default
formatting may not always be visually ideal. Consider the following program:
Listing 11: Demonstrating Need for setw
# include < iostream >
using namespace std ;
int main () {
int pop1 = 2425785 , pop2 = 47 , pop3 = 9761;
cout << " LOCATION " << " POP . " << endl
<< " Portcity " << pop1 << endl
<< " Hightown " << pop2 << endl
<< " Lowville " << pop3 << endl ;
return 0;
}
20
Chapter 2: Basics of c++ Programming Object Oriented Programming
Sample Output:
LOCATION POP.
Portcity 2425785
Hightown 47
Lowville 9761
As you can see, this format makes it hard to compare the population numbers.
Ideally, we want the population values to align to the right for better readability.
Furthermore, inserting spaces manually to separate city names and numbers is
inconvenient.
In such cases, the setw manipulator can be used to specify a consistent field width
for numerical output, improving alignment and presentation. To improve the read-
ability of output and ensure proper alignment, C++ provides the setw manipulator
(from the iomanip header). The setw(n) function prints the following item in a
field at least n characters wide, right-justified by default.
Here is a revised version of the earlier program that demonstrates the use of setw:
Listing 12: Demonstration of setw Manipulator
# include < iostream >
# include < iomanip > // for setw
using namespace std ;
int main () {
int pop1 = 2425785 , pop2 = 47 , pop3 = 9761;
cout << setw (8) << " LOCATION " << setw (12) << " POPULATION " <<
endl
<< setw (8) << " Portcity " << setw (12) << pop1 << endl
<< setw (8) << " Hightown " << setw (12) << pop2 << endl
<< setw (8) << " Lowville " << setw (12) << pop3 << endl ;
return 0;
}
Sample Output:
LOCATION POPULATION
Portcity 2425785
Hightown 47
Lowville 9761
The setw manipulator improves the visual alignment of the output and avoids the
need to manually adjust spacing.
21
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main () {
string name1 = " Alice " ;
string name2 = " Bob " ;
int score1 = 95;
int score2 = 87;
cout << left << setw (10) << " Name " << right << setw (6) << "
Score " << endl ;
cout << left << setw (10) << name1 << right << setw (6) << score1
<< endl ;
cout << left << setw (10) << name2 << right << setw (6) << score2
<< endl ;
return 0;
}
Sample Output:
Name Score
Alice 95
Bob 87
Note that setw() only applies to the next output item, and must be used repeatedly
for each value if consistent formatting is desired.
22
Chapter 2: Basics of c++ Programming Object Oriented Programming
Sample Output:
*******123
-----Hello
int main () {
float a = 0.00123 f ;
return 0;
}
Sample Output:
0.00123
0.0012
1.2300e-03
23
Chapter 2: Basics of c++ Programming Object Oriented Programming
– The first cout statement simply outputs the value of the float variable a. By
default, C++ prints floating-point numbers using the shortest representation
that accurately reflects the value, which is 0.00123 in this case.
– The second cout uses the fixed manipulator along with setprecision(4).
In fixed-point notation, setprecision controls the number of digits displayed
after the decimal point. Thus, the output becomes 0.0012, rounding the value
to four decimal places.
– The third cout uses the scientific manipulator along with setprecision(4).
In scientific notation, setprecision again sets the number of digits after the
decimal point. Therefore, the output is displayed as 1.2300e-03, which is the
scientific representation of 0.00123 rounded to four digits after the decimal
point.
This example clearly illustrates how the formatting manipulators fixed and scientific,
when used with setprecision, can control the precision and format of floating-
point output in C++. Note: To revert back to normal (default) formatting,
use cout.unsetf(scientific);
int main () {
float a = 123.456 f ;
float b = 0.00123456 f ;
cout << setprecision (3) << " a = " << a << " , b = " << b << endl ;
cout << setprecision (4) << " a = " << a << " , b = " << b << endl ;
cout << setprecision (6) << " a = " << a << " , b = " << b << endl ;
return 0;
}
Sample Output:
a = 123, b = 0.0012
a = 123.5, b = 0.001235
a = 123.456, b = 0.00123456
The code in Listing 16 demonstrates the behavior of the setprecision manipulator when
used without the fixed or scientific manipulators. In this case, setprecision(n)
controls the total number of significant digits displayed in the output.
• With setprecision(3):
– a = 123.456 is displayed as 123, keeping only the first three significant digits
and rounding the rest.
– b = 0.00123456 is shown as 0.00123, rounded to three significant digits.
• With setprecision(4):
24
Chapter 2: Basics of c++ Programming Object Oriented Programming
• With setprecision(6):
– Both a and b are shown in full, as they originally have six significant digits.
The output is 123.456 and 0.00123456, respectively.
This example highlights that when fixed or scientific is not specified, the C++ output
stream chooses between fixed-point and scientific notation automatically based on the
value and the number of significant digits requested.
Q:
Write a C++ program to display the following table using the setw() and left manip-
ulators from the <iomanip> library to align the columns properly[Note: Can use left
manipulator.]:
int main ()
{
int count = 7;
float avgWeight = 155.5 F ;
double totalWeight = count * avgWeight ;
Here, a variable of type int is multiplied by a variable of type float to yield a result
of type double. This program compiles without error; the compiler considers it normal
that you want to multiply (or perform any other arithmetic operation on) numbers of
different types.
C++ and C, however, assume that you must have a good reason for doing what you’re
doing, and they help carry out your intentions. This is one reason for the popularity of
C++ and C: they give you more freedom. Of course, with more freedom, there’s also
more opportunity for you to make a mistake.
25
Chapter 2: Basics of c++ Programming Object Oriented Programming
the order shown in Table 7. The process and promotion of data types is shown in Figure
10. When mixed-type expressions are encountered, the lower-type operand is converted
to the higher-type operand before computation. For instance, in above example:
These conversions are implicit and automatic, but they can sometimes cause unexpected
behavior or loss of precision.
2.5.2 Casts
Casts are also called type casts. What are casts for? Sometimes a programmer needs to
convert a value from one type to another in a situation where the compiler will not do it
automatically or without complaining. There are several kinds of casts in Standard C++:
26
Chapter 2: Basics of c++ Programming Object Oriented Programming
static casts, dynamic casts, reinterpret casts, and const casts. Here we’ll be concerned
only with static casts.
Listing 18: Using cast to get a floating-point result from integer division
# include < iostream >
using namespace std ;
int main () {
int a = 5;
int b = 2;
return 0;
}
static cast is used in C++ to explicitly convert a variable from one data type to
another. It is a safer and more visible alternative to traditional C-style casting.
• Syntax: static cast<new type>(expression);
• It creates a temporary variable of the specified new type, initialized with the value
of expression.
• Useful when implicit conversion might result in loss of data or when precision is
required (e.g., converting int to float to avoid integer division).
Example:
float result = static_cast<float>(5) / 2; // Outputs 2.5
Without static cast, 5 / 2 would perform integer division, yielding 2.
Question: Write a C++ program that takes an integer input between 65 and 90 (in-
clusive), and prints the corresponding uppercase alphabet character using static cast.
Sample Output :
Input: 65
Output: A
The keyword const (short for constant) precedes the data type of a variable. It specifies
that the value of the variable will not change throughout the program. Any attempt
to modify a variable defined with this qualifier will result in a compiler error. The line
number 2 will throw a compilition error error as constant is not initialized.
27
Chapter 2: Basics of c++ Programming Object Oriented Programming
2.7 Operators
• Arithmetic Operators: C++ uses the four normal arithmetic operators +, -, *,
and / for addition, subtraction, multiplication, and division. These operators work
on all the data types, both integer and floating-point. There is a fifth arithmetic
operator that works only with integer variables (types char, short, int, and long).
It is called the remainder operator, and is represented by the percent symbol (%).
This operator is also known as the modulus operator. It finds the remainder
when one number is divided by another.
In this situation you add something to an existing value (or you perform some other
arithmetic operation on it). But the syntax of this statement offends those for
whom brevity is important, because the name total appears twice. So C++ offers
a condensed approach: the arithmetic assignment operator, which combines
an arithmetic operator and an assignment operator. Here’s a statement that has
exactly the same effect as the preceding one:
There are arithmetic assignment operators corresponding to all the arithmetic op-
erations: +=, -=, *=, /=, and %= (and some other operators as well).
28
Chapter 2: Basics of c++ Programming Object Oriented Programming
• Increment Operators: Here’s an even more specialized operator. You often need
to add 1 to the value of an existing variable. You can do this the “normal” way:
The question here is this: Is the multiplication performed before or after count
is incremented? In this case count is incremented first. How do we know that?
Because prefix notation is used: ++count. If we had used postfix notation, count++,
the multiplication would have been performed first, then count would have been
incremented. This is shown in Figure 12.
The Decrement Operator: The decrement operator, --, behaves very much
like the increment operator, except that it subtracts 1 from its operand. It too can
be used in both prefix and postfix forms.
• Relational Operators: A relational operator compares two values. The values
can be any built-in C++ data type, such as char, int, and float, or—as we’ll see
later—they can be user-defined classes. The comparison involves such relationships
as equal to, less than, and greater than. The result of the comparison is true or
false; for example, either two values are equal (true), or they’re not (false).
Here’s the complete list of C++ relational operators:
Operator Meaning
> Greater than
< Less than
== Equal to
!= Not equal to
>= Greater than or equal to
<= Less than or equal to
• The Conditional Operator: This operator consists of two symbols, which oper-
ate on three operands. It’s the only such operator in C++; other operators operate
on one or two operands. Here’s the equivalent of the same program fragment, using
a conditional operator:
29
Chapter 2: Basics of c++ Programming Object Oriented Programming
The part of this statement to the right of the equal sign is called the conditional
expression:
Figure 13 shows the syntax of conditional operator and 14 shows the execution of
conditional operator.
30
Chapter 2: Basics of c++ Programming Object Oriented Programming
• Precedence: Let’s summarize the precedence situation for the operators we’ve
seen so far. The operators higher on the list have higher precedence than those
lower down. This is show in Table 9.
Table 9: Operator Types, Symbols, and Their Precedence
31
Chapter 2: Basics of c++ Programming Object Oriented Programming
Syntax
datatype &referenceName = originalVariable;
Example
int a = 10;
int &b = a;
Key Characteristics
• A reference must be initialized when declared.
• Once a reference is initialized to a variable, it cannot be changed to refer to another
variable.
• Modifying the reference modifies the original variable.
32
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main () {
int a = 10;
{
int b = 20;
}
cout << b ; // Error : 'b ' is out of scope here
return 0;
}
int main ()
{
int x ;
cout << " Enter a number : " ;
cin >> x ;
if ( x > 100)
cout << " That number is greater than 100\ n " ;
return 0;
}
33
Chapter 2: Basics of c++ Programming Object Oriented Programming
You can nest ifs inside loops, loops inside ifs, ifs inside ifs, and so on. Here’s
an example, PRIME, that nests an if.
Listing 22: Prime Number – nested if inside loop
# include < iostream >
using namespace std ;
# include < cstdlib > // for exit ()
34
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
unsigned long n , j ;
cout << " Enter a number : " ;
cin >> n ; // get number to test
35
Chapter 2: Basics of c++ Programming Object Oriented Programming
36
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
int num ;
cout << " Enter a number : " ;
cin >> num ;
if ( num >= 0)
{
if ( num == 0)
cout << " The number is zero .\ n " ;
else
cout << " The number is positive .\ n " ;
}
else
{
cout << " The number is negative .\ n " ;
}
return 0;
}
37
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
int marks ;
cout << " Enter your marks : " ;
cin >> marks ;
return 0;
}
• Switch: If you have a large decision tree, and all the decisions depend on the
value of the same variable, you will probably want to consider a switch statement
instead of a ladder of if...else or else if constructions.
The switch statement provides a cleaner and more readable way to handle such
cases, especially when comparing the same variable against multiple constant values.
The Syntax is shown in Figure 20 and execution is shown in Figure 21.
38
Chapter 2: Basics of c++ Programming Object Oriented Programming
39
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
double num1 , num2 ;
char op ;
switch ( op )
{
case '+ ':
cout << " Result : " << num1 + num2 << endl ;
break ;
case ' - ':
cout << " Result : " << num1 - num2 << endl ;
break ;
case '* ':
cout << " Result : " << num1 * num2 << endl ;
break ;
case '/ ':
if ( num2 != 0)
cout << " Result : " << num1 / num2 << endl ;
else
cout << " Error : Division by zero is not allowed .\ n "
;
break ;
default :
cout << " Invalid operator !\ n " ;
}
return 0;
}
2.9.2 Loops:
Loops cause a section of your program to be repeated a certain number of times. The
repetition continues while a condition is true. When the condition becomes false, the
loop ends and control passes to the statements following the loop.
There are three kinds of loops in C++ for, while and do...while loop.
• for loop: The for loop is (for many people, anyway) the easiest C++ loop to
understand. All its loop-control elements are gathered in one place, while in the
other loop constructions they are scattered about the program, which can make it
harder to unravel how these loops work.
40
Chapter 2: Basics of c++ Programming Object Oriented Programming
The for loop executes a section of code a fixed number of times. It’s usually
(although not always) used when you know, before entering the loop, how many
times you want to execute the code.
Listing 27: Using the for loop
# include < iostream >
using namespace std ;
int main ()
{
int j ; // define a loop variable
for ( j = 0; j < 15; j ++) // loop from 0 to 14
cout << j * j << " " ; // displaying the square of j
The for statement controls the loop. It consists of the keyword for, followed by
parentheses that contain three expressions separated by semicolons:
These three expressions usually (but not always) involve the same variable, which
we call the loop variable. The body of the loop is the code to be executed each
time through the loop. The operation of for loop is shown in Figure 23.
41
Chapter 2: Basics of c++ Programming Object Oriented Programming
This is a common construction in C++, and in most cases it’s the best approach
to loop variables. It defines the variable as closely as possible to its point of use in
the listing.
42
Chapter 2: Basics of c++ Programming Object Oriented Programming
Variables defined in the loop statement this way are visible in the loop body only.
• while loop: The for loop does something a fixed number of times. What happens
if you don’t know how many times you want to do something before you start the
loop?
In this case, a different kind of loop may be used: the while loop.
Listing 28: Using the while loop
# include < iostream >
using namespace std ;
int main ()
{
int n = 99; // make sure n isn 't initialized to 0
The while loop looks like a simplified version of the for loop. It contains a test
expression but no initialization or increment expressions. The syntax of while loop
is shown in Figure 24 and operation is shown in 25.
43
Chapter 2: Basics of c++ Programming Object Oriented Programming
• do...while loop: n a while loop, the test expression is evaluated at the beginning
of the loop. If the test expression is false when the loop is entered, the loop body
won’t be executed at all.
In some situations, this is what you want. But sometimes you want to guarantee
that the loop body is executed at least once, no matter what the initial state of the
test expression.
When this is the case, you should use the do loop, which places the test expression
at the end of the loop.
Listing 29: Using the do...while loop
# include < iostream >
using namespace std ;
int main ()
{
long dividend , divisor ;
char ch ;
do // start of do loop
{
// do some processing
cout << " Enter dividend : " ;
cin >> dividend ;
return 0;
44
Chapter 2: Basics of c++ Programming Object Oriented Programming
Most of this program resides within the do loop. First, the keyword do marks the
beginning of the loop. Then, as with the other loops, braces delimit the body of
the loop.
Finally, a while statement provides the test expression and terminates the loop.
This while statement looks much like the one in a while loop, except for its position
at the end of the loop and the fact that it ends with a semicolon (which is easy to
forget!).
The syntax of the do loop is shown in Figure 26 and operation is shown in 27.
45
Chapter 2: Basics of c++ Programming Object Oriented Programming
Sometimes, however, you want to go back to the top of the loop when something
unexpected happens.
Executing continue has this effect. (Strictly speaking, the continue takes you to
the closing brace of the loop body, from which you may jump back to the top.)
Figure 29 shows the operation of continue.
int main () {
for ( int i = 1; i <= 10; i ++) {
if ( i == 5) {
46
Chapter 2: Basics of c++ Programming Object Oriented Programming
• Namespaces define a scope for identifiers like variables, functions, classes, etc.
• The std namespace contains all the standard C++ library identifiers.
• Use the scope resolution operator (::) to access elements within a namespace.
namespace mynamespace {
int a = 10;
}
int main () {
cout << mynamespace :: a ;
return 0;
}
namespace mynamespace {
int a = 10;
}
int main () {
cout << a ;
return 0;
}
47
Chapter 2: Basics of c++ Programming Object Oriented Programming
namespace First {
int value = 10;
void display () {
cout << " First namespace value : " << value << endl ;
}
}
namespace Second {
int value = 20;
void display () {
cout << " Second namespace value : " << value << endl ;
}
}
int main () {
First :: display () ; // Calls First 's display ()
Second :: display () ; // Calls Second 's display ()
return 0;
}
2.11 Functions
A function groups a number of program statements into a unit and gives it a name. This
unit can then be invoked from other parts of the program.
Functions in C++ (and C) are similar to subroutines and procedures in various other
languages.
48
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main () {
int num ;
cout << " Enter a number : " ;
cin >> num ;
if ( isPositive ( num ) ) {
cout << " The number is positive . " << endl ;
} else {
cout << " The number is zero or negative . " << endl ;
}
return 0;
}
49
Chapter 2: Basics of c++ Programming Object Oriented Programming
// Area of a square
int Area ( int side ) {
return side * side ;
}
// Area of a rectangle
int Area ( int length , int width ) {
return length * width ;
int main () {
cout << " Area of square : " << Area (5) << endl ;
cout << " Area of rectangle : " << Area (5 , 10) << endl ;
return 0;
}
The program contains two functions with the same name. There are two function
calls, and two definitions. What keeps the compiler from becoming hopelessly
confused? It uses the function signature—the number of arguments, and their
data types—to distinguish one function from another. The compiler, seeing several
functions with the same name but different numbers of arguments, could decide the
programmer had made a mistake (which is what it would do in C). Instead, it very
tolerantly sets up a separate function for every such definition. Which one of these
functions will be called depends on the number of arguments supplied in the call.
50
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main () {
cout << " Area of square : " << Area (5) << endl ; //
int
cout << " Area of circle : " << Area (7.0) << endl ; //
double
return 0;
}
Long sections of repeated code are generally better off as normal functions: The
savings in memory space is worth the comparatively small sacrifice in execution speed.
But making a short section of code into an ordinary function may result in little savings
in memory space, while imposing just as much time penalty as a larger function. In fact,
if a function is very short, the instructions necessary to call it may take up as much space
as the instructions within the function body, so that there is not only a time penalty
but a space penalty as well. In such cases you could simply repeat the necessary code
in your program, inserting the same group of statements wherever it was needed. The
trouble with repeatedly inserting the same code is that you lose the benefits of program
organization and clarity that come with using functions. The program may run faster
and take less space, but the listing is longer and more complex.
51
Chapter 2: Basics of c++ Programming Object Oriented Programming
The solution to this quandary is the inline function. This kind of function is written
like a normal function in the source file but compiles into inline code instead of into a
function. The source file remains well organized and easy to read, since the function is
shown as a separate entity. However, when the program is compiled, the function body
is actually inserted into the program wherever a function call occurs.
It’s easy to make a function inline: All you need is the keyword inline in the function
definition:
// Inline function definition
inline int square ( int x ) {
return x * x ;
}
int main () {
int num = 5;
int result = square ( num ) ;
return 0;
}
int main () {
display (5) ; // Output : a = 5 , b = 10 , c = 20
display (5 , 15) ; // Output : a = 5 , b = 15 , c = 20
display (5 , 15 , 25) ; // Output : a = 5 , b = 15 , c = 25
return 0;
}
// Function definition
void display ( int a , int b , int c ) {
cout << " a = " << a << " , b = " << b << " , c = " << c << endl ;
}
52
Chapter 2: Basics of c++ Programming Object Oriented Programming
// Declaration
void display ( int a , int b = 10 , int c = 20) ;
A block is basically the code between an opening brace { and a closing brace }. Thus,
a function body is a block.
There are two storage classes: automatic and static.
• Variables with storage class automatic exist during the lifetime of the function
in which they’re defined.
• Variables with storage class static exist for the lifetime of the program.
53
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main () {
int a = 10 , b = 20;
cout << " Before swap : a = " << a << " , b = " << b << endl ;
cout << " After swap : a = " << a << " , b = " << b << endl ;
return 0;
}
Output:
Before swap: a = 10, b = 20
After swap: a = 20, b = 10
Problem: Write a function that calculates the sum, difference, and product of two
integers and returns all three using reference parameters.
# include < iostream >
using namespace std ;
// Function definition
void calculate ( int a , int b , int & sum , int & diff , int & prod ) {
sum = a + b ;
diff = a - b ;
prod = a * b ;
}
int main () {
int num1 , num2 ;
int sum , difference , product ;
return 0;
}
Returning by Reference:
Returning by reference allows us to use a function call on the left sign side of the equal
sign. The following example demonstrates how to return a reference from a function:
54
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
// set x to a value , using function call on left side
setx () = 92;
cout << " x = " << x << endl ; // display new value in x
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int & setx ()
{
return x ; // returns the value to be modified
}
Explanation:
• This allows the function call setx() to appear on the left-hand side of an assign-
ment.
int main ()
{
int age [4]; // array ' age ' of 4 ints
for ( int j = 0; j < 4; j ++) // get 4 ages
{
cout << " Enter an age : " ;
cin >> age [ j ]; // access array element
}
for ( int j = 0; j < 4; j ++) // display 4 ages
cout << " You entered " << age [ j ] << endl ;
return 0;
}
55
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
// Initialization with explicit values
int numbers [5] = {1 , 2 , 3 , 4 , 5};
// Zero initialization
int zeros [5] = {0};
return 0;
}
56
Chapter 2: Basics of c++ Programming Object Oriented Programming
So far we’ve looked at arrays of one dimension: A single variable specifies each array
element. But arrays can have higher dimensions.
// displays sales chart using 2 - d array
# include < iostream >
# include < iomanip > // for setprecision , etc .
using namespace std ;
int main ()
{
int d , m ;
double sales [ DISTRICTS ][ MONTHS ]; // two - dimensional array definition
57
Chapter 2: Basics of c++ Programming Object Oriented Programming
2.12.2 Pointers
Pointers are an important feature of C++ (and C), while many other languages, such as
Visual Basic and Java, have no pointers at all. A variable that holds an address value is
called a pointer variable, or simply a pointer.
Listing 39: Pointer Basics: Printing Addresses Using a Pointer
# include < iostream >
58
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
int var1 = 11; // two integer variables
int var2 = 22;
return 0;
}
• int* ptr;
This declares a pointer variable named ptr that can store the address of an int
type variable. The asterisk * indicates that ptr is not a regular integer variable,
but a pointer to an integer.
59
Chapter 2: Basics of c++ Programming Object Oriented Programming
• ptr = &var1;
This assigns the address of the variable var1 to the pointer ptr.
The ampersand & is the ”address-of” operator, which returns the memory address
of the variable var1.
After this statement, ptr holds the address of var1, and *ptr can be used to access
the value of var1.
int main ()
{
int var1 = 11; // two integer variables
int var2 = 22;
int * ptr ; // pointer to integers
return 0;
}
– If ptr = &var1;, then *ptr refers to var1, and *ptr will give the value 11.
– If ptr = &var2;, then *ptr refers to var2, and *ptr will give the value 22.
So, cout << *ptr; will output the value stored in the variable to which ptr cur-
rently points.
int main ()
{
int var1 , var2 ; // two integer variables
int * ptr ; // pointer to integers
return 0;
}
60
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
// array
int intarray [5] = { 31 , 54 , 77 , 52 , 93 };
return 0;
}
2.12.3 Strings
The are two kinds of strings commonly used in c++: c strings and strings that are objects
of the string class.
61
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
const int MAX = 80; // max characters in string
char str [ MAX ]; // string variable str
return 0;
}
int main ()
{
const int MAX = 20; // max characters in string
char str [ MAX ]; // string variable str
cout << " You entered : " << str << endl ;
62
Chapter 2: Basics of c++ Programming Object Oriented Programming
return 0;
}
int main ()
{
const int MAX = 80; // max characters in string
char str [ MAX ]; // string variable str
cout << " You entered : " << str << endl ;
return 0;
}
int main ()
{
cout << " \ nEnter a string :\ n " ;
cin . get ( str , MAX , '$ ') ; // terminate with $
cout << " You entered :\ n " << str << endl ;
return 0;
}
int main ()
{
char str1 [] = " Tiger , tiger , burning bright \ n "
" In the forests of the night " ;
const int MAX = 80; // size of str2 buffer
char str2 [ MAX ]; // empty string
strcpy ( str2 , str1 ) ; // copy str1 to str2
cout << str2 << endl ; // display str2
return 0;
}
63
Chapter 2: Basics of c++ Programming Object Oriented Programming
• The Standard C++ string Class: Standard C++ includes a new class called
string. This class improves on the traditional Cstring in many ways. For one thing,
you no longer need to worry about creating an array of the right size to hold string
variables. The string class assumes all the responsibility for memory management.
Listing 48: Defining and assigning std::string objects
# include < iostream >
# include < string >
using namespace std ;
int main ()
{
string s1 ( " Man " ) ; // initialize
string s2 = " Beast " ; // initialize
string s3 ;
s3 = s1 ; // assign
cout << " s3 = " << s3 << endl ;
return 0;
}
s3 = Man
s3 = Neither Man nor Beast
Beast nor Man
cout << " Your full name is : " << full_name << endl ;
cout << greeting << endl ; // output : " Hello , Jim "
64
Chapter 2: Basics of c++ Programming Object Oriented Programming
cout << " Your address is : " << address << endl ;
return 0;
}
65
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
part part1 ; // define a structure variable
part1 . modelnumber = 6244; // give values to structure members
part1 . partnumber = 373;
part1 . cost = 217.55 F ;
return 0;
}
Output:
66
Chapter 2: Basics of c++ Programming Object Oriented Programming
One of the aims of C++ is to make the syntax and the operation of user-defined data
types as similar as possible to that of built-in data types. (In C you need to include the
keyword struct in structure definitions, as in struct part part1;. In C++ the keyword is
not necessary.)
Once a structure variable has been defined, its members can be accessed using some-
thing called the dot operator as shown in Figure 42.
67
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
// initialize variable
part part1 = { 6244 , 373 , 217.55 F };
part part2 ; // define another variable
68
Chapter 2: Basics of c++ Programming Object Oriented Programming
return 0;
}
Output:
Question:
Write a C++ program that uses nested structures to represent a rectangular room’s
dimensions in feet and inches. Define a Distance structure with members for feet and
inches, and a Room structure that contains two Distance members: one for length and
one for width. Your program should:
• Prompt the user (or directly assign) the length and width of the room in feet and
inches
int main ()
{
Room dining ; // define a room
69
Chapter 2: Basics of c++ Programming Object Oriented Programming
Output:
Dining room area is 143.25 square feet
2.14 Enumeration
As we’ve seen, structures can be looked at as a way to provide user-defined data types.
A different approach to defining your own data type is the enumeration. Enumerated
types work when you know in advance a finite (usually short) list of values that a data
type can take on.
Listing 52: Demonstrating Enum Types and Operations
# include < iostream >
70
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main ()
{
days_of_week day1 , day2 ; // define variables of type days_of_week
day1 = Mon ; // give values to variables
day2 = Thu ;
return 0;
}
Days between = 3
day1 comes before day2
An enum declaration defines the set of all names that will be permissible values of the
type. These permissible values are called enumerators. The enum type days of week has
seven enumerators: Sun, Mon, Tue, and so on, up to Sat. An enumerators is a list of all
possible values.
71
Chapter 2: Basics of c++ Programming Object Oriented Programming
Enumerations are treated internally as integers. This explains why you can perform
arithmetic and relational operations on them. Ordinarily the first name in the list is
given the value 0, the next name is given the value 1, and so on.
However, C++ allows you to assign custom values to enumeration constants, including
changing the starting value or assigning specific values to individual members.
Note: Once a value is explicitly assigned to an enum member, the subsequent members
(if not explicitly assigned) continue incrementing from that value.
Example:
Listing 53: Enumeration with Custom Starting Values
# include < iostream >
using namespace std ;
enum Status {
Pending = 10 ,
Approved ,
Rejected = 100 ,
Cancelled
};
72
Chapter 2: Basics of c++ Programming Object Oriented Programming
int main () {
cout << " Pending = " << Pending << endl ;
cout << " Approved = " << Approved << endl ;
cout << " Rejected = " << Rejected << endl ;
cout << " Cancelled = " << Cancelled << endl ;
return 0;
}
Sample Output:
Pending = 10
Approved = 11
Rejected = 100
Cancelled = 101
Explanation:
This flexibility is useful when mapping enumeration values to specific codes in an appli-
cation or protocol, such as status codes, error codes, or menu options.
Listing 54: Word Count in a String
# include < iostream >
# include < string >
using namespace std ;
int main () {
itsaWord isWord = NO ;
int wordcount = 0;
73
Chapter 2: Basics of c++ Programming Object Oriented Programming
cout << " --- Word count is " << wordcount << " ---" << endl ;
return 0;
}
The program counts the number of words in a hard-coded string. It correctly handles
leading, trailing, and multiple intermediate spaces.
Sample Output:
Question:
Write a C++ program using an enum to represent three geometric shapes — CIRCLE,
SQUARE, and TRIANGLE. The program should let the user guess a secret shape by
entering a number (1 to 3), and then check if the guess matches the secret shape. If it
matches, display a success message; otherwise, display a failure message. Use a function
checkGuess() that returns true if the guess is correct, otherwise false.
# include < iostream >
using namespace std ;
enum SecretShape {
CIRCLE ,
SQUARE ,
TRIANGLE
};
int main () {
SecretShape secret = TRIANGLE ;
SecretShape playerGuess ;
int guess ;
cout < < " Guess a Shape (1. Circle ,2. Square ,3. Triangle ) " ;
cin > > guess ;
switch ( guess )
{
case 1 : playerGuess = CIRCLE ; break ;
case 2 : playerGuess = SQUARE ; break ;
case 3 : playerGuess = TRIANGLE ; break ;
}
74
Chapter 2: Basics of c++ Programming Object Oriented Programming
return 0;
}
reserves memory space for 100 integers. This approach is simple and efficient when
the required size is known in advance.
However, arrays have a major limitation: The size of the array must be known at
compile time. This means that the programmer must decide how large the array will be
before the program runs.
It is not possible to wait until runtime to specify the array size using static arrays. This
makes arrays inflexible for programs where the amount of data is only known during
execution.
int main ()
{
char * str = " Idle hands are the devil 's workshop . " ;
int len = strlen ( str ) ; // get length of str
char * ptr ; // make a pointer to char
ptr = new char [ len + 1]; // set aside memory : string + '\0 '
strcpy ( ptr , str ) ; // copy str to new memory area ptr
cout << " ptr = " << ptr << endl ; // show that ptr is now pointing to
str 's copy
return 0;
}
75
Chapter 2: Basics of c++ Programming Object Oriented Programming
The delete Operator: If your program reserves many chunks of memory using
new, eventually all the available memory will be reserved and the system will crash. To
ensure safe and efficient use of memory, the new operator is matched by a corresponding
delete operator that returns memory to the operating system. In the statement
delete[] ptr;
76
Chapter 2: Basics of c++ Programming Object Oriented Programming
be destroyed when the function terminates, but the memory will be left as an orphan,
taking up space that is inaccessible to the rest of the program. Thus it is always good
practice, and often essential, to delete memory when you’re through with it.
The brackets following delete indicate that we’re deleting an array. If you create a
single object with new, you don’t need the brackets when you delete it.
# include < iostream >
using namespace std ;
int main () {
int size ;
// Input elements
cout << " Enter " << size << " integers :\ n " ;
for ( int i = 0; i < size ; ++ i ) {
cin >> arr [ i ];
}
// Display elements
cout << " You entered : " ;
for ( int i = 0; i < size ; ++ i ) {
cout << arr [ i ] << " " ;
}
cout << endl ;
return 0;
}
77
Chapter 2: Basics of c++ Programming Object Oriented Programming
Points to Remember
• In C++, floating-point literals like 1.123 are of type double by default. To assign
them to a float, use the suffix f (e.g., 1.123f).
• When a double literal (e.g., 10.54) is assigned to a float variable (e.g., float
a = 10.54;), it is implicitly converted to float. This is a narrowing conversion,
which may lead to loss of precision and is considered an unusual implicit conversion
that C++ allows.
• Implicit type conversions occur automatically (e.g., int to float); use casting
(static cast<type>(value)) for safe explicit conversions.
• Pointers store memory addresses and can be reassigned or null; references are aliases
that must be initialized and cannot be changed.
• Arrays are fixed-size collections; pointers can dynamically manage memory using
new and delete.
• Strings in C++ can be handled via character arrays or the std::string class for
easier manipulation.
• Enumerations can start from custom values; the next values increment from the
previous unless specified.
• Dynamic memory allocation in C++ uses new (e.g., int *p = new int;) and must
be released with delete.
78
Chapter 3: Objects and Classes Object Oriented Programming
int main ()
{
smallobj s1 , s2 ; // define two objects of class smallobj
s1 . setdata (1066) ; // call member function to set data
s2 . setdata (1776) ;
s1 . showdata () ; // call member function to display data
s2 . showdata () ;
return 0;
}
The class smallobj defined in this program contains one data item and two member
functions. The two member functions provide the only access to the data item from
outside the class. The first member function sets the data item to a value, and the
second displays the value. Placing data and functions together into a single entity is a
central idea in object-oriented programming. This is shown in Figure 48
79
Chapter 3: Objects and Classes Object Oriented Programming
The definition starts with the keyword class, followed by the class name—smallobj
in this example. Like a structure, the body of the class is delimited by braces and
terminated by a semicolon. A key feature of object-oriented programming is data hiding.
The primary mechanism for hiding data is to put it in a class and make it private.
Private data or functions can only be accessed from within the class. Public data or
functions, on the other hand, are accessible from outside the class. This is shown in
Figure 50
80
Chapter 3: Objects and Classes Object Oriented Programming
• Class Data: The smallobj class contains one data item: somedata, which is of
type int. The data items within a class are called data members (or sometimes
member data). There can be any number of data members in a class, just as there
can be any number of data items in a structure. The data member somedata
follows the keyword private, so it can be accessed from within the class, but not
from outside.
• Member Functions: Member functions are functions that are included within
a class. (In some object-oriented languages, such as Smalltalk, member functions
are called methods; some writers use this term in C++ as well.) There are two
member functions in smallobj: setdata() and showdata(). The function bodies
of these functions have been written on the same line as the braces that delimit
them. Because setdata() and showdata() follow the keyword public, they can
be accessed from outside the class.
Functions Are Public, Data Is Private
Usually the data within a class is private and the functions are public. This is a result
of the way classes are used. The data is hidden so it will be safe from accidental manip-
ulation, while the functions that operate on the data are public so they can be accessed
from outside the class. However, there is no rule that says data must be private and func-
tions public; in some circumstances you may find you’ll need to use private functions and
public data. Note that the member functions setdata() and showdata() are definitions
in that the actual code for the function is contained within the class definition. Mem-
ber functions defined inside a class this way are created as inline functions by default.
We’ll see later that it is also possible to declare a function within a class but to define it
elsewhere. Functions defined outside the class are not normally inline.
81
Chapter 3: Objects and Classes Object Oriented Programming
The next two statements in main() call the member function setdata():
s1.setdata(1066);
s2.setdata(1776);
To use a member function, the dot operator (the period) connects the object name
and the member function. The syntax is similar to the way we refer to structure members,
but the parentheses signal that we’re executing a member function rather than referring
to a data item. (The dot operator is also called the class member access operator.)
Here’s another kind of entity C++ objects can represent: variables of a user-defined
data type.
// Distance class
# include < iostream >
using namespace std ;
82
Chapter 3: Objects and Classes Object Oriented Programming
{
cout << " \ nEnter feet : " ; cin >> feet ;
cout << " Enter inches : " ; cin >> inches ;
}
int main ()
{
Distance dist1 , dist2 ; // define two lengths
dist1 . setdist (11 , 6.25) ; // set dist1
dist2 . getdist () ; // get dist2 from user
// display lengths
cout << " \ ndist1 = " ; dist1 . showdist () ;
cout << " \ ndist2 = " ; dist2 . showdist () ;
cout << endl ;
return 0;
}
83
Chapter 3: Objects and Classes Object Oriented Programming
In most situations you don’t need to know that there is only one member function for
an entire class. It’s simpler to visualize each object as containing both its own data and
its own member functions. But in some situations, such as in estimating the size of an
executing program, it’s helpful to know what’s happening behind the scenes.
This tells the compiler that this function is a member of the class but that it will be
defined outside the class declaration, someplace else in the listing.
Listing 56: Member Function Defined Outside the Class
# include < iostream >
using namespace std ;
class Distance
84
Chapter 3: Objects and Classes Object Oriented Programming
{
private :
int feet ;
float inches ;
public :
void getdist () // get length from user
{
cout << " \ nEnter feet : " ; cin >> feet ;
cout << " Enter inches : " ; cin >> inches ;
}
int main ()
{
Distance dist1 , dist2 , dist3 ; // define two lengths
dist1 . getdist () ;
dist2 . getdist () ;
dist3 . add_dist ( dist1 , dist2 ) ;
return 0;
}
85
Chapter 3: Objects and Classes Object Oriented Programming
Syntax
inline ReturnType ClassName::FunctionName(parameters) {
// function body
}
86
Chapter 3: Objects and Classes Object Oriented Programming
int main ()
{
Distance dist1 , dist2 ; // define two lengths
dist1 . setdist (11 , 6.25) ; // set dist1
dist2 . getdist () ; // get dist2 from user
// display lengths
cout << " \ ndist1 = " ; dist1 . showdist () ;
cout << " \ ndist2 = " ; dist2 . showdist () ;
cout << endl ;
return 0;
}
Output
Enter feet: 5
Enter inches: 8.5
dist1 = 11'-6.25"
dist2 = 5'-8.5"
Note
The function showdist() is defined outside the class with the inline keyword. While
the compiler is not guaranteed to inline the function, it is a request for inlining small,
performance-sensitive functions.
class Date {
private :
int day , month , year ;
public :
void setDate ( int d , int m , int y ) {
day = d ;
month = m ;
year = y ;
}
void displayDate () {
cout << day << " / " << month << " / " << year ;
}
};
class Employee {
87
Chapter 3: Objects and Classes Object Oriented Programming
private :
int id ;
Date joiningDate ; // Object as member
public :
void setEmployee ( int i , int d , int m , int y ) {
id = i ;
joiningDate . setDate (d , m , y ) ; // Calling function of member
object
}
void showEmployee () {
cout << " ID : " << id << " \ nJoining Date : " ;
joiningDate . displayDate () ; // Calling function of member object
cout << endl ;
}
};
int main () {
Employee emp1 ;
emp1 . setEmployee (101 , 1 , 1 , 2024) ;
emp1 . showEmployee () ;
return 0;
}
Output:
ID: 101
Joining Date: 1/1/2024
In this example, the Employee class contains an object of the Date class as a data
member. We set and display data using member functions of both classes.
88
Chapter 3: Objects and Classes Object Oriented Programming
c1 . inc_count () ; // increment c1
c2 . inc_count () ; // increment c2
c2 . inc_count () ; // increment c2
class Counter
{
private :
unsigned int count ; // count
public :
// Parameterized constructor
Counter ( unsigned int c ) : count ( c )
{ /* empty body */ }
89
Chapter 3: Objects and Classes Object Oriented Programming
int main ()
{
Counter c1 (0) , c2 (5) ; // initialized with different starting
values
cout << " \ nc1 = " << c1 . get_count () ; // display
cout << " \ nc2 = " << c2 . get_count () ;
c1 . inc_count () ; // increment c1
c2 . inc_count () ; // increment c2
c2 . inc_count () ; // increment c2
class Counter {
private :
unsigned int count ;
public :
// Default constructor
Counter () : count (0) { }
// Parameterized constructor
Counter ( unsigned int c ) : count ( c ) { }
90
Chapter 3: Objects and Classes Object Oriented Programming
// Copy constructor
Counter ( const Counter & other ) : count ( other . count ) {
cout << " Copy constructor called \ n " ;
}
int main () {
Counter c1 (5) ; // parameterized constructor
Counter c2 ( c1 ) ; // direct copy constructor call
Counter c3 = c2 ; // copy initialization
return 0;
}
public :
Counter () : count (0) { } // Default
constructor
Write a C++ class Box that models a three-dimensional box. Implement constructor
overloading by providing:
91
Chapter 3: Objects and Classes Object Oriented Programming
Include a member function display() that prints the box dimensions in the format
length x width x height.
Write a main() function to demonstrate the use of all three constructors and display
their initialized dimensions.
Listing 64: Example of Constructor Overloading with Different Parameter Lists
# include < iostream >
using namespace std ;
class Box
{
private :
double length ;
double width ;
double height ;
public :
// Default constructor
Box () : length (1) , width (1) , height (1) { }
void display ()
{
cout << " Box dimensions : "
<< length << " x " << width << " x " << height << endl
;
}
};
int main ()
{
Box box1 ; // Calls default constructor
Box box2 (3.5 , 4.2 , 5) ; // Calls parameterized constructor
Box box3 (7.0) ; // Calls cube constructor
box1 . display () ;
box2 . display () ;
box3 . display () ;
return 0;
}
3.7.2 Destructors
We’ve seen that a special member function—the constructor—is called automatically
when an object is first created. You might guess that another function is called automat-
92
Chapter 3: Objects and Classes Object Oriented Programming
ically when an object is destroyed. This is indeed the case. Such a function is called a
destructor. A destructor has the same name as the constructor (which is the same as
the class name) but is preceded by a tilde (~).
Listing 65: Constructor and Destructor Example
class Foo
{
private :
int data ;
public :
Foo () : data (0) // constructor ( same name as class )
{ }
Like constructors, destructors do not have a return value. They also take no arguments
(the assumption being that there’s only one way to destroy an object). The most common
use of destructors is to deallocate memory that was allocated for the object by the
constructor.
Listing 66: Counter Class Demonstrating Constructor and Destructor
# include < iostream >
using namespace std ;
class Counter
{
private :
unsigned int count ; // count
public :
Counter () : count (0) // constructor
{
cout << " Constructor called . Count initialized to 0. " << endl ;
}
~ Counter () // destructor
{
cout << " Destructor called . Final count was : " << count << endl
;
}
int main ()
{
Counter c1 , c2 ; // define and initialize
cout << " \ nc1 = " << c1 . get_count () ;
93
Chapter 3: Objects and Classes Object Oriented Programming
c1 . inc_count () ; // increment c1
c2 . inc_count () ; // increment c2
c2 . inc_count () ; // increment c2
return 0;
}
In this specific program, the destructor is not strictly necessary because the class Counter
does not allocate any dynamic memory or open resources like files or network sockets.
When the program ends, the objects c1 and c2 go out of scope, and their destructors are
called automatically.
# include < iostream >
# include < cstring >
using namespace std ;
class MyString {
private :
char * str ;
public :
MyString ( const char * input ) {
str = new char [ strlen ( input ) + 1];
strcpy ( str , input ) ;
cout << " Constructor : Allocated \" " << str << " \"\ n " ;
}
~ MyString () {
cout << " Destructor : Deleting \" " << str << " \"\ n " ;
delete [] str ;
}
void display () {
cout << " Stored string : " << str << endl ;
}
};
int main () {
MyString name ( " Ram Thapa " ) ;
name . display () ;
return 0;
}
94
Chapter 3: Objects and Classes Object Oriented Programming
simple data types such as int: the object name is supplied as the argument. Since
add dist() is a member function of the Distance class, it can access the private data in
any object of class Distance supplied to it as an argument, using names like dist1.inches
and dist2.feet.
Close examination of add dist() emphasizes some important truths about member
functions. A member function is always given access to the object for which it was
called: the object connected to it with the dot operator. But it may be able to access
other objects. In the following statement, what objects can add dist() access?
dist3.add dist(dist1, dist2);
Besides dist3, the object for which it was called, it can also access dist1 and dist2,
because they are supplied as arguments. You might think of dist3 as a sort of phantom
argument; the member function always has access to it, even though it is not supplied
as an argument. That’s what this statement means: “Execute the add dist() member
function of dist3.” When the variables feet and inches are referred to within this
function, they refer to dist3.feet and dist3.inches.
Notice that the result is not returned by the function. The return type of add dist()
is void. The result is stored automatically in the dist3 object. Figure Figure 54 shows
the two distances dist1 and dist2 being added together, with the result stored in dist3.
To summarize, every call to a member function is associated with a particular object
(unless it’s a static function; we’ll get to that later). Using the member names alone
(feet and inches), the function has direct access to all the members, whether private or
public, of that object. It also has indirect access, using the object name and the member
name, connected with the dot operator (dist1.inches or dist2.feet) to other objects
of the same class that are passed as arguments.
95
Chapter 3: Objects and Classes Object Oriented Programming
class Distance
{
private :
int feet ;
float inches ;
public :
void getdist () // get length from user
{
cout << " \ nEnter feet : " ; cin >> feet ;
cout << " Enter inches : " ; cin >> inches ;
}
return temp ;
}
int main ()
{
Distance dist1 , dist2 , dist3 ; // define three distances
dist1 . getdist () ;
dist2 . getdist () ;
96
Chapter 3: Objects and Classes Object Oriented Programming
return 0;
}
class Distance
{
private :
int feet ;
float inches ;
public :
void getdist () // get length from user
{
cout << " \ nEnter feet : " ; cin >> feet ;
cout << " Enter inches : " ; cin >> inches ;
}
void showdist () const // display distance
{
cout << feet << " \ ' - " << inches << ' \" ';
}
};
int main ()
{
Distance dist [100]; // array of distances
int n = 0; // count the entries
char ans ; // user response ( ' y ' or 'n ')
Sample Output
Enter distance number 1
97
Chapter 3: Objects and Classes Object Oriented Programming
Enter feet: 5
Enter inches: 7.5
Enter another (y/n)?: y
Enter distance number 2
Enter feet: 6
Enter inches: 2.3
Enter another (y/n)?: n
Distance dist;
98
Chapter 3: Objects and Classes Object Oriented Programming
int main ()
{
Distance * distptr ; // pointer to Distance
distptr = new Distance ; // points to new Distance object
distptr - > getdist () ; // access object members with -> operator
distptr - > showdist () ;
delete distptr ;
cout << endl ;
return 0;
}
The dot operator requires the identifier on its left to be a variable. Since distptr is a
pointer to a variable, we need another syntax. A concise approach to accessing members of
an object via pointer is furnished by the membership-access operator, which consists
of a hyphen and a greater-than sign (->).
distptr->getdist();
(*distptr).getdist();
Here, distptr is a pointer to a Distance object. The -> operator is a shorthand for
dereferencing the pointer and then accessing a member, making it a common and clean
syntax in object-oriented C++ programming when working with pointers to objects.
class Distance
99
Chapter 3: Objects and Classes Object Oriented Programming
{
private :
int feet ;
float inches ;
public :
void getdist () // get length from user
{
cout << " \ nEnter feet : " ; cin >> feet ;
cout << " Enter inches : " ; cin >> inches ;
}
void showdist () const // display distance
{
cout << feet << " \ ' - " << inches << ' \" ';
}
};
int main ()
{
int n ;
cout << " How many distances do you want to enter ? " ;
cin >> n ;
// input distances
for ( int i = 0; i < n ; i ++) {
cout << " Enter distance number " << i + 1;
dist [ i ]. getdist () ;
}
// deallocate memory
delete [] dist ;
class MyString {
private :
char * str ; // Pointer to dynamically allocated char array
100
Chapter 3: Objects and Classes Object Oriented Programming
public :
// Constructor allocates memory dynamically and copies input string
MyString ( const char * s ) {
str = new char [ strlen ( s ) + 1]; // Allocate memory on heap
strcpy ( str , s ) ; // Copy string content
std :: cout << " Constructor : allocated memory for string \ n " ;
}
int main () {
MyString greeting ( " Hello , dynamic memory in constructor ! " ) ;
greeting . print () ;
return 0;
}
101
Chapter 3: Objects and Classes Object Oriented Programming
int main ()
{
foo c1 ;
cout < < c1 . getcount () << endl ;
foo c2 ;
cout < < c2 . getcount () << endl ;
foo c3 ;
cout < < c3 . getcount () << endl ;
return 0;
}
Static class variables are not used as often as ordinary non-static variables, but they are
important in many situations.
Static member data requires an unusual format. Ordinary variables are usually de-
clared (the compiler is told about their name and type) and defined (the compiler sets
aside memory to hold the variable) in the same statement. Static member data, on the
other hand, requires two separate statements. The variable’s declaration appears in the
class definition, but the variable is actually defined outside the class, in much the same
way as a global variable. Why is this two-part approach used? If static member data
were defined inside the class (as it actually was in early versions of C++), it would violate
the idea that a class definition is only a blueprint and does not set aside any memory.
102
Chapter 3: Objects and Classes Object Oriented Programming
Putting the definition of static member data outside the class also serves to emphasize
that the memory space for such data is allocated only once, before the program starts to
execute, and that one static member variable is accessed by an entire class; each object
does not have its own version of the variable, as it would with ordinary member data. In
this way a static member variable is more like a global variable.
A static member function can be called using the class name without creating an
object. It can only access static data members.
To achieve this:
class Employee {
private :
string name ;
int id ;
static int count ; // Static variable to count employees
public :
Employee ( string empName , int empId ) {
name = empName ;
id = empId ;
count ++; // Increment when a new employee is created
}
103
Chapter 3: Objects and Classes Object Oriented Programming
int main () {
Employee e1 ( " Alice " , 101) ;
Employee e2 ( " Bob " , 102) ;
e1 . display () ;
e2 . display () ;
return 0;
}
5. Output
Name: Alice, ID: 101
Name: Bob, ID: 102
Total Employees: 2
Syntax Rules
• The keyword const must be placed after the function signature.
To avoid raising too many subjects at once, we have, up to now, avoided using const
member functions in the example programs. However, there are many places where const
member functions should be used. For example, in the Distance class (used in several
programs), the showdist() member function could be made const because it doesn’t
(or certainly shouldn’t!) modify any of the data in the object for which it was called. Its
only role is to display the data. Marking such functions as const not only improves code
clarity but also helps catch potential logic errors during compilation. It enforces the rule
that accessor or display functions must not change the object’s internal state.
Listing 72: Using const with member functions and arguments
# include < iostream >
using namespace std ;
104
Chapter 3: Objects and Classes Object Oriented Programming
public :
// constructor ( no args )
Distance () : feet (0) , inches (0.0) { }
int main ()
{
Distance dist1 , dist3 ; // define two lengths
Distance dist2 (11 , 6.25) ; // define , initialize dist2
105
Chapter 3: Objects and Classes Object Oriented Programming
return 0;
}
class alpha {
private :
int data ;
public :
alpha () : data (3) { } // No - arg constructor
friend int frifunc ( alpha , beta ) ; // Friend function
};
class beta {
private :
int data ;
public :
beta () : data (7) { } // No - arg constructor
friend int frifunc ( alpha , beta ) ; // Friend function
};
int main () {
alpha aa ;
beta bb ;
cout << frifunc ( aa , bb ) << endl ; // Call the function
return 0;
}
In this program, the two classes are alpha and beta. The constructors in these classes
initialize their single data items to fixed values (3 in alpha and 7 in beta). We want the
function frifunc() to have access to both of these private data members, so we make it
a friend function. It’s declared with the friend keyword in both classes:
friend int frifunc(alpha, beta);
106
Chapter 3: Objects and Classes Object Oriented Programming
This declaration can be placed anywhere in the class; it doesn’t matter whether it goes
in the public or the private section. An object of each class is passed as an argument to
the function frifunc(), and it accesses the private data member of both classes through
these arguments. The function doesn’t do much: it adds the data items and returns the
sum. The main() program calls this function and prints the result.
A minor point: Remember that a class can’t be referred to until it has been declared.
Class beta is referred to in the declaration of the function frifunc() in class alpha, so
beta must be declared before alpha. Hence the declaration:
class beta;
The following examples demonstrate how to square a private integer member using
both methods:
Listing 74: Squaring a Private Variable without Using Friend Function
# include < iostream >
using namespace std ;
class Number {
private :
int value ;
public :
Number ( int v ) : value ( v ) {}
void square () {
value = value * value ;
}
void display () {
cout << " Value : " << value << endl ;
}
};
int main () {
Number num (5) ;
num . square () ; // Squaring using member function
num . display () ; // Output : Value : 25
return 0;
}
107
Chapter 3: Objects and Classes Object Oriented Programming
class Number {
private :
int value ;
public :
Number ( int v ) : value ( v ) {}
void display () {
cout << " Value : " << value << endl ;
}
};
int main () {
Number num (5) ;
square ( num ) ; // Squaring using friend function
num . display () ; // Output : Value : 25
return 0;
}
As seen in the first example, the square operation is performed using a public member
function, keeping everything encapsulated within the class.
In the second example, a friend function is used. This allows the squaring operation
to be performed by a non-member function that still has access to the class’s private
data.
While friend functions break the encapsulation slightly, they are useful when two or
more classes or external functions need to work closely with a class’s private members.
friend Classes The member functions of a class can all be made friend at the same
time by declaring the entire class as a friend of another class. This allows every member
function of the friend class to access the private and protected members of the class
granting the friendship.
Listing 76: Friend Class Accessing Private Members
# include < iostream >
using namespace std ;
class alpha {
private :
int data1 ;
public :
alpha () : data1 (99) { } // constructor
friend class beta ; // beta is a friend class
};
class beta {
public :
// All member functions of beta can access private members of alpha
void func1 ( alpha a ) { cout << " \ ndata1 = " << a . data1 ; }
108
Chapter 3: Objects and Classes Object Oriented Programming
void func2 ( alpha a ) { cout << " \ ndata1 = " << a . data1 ; }
};
int main () {
alpha a ;
beta b ;
b . func1 ( a ) ;
b . func2 ( a ) ;
cout << endl ;
return 0;
}
In class alpha, the entire class beta is proclaimed a friend. Now all the member functions
of beta can access the private data of alpha (in this program, the single data item data1).
Note that in the friend declaration we specify that beta is a class using the class keyword:
We could have also declared beta to be a class before the alpha class specifier, as in
previous examples:
class beta;
and then, within alpha, referred to beta without the class keyword:
friend beta;
109
Chapter 4: Operator Overloading Object Oriented Programming
Overloadable Operators
The following operators can be overloaded in C++:
• Arithmetic Operators: +, -, *, /, %
• Subscript Operator: []
110
Chapter 4: Operator Overloading Object Oriented Programming
Non-Overloadable Operators
Some of the operators that cannot be overloaded:
• sizeof Operator
return_type class_name::operator<op>(argument_list) {
// operator definition
}
class ClassName {
public:
ReturnType operator<op>(ClassName obj);
};
class ClassName {
friend ReturnType operator<op>(ClassName a, ClassName b);
};
111
Chapter 4: Operator Overloading Object Oriented Programming
c1.inc_count();
This approach was functional, but the code could be made more readable and intuitive
by using the built-in increment operator ++ instead:
++c1;
All experienced C++ (and C) programmers would immediately understand that this
expression increments c1, making the code more natural and expressive.
Operator overloading allows us to define custom behavior for the ++ operator when
used with user-defined types such as our Counter class. This improves both code clarity
and maintainability.
The following program demonstrates how to overload the prefix increment operator
++ to increment a counter variable:
class Counter {
private:
unsigned int count; // count
public:
Counter() : count(0) { } // constructor
int main() {
Counter c1, c2; // define and initialize
++c1; // increment c1
++c2; // increment c2
112
Chapter 4: Operator Overloading Object Oriented Programming
return 0;
}
Output:
c1 = 0
c2 = 0
c1 = 1
c2 = 2
The keyword operator is used to overload the ++ operator in the following declarator:
void operator++();
The return type (in this case, void) comes first, followed by the keyword operator,
then the operator itself (++), and finally the argument list enclosed in parentheses (which
is empty for the prefix version).
This declarator syntax tells the compiler to call this member function whenever the
++ operator is encountered, provided the operand (i.e., the variable operated on by ++)
is of type Counter.
We learned in “Functions Overloading,” that the only way the compiler can distin-
guish between overloaded functions is by examining the data types and number of their
arguments. In the same way, the compiler distinguishes between overloaded operators by
looking at the data type of their operands.
If the operand is a built-in type such as int, as in:
++intvar;
then the compiler uses its built-in routine to increment an int. However, if the
operand is a Counter object, the compiler knows to invoke the user-defined operator++()
function instead.
113
Chapter 4: Operator Overloading Object Oriented Programming
class Counter {
private :
unsigned int count ; // count
public :
Counter () : count (0) { } // constructor
int main () {
Counter c1 , c2 ; // c1 = 0 , c2 = 0
++ c1 ; // c1 = 1
c2 = ++ c1 ; // c1 = 2 , c2 = 2
return 0;
}
Output:
c1 = 0
c2 = 0
c1 = 2
c2 = 2
Here the operator++() function creates a new object of type Counter, called temp, to
use as a return value. It increments the count data in its own object as before, then
creates the new temp object and assigns count in the new object the same value as in its
own object. Finally, it returns the temp object.
In above we created a temporary object of type Counter, named temp, whose sole
purpose was to provide a return value for the ++ operator. This required three statements:
Counter temp; % make a temporary Counter object
114
Chapter 4: Operator Overloading Object Oriented Programming
There are more convenient ways to return temporary objects from functions and over-
loaded operators.
Listing 77: Counter class with overloaded prefix increment operator
# include < iostream >
using namespace std ;
class Counter
{
private :
unsigned int count ; // count
public :
Counter () : count (0) { } // constructor : no args
Counter ( int c ) : count ( c ) { } // constructor : one arg
int main ()
{
Counter c1 , c2 ; // c1 =0 , c2 =0 initially
cout << " \ nc1 = " << c1 . get_count () ; // display c1 count
cout << " \ nc2 = " << c2 . get_count () ; // display c2 count
++ c1 ; // c1 =1
c2 = ++ c1 ; // c1 =2 , c2 =2
return 0;
}
return Counter(count);
does what all three statements did in previous program. This statement creates an
object of type Counter. This object has no name; it won’t be around long enough to need
one. This unnamed object is initialized to the value provided by the argument count.
But wait: Doesn’t this require a constructor that takes one argument? It does, and to
make this statement work, we sneakily inserted just such a constructor into the member
function list in COUNTPP3:
115
Chapter 4: Operator Overloading Object Oriented Programming
Once the unnamed object is initialized to the value of count, it can then be returned.
Listing 78: Overloading prefix and postfix ++ operators
# include < iostream >
using namespace std ;
class Counter
{
private :
unsigned int count ; // count
public :
Counter () : count (0) { } // constructor : no args
Counter ( int c ) : count ( c ) { } // constructor : one arg
// Prefix increment
Counter operator ++() {
return Counter (++ count ) ; // increment first , then return
temporary
}
// Postfix increment
Counter operator ++( int ) {
return Counter ( count ++) ; // return temporary , then
increment
}
};
int main ()
{
Counter c1 , c2 ; // c1 = 0 , c2 = 0
cout << " \ nc1 = " << c1 . get_count () ;
cout << " \ nc2 = " << c2 . get_count () ;
++ c1 ; // c1 = 1
c2 = ++ c1 ; // c1 = 2 , c2 = 2 ( prefix )
cout << " \ nc1 = " << c1 . get_count () ;
cout << " \ nc2 = " << c2 . get_count () ;
c2 = c1 ++; // c2 = 2 , c1 = 3 ( postfix )
cout << " \ nc1 = " << c1 . get_count () ;
cout << " \ nc2 = " << c2 . get_count () << endl ;
return 0;
}
Now there are two different declarators for overloading the ++ operator. The one
we’ve seen before, for prefix notation, is:
Counter operator++()
116
Chapter 4: Operator Overloading Object Oriented Programming
Counter operator++(int)
The only difference is the int in the parentheses. This int isn’t really an argument,
and it doesn’t mean integer. It’s simply a signal to the compiler to create the postfix
version of the operator. The designers of C++ are fond of recycling existing operators
and keywords to play multiple roles, and int is the one they chose to indicate postfix.
(Well, can you think of a better syntax?)
Program Output
c1=0
c2=0
c1=2
c2=2
c1=3
c2=2
dist3.add_dist(dist1, dist2);
Below is the listing for the Distance program which demonstrates this:
Listing 79: Overloaded + operator for Distance
# include < iostream >
using namespace std ;
class Distance
{
private :
int feet ;
float inches ;
public :
Distance () : feet (0) , inches (0.0) { } // no - arg
constructor
Distance ( int ft , float in ) : feet ( ft ) , inches ( in ) { } // two - arg
constructor
void getdist () {
cout << " \ nEnter feet : " ; cin >> feet ;
cout << " Enter inches : " ; cin >> inches ;
}
117
Chapter 4: Operator Overloading Object Oriented Programming
if ( i >= 12.0) {
i -= 12.0;
f ++;
}
return Distance (f , i ) ;
}
int main ()
{
Distance dist1 , dist3 , dist4 ;
dist1 . getdist () ; // get input for dist1
Distance dist2 (11 , 6.25) ; // initialize dist2
cout << " dist1 = "; dist1 . showdist () ; cout << endl ;
cout << " dist2 = "; dist2 . showdist () ; cout << endl ;
cout << " dist3 = "; dist3 . showdist () ; cout << endl ;
cout << " dist4 = "; dist4 . showdist () ; cout << endl ;
return 0;
}
Sample Output
Enter feet: 10
Enter inches: 6.5
dist1 = 10'-6.5"
dist2 = 11'-6.25"
dist3 = 22'-0.75"
dist4 = 44'-1.5"
To demonstrate that the result of an addition can itself be used in another addition
(as well as an assignment), the following statement adds three distances:
This uses the associativity of the + operator and constructs intermediate unnamed
temporary objects. The key declaration in the class is:
Distance operator+(Distance);
118
Chapter 4: Operator Overloading Object Oriented Programming
This function returns a Distance object and takes one argument of type Distance.
In the statement:
The left-hand operand dist1 is the object that calls the operator+ function. The
right-hand operand dist2 is passed as an argument. The function returns a new tempo-
rary Distance object containing the sum, which is then assigned to dist3.
This structure allows chaining:
dist4 = dist1 + dist2 + dist3;
is treated as:
temp = dist1 + dist2;
dist4 = temp + dist3;
In the operator+() function, the left operand is accessed directly—since this is the
object of which the operator is a member—using feet and inches. The right operand is
accessed as the function’s argument, as d2.feet and d2.inches. We can generalize and
say that an overloaded operator always requires one less argument than its number of
operands, since one operand is the object of which the operator is a member. That’s why
unary operators require no arguments.(This rule does not apply to friend functions and
operators)
The + operator cannot be used to concatenate C-style strings. That is, the following
expression is invalid in standard C++:
119
Chapter 4: Operator Overloading Object Oriented Programming
where str1, str2, and str3 are C-string variables (i.e., arrays of type char), as
in "cat" plus "bird" equals "catbird". However, if we use a user-defined String
class—like the one shown in the String program in Chapter 3—we can overload the +
operator to enable such concatenation.
This functionality is also provided by the Standard C++ std::string class, but
implementing it ourselves using a custom class makes the underlying mechanism more
transparent. Overloading the + operator to perform concatenation—something that isn’t
numerically additive—is a good example of how C++ enables redefining the meaning of
built-in operators to support user-defined behavior.
Such operator overloading enhances the usability of the class and provides syntactic
convenience, allowing us to write intuitive expressions like:
String s1("cat");
String s2("bird");
String s3 = s1 + s2; // yields "catbird"
This approach makes the String class behave more like built-in types, thereby con-
tributing to more readable and expressive code. The following program demonstrates
how the + operator can be overloaded to concatenate two user-defined String objects.
// overloaded + operator concatenates strings
# include < iostream >
using namespace std ;
# include < string .h > // for strcpy () , strcat ()
# include < stdlib .h > // for exit ()
public :
String () // constructor , no args
{ strcpy ( str , " " ) ; }
120
Chapter 4: Operator Overloading Object Oriented Programming
}
return temp ; // return temp String
}
};
int main ()
{
String s1 = " \ nMerry Christmas ! " ; // uses constructor 2
String s2 = " Happy new year ! " ; // uses constructor 2
String s3 ; // uses constructor 1
s3 = s1 + s2 ; // add s2 to s1 , assign to s3
s3 . display () ; // display s3
Program Output:
This example illustrates how a custom String class can make use of operator over-
loading to support intuitive operations like concatenation using the + symbol—something
that isn’t directly possible with C-style strings.
Comparison Operators:
Listing 80: Overloaded comparison Operator to Compare Distances
# include < iostream >
using namespace std ;
121
Chapter 4: Operator Overloading Object Oriented Programming
int main ()
{
Distance dist1 ; // define Distance dist1
dist1 . getdist () ; // get dist1 from user
Distance dist2 (6 , 2.5) ; // define and initialize dist2
// display distances
cout << " \ ndist1 = " ; dist1 . showdist () ;
cout << " \ ndist2 = " ; dist2 . showdist () ;
122
Chapter 4: Operator Overloading Object Oriented Programming
int main ()
{
Distance dist1 ; // define dist1
dist1 . getdist () ; // get dist1 from user
cout << " \ ndist1 = " ; dist1 . showdist () ;
class safearay
{
private :
int arr [ LIMIT ];
public :
int & operator []( int n ) // return by reference
{
if ( n < 0 || n >= LIMIT )
{
cout << " \ nIndex out of bounds " ;
exit (1) ;
}
return arr [ n ];
}
};
123
Chapter 4: Operator Overloading Object Oriented Programming
int main ()
{
safearay sa1 ;
// Insert elements
for ( int j = 0; j < LIMIT ; j ++)
sa1 [ j ] = j * 10; // * left * side of equal sign
// Display elements
for ( int j = 0; j < LIMIT ; j ++)
{
int temp = sa1 [ j ]; // * right * side of equal sign
cout << " Element " << j << " is " << temp << endl ;
}
return 0;
}
Explanation
In this program we can use natural subscript expressions:
returns a reference to an element in the internal array. This allows the array to be used
like a regular C++ array but with built-in bounds checking, improving safety without
sacrificing syntax.
Note: Returning by reference is crucial when the operator is used on the left-hand
side of an assignment statement, as it allows direct modification of the array element.
overloading the Assignment Operator
# include < iostream >
using namespace std ;
class alpha {
private :
int data ;
public :
alpha () { } // no - arg constructor
alpha ( int d ) { data = d ; } // one - arg constructor
void display () {
cout << data ;
}
124
Chapter 4: Operator Overloading Object Oriented Programming
int main () {
alpha a1 (37) ; // initialize a1
alpha a2 ; // uninitialized
a2 = a1 ; // invokes overloaded =
Output
Assignment operator invoked
a2 =37
a3 =37
• The line a2 = a1; calls this function, printing a message and assigning data.
• The statement alpha a3 = a2; does not invoke the assignment operator — it calls
the copy constructor (default or compiler-generated).
• Note: Returning by value instead of by reference here is acceptable for this simple
class but not efficient or typical in real-world scenarios.
When we want to keep operator logic external or allow operations where the left-hand
operand is not an object of the class (e.g., 5 + obj), we can use a non-member function.
To allow a non-member function to access private members of the class, we declare
it as a friend of the class.
In this example, we overload the prefix ++ operator using a non-member function.
// co unter_ nonmem ber . cpp
# include < iostream >
using namespace std ;
class Counter
{
private :
unsigned int count ; // count
public :
Counter () : count (0) { } // constructor : no args
125
Chapter 4: Operator Overloading Object Oriented Programming
int main ()
{
Counter c1 , c2 ; // c1 = 0 , c2 = 0
cout << " \ nc1 = " << c1 . get_count () ; // display c1
cout << " \ nc2 = " << c2 . get_count () ; // display c2
++ c1 ; // c1 = 1
c2 = ++ c1 ; // c1 = 2 , c2 = 2
return 0;
}
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 << " Enter inches : " ; cin >> inches ;
}
126
Chapter 4: Operator Overloading Object Oriented Programming
};
if ( i >= 12.0) {
i -= 12.0;
f ++;
}
return Distance (f , i ) ;
}
int main () {
Distance dist1 , dist3 , dist4 ;
dist1 . getdist () ;
Distance dist2 (11 , 6.25) ;
cout << " dist1 = "; dist1 . showdist () ; cout << endl ;
cout << " dist2 = "; dist2 . showdist () ; cout << endl ;
cout << " dist3 = "; dist3 . showdist () ; cout << endl ;
cout << " dist4 = "; dist4 . showdist () ; cout << endl ;
return 0;
}
In the given program, the binary + operator is overloaded using a friend function.
Function Definition
Distance operator+(const Distance& d1, const Distance& d2) {
int f = d1.feet + d2.feet;
float i = d1.inches + d2.inches;
if (i >= 12.0) {
i -= 12.0;
f++;
}
127
Chapter 4: Operator Overloading Object Oriented Programming
Note:
• Member functions implicitly use the left-hand operand as the object (’*this’).
• Friend functions require explicit parameters for both operands but can access pri-
vate members.
In C++, overloading the + operator using both a member function and a friend
function allows flexible arithmetic-like expressions involving user-defined types. This
example demonstrates how to support both obj + 5 and 5 + obj with a Number class.
Listing 84: Operator Overloading to Support obj + 5 and 5 + obj
# include < iostream >
using namespace std ;
class Number {
private :
int value ;
public :
Number ( int v = 0) : value ( v ) {}
128
Chapter 4: Operator Overloading Object Oriented Programming
int main () {
Number obj (10) ;
Number res1 = obj + 5; // Calls member function
Number res2 = 5 + obj ; // Calls friend function
return 0;
}
• Member Function: The statement obj + 5 calls the member function operator+(int).
The object obj is the left-hand operand, and 5 is passed as the argument.
• Friend Function: The statement 5 + obj is not valid with a member function
because the left-hand operand (5) is not an object. To support this, we define a
non-member friend function that takes the integer first and the object second.
Conclusion: To support both obj + 5 and 5 + obj, we must overload the + operator
using:
• A member function for obj + 5
class Point {
private :
int x , y ;
public :
Point () : x (0) , y (0) {}
129
Chapter 4: Operator Overloading Object Oriented Programming
int main () {
Point p ;
cin >> p ;
cout << " Point : " << p << endl ;
return 0;
}
• operator<< takes an ostream and a const Point& and returns a reference to the
stream.
• In main(), input is taken using cin >> p, and output is shown using cout << p.
Sample Output
Console Output
Enter x and y: 3 4
Point: (3, 4)
Overloading the input (>>) and output (<<) operators using friend functions allows
for seamless and readable I/O of class objects, just like built-in types.
intvar = floatvar;
where intvar is of type int and floatvar is of type float, we are assuming that the
compiler will automatically invoke a special routine to convert the value of floatvar,
which is expressed in floating-point format, to an integer format so that it can be assigned
to intvar.
There are, of course, many such type conversions supported in C++, such as:
• float to double
130
Chapter 4: Operator Overloading Object Oriented Programming
• char to float
• int to double
• double to int
Each such conversion has its own rules, precision implications, and performance
cost. The compiler performs automatic type conversion (also known as implicit conver-
sion) only when there is no risk of data loss, such as converting an int to a float.
However, when converting from a float to an int, the compiler may truncate the
decimal part, potentially resulting in data loss. This is why such conversions must be
well-understood by the programmer.
• Explicit conversions, or type casting, allow manual control over how data types
are converted.
This is known as explicit type conversion or type casting. The use of static cast<int>()
makes it clear in the source code that the conversion from float to int is intentional.
class Box {
131
Chapter 4: Operator Overloading Object Oriented Programming
int length ;
public :
// Constructor to convert int to Box
Box ( int l ) {
length = l ;
}
void show () {
cout << " Length = " << length << endl ;
}
};
int main () {
Box b1 = 10; // int to Box conversion
b1 . show () ; // Output : Length = 10
return 0;
}
• Box b1 = 10; invokes the Box(int) constructor, converting the integer 10 into a
Box object.
• int x = b1; invokes the conversion operator operator int(), converting the
Box object into an int This operator can be called with an explicit cast x =
static cast<int>(b1);.
• This shows how user-defined types can participate in assignments and expressions
involving built-in types using conversion mechanisms.
Our next example shows how to convert between a basic type and a user-defined type.
In this example, the user-defined type is (surprise!) the English Distance class from
previous examples, and the basic type is float, which we use to represent meters, a unit
of length in the metric measurement system.
Listing 88: Distance class with conversion between meters (float) and feet/inches
# include < iostream >
using namespace std ;
class Distance {
private :
const float MTF ; // meters to feet conversion factor
int feet ;
float inches ;
public :
// No - arg constructor
132
Chapter 4: Operator Overloading Object Oriented Programming
void getdist () {
cout << " \ nEnter feet : " ; cin >> feet ;
cout << " Enter inches : " ; cin >> inches ;
}
int main () {
float mtrs ;
Distance dist1 = 2.35 F ; // uses 1 - arg constructor to convert
meters to Distance
cout << " \ ndist1 = " ; dist1 . showdist () ;
return 0;
}
133
Chapter 4: Operator Overloading Object Oriented Programming
class Rectangle {
float x , y ;
public :
Rectangle ( float a , float b ) : x ( a ) , y ( b ) {}
float getX () const { return x; }
float getY () const { return y; }
void show () {
cout << " Rectangle : x = " << x << " , y = " << y << endl ;
}
};
class Polar {
float radius , angle ; // angle in degrees
public :
Polar () : radius (0) , angle (0) {}
void show () {
cout << " Polar : radius = " << radius << " , angle = " <<
angle << " degrees " << endl ;
}
};
int main () {
Rectangle rect (3.0 , 4.0) ;
134
Chapter 4: Operator Overloading Object Oriented Programming
rect . show () ;
return 0;
}
In the main() function of the first program, we define an object of type Rectangle,
named rect, with given x and y coordinates. We also define an object of type
Polar, named p, and initialize it using the statement:
Polar p = rect ;
Since these objects belong to different classes, a conversion must take place. In this
example, the constructor:
Polar ( const Rectangle & rect )
performs the conversion. It is a member of the Polar class and accepts a Rectangle
object as a parameter. The constructor accesses the rectangle’s dimensions via
public getter functions, calculates the radius and angle (in degrees), and initializes
the new Polar object accordingly.
Sample Interaction:
The values x = 3.0 and y = 4.0 form a right triangle with hypotenuse (radius) 5,
and an angle of approximately 53.13 degrees, confirming the conversion is correct.
class Polar {
float radius , angle ;
public :
Polar () : radius (0) , angle (0) {}
Polar ( float r , float a ) : radius ( r ) , angle ( a ) {}
void show () {
cout << " Polar : radius = " << radius << " , angle = " <<
angle << " degrees " << endl ;
}
};
class Rectangle {
float x , y ;
public :
Rectangle ( float a , float b ) : x ( a ) , y ( b ) {}
135
Chapter 4: Operator Overloading Object Oriented Programming
void show () {
cout << " Rectangle : x = " << x << " , y = " << y << endl ;
}
};
int main () {
Rectangle rect (3.0 , 4.0) ;
rect . show () ;
return 0;
}
In the second program, we again define a Rectangle object, rect, and a Polar
object, p. This time, we use the statement:
Polar p = rect ;
This operator is a member of the Rectangle class. It uses the values of x and y
(accessed directly within the class) to compute the radius and angle, constructs a
temporary Polar object with these values, and returns it.
Sample Interaction:
This result is again based on a right triangle (6-8-10), confirming accurate and
meaningful conversion between the two user-defined types using operator overload-
ing. Both techniques allow seamless conversion between user-defined types:
• Use a constructor in the destination class when you want the conversion
logic in the receiving object.
• Use a conversion operator in the source class when you want the source
object to define how it should be converted.
136
Chapter 4: Operator Overloading Object Oriented Programming
class Distance {
private :
int meter ;
public :
// Explicit constructor
explicit Distance ( int m ) {
meter = m ;
cout << " Constructor called \ n " ;
}
void display () {
cout << " Meter = " << meter << endl ;
}
};
int main () {
Distance d1 (5) ; // OK : Direct initialization
// Distance d2 = 10; // Error : Implicit conversion not allowed
d1 . display () ;
return 0;
}
Console Output
Constructor called
Meter = 5
explicit constructors add safety to object creation, especially when dealing with single-
argument constructors, by preventing automatic conversions that may lead to bugs.
137
Chapter 5: Inheritance Object Oriented Programming
Chapter 5: Inheritance
5.1 Base class and derived class
Inheritance is probably the most powerful feature of object-oriented programming, af-
ter classes themselves. Inheritance is the process of creating new classes, called derived
classes, from existing or base classes. The derived class inherits all the capabilities of the
base class but can add embellishments and refinements of its own. The base class is un-
changed by this process. Inheritance is an essential part of object-oriented programming
(OOP). Its big payoff is that it permits code reusability. Once a base class is written
and debugged, it need not be touched again but, using inheritance, can nevertheless be
adapted to work in different situations. Reusing existing code saves time and money and
increases a program’s reliability.
Inheritance can also help in the original conceptualization of a programming problem,
and in the overall design of the program. An important result of reusability is the ease
of distributing class libraries. 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.
Let’s suppose that we have worked long and hard to make the Counter class operate
138
Chapter 5: Inheritance Object Oriented Programming
just the way we want, and we’re pleased with the results—except for one thing. We really
need a way to decrement the count. Perhaps we’re counting people entering a bank,
and we want to increment the count when they come in and decrement it when they go
out, so that the count represents the number of people in the bank at any moment.
We could insert a decrement routine directly into the source code of the Counter
class. However, there are several reasons that we might not want to do this. First, the
Counter class works very well and has undergone many hours of testing and debugging.
(Of course that’s an exaggeration in this case, but it would be true in a larger and more
complex class.) If we start fooling around with the source code for Counter, the testing
process will need to be carried out again, and of course we may foul something up and
spend hours debugging code that worked fine before we modified it.
In some situations there might be another reason for not modifying the Counter class:
We might not have access to its source code, especially if it was distributed as part of a
class library.
To avoid these problems, we can use inheritance to create a new class based on
Counter, without modifying Counter itself. Here’s the listing for COUNTEN, which includes
a new class, CountDn, that adds a decrement operator to the Counter class:
Listing 90: Inheritance with Counter Class
# include < iostream >
using namespace std ;
public :
Counter () : count (0) {} // no - arg constructor
Counter ( int c ) : count ( c ) {} // 1 - arg constructor
int main ()
{
CountDn c1 ; // c1 of class CountDn
cout << " \ nc1 = " << c1 . get_count () ; // display c1
++ c1 ; ++ c1 ; ++ c1 ; // increment c1 , 3 times
cout << " \ nc1 = " << c1 . get_count () ; // display it
-- c1 ; -- c1 ; // decrement c1 , twice
139
Chapter 5: Inheritance Object Oriented Programming
Following the Counter class in the listing is the specification for a new class, CountDn.
This class incorporates a new function, operator--(), which decrements the count.
However—and here’s the key point—the new CountDn class inherits all the features of the
Counter class. CountDn doesn’t need a constructor or the get count() or operator++()
functions, because these already exist in Counter.
The first line of CountDn specifies that it is derived from Counter:
Here we use a single colon (not the double colon used for the scope resolution operator),
followed by the keyword public and the name of the base class Counter. This sets up
the relationship between the classes. This line says that CountDn is derived from the base
class Counter.
140
Chapter 5: Inheritance Object Oriented Programming
The moral is that if you are writing a class that you suspect might be used, at any
point in the future, as a base class for other classes, then any member data that the
derived classes might need to access should be made protected rather than private.
This ensures that the class is “inheritance ready.”
141
Chapter 5: Inheritance Object Oriented Programming
Syntax:
class DerivedClassName : visibility_mode BaseClassName {
// additional members and functions
};
Here, visibility mode is usually public, protected, or private, and it controls
the accessibility of the base class members in the derived class.
Example: Consider the classes Counter and Counterdn where Counterdn is derived
from Counter:
public:
Counter() : count(0) {} // no-arg constructor
Counter(int c) : count(c) {} // 1-arg constructor
142
Chapter 5: Inheritance Object Oriented Programming
In this example:
• This means all public and protected members of Counter are accessible in Counterdn.
Is-a Relation The Is-a relationship represents inheritance. It means that a derived
class is a specialized type of the base class. This relationship is modeled using inheritance
in C++.
• The derived class inherits attributes and behaviors (data members and member
functions) from the base class.
143
Chapter 5: Inheritance Object Oriented Programming
class Car {
private :
Engine engine ; // Car has an Engine
public :
void startCar () { engine . start () ; }
};
Public Inheritance
• Public and protected members of the base class keep their access levels in the
derived class.
Protected Inheritance
• Public and protected members of the base class become protected members in the
derived class.
• This restricts access to base class members from outside the derived class.
Private Inheritance
• Public and protected members of the base class become private members in the
derived class.
• This means even the formerly public members are hidden from outside access
through the derived class.
144
Chapter 5: Inheritance Object Oriented Programming
Summary Table
1. Without Overriding (Separate Functions) Here, the base and derived classes
define different function names: getPerson(), getEmployee(), etc. There is no overrid-
ing.
Listing 93: No Overriding – Separate Functions
# include < iostream >
using namespace std ;
class Person {
protected :
string name ;
int age ;
public :
void getPerson () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
void showPerson () {
cout << " Name : " << name << " \ nAge : " << age << endl ;
}
};
145
Chapter 5: Inheritance Object Oriented Programming
int main () {
Employee e ;
e . getPerson () ;
e . getEmployee () ;
e . showPerson () ;
e . showEmployee () ;
}
2. With Member Overriding (Same Function Names) Here, both classes define
functions with the same name (getData(), showDetails()), and the derived version
overrides the base version. Note: no virtual is used.
Listing 94: Member Overriding – Same Function Names
# include < iostream >
using namespace std ;
class Person {
protected :
string name ;
int age ;
public :
void getData () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
void showDetails () {
cout << " Name : " << name << " \ nAge : " << age << endl ;
}
};
int main () {
146
Chapter 5: Inheritance Object Oriented Programming
Employee e ;
e . getData () ; // Calls Employee :: getData ()
e . showDetails () ; // Calls Employee :: showDetails ()
}
3. Using Scope Resolution to Access Base Class Function In this example, the
derived class uses Person::getData() to explicitly call the base class version from within
its own function.
Listing 95: Calling Base Class Method using Scope Resolution
# include < iostream >
using namespace std ;
class Person {
protected :
string name ;
int age ;
public :
void getData () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
};
int main () {
Employee e ;
e . getData () ;
e . showDetails () ;
}
Conclusion:
• Without overriding, different function names are used in base and derived classes.
147
Chapter 5: Inheritance Object Oriented Programming
• With overriding, same function names exist, and derived versions are preferred.
• Base class functions can be accessed using scope resolution syntax like BaseClass::function().
Note: Here’s the rule: When the same function exists in both the base class and the
derived class, the function in the derived class will be executed. (This is true of objects
of the derived class. Objects of the base class don’t know anything about the derived
class and will always use the base class functions.) We say that the derived class function
overrides the base class function.
Person
Employee
class base_classname2 {
// members of base_classname2
};
148
Chapter 5: Inheritance Object Oriented Programming
Person Department
Employee
class Person {
protected :
string name ;
int age ;
public :
void getPersonData () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
void showPersonData () {
cout << " Name : " << name << " \ nAge : " << age << endl ;
}
};
class Department {
protected :
string deptName ;
public :
void get Depart mentD ata () {
cout << " Enter department name : " ;
cin >> deptName ;
}
void s ho wD ep ar tm en tD at a () {
cout << " Department : " << deptName << endl ;
}
};
149
Chapter 5: Inheritance Object Oriented Programming
void showEmployeeData () {
showPersonData () ;
sh ow De pa rt me nt Da ta () ;
cout << " Employee ID : " << empID << " \ nSalary : " << salary <<
endl ;
}
};
int main () {
Employee e ;
e . getEmployeeData () ;
e . showEmployeeData () ;
}
Explanation:
• Employee inherits from both Person and Department using public inheritance.
• It combines attributes from both base classes along with its own.
• Functions from both base classes are used in the derived class to gather and display
full details.
class Person {
protected :
string name ;
int age ;
public :
void getData () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
void showData () {
cout << " Name : " << name << " \ nAge : " << age << endl ;
}
};
class Department {
protected :
string deptName ;
public :
void getData () {
cout << " Enter department name : " ;
cin >> deptName ;
150
Chapter 5: Inheritance Object Oriented Programming
}
void showData () {
cout << " Department : " << deptName << endl ;
}
};
void showEmployee () {
cout << " Employee ID : " << empID << " \ nSalary : " << salary <<
endl ;
}
};
int main () {
Employee e ;
// e . getData () ; // Ambiguous call
e . Person :: showData () ;
e . Department :: showData () ;
e . showEmployee () ;
return 0;
}
This ensures that the correct base class version of the function is invoked and ambi-
guity is eliminated.
151
Chapter 5: Inheritance Object Oriented Programming
Person
Employee
Manager
class Person {
protected :
string name ;
int age ;
public :
void getPersonData () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
void showPersonData () {
cout << " Name : " << name << " \ nAge : " << age << endl ;
}
};
152
Chapter 5: Inheritance Object Oriented Programming
}
};
int main () {
Manager m ;
m . getManagerData () ;
m . showManagerData () ;
return 0;
}
Person
Employee Manager
class Person {
protected :
string name ;
int age ;
public :
void getPersonData () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
153
Chapter 5: Inheritance Object Oriented Programming
void showPersonData () {
cout << " Name : " << name << " \ nAge : " << age << endl ;
}
};
int main () {
Employee e ;
Manager m ;
e . getEmployeeData () ;
e . showEmployeeData () ;
m . getManagerData () ;
m . showManagerData () ;
return 0;
}
154
Chapter 5: Inheritance Object Oriented Programming
Person Department
Employee
Manager
class Person {
protected :
string name ;
int age ;
public :
void getPersonData () {
cout << " Enter name : " ;
cin >> name ;
cout << " Enter age : " ;
cin >> age ;
}
void showPersonData () {
cout << " Name : " << name << " \ nAge : " << age << endl ;
}
};
class Department {
protected :
string deptName ;
public :
void get Depart mentD ata () {
cout << " Enter department name : " ;
cin >> deptName ;
}
void s ho wD ep ar tm en tD at a () {
cout << " Department : " << deptName << endl ;
}
};
155
Chapter 5: Inheritance Object Oriented Programming
float salary ;
public :
void getEmployeeData () {
getPersonData () ;
cout << " Enter employee ID : " ;
cin >> empID ;
cout << " Enter salary : " ;
cin >> salary ;
}
void showEmployeeData () {
showPersonData () ;
cout << " Employee ID : " << empID << " \ nSalary : " << salary <<
endl ;
}
};
int main () {
Manager m ;
m . getManagerData () ;
m . showManagerData () ;
return 0;
}
156
Chapter 5: Inheritance Object Oriented Programming
class A {
public :
A () {
cout << " Base class A constructor called " << endl ;
}
};
class B : public A {
public :
B () {
cout << " Derived class B constructor called " << endl ;
}
};
int main () {
B obj ;
return 0;
}
Output:
Base class A constructor called
Derived class B constructor called
When object obj of class B is created, the constructor of A is called first automatically,
then the constructor of B.
class A {
public :
A () {
cout << " Base class A constructor called " << endl ;
}
};
class B {
public :
B () {
cout << " Base class B constructor called " << endl ;
}
};
157
Chapter 5: Inheritance Object Oriented Programming
int main () {
C obj ;
return 0;
}
Output:
The base classes A and B are listed in that order in the declaration of C. Therefore,
constructors of A and B are called in that sequence before the constructor of C.
class A {
public :
A ( int x ) {
cout << " Base class A constructor called with x = " << x <<
endl ;
}
};
class B : public A {
public :
B ( int y , int x ) : A ( x ) {
cout << " Derived class B constructor called with y = " << y <<
endl ;
}
};
int main () {
B obj (5 ,4) ;
return 0;
}
• The derived class B passes the value of x to A’s constructor using an initialization
list: B(int y, int x): A(x).
158
Chapter 5: Inheritance Object Oriented Programming
Derived class constructors must use initialization lists to explicitly call base class
constructors when they are parameterized.
In multiple inheritance, the derived class must use an initialization list to pass argu-
ments to all base class constructors. The base class constructors are called in the order
of their appearance in the class declaration — not the order in the initialization list.
Listing 105: Multiple Inheritance with Constructor Arguments
# include < iostream >
using namespace std ;
class A {
public :
A ( int x ) {
cout << " Base class A constructor called with x = " << x <<
endl ;
}
};
class B {
public :
B ( int y ) {
cout << " Base class B constructor called with y = " << y <<
endl ;
}
};
int main () {
C obj (1 , 2 , 3) ;
return 0;
}
159
Chapter 5: Inheritance Object Oriented Programming
class A {
public :
A () { cout << " Constructor of A \ n " ; }
~ A () { cout << " Destructor of A \ n " ; }
};
class B : public A {
public :
B () { cout << " Constructor of B \ n " ; }
~ B () { cout << " Destructor of B \ n " ; }
};
int main () {
B obj ;
return 0;
}
Constructor of A
Constructor of B
Destructor of B
Destructor of A
class A {
public :
A () { cout << " Constructor of A \ n " ; }
~ A () { cout << " Destructor of A \ n " ; }
};
class B {
public :
B () { cout << " Constructor of B \ n " ; }
~ B () { cout << " Destructor of B \ n " ; }
};
160
Chapter 5: Inheritance Object Oriented Programming
};
int main () {
C obj ;
return 0;
}
Constructor of A
Constructor of B
Constructor of C
Destructor of C
Destructor of B
Destructor of A
• This ensures proper cleanup starting from the most derived class.
• In multiple inheritance, base class constructors are called in the order they appear
in the inheritance list. Destructors are called in the reverse of that order.
Person
Employee Student
Intern
class Person {
protected :
string name ;
public :
161
Chapter 5: Inheritance Object Oriented Programming
void getName () {
cout << " Enter name : " ;
cin >> name ;
}
void showName () {
cout << " Name : " << name << endl ;
}
};
void showIntern () {
showName () ;
showEmployee () ;
showStudent () ;
}
};
int main () {
Intern i ;
i . getIntern () ;
i . showIntern () ;
return 0;
}
162
Chapter 5: Inheritance Object Oriented Programming
to avoid ambiguity.
• The base class Person contains a member function getName() that collects the
name of a person.
• Two classes, Employee and Student, inherit from Person using virtual public
inheritance. This makes Person a virtual base class.
• The Intern class inherits from both Employee and Student, forming a diamond-
shaped inheritance hierarchy.
If we inherit Person normally (without the virtual keyword), then both Employee
and Student will maintain their own separate copies of the Person class. This results in
two copies of the Person members in the Intern class, which leads to ambiguity:
Intern i ;
i . getName () ; // Error : ambiguous - two paths to getName ()
The compiler ensures that there is only one shared copy of the Person class in the
entire inheritance chain. As a result, when the Intern class inherits from both Employee
and Student, it receives only one unique instance of the Person class, avoiding
ambiguity.
When calling i.getName() in the Intern object, the compiler uses the single shared
instance of Person:
This resolves the ambiguity and ensures that getName() is called safely without re-
quiring explicit path specification.
Multipath inheritance can lead to ambiguity when a base class is inherited more than
once through different paths. This is resolved using virtual inheritance, which ensures
only one shared copy of the base class exists in the derived class hierarchy.
163
Chapter 6: Virtual Functions Object Oriented Programming
If you insert pointers to all the shapes into this array, you can then draw an entire picture
using a simple loop:
This is an amazing capability: Completely different functions are executed by the same
function call. If the pointer in ptrarr points to a ball, the function that draws a ball is
called; if it points to a triangle, the triangle-drawing function is called.
This is called polymorphism, which means different forms. The functions have
the same appearance, the draw() expression, but different actual functions are called,
depending on the contents of ptrarr[j]. Polymorphism is one of the key features of
object-oriented programming, after classes and inheritance.
For the polymorphic approach to work, several conditions must be met. First, all the
different classes of shapes, such as balls and triangles, must be descended from a single
base class (called shape). Second, the draw() function must be declared to be virtual
in the base class. This is all rather abstract, so let’s start with some short programs that
show parts of the situation, and put everything together later.
Listing 109: Normal Functions Accessed from Pointer
# include < iostream >
using namespace std ;
164
Chapter 6: Virtual Functions Object Oriented Programming
void show ()
{ cout << " Derv1 \ n " ; }
};
int main ()
{
Derv1 dv1 ; // object of derived class 1
Derv2 dv2 ; // object of derived class 2
Base * ptr ; // pointer to base class
return 0;
}
The Derv1 and Derv2 classes are derived from class Base. Each of these three classes has
a member function show(). In main() we create objects of class Derv1 and Derv2, and
a pointer to class Base. Then we put the address of a derived class object in the base
class pointer in the line:
But wait—how can we get away with this? Doesn’t the compiler complain that we’re
assigning an address of one type (Derv1) to a pointer of another (Base)? On the contrary,
the compiler is perfectly happy, because type checking has been relaxed in this situation,
for reasons that will become apparent soon.
The rule is that pointers to objects of a derived class are type-compatible with pointers
to objects of the base class.
Now the question is, when you execute the line:
ptr->show();
ptr->show();
Which of the show() functions is called here? The output from the program answers
these questions:
Base
Base
165
Chapter 6: Virtual Functions Object Oriented Programming
As you can see, the function in the base class is always executed. The compiler ignores
the contents of the pointer ptr and chooses the member function that matches the type
of the pointer, as shown in Figure 62.
Sometimes this is what we want, but it doesn’t solve the problem posed at the beginning
of this section: accessing objects of different classes using the same statement.
Let’s make a single change in our program: We’ll place the keyword virtual in front of
the declarator for the show() function in the base class.
Listing 110: Using virtual function for polymorphism
# include < iostream >
using namespace std ;
class Base // base class
{
public :
virtual void show () // virtual function
{ cout << " Base \ n " ; }
};
class Derv1 : public Base // derived class 1
{
public :
void show ()
{ cout << " Derv1 \ n " ; }
};
class Derv2 : public Base // derived class 2
{
public :
void show ()
{ cout << " Derv2 \ n " ; }
166
Chapter 6: Virtual Functions Object Oriented Programming
};
int main ()
{
Derv1 dv1 ; // object of derived class 1
Derv2 dv2 ; // object of derived class 2
Base * ptr ; // pointer to base class
return 0;
}
167
Chapter 6: Virtual Functions Object Oriented Programming
ptr->show();
It always compiles a call to the show() function in the base class. But in Second Program,
the compiler doesn’t know what class the contents of ptr may contain. It could be the
address of an object of the Derv1 class or of the Derv2 class. Which version of draw()
does the compiler call?
In fact, the compiler doesn’t know what to do, so it arranges for the decision to be deferred
until the program is running. At runtime, when it is known what class is pointed to by
ptr, the appropriate version of draw() will be called.
This is called late binding or dynamic binding. (Choosing functions in the normal
way, during compilation, is called early binding or static binding.) Late binding
requires some overhead but provides increased power and flexibility.
class Base {
public :
virtual void show () {
168
Chapter 6: Virtual Functions Object Oriented Programming
int main () {
Base * ptrarr [3]; // Array of pointers to Base
Derv1 obj1 ;
Derv2 obj2 ;
Base obj3 ;
return 0;
}
Derv1
Derv2
Base
This demonstrates that although the array holds pointers to the base class, the appro-
priate overridden functions in the derived classes are called at runtime due to the use of
virtual functions. This mechanism is known as polymorphism.
169
Chapter 6: Virtual Functions Object Oriented Programming
This is done by declaring at least one pure virtual function in the base class. A pure
virtual function is declared by assigning = 0 to its declaration. For example, in the shape
class, we can declare two pure virtual functions, getArea() and getPerimeter(), which
derived classes must override:
Listing 112: Abstract class shape with pure virtual functions
class shape {
public :
virtual double getArea () = 0; // pure virtual function
virtual double getPerimeter () = 0; // pure virtual function
};
Derived classes must provide implementations for these functions. Here is an example
with circle and rectangle classes:
Listing 113: Derived classes implementing pure virtual functions
# include < iostream >
# include < cmath >
using namespace std ;
class shape {
public :
virtual double getArea () = 0;
virtual double getPerimeter () = 0;
};
int main () {
circle c (5.0) ;
rectangle r (4.0 , 6.0) ;
170
Chapter 6: Virtual Functions Object Oriented Programming
class shape {
public :
virtual double getArea () = 0;
virtual double getPerimeter () = 0;
virtual ~ shape ()
{ cout < < " shape destructor " << endl ; }
};
171
Chapter 6: Virtual Functions Object Oriented Programming
int main () {
shape * shapes [2];
shapes [0] = new circle (5.0) ;
shapes [1] = new rectangle (4.0 ,6.0) ;
class where {
private :
char charray [10]; // occupies 10 bytes
public :
void reveal () {
cout << " \ nMy object 's address is " << this ;
}
};
int main () {
where w1 , w2 , w3 ; // make three objects
w1 . reveal () ; // see where they are
w2 . reveal () ;
w3 . reveal () ;
cout << endl ;
return 0;
}
The main() function creates three objects of the class where and calls the reveal()
function for each of them. The function prints the address of the current object by
using the this pointer, which is an implicit pointer to the calling object inside a member
function.
Below is an example output showing the memory addresses of the objects:
172
Chapter 6: Virtual Functions Object Oriented Programming
Since the data in each object consists of an array of 10 bytes, the objects are spaced 10
bytes apart in memory. (EC minus E2 is 10 decimal, as is E2 minus D8.) Some compilers
may place extra bytes in objects, making them slightly larger than 10 bytes.
class Simple {
private :
int alpha ;
public :
Simple ( int a ) {
this - > alpha = a ; // explicitly using ' this '
}
void tester () {
cout << " Value of alpha is : " << this - > alpha << endl ;
}
};
int main () {
Simple obj (11) ;
obj . tester () ;
return 0;
}
class alpha {
private :
int data ;
public :
alpha () { } // no - arg constructor
alpha ( int d ) { data = d ; } // one - arg constructor
void display () {
cout << data ;
173
Chapter 6: Virtual Functions Object Oriented Programming
int main () {
alpha a1 (37) ;
alpha a2 , a3 ;
a3 = a2 = a1 ;
cout << " \ na2 = " ; a2 . display () ; // display a2
cout << " \ na3 = " ; a3 . display () ; // display a2
cout << endl ;
return 0;
}
Since this is a pointer to the object of which the function is a member, *this is that
object itself, and the statement returns it by reference.
Each time the equal sign is encountered in the expression
a3 = a2 = a1;
the overloaded operator=() function is called, which prints the messages. The three
objects all end up with the same value.
You usually want to return by reference from overloaded assignment operators, using
*this, to avoid the creation of extra objects.
class Student {
private :
string name ;
int roll ;
public :
Student ( string name , int roll ) {
this - > name = name ; // ' this ' resolves ambiguity
this - > roll = roll ;
}
void display () {
cout << " Name : " << name << " , Roll : " << roll << endl ;
}
};
174
Chapter 6: Virtual Functions Object Oriented Programming
int main () {
Student s1 ( " Alice " , 101) ;
s1 . display () ;
return 0;
}
In the above code, the this pointer refers to the current object and helps distinguish
between the constructor’s parameters and the class’s data members.
• Used for low-level casts that yield implementation-defined and potentially unsafe
results.
• Typically used to cast between unrelated pointer types or between integer and
pointer types.
• Should be used with extreme caution, as it can easily result in undefined behavior.
• Unlike static cast, it does not perform any safety checks at compile time.
Syntax:
reinterpret_cast<new_type>(expression)
int main () {
int a = 65;
char * ptr = reinterpret_cast < char * >(& a ) ;
cout << " Integer a = " << a << endl ;
cout << " Reinterpreted as char = " << * ptr << endl ;
return 0;
}
Output:
Integer a = 65
Reinterpreted as char = A
175
Chapter 6: Virtual Functions Object Oriented Programming
• typeid operator
These are advanced capabilities, typically used when working with a variety of classes
that are descended (sometimes in complex ways) from a common base class.
The dynamic cast operator safely converts pointers and references to classes up and
down the inheritance hierarchy. It checks the validity of the cast at runtime, ensuring
type safety. If the cast is invalid, it returns a null pointer (in the case of pointers) or
throws a std::bad cast exception (for references).
Important: For dynamic cast to work, the base class must be polymorphic—it must
have at least one virtual function.
The typeid operator allows you to determine the exact type of an object at runtime.
It returns a reference to a type info object, which can be used to compare types or
extract type names. You must include the standard template library header typeinfo to
use the typeid operator.
Syntax of dynamic case:
pointer_to_derived = dynamic_cast<DerivedClass*>(pointer_to_base);
reference_to_derived = dynamic_cast<DerivedClass&>(reference_to_base);
The dynamic cast operator allows you to cast upward and downward in the inheritance
tree. However, it allows such casting only in limited ways.
Syntax of typeid:
typeid(expression)
class Base {
protected :
int ba ;
public :
Base () : ba (0) { }
Base ( int b ) : ba ( b ) { }
virtual void vertFunc () { } // Required for RTTI
void show () {
cout << " Base : ba = " << ba << endl ;
}
};
176
Chapter 6: Virtual Functions Object Oriented Programming
int da ;
public :
Derv ( int b , int d ) : Base ( b ) , da ( d ) {
}
void show () {
cout << " Derv : ba = " << ba << " , da = " << da << endl ;
}
};
int main () {
Base * pBase = new Base (10) ;
Derv * pDerv = new Derv (21 , 22) ;
return 0;
}
• dynamic cast ensures type-safe conversion between base and derived pointers.
• Downcasting requires that the base pointer actually points to a derived object;
otherwise, the cast fails.
class Base {
public :
virtual void show () { cout << " Base class \ n " ; }
};
int main () {
Base * b1 = new Base () ;
177
Chapter 6: Virtual Functions Object Oriented Programming
cout << " Type of b1 : " << typeid (* b1 ) . name () << endl ;
cout << " Type of b2 : " << typeid (* b2 ) . name () << endl ;
delete b1 ;
delete b2 ;
return 0;
}
Sample Output
Type of b1: 4Base
Type of b2: 7Derived
• typeid(*b1) returns the type of the object b1 points to, which is Base.
• typeid(*b2) returns the type of the object b2 points to, which is Derived, even
though the pointer type is Base*.
• Without a virtual function in the base class, both typeid(*b1) and typeid(*b2)
would return Base, due to static binding.
178
Chapter 7: Stream Computation Object Oriented Programming
• cin is an object of class istream, used for input from standard input (usually the
keyboard).
• cout is an object of class ostream, used for output to standard output (usually the
screen).
C programmers may wonder what advantages there are to using the stream classes for
I/O instead of traditional C functions such as printf() and scanf(), and—for files—
fprintf(), fscanf(), and so on.
Another advantage is that you can overload existing operators and functions,
such as the insertion (<<) and extraction (>>) operators, to work with classes that you
create. This allows your own classes to behave in the same way as built-in types, mak-
ing programming easier, more consistent, and less error-prone—not to mention more
aesthetically satisfying.
You may wonder whether stream I/O is important if you plan to program in an
environment with a graphical user interface (GUI), such as Windows, where direct text
output to the screen is not commonly used. Should you still learn about C++ streams?
Yes, because they are the best way to:
179
Chapter 7: Stream Computation Object Oriented Programming
We’ve already made extensive use of some stream classes. The extraction operator >>
is a member of the std::istream class, and the insertion operator << is a member of the
std::ostream class. Both of these classes are derived from the std::ios class, which in
turn is derived from std::ios base. The std::cout object, representing the standard
output stream, which is usually directed to the video display, is a predefined object of
the std::ostream class. Similarly, std::cin is a predefined object of the std::istream
class.
The classes used for input and output to the video display and keyboard are declared
in the header file <iostream>, which we have routinely included in previous examples.
The classes used specifically for disk file I/O are declared in the header file <fstream>.
Figure 65 illustrates which classes belong to these header files.
Additionally, some manipulators (such as std::setw(), std::setprecision(), etc.)
are declared in the <iomanip> header, which is used for controlling the format of input
and output.
If you are curious about the internal structure of these stream classes, it can be educa-
tional to explore the source or documentation of these headers provided by your compiler
in its include directory. Many questions about stream behavior and functionality can
be answered by examining the class definitions, inheritance relationships, and constant
declarations.
The istream and ostream classes are derived from the ios class and are dedicated
to input and output operations, respectively.
• The istream class handles input operations. It provides member functions such as:
180
Chapter 7: Stream Computation Object Oriented Programming
• The ostream class handles output operations. It provides functions such as:
These classes form the foundation of stream-based I/O in C++, enabling both low-
level and high-level data handling in a consistent and extensible manner. The iostream
class is derived from both istream and ostream using multiple inheritance. This
allows it to support both input and output operations simultaneously.
Classes derived from iostream can be used with devices that support bidirectional
data flow, such as disk files that are opened for both reading and writing.
For example, the fstream class is derived from iostream and enables reading from
and writing to the same file within a single program, using the same stream object.
However, as you may have discovered, this approach assumes that nothing will go
wrong during the I/O process. Unfortunately, this isn’t always the case, especially with
input.
What happens if a user enters the string "nine" instead of the integer 9? Or presses
the Enter key without entering anything? Or what if there’s a hardware failure?
In this section, we will explore how to handle such problems using the error-handling
capabilities of C++ streams. Many of the techniques discussed here are also applicable
to file input and output operations.
181
Chapter 7: Stream Computation Object Oriented Programming
int main () {
int number ;
while ( true ) {
cout << " Enter an integer : " ;
cin >> number ;
if ( cin . good () ) {
break ; // Valid input , exit loop
}
cout << " You entered : " << number << endl ;
182
Chapter 7: Stream Computation Object Oriented Programming
return 0;
}
The most common error this scheme detects when reading keyboard input is the user
typing nondigits (for instance, “nine” instead of “9”). This causes the failbit to be set.
However, it also detects system-related failures that are more common with disk files.
Syntax:
• To read a character:
cin.get(var);
• To read a line:
cin.getline(array, size);
• To write a character:
cout.put(char);
int main () {
char ch ;
183
Chapter 7: Stream Computation Object Oriented Programming
return 0;
}
int main () {
char str [50];
return 0;
}
There are several ways to set the formatting flags, and different ones can be set in
different ways. Since they are members of the ios class, you must usually precede them
with the name ios and the scope-resolution operator (for example, ios::skipws).
184
Chapter 7: Stream Computation Object Oriented Programming
All the flags can be set using the setf() and unsetf() ios member functions. Look
at the following example:
Many formatting flags can be set using manipulators, so let’s look at them now.
Manipulators are formatting instructions inserted directly into a stream. We’ve seen
examples before, such as the manipulator endl, which sends a newline to the stream and
flushes it:
As these examples demonstrate, manipulators come in two flavors: those that take
an argument and those that don’t. Table 12.2 summarizes the important no-argument
manipulators.
You insert these manipulators directly into the stream. For example, to output var
in hexadecimal format, you can write:
Note that manipulators affect only the data that follows them in the stream, not the
data that precedes them. Table 12.3 summarizes the important manipulators that take
arguments. You need the <iomanip> header file for these functions.
185
Chapter 7: Stream Computation Object Oriented Programming
The ios class contains a number of functions that you can use to set the formatting
flags and perform other tasks. Table 12.4 shows most of these functions, except those
that deal with errors, which we’ll examine separately.
These functions are called for specific stream objects using the normal dot operator.
For example, to set the field width to 14, you can write:
cout.width(14);
The following statement sets the fill character to an asterisk (as for check printing):
cout.fill('*');
You can use several functions to manipulate the ios formatting flags directly. For
example, to set left justification, use:
cout.setf(ios::left);
cout.unsetf(ios::left);
186
Chapter 7: Stream Computation Object Oriented Programming
A two-argument version of setf() uses the second argument to reset all the flags
of a particular type or field. Then the flag specified in the first argument is set. This
makes it easier to reset the relevant flags before setting a new one. Table 12.5 shows the
arrangement.
For example:
cout.setf(ios::left, ios::adjustfield);
clears all the flags dealing with text justification and then sets the left flag for left-
justified output.
By using the techniques shown here with the formatting flags, you can usually figure
out a way to format I/O not only for the keyboard and display, but, as we’ll see later in
this chapter, for files as well.
The following program reads a decimal number from the user and displays its equiva-
lent hexadecimal and octal representations. It uses the setf() member function of cout
with the ios::basefield mask to safely set the numeric base format for output.
# include < iostream >
using namespace std ;
int main () {
int decimalNumber ;
return 0;
}
187
Chapter 7: Stream Computation Object Oriented Programming
The left and right formatting flags are used to align the text within a specified
width. Here, the same text is printed twice — first left-justified and then right-justified
— both within a width of 50 characters.
// Program to demonstrate left and right justification
int main () {
string text = " Justify this text " ;
// Left justification
cout . setf ( ios :: left , ios :: adjustfield ) ;
cout << setw (50) << text << endl ;
// Right justification
cout . setf ( ios :: right , ios :: adjustfield ) ;
cout << setw (50) << text << endl ;
return 0;
}
Output
int main () {
cout . width (50) ;
cout . setf ( ios :: left ) ;
cout << " This text is left justified . " << endl ;
return 0;
}
Output
188
Chapter 7: Stream Computation Object Oriented Programming
The precision() function in C++ is used to control the number of significant digits
displayed for floating-point numbers. This function is particularly useful when we want
to limit or standardize the output format of decimal numbers. The following program
demonstrates how to use precision() to display a floating-point number with varying
levels of precision.
Listing 117: Display Floating-Point Number Using precision()
# include < iostream >
using namespace std ;
int main () {
double num = 123.456789;
cout << " Default precision : " << num << endl ;
return 0;
}
int main () {
double num = 12345.6789;
// Default format
cout << " Default format : " << num << endl ;
// Scientific format
cout . setf ( ios :: scientific , ios :: floatfield ) ;
cout << " Scientific format : " << num << endl ;
// Fixed format
cout . setf ( ios :: fixed , ios :: floatfield ) ;
cout << " Fixed format : " << num << endl ;
return 0;
}
189
Chapter 7: Stream Computation Object Oriented Programming
The setw() manipulator in C++ sets the width of the next output field. It is com-
monly used to align output in columns or format text neatly. The following example
demonstrates how setw() affects the display of numbers and strings.
Listing 119: Illustration of setw() Usage
# include < iostream >
# include < iomanip > // Required for setw
using namespace std ;
int main () {
cout << " Without setw : " << endl ;
cout << 123 << " " << 4567 << endl ;
cout << " \ nWith setw (10) and left justification : " << endl ;
cout << left ;
cout << setw (10) << 123 << " " << setw (10) << 4567 << endl ;
return 0;
}
Without setw:
123 4567
With setw(10):
123 4567
The setfill() manipulator in C++ is used to specify the character that fills the
unused spaces when setting a field width using setw(). This helps in formatting output
by replacing the default space character with a custom fill character. The following
program demonstrates this concept.
Listing 120: Illustration of setfill() Usage
# include < iostream >
# include < iomanip > // Required for setw and setfill
using namespace std ;
int main () {
cout << " Default fill character ( space ) : " << endl ;
cout << setw (10) << 123 << endl ;
cout << " \ nUsing setfill ( '* ') : " << endl ;
cout << setfill ( '* ') << setw (10) << 123 << endl ;
190
Chapter 7: Stream Computation Object Oriented Programming
cout << " \ nUsing setfill ( '# ') with left justification : " << endl ;
cout << setfill ( '# ') << left << setw (10) << 123 << endl ;
return 0;
}
Using setfill('*'):
*******123
int main () {
double pi = 3 . 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 ;
return 0;
}
191
Chapter 8: Templates Object Oriented Programming
Chapter 8: Templates
192
Chapter 9: Exception Handling Object Oriented Programming
193
REFERENCES Object Oriented Programming
References
[1] R. Lafore, Object-Oriented Programming in C++, 4th ed. Indianapolis, IN, USA:
Sams Publishing, 2002.
194