Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
84 views

C++ Tutorial

This document discusses the advantages and disadvantages of object-oriented programming (OOP). Some key advantages include improved productivity, maintainability, and reusability due to OOP principles like modularity, extensibility, and reusability. Some disadvantages include a steeper learning curve, larger program size, and slower program execution compared to procedural programming. Popular OOP languages include Java and C++.

Uploaded by

Musariri Talent
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
84 views

C++ Tutorial

This document discusses the advantages and disadvantages of object-oriented programming (OOP). Some key advantages include improved productivity, maintainability, and reusability due to OOP principles like modularity, extensibility, and reusability. Some disadvantages include a steeper learning curve, larger program size, and slower program execution compared to procedural programming. Popular OOP languages include Java and C++.

Uploaded by

Musariri Talent
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 250

Advantages and Disadvantages of Object-Oriented Programming (OOP)

This reading discusses advantages and disadvantages of object-oriented programming, which is a


well-adopted programming style that uses interacting objects to model and solve complex
programming tasks. Two examples of popular object-oriented programming languages are Java
and C++.

Some of the advantages of object-oriented programming include:


1. Improved software-development productivity: Object-oriented programming is modular, as it
provides separation of duties in inobject-based program development. It is also extensible, as
objects can be extended to include new attributes and behaviors. Objects can also be reused
within an across applications. Because of these three factors – modularity, extensibility, and
reusability – object-oriented programming provides improved software-development
productivity over traditional procedure-based programming techniques.

2. Improved software maintainability: For the reasons mentioned above, object oriented software
is also easier to maintain. Since the design is modular, part of the system can be updated in case
of issues without a need to make large-scale changes.

3. Faster development: Reuse enables faster development. Object-oriented programming


languages come with rich libraries of objects, and code developed during projects is also
reusable in future projects.

4. Lower cost of development: The reuse of software also lowers the cost of development.
Typically, more effort is put into the object-oriented analysis and design, which lowers the
overall cost of development.

5. Higher-quality software: Faster development of software and lower cost of development


allows more time and resources to be used in the verification of the software. Although quality is
dependent upon the experience of the teams, object oriented programming tends to result in
higher-quality software.

Compiled By B T Chisuwa Page 1


Some of the disadvantages of object-oriented programming include:
1. Steep learning curve: The thought process involved in object-oriented programming may not
be natural for some people, and it can take time to get used to it. It is complex to create
programs based on interaction of objects. Some of the key programming techniques, such as
inheritance and polymorphism, can be challenging to comprehend initially.

2. Larger program size: Object-oriented programs typically involve more lines of code than
procedural programs.

3. Slower programs: Object-oriented programs are typically slower than procedure based
programs, as they typically require more instructions to be executed.

4. Not suitable for all types of problems: There are problems that lend themselves well to
functional-programming style, logic-programming style, or procedure-based programming
style, and applying object-oriented programming in those situations will not result in efficient
programs.

STRUCTURE OF A PROGRAM
Typically, the first program beginners write is a program called "Hello World", which simply
prints "Hello World" to your computer screen. Although it is very simple, it contains all the
fundamental components C++ programs have:

1 // my first program in C++


2 #include <iostream>
3 Using namespace std; Hello World!
4
5 int main()
6 {
7 cout << "Hello World!";
8 return 0;
9 }

Compiled By B T Chisuwa Page 2


The left panel above shows the C++ code for this program. The right panel shows the result
when the program is executed by a computer. The grey numbers to the left of the panels are line
numbers to make discussing programs and researching errors easier. They are not part of the
program.

Line 1: // my first program in C++

Two slash signs indicate that the rest of the line is a comment inserted by the programmer
but which has no effect on the behavior of the program. Programmers use them to include
short explanations or observations concerning the code or program. In this case, it is a
brief introductory description of the program.

Line 2: #include <iostream>


Lines beginning with a hash sign (#) are directives for the preprocessor. They are not regular
code lines with expressions but indications for the compiler's preprocessor. In this case the
directive #include <iostream> tells the preprocessor to include the iostream standard file. This
specific file (iostream) includes the declarations of the basic standard input-output library in
C++, and it is included because its functionality is going to be used later in the program.

Line 3: Using namespace std;


std is an abbreviation of standard. std is the standard namespace. cout, cin and a lot of other
things are defined in it. All the elements of the standard C++ library are declared within what is
called a namespace, the namespace with the name std. So in order to access its functionality we
declare with this expression that we will be using these entities. This line is very frequent in C++
programs that use the standard library, and in fact it will be included in most of the source codes
included in these tutorials.

Line 4: A blank line.


Blank lines have no effect on a program. They simply improve readability of the code.

Line 5: int main ()

Compiled By B T Chisuwa Page 3


This line corresponds to the beginning of the definition of the main function. The main function
is the point by where all C++ programs start their execution, independently of its location within
the source code. It does not matter whether there are other functions with other names defined
before or after it – the instructions contained within this function's definition will always be the
first ones to be executed in any C++ program. For that same reason, it is essential that all C++
programs have a main function.

The word main is followed in the code by a pair of parentheses (()). That is because it is a
function declaration: In C++, what differentiates a function declaration from other types of
expressions are these parentheses that follow its name. Optionally, these parentheses may
enclose a list of parameters within them.

Lines 6 and 9: { and }


The open brace ({) at line 5 indicates the beginning of main's function definition, and the closing
brace (}) at line 9, indicates its end. Everything between these braces is the function's body that
defines what happens when main is called. All functions use braces to indicate the beginning and
end of their definitions.

Line 7: cout << "Hello World!";


This line is a C++ statement. A statement is an expression that can actually produce some effect.
It is the meat of a program, specifying its actual behavior. Statements are executed in the same
order that they appear within a function's body.

This statement has three parts: First, cout, which identifies the standard character output device
(usually, this is the computer screen). Second, the insertion operator (<<), which indicates that
what follows is inserted into cout. Finally, a sentence within quotes ("Hello world!"), is the
content inserted into the standard output.

Notice that the statement ends with a semicolon (;). This character marks the end of the
statement, just as the period ends a sentence in English. All C++ statements must end with a

Compiled By B T Chisuwa Page 4


semicolon character. One of the most common syntax errors in C++ is forgetting to end a
statement with a semicolon.

Line 8: return 0;
The return statement causes the main function to finish. Return may be followed by a return code
(in our example is followed by the return code 0). A return code of 0 for the main function is
generally interpreted as the program worked as expected without any errors during its execution.
This is the most usual way to end a C++ console program.

Compiled By B T Chisuwa Page 5


COMMENTS

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

C++ supports two ways to insert comments:

// line comment
/* block comment */

The first of them, known as line comment, discards everything from where the pair of slash signs
(//) is found up to the end of that same line. The second one, known as block comment, discards
everything between the /* characters and the first appearance of the */ characters, with the
possibility of including more than one line. We are going to add comments to our second
program:

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

Compiled By B T Chisuwa Page 6


Semicolons & Blocks in C++:
In C++, the semicolon is a statement terminator. That is, each individual statement must be
ended with a semicolon. It indicates the end of one logical entity.

For example, following are three different statements:


x = y;
y = y+1;
add(x, y);

A block is a set of logically connected statements that are surrounded by opening and closing
braces. For example:
{
cout <<"Hello World"; // prints Hello World
return 0;
}

C++ does not recognize the end of the line as a terminator. For this reason, it does not matter
where on a line you put a statement. For example:
x = y;
y = y+1;
add(x, y);

is the same as
x = y; y = y+1; add(x, y);

Compiled By B T Chisuwa Page 7


TOKENS

As we know, the smallest individual units in a program are known as tokens. C++ has the
following tokens:
• Keywords
• Identifiers
• Constants
• Strings
• Operators

A C++ program is written using these tokens, white spaces, and the syntax of the language. Most
of the C++ tokens are basically similar to the C tokens with the exception of some additions and
minor modifications.

Compiled By B T Chisuwa Page 8


C++ KEYWORDS:

The following list shows the reserved words in C++. These reserved words may not be used as
constant or variable or any other identifier names.

Asm else new this


Auto enum operator throw
Bool explicit private true
Break export protected try
Case extern public typedef
Catch false register typeid
Char float reinterpret_cast typename
Class for return union
Const friend short unsigned
const_cast goto signed using
continue If sizeof virtual
Default inline Static void
Delete int static_cast volatile
Do long Struct wchar_t
Double mutable Switch while
dynamic_cast namespace Template

Compiled By B T Chisuwa Page 9


WHITESPACE IN C++:

A line containing only whitespace, possibly with a comment, is known as a blank line, and C++
compiler totally ignores it.
Whitespace is the term used in C++ to describe blanks, tabs, newline characters and comments.
Whitespace separates one part of a statement from another and enables the compiler to identify
where one element in a statement, such as int, ends and the next element begins. Therefore, in
the statement,
int age; .

there must be at least one whitespace character (usually a space) between int and age for the
compiler to be able to distinguish them. On the other hand, in the statement,
fruit = apples + oranges;// Get the total fruit .

no whitespace characters are necessary between fruit and =, or between = and apples, although
you are free to include some if you wish for readability purpose.

Compiled By B T Chisuwa Page 10


DATA TYPES

Primitive Built-in Types:


C++ offer the programmer a rich assortment of built-in as well as user defined data types.
Following table lists down seven basic C++ data types:
Type Keyword
Boolean bool
Character char
Integer int
Floating point float
Double floating point double
Valueless void
Wide character wchar_t

Several of the basic types can be modified using one or more of these type modifiers:
• signed
• unsigned
• short
• long

The following table shows the variable type, how much memory it takes to store the value in
memory, and what is maximum and minimum vaue, which can be stored in such type of
variables.

Compiled By B T Chisuwa Page 11


Type Typical Bit Width Typical Range
char 1byte -127 to 127 or 0 to 255
unsigned char 1byte 0 to 255
signed char 1byte -127 to 127
int 4bytes -2147483648 to 2147483647
unsigned int 4bytes 0 to 4294967295
signed int 4bytes -2147483648 to 2147483647
short int 2bytes -32768 to 32767
unsigned short int Range 0 to 65,535
signed short int Range -32768 to 32767
long int 4bytes -2,147,483,647 to 2,147,483,647
signed long int 4bytes same as long int
unsigned long int 4bytes 0 to 4,294,967,295
float 4bytes +/- 3.4e +/- 38 (~7 digits)
double 8bytes +/- 1.7e +/- 308 (~15 digits)
long double 8bytes +/- 1.7e +/- 308 (~15 digits)
wchar_t 2 or 4 bytes 1 wide character

The sizes of variables might be different from those shown in the above table, depending on the
compiler and the computer you are using.
Following is the example, which will produce correct size of various data types on your
computer.
#include<iostream>
usingnamespace std;
int main()
{
cout <<"Size of char : "<<sizeof(char)<< endl;
cout <<"Size of int : "<<sizeof(int)<< endl;
cout <<"Size of short int : "<<sizeof(shortint)<< endl;
cout <<"Size of long int : "<<sizeof(longint)<< endl;
cout <<"Size of float : "<<sizeof(float)<< endl;
cout <<"Size of double : "<<sizeof(double)<< endl;
cout <<"Size of wchar_t : "<<sizeof(wchar_t)<< endl;
return0;
}

Compiled By B T Chisuwa Page 12


This example uses endl, which inserts a new-line character after every line and << operator is
being used to pass multiple values out to the screen. We are also using sizeof() function to get
size of various data types.

When the above code is compiled and executed, it produces the following result, which can vary
from machine to machine:
Size of char:1
Size of int:4
Size of shortint:2
Size of longint:4
Size of float:4
Size of double:8
Size of wchar_t:4

typedef Declarations:
You can create a new name for an existing type using typedef. Following is the simple syntax to
define a new type using typedef:
typedef type newname;

For example, the following tells the compiler that feet is another name for int:
typedef int feet;

Now, the following declaration is perfectly legal and creates an integer variable called distance:
feet distance;

Compiled By B T Chisuwa Page 13


ENUMERATED TYPES:

An enumerated type declares an optional type name and a set of zero or more identifiers that can
be used as values of the type. Each enumerator is a constant whose type is the enumeration.

To create an enumeration requires the use of the keyword enum. The general form of an
enumeration type is:
enum enum-name {list of names }var-list;

Here, the enum-name is the enumeration's type name. The list of names is comma separated.

For example, the following code defines an enumeration of colors called colors and the variable
c of type color. Finally, c is assigned the value "blue".
enum color {red, green, blue} c;
c = blue;

By default, the value of the first name is 0, the second name has the value 1, the third has the
value 2, and so on. But you can give a name a specific value by adding an initializer. For
example, in the following enumeration, green will have the value 5.
enum color {red, green=5, blue};

Here, blue will have a value of 6 because each name will be one greater than the one that
precedes it.

Compiled By B T Chisuwa Page 14


VARIABLE/DATA TYPES

A C++ identifier is a name used to identify a variable, function, class, module, or any other user-
defined item. An identifier starts with a letter A to Z or a to z or an underscore (_) followed by
zero or more letters, underscores, and digits (0 to 9).

C++ does not allow punctuation characters such as @, $, and % within identifiers. C++ is a case-
sensitive programming language. Thus, Manpower and manpower are two different identifiers
in C++.

Here are some examples of acceptable identifiers:


mohd zara abc move_name a_123
myname50 _temp j a23b9 retVal

A variable provides us with named storage that our programs can manipulate. Each variable in
C++ has a specific type, which determines the size and layout of the variable's memory; the
range of values that can be stored within that memory; and the set of operations that can be
applied to the variable.

The name of a variable can be composed of letters, digits, and the underscore character. It must
begin with either a letter or an underscore. Upper and lowercase letters are distinct because C++
is case-sensitive:

There are following basic types of variable in C++ as explained in last chapter:
Type Description
Bool Stores either value true or false.
Char Typically a single octet(one byte). This is an integer type.
Int The most natural size of integer for the machine.
Float A single-precision floating point value.

Compiled By B T Chisuwa Page 15


Double A double-precision floating point value.
Void Represents the absence of type.
wchar_t A wide character type.

C++ also allows to define various other types of variables, which we will cover in subsequent
chapters like Enumeration, Pointer, Array, Reference, Data structures, and Classes.

Following section will cover how to define, declare and use various types of variables.

Variable Definition in C++


A variable definition means to tell the compiler where and how much to create the storage for the
variable. A variable definition specifies a data type, and contains a list of one or more variables
of that type as follows:
type variable_list;

Here, type must be a valid C++ data type including char, w_char, int, float, double, bool or any
user-defined object, etc., and variable_list may consist of one or more identifier names separated
by commas. Some valid declarations are shown here:
int i, j, k;
char c, ch;
float f, salary;
double d;

The line int i, j, k; both declares and defines the variables i, j and k; which instructs the compiler
to create variables named i, j and k of type int.

Variables can be initialized (assigned an initial value) in their declaration. The initializer consists
of an equal sign followed by a constant expression as follows:
type variable_name = value;

Compiled By B T Chisuwa Page 16


Some examples are:
extern int d = 3, f = 5; // declaration of d and f.
int d = 3, f = 5; // definition and initializing d and f.
byte z = 22; // definition and initializes z.
char x = 'x'; // the variable x has the value 'x'.

For definition without an initializer: variables with static storage duration are implicitly
initialized with NULL (all bytes have the value 0); the initial value of all other variables is
undefined.

Variable Declaration in C++:


A variable declaration is useful when you are using multiple files and you define your variable in
one of the files, which will be available at the time of linking of the program. You will use extern
keyword to declare a variable at any place. Though you can declare a variable multiple times in
your C++ program, but it can be defined only once in a file, a function or a block of code.

Example
Try the following example where variables have been declared at the top, but they have been
defined and initialized inside the main function:
#include<iostream>
usingnamespace std;
// Variable definition:
extern int a, b;
extern int c;
extern float f;

int main ()
{
// Variable definition:
int a, b;
int c;

Compiled By B T Chisuwa Page 17


float f;

// actual initialization
a =10;
b =20;
c = a + b;
cout << c << endl ;
f =70.0/3.0;
cout << f << endl ;
return 0;
}

When the above code is compiled and executed, it produces the following result:
30
23.3333

Lvalues and Rvalues:


There are two kinds of expressions in C++:
• lvalue: An expression that is an lvalue may appear as either the left-hand or right-hand
side of an assignment.
• rvalue: An expression that is an rvalue may appear on the right- but not left-hand side of
an assignment.

Variables are lvalues and so may appear on the left hand side of an assignment. Numeric literals
are rvalues and so may not be assigned and can not appear on the left-hand side. Following is a
valid statement:
int g =20;

But following is not a valid statement and would generate compile-time error:
10=20;

Compiled By B T Chisuwa Page 18


Variable Scope
A scope is a region of the program and broadly speaking there are three places, where variables
can be declared:
• Inside a function or a block which is called local variables,
• In the definition of function parameters which is called formal parameters.
• Outside of all functions which is called global variables.

We will learn what a function is and it's parameters in subsequent chapters. Here, let us explain
what local and global variables are.

Local Variables:
Variables that are declared inside a function or block are local variables. They can be used only
by statements that are inside that function or block of code. Local variables are not known to
functions outside their own. Following is the example using local variables:
#include<iostream>
using namespace std;
int main ()
{
// Local variable declaration:
int a, b;
int c;
// actual initialization
a =10;
b =20;
c = a + b;
cout << c;
return 0;
}

Compiled By B T Chisuwa Page 19


Global Variables:
Global variables are defined outside of all the functions, usually on top of the program. The
global variables will hold their value throughout the life-time of your program.

A global variable can be accessed by any function. That is, a global variable is available for use
throughout your entire program after its declaration. Following is the example using global and
local variables:
#include<iostream>
using namespace std;

// Global variable declaration:


int g;
int main ()
{
// Local variable declaration:
int a, b;
// actual initialization
a =10;
b =20;
g = a + b;
cout << g;
return 0;
}

A program can have same name for local and global variables but value of local variable inside a
function will take preference. For example:
#include<iostream>
using namespace std;
// Global variable declaration:
int g =20;
int main ()

Compiled By B T Chisuwa Page 20


{
// Local variable declaration:
int g =10;
cout << g;
return 0;
}

When the above code is compiled and executed, it produces the following result:
10

Initializing Local and Global Variables:


When a local variable is defined, it is not initialized by the system, you must initialize it yourself.
Global variables are initialized automatically by the system when you define them as follows:

Data Type Initializer


Int 0
Char '\0'
Float 0
Double 0
Pointer NULL

It is a good programming practice to initialize variables properly; otherwise sometimes program


would produce unexpected result.

Dynamic Initialisation of Variables


In C, a variable must be initialised using a constant expression, and the C compiler would fix the
initialisation code at the time of compilation. C++, however, permits initialisation of the
variables at run time. This is referred to as dynamic initialisation. In C++, a variable can be

Compiled By B T Chisuwa Page 21


initialised at run time using expressions at the place of declaration. For example, the following
are valid initialisation statements:
…..
…..
int n = strlen(string);
…..
float area = 3.14159 * rad * rad;

Thus, both the declaration and the initialisation of a variable can be done simultaneously at the
place where the variable is used for the first time. The following two statements in the example
of the previous section
float average; // declare where it is necessary.
average = sum/i;

can be combined into a single statement:


float average = sum/i; //initialise dynamically at run time

Dynamic initialisation is extensively used in object oriented programming. We can create exactly
the type of object needed, using information that is known only at run time.

Compiled By B T Chisuwa Page 22


CONSTANTS/LITERALS

Constants refer to fixed values that the program may not alter and they are called literals.

Constants can be of any of the basic data types and can be divided into Integer Numerals,
Floating-Point Numerals, Characters, Strings and Boolean Values.

Again, constants are treated just like regular variables except that their values cannot be modified
after their definition.

Defining Constants
There are two simple ways in C++ to define constants:
• Using #define preprocessor.
• Using const keyword.

The #define Preprocessor


Following is the form to use #define preprocessor to define a constant:
#define identifier value

Following example explains it in detail:


#include<iostream>
using namespace std;
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
int main()
{
int area;
area = LENGTH * WIDTH;
cout << area;

Compiled By B T Chisuwa Page 23


cout << NEWLINE;
return 0;
}

When the above code is compiled and executed, it produces the following result:
50

The const Keyword


You can use const prefix to declare constants with a specific type as follows:
const type variable = value;

Following example explains it in detail


#include<iostream>
using namespace std;
int main()
{
const int LENGTH =10;
const int WIDTH =5;
const char NEWLINE ='\n';
int area;
area = LENGTH * WIDTH;
cout << area;
cout << NEWLINE;
return 0;
}
When the above code is compiled and executed, it produces the following result:
50

Note that it is a good programming practice to define constants in CAPITALS.

Compiled By B T Chisuwa Page 24


Escape sequences

Escape sequence Meaning


\\ \ character
\' ' character
\" " character
\? ? character
\a Alert or bell
\b Backspace
\f Form feed
\n Newline
\r Carriage return
\t Horizontal tab
\v Vertical tab

Compiled By B T Chisuwa Page 25


OPERATORS

An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations. C++ is rich in built-in operators and provides the following types of operators:
• Arithmetic Operators
• Relational Operators
• Logical Operators
• Bitwise Operators
• Assignment Operators
• Misc Operators

Arithmetic Operators
There are following arithmetic operators supported by C++ language:

Assume variable A holds 10 and variable B holds 20, then:


Operator Description Example
+ Adds two operands A + B will give 30
- Subtracts second operand from the first A - B will give -10
* Multiplies both operands A * B will give 200
/ Divides numerator by de-numerator B / A will give 2
% Modulus Operator and remainder of after an integer B % A will give 0
division
++ Increment operator, increases integer value by one A++ will give 11
-- Decrement operator, decreases integer value by one A-- will give 9

Increment and Decrement operators


The increment operator ++ adds 1 to its operand, and the decrement operator -- subtracts 1 from
its operand. Thus:
x = x+1;

Compiled By B T Chisuwa Page 26


is the same as
x++;

And similarly:
x = x-1;

is the same as
x--;

Both the increment and decrement operators can either precede (prefix) or follow (postfix) the
operand. For example:
x = x+1;

can be written as
++x; // prefix form

or as:
x++; // postfix form

When an increment or decrement is used as part of an expression, there is an important


difference in prefix and postfix forms. If you are using prefix form, then increment or decrement
will be done before rest of the expression, and if you are using postfix form, then increment or
decrement will be done after the complete expression is evaluated.

Example:
Following is the example to understand this difference:
#include<iostream>
using namespace std;
main()
{

Compiled By B T Chisuwa Page 27


int a =21;
int c ;
// Value of a will not be increased before assignment.
c = a++;
cout <<"Line 1 - Value of a++ is :"<< c << endl ;
// After expression value of a is increased
cout <<"Line 2 - Value of a is :"<< a << endl ;
// Value of a will be increased before assignment.
c =++a;
cout <<"Line 3 - Value of ++a is :"<< c << endl ;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Line1-Value of a++is:21
Line2-Value of a is:22
Line3-Value of ++a is:23

Relational Operators:
There are following relational operators supported by C++ language

Assume variable A holds 10 and variable B holds 20, then:


Operator Description Example
== Checks if the values of two operands are equal or not, if yes then (A == B) is not
condition becomes true. true.
!= Checks if the values of two operands are equal or not, if values are (A != B) is
not equal then condition becomes true. true.
> Checks if the value of left operand is greater than the value of right (A > B) is not
operand, if yes then condition becomes true. true.
< Checks if the value of left operand is less than the value of right (A < B) is true.

Compiled By B T Chisuwa Page 28


operand, if yes then condition becomes true.
>= Checks if the value of left operand is greater than or equal to the (A >= B) is not
value of right operand, if yes then condition becomes true. true.
<= Checks if the value of left operand is less than or equal to the (A <= B) is
value of right operand, if yes then condition becomes true. true.

Logical Operators:
There are following logical operators supported by C++ language

Assume variable A holds 1 and variable B holds 0, then:


Operator Description Example
&& Called Logical AND operator. If both the operands are non- (A && B) is false.
zero, then condition becomes true.
|| Called Logical OR Operator. If any of the two operands is non- (A || B) is true.
zero, then condition becomes true.
! Called Logical NOT Operator. Use to reverses the logical state !(A && B) is true.
of its operand. If a condition is true, then Logical NOT operator
will make false.

Assignment Operators:
There are following assignment operators supported by C++ language:

Operator Description Example


= Simple assignment operator, Assigns values from C = A + B will assign value of
right side operands to left side operand A + B into C
+= Add AND assignment operator, It adds right C += A is equivalent to C = C
operand to the left operand and assign the result +A
to left operand
-= Subtract AND assignment operator, It subtracts C -= A is equivalent to C = C -
right operand from the left operand and assign the A
result to left operand
*= Multiply AND assignment operator, It multiplies C *= A is equivalent to C = C
right operand with the left operand and assign the *A
result to left operand
/= Divide AND assignment operator, It divides left C /= A is equivalent to C = C /
operand with the right operand and assign the A

Compiled By B T Chisuwa Page 29


result to left operand
%= Modulus AND assignment operator, It takes C %= A is equivalent to C = C
modulus using two operands and assign the result % A
to left operand

Compiled By B T Chisuwa Page 30


C++ LOOP TYPES

There may be a situation, when you need to execute a block of code several number of times. In
general, statements are executed sequentially: The first statement in a function is executed first,
followed by the second, and so on.

A loop statement allows us to execute a statement or group of statements multiple times.

While loop
A while loop statement repeatedly executes a target statement as long as a given condition is
true. When the condition becomes false, program control passes to the line immediately
following the loop. Here, key point of the while loop is that the loop might not ever run. When
the condition is tested and the result is false, the loop body will be skipped and the first statement
after the while loop will be executed.

Example:
#include <iostream>
using namespace std;

int main ()
{
// Local variable declaration:
int a = 10;
// while loop execution
while(a < 20 )
{
cout << "value of a: " << a << endl;
a++;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
value of a: 10

Compiled By B T Chisuwa Page 31


value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 15
value of a: 16
value of a: 17
value of a: 18
value of a: 19

for loop
A for loop is a repetition control structure that allows you to efficiently write a loop that needs to
execute a specific number of times.

Syntax:
The syntax of a for loop in C++ is:
for ( init; condition; increment )
{
statement(s);
}

Here is the flow of control in a for loop:


• The init step is executed first, and only once. This step allows you to declare and
initialize any loop control variables. You are not required to put a statement here, as long
as a semicolon appears.
• Next, the condition is evaluated. If it is true, the body of the loop is executed. If it is
false, the body of the loop does not execute and flow of control jumps to the next
statement just after the for loop.
• After the body of the for loop executes, the flow of control jumps back up to the
increment statement. This statement allows you to update any loop control variables.
This statement can be left blank, as long as a semicolon appears after the condition.

Compiled By B T Chisuwa Page 32


• The condition is now evaluated again. If it is true, the loop executes and the process
repeats itself (body of loop, then increment step, and then again condition). After the
condition becomes false, the for loop terminates.
Example:
#include <iostream>
using namespace std;
int main ()
{
// for loop execution
for( int a = 10; a < 20; a = a + 1 )
{
cout << "value of a: " << a << endl;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 15
value of a: 16
value of a: 17
value of a: 18
value of a: 19

do…while loop
Unlike for and while loops, which test the loop condition at the top of the loop, the do...while
loop checks its condition at the bottom of the loop.

Compiled By B T Chisuwa Page 33


A do...while loop is similar to a while loop, except that a do...while loop is guaranteed to execute
at least one time.

Syntax:
The syntax of a do...while loop in C++ is:
do
{
statement(s);
}while(condition);

Notice that the conditional expression appears at the end of the loop, so the statement(s) in the
loop execute once before the condition is tested.

If the condition is true, the flow of control jumps back up to do, and the statement(s) in the loop
execute again. This process repeats until the given condition becomes false.

Example:
#include <iostream>
using namespace std;
int main ()
{
// Local variable declaration:
int a = 10;

// do loop execution
do
{
cout << "value of a: " << a << endl;
a = a + 1;
}while( a < 20 );
return 0;

Compiled By B T Chisuwa Page 34


}

When the above code is compiled and executed, it produces the following result:
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 15
value of a: 16
value of a: 17
value of a: 18
value of a: 19

nested loops
A loop can be nested inside of another loop. C++ allows at most 256 levels of nesting.

Syntax:
The syntax for a nested for loop statement in C++ is as follows:
for ( init; condition; increment )
{
for ( init; condition; increment )
{
statement(s);
}
statement(s); // you can put more statetments.
}

The syntax for a nested while loop statement in C++ is as follows:


while(condition)
{

Compiled By B T Chisuwa Page 35


while(condition)
{
statement(s);
}
statement(s); // you can put more statetments.
}

The syntax for a nested do...while loop statement in C++ is as follows:


do
{
statement(s); // you can put more statetments.
do
{
statement(s);
}while( condition );
}while( condition );

Example:
The following program uses a nested for loop to find the prime numbers from 2 to 100:
#include <iostream>
using namespace std;
int main ()
{
int i, j;
for(i=2; i<100; i++)
{
for(j=2; j <= (i/j); j++)
if(!(i%j)) break; // if factor found, not prime
if(j > (i/j)) cout << i << " is prime\n";
}
return 0;

Compiled By B T Chisuwa Page 36


}

This would produce the following result:


2 is prime
3 is prime
5 is prime
7 is prime
11 is prime
13 is prime
17 is prime
19 is prime
23 is prime
29 is prime
31 is prime
37 is prime
41 is prime
43 is prime
47 is prime
53 is prime
59 is prime
61 is prime
67 is prime
71 is prime
73 is prime
79 is prime
83 is prime
89 is prime
97 is prime

Loop Control Statements:


Loop control statements change execution from its normal sequence. When execution leaves a
scope, all automatic objects that were created in that scope are destroyed.

Break statement
The break statement has the following two usages in C++:
• When the break statement is encountered inside a loop, the loop is immediately
terminated and program control resumes at the next statement following the loop.
• It can be used to terminate a case in the switch statement.

Compiled By B T Chisuwa Page 37


If you are using nested loops (i.e., one loop inside another loop), the break statement will stop
the execution of the innermost loop and start executing the next line of code after the block.
Example:
#include <iostream>
using namespace std;
int main ()
{
// Local variable declaration:
int a = 10;
// do loop execution
do
{
cout << "value of a: " << a << endl;
a = a + 1;
if( a > 15)
{
// terminate the loop
break;
}
}while( a < 20 );
return 0;
}

When the above code is compiled and executed, it produces the following result:
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 15

continue statement
The continue statement works somewhat like the break statement. Instead of forcing
termination, however, continue forces the next iteration of the loop to take place, skipping any
code in between.

For the for loop, continue causes the conditional test and increment portions of the loop to
execute. For the while and do...while loops, program control passes to the conditional tests.

Compiled By B T Chisuwa Page 38


Example:

#include <iostream>
using namespace std;
int main ()
{
// Local variable declaration:
int a = 10;
// do loop execution
do
{
if( a == 15)
{
// skip the iteration.
a = a + 1;
continue;
}
cout << "value of a: " << a << endl;
a = a + 1;
}while( a < 20 );
return 0;
}

When the above code is compiled and executed, it produces the following result:
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 16
value of a: 17
value of a: 18
value of a: 19

goto statement
A goto statement provides an unconditional jump from the goto to a labeled statement in the
same function.

NOTE: Use of goto statement is highly discouraged because it makes difficult to trace the
control flow of a program, making the program hard to understand and hard to modify. Any
program that uses a goto can be rewritten so that it doesn't need the goto.
Compiled By B T Chisuwa Page 39
A labeled statement is any statement that is preceded by an identifier followed by a colon (:).
Example:
#include <iostream>
using namespace std;

int main ()
{
// Local variable declaration:
int a = 10;
// do loop execution

LOOP:
do
{
if( a == 15)
{
// skip the iteration.
a = a + 1;
goto LOOP;
}
cout << "value of a: " << a << endl;
a = a + 1;
}while( a < 20 );
return 0;
}

When the above code is compiled and executed, it produces the following result:
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 16
value of a: 17
value of a: 18
value of a: 19

The Infinite Loop:


A loop becomes infinite loop if a condition never becomes false. The for loop is traditionally
used for this purpose. Since none of the three expressions that form the for loop are required, you
can make an endless loop by leaving the conditional expression empty.
Compiled By B T Chisuwa Page 40
#include<iostream>
using namespace std;
int main ()
{
for(;;)
{
printf("This loop will run forever.\n");
}
return 0;
}

When the conditional expression is absent, it is assumed to be true. You may have an
initialization and increment expression, but C++ programmers more commonly use the for(;;)
construct to signify an infinite loop.

NOTE: You can terminate an infinite loop by pressing Ctrl + C keys.

Compiled By B T Chisuwa Page 41


DECISION MAKING

Decision making structures require that the programmer specify one or more conditions to be
evaluated or tested by the program, along with a statement or statements to be executed if the
condition is determined to be true, and optionally, other statements to be executed if the
condition is determined to be false.

if statement
An if statement consists of a boolean expression followed by one or more statements.

Syntax:
The syntax of an if statement in C++ is:
if(boolean_expression)
{
// statement(s) will execute if the boolean expression is true
}

If the boolean expression evaluates to true, then the block of code inside the if statement will be
executed. If boolean expression evaluates to false, then the first set of code after the end of the if
statement (after the closing curly brace) will be executed.

Example:
#include <iostream>
using namespace std;
int main () {
// local variable declaration:
int a = 10;
// check the boolean condition
if( a < 20 )
{
// if condition is true then print the following
cout << "a is less than 20;" << endl;
}
cout << "value of a is : " << a << endl;
return 0;
}

Compiled By B T Chisuwa Page 42


When the above code is compiled and executed, it produces the following result:
a is less than 20;
value of a is : 10

if…else statement
An if statement can be followed by an optional else statement, which executes when the boolean
expression is false.

If the boolean expression evaluates to true, then the if block of code will be executed, otherwise
else block of code will be executed.

Example:
#include <iostream>
using namespace std;
int main ()
{
// local variable declaration:
int a = 100;
// check the boolean condition
if( a < 20 )
{
// if condition is true then print the following
cout << "a is less than 20;" << endl;
}
else
{
// if condition is false then print the following
cout << "a is not less than 20;" << endl;
}
cout << "value of a is : " << a << endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
a is not less than 20;
value of a is : 100

Compiled By B T Chisuwa Page 43


The if...else if...else Statement:
An if statement can be followed by an optional else if...else statement, which is very usefull to
test various conditions using single if...else if statement.
When using if , else if , else statements there are few points to keep in mind.
• An if can have zero or one else's and it must come after any else if's.
• An if can have zero to many else if's and they must come before the else.
• Once an else if succeeds, none of he remaining else if's or else's will be tested.

Example:
#include <iostream>
using namespace std;
int main ()
{
int a = 100;
if( a == 10 )
{
cout << "Value of a is 10" << endl;
}
else if( a == 20 )
{
cout << "Value of a is 20" << endl;
}
else if( a == 30 )
{
cout << "Value of a is 30" << endl;
}
else
{
cout << "Value of a is not matching" << endl;
}
cout << "Exact value of a is : " << a << endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Value of a is not matching
Exact value of a is : 100

Compiled By B T Chisuwa Page 44


nested if statements
It is always legal to nest if-else statements, which means you can use one if or else if statement
inside another if or else if statement(s).

Example:
#include <iostream>
using namespace std;
int main ()
{
// local variable declaration:
int a = 100;
int b = 200;
// check the boolean condition
if( a == 100 )
{
// if condition is true then check the following
if( b == 200 )
{
// if condition is true then print the following
cout << "Value of a is 100 and b is 200" << endl;
}
}
cout << "Exact value of a is : " << a << endl;
cout << "Exact value of b is : " << b << endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Value of a is 100 and b is 200
Exact value of a is : 100
Exact value of b is : 200

Compiled By B T Chisuwa Page 45


switch statement
A switch statement allows a variable to be tested for equality against a list of values. Each value
is called a case, and the variable being switched on is checked for each case.

The following rules apply to a switch statement:


• The expression used in a switch statement must have an integral or enumerated type, or
be of a class type in which the class has a single conversion function to an integral or
enumerated type.
• You can have any number of case statements within a switch. Each case is followed by
the value to be compared to and a colon.
• The constant-expression for a case must be the same data type as the variable in the
switch, and it must be a constant or a literal.
• When the variable being switched on is equal to a case, the statements following that case
will execute until a break statement is reached.
• When a break statement is reached, the switch terminates, and the flow of control jumps
to the next line following the switch statement.
• Not every case needs to contain a break. If no break appears, the flow of control will fall
through to subsequent cases until a break is reached.
• A switch statement can have an optional default case, which must appear at the end of
the switch. The default case can be used for performing a task when none of the cases is
true. No break is needed in the default case.

Example:
#include <iostream>
using namespace std;
int main ()
{
char grade = 'D';
switch(grade)
{
case 'A' :
cout << "Excellent!" << endl;
break;
case 'B' :

Compiled By B T Chisuwa Page 46


case 'C' :
cout << "Well done" << endl;
break;
case 'D' :
cout << "You passed" << endl;
break;
case 'F' :
cout << "Better try again" << endl;
break;
default :
cout << "Invalid grade" << endl;
}
cout << "Your grade is " << grade << endl;
return 0;
}

This would produce the following result:


You passed
Your grade is D

nested switch statements


It is possible to have a switch as part of the statement sequence of an outer switch. Even if the
case constants of the inner and outer switch contain common values, no conflicts will arise.
C++ specifies that at least 256 levels of nesting be allowed for switch statements.

Example:
#include <iostream>
using namespace std;
int main ()
{
int a = 100;
int b = 200;
switch(a) {
case 100:
cout << "This is part of outer switch" << endl;
switch(b) {
case 200:
cout << "This is part of inner switch" << endl;
}
}
cout << "Exact value of a is : " << a << endl;
cout << "Exact value of b is : " << b << endl;
Compiled By B T Chisuwa Page 47
return 0;
}

This would produce the following result:


This is part of outer switch
This is part of inner switch
Exact value of a is : 100
Exact value of b is : 200

The ? : Operator:
The ternary operator can be used to replace if...else statements. It has the following general form:
Exp1 ? Exp2 : Exp3;

Where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.
The value of a ? expression is determined like this: Exp1 is evaluated. If it is true, then Exp2 is
evaluated and becomes the value of the entire ? expression. If Exp1 is false, then Exp3 is
evaluated and its value becomes the value of the expression.

Compiled By B T Chisuwa Page 48


FUNCTIONS

A function is a group of statements that together perform a task. Every C++ program has at least
one function, which is main(), and all the most trivial programs can define additional functions.

You can divide up your code into separate functions. How you divide up your code among
different functions is up to you, but logically the division usually is such that each function
performs a specific task.

A function declaration tells the compiler about a function's name, return type, and parameters.

A function is known with various names like a method or a sub-routine or a procedure etc.

Defining a Function
The general form of a C++ function definition is as follows −
return_type function_name( parameter list )
{
body of the function
}

A C++ function definition consists of a function header and a function body. Here are all the
parts of a function −

• Return Type − A function may return a value. The return_type is the data type of the
value the function returns. Some functions perform the desired operations without
returning a value. In this case, the return_type is the keyword void.
• Function Name − This is the actual name of the function. The function name and the
parameter list together constitute the function signature.
• Parameters − A parameter is like a placeholder. When a function is invoked, you pass a
value to the parameter. This value is referred to as actual parameter or argument. The
parameter list refers to the type, order, and number of the parameters of a function.
Parameters are optional; that is, a function may contain no parameters.

Compiled By B T Chisuwa Page 49


• Function Body − The function body contains a collection of statements that define what
the function does.

Example1
Following is the source code for a function called max(). This function takes two parameters
num1 and num2 and returns the maximum between the two
// function returning the max between two numbers
int max(int num1, int num2)
{
// local variable declaration
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}

Example 2

This program is divided in two functions: addition and main. Remember that no matter the order
in which they are defined, a C++ program always starts by calling main. In fact, main is the only

Compiled By B T Chisuwa Page 50


function called automatically, and the code in any other function is only executed if its function
is called from main.

In the example above, the call to addition can be compared to its definition just a few lines
earlier:

Function Declarations
A function declaration tells the compiler about a function name and how to call the function.
The actual body of the function can be defined separately.

A function declaration has the following parts –

For the above defined function max(), following is the function declaration –

Note that each argument variable must be declared independently inside the parenthesis. That is,
a combined declaration like
Float volume(int x, float y, z)

Is illegal.

Parameter names are not important in function declaration only their type is required, so
following is also valid declaration –

Compiled By B T Chisuwa Page 51


Calling a Function
While creating a C++ function, you give a definition of what the function has to do. To use a
function, you will have to call or invoke that function.

When a program calls a function, program control is transferred to the called function. A called
function performs defined task and when it’s return statement is executed or when its function-
ending closing brace is reached, it returns program control back to the main program.

To call a function, you simply need to pass the required parameters along with function name,
and if function returns a value, then you can store returned value. For example –
#include <iostream>
using namespace std;
// function declaration
int max(int num1, int num2);
int main ()
{
// local variable declaration:
int a = 100;
int b = 200;
int ret;
// calling a function to get max value.
ret = max(a, b);
cout << "Max value is : " << ret << endl;
return 0;
}
// function returning the max between two numbers
int max(int num1, int num2)
{
// local variable declaration
int result;
if (num1 > num2)

Compiled By B T Chisuwa Page 52


result = num1;
else
result = num2;
return result;
}

I kept max() function along with main() function and compiled the source code. While running
final executable, it would produce the following result:
Max value is : 200

Void Functions
Void is used when the function does not need to return a value. Void is a special type to
represent the absence of value. For example, a function that simply prints a message may not
need to return any value:

void can also be used in the function's parameter list to explicitly specify that the function takes
no actual parameters when called. For example, printmessage could have been declared as:

Compiled By B T Chisuwa Page 53


Function Prototyping
Function prototyping is a function declaration statement that tells the compiler about the return
type of the function and the number as well as type of arguments required by the function at the
time of calling it.

Example Function Prototyping


#include<iostream>
using namespace std;

void RectangleArea(); // Function Prototype

int main ()
{
RectangleArea(); // Function Call
return 0;
}

void RectangleArea() // Function Definition


{
int length, breadth, area;

cout << "Enter the length of Rectangle :-\n";


cin >> length;

cout << "Enter the width of Rectangle :-\n";


cin >> breadth;

area = length*breadth;

cout << "The area of Rectangle is " << area;


}

Advantages of function prototype:


• It helps the compiler in determining whether a function is called correctly or not. Each
time when a function is called, its calling statement is compared with its prototype. In
case of any mismatch, compiler reports an error.
• A function must be defined before calling it. But prototyping allows a function to be
called before defining it.

Compiled By B T Chisuwa Page 54


Default Arguments
When we mention a default value for a parameter while declaring the function, it is said to be as
default argument. In this case, even if we make a call to the function without passing any value
for that parameter, the function will take the default value specified.

Here we have provided a default value for y, during function definition.

Output

First two function calls will produce the exact same value. For the third function call, y will take
10 as value and output will become 20.

Compiled By B T Chisuwa Page 55


Function Arguments
If a function is to use arguments, it must declare variables that accept the values of the
arguments. These variables are called the formal parameters of the function.

The formal parameters behave like other local variables inside the function and are created upon
entry into the function and destroyed upon exit.

While calling a function, there are two ways that arguments can be passed to a function:
Call Type Description
Call by This method copies the actual value of an argument into the formal parameter of
value the function. In this case, changes made to the parameter inside the function have
no effect on the argument.
Call by This method copies the address of an argument into the formal parameter. Inside
pointer the function, the address is used to access the actual argument used in the call. This
means that changes made to the parameter affect the argument.
Call by This method copies the reference of an argument into the formal parameter. Inside
reference the function, the reference is used to access the actual argument used in the call.
This means that changes made to the parameter affect the argument.

Compiled By B T Chisuwa Page 56


Call by value
The call by value method of passing arguments to a function copies the actual value of an
argument into the formal parameter of the function. In this case, changes made to the parameter
inside the function have no effect on the argument.

By default, C++ uses call by value to pass arguments. In general, this means that code within a
function cannot alter the arguments used to call the function.

#include <iostream>
using namespace std;
// function definition to swap the values.
void swap(int x, int y)
{
int temp;
temp = x; /* save the value of x */
x = y; /* put y into x */
y = temp; /* put x into y */
}
int main ()
{
int a = 100;
int b = 200;
cout << "Before swap, value of a :" << a << endl;
cout << "Before swap, value of b :" << b << endl;
// calling a function to swap the values.
swap(a, b);
cout << "After swap, value of a :" << a << endl;
cout << "After swap, value of b :" << b << endl;
return 0;
}

Compiled By B T Chisuwa Page 57


When the above code is put together in a file, compiled and executed, it produces the following
result:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :100
After swap, value of b :200

Which shows that there is no change in the values though they had been changed inside the
function.

Call by pointer
The call by pointer method of passing arguments to a function copies the address of an
argument into the formal parameter. Inside the function, the address is used to access the actual
argument used in the call. This means that changes made to the parameter affect the passed
argument.

To pass the value by pointer, argument pointers are passed to the functions just like any other
value. So accordingly you need to declare the function parameters as pointer types as in the
following function swap(), which exchanges the values of the two integer variables pointed to by
its arguments.
#include <iostream>
using namespace std;

void swap(int *x, int *y)


{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
}

Compiled By B T Chisuwa Page 58


int main ()
{
int a = 100;
int b = 200;
cout << "Before swap, value of a :" << a << endl;
cout << "Before swap, value of b :" << b << endl;
swap(&a, &b);
cout << "After swap, value of a :" << a << endl;
cout << "After swap, value of b :" << b << endl;
return 0;
}

When the above code is put together in a file, compiled and executed, it produces the following
result:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :200
After swap, value of b :100

Call by reference
The call by reference method of passing arguments to a function copies the reference of an
argument into the formal parameter. Inside the function, the reference is used to access the actual
argument used in the call. This means that changes made to the parameter affect the passed
argument.

To pass the value by reference, argument reference is passed to the functions just like any other
value. So accordingly you need to declare the function parameters as reference types as in the
following function swap(), which exchanges the values of the two integer variables pointed to by
its arguments.
#include <iostream>
using namespace std;

Compiled By B T Chisuwa Page 59


void swap(int &x, int &y)
{
int temp;
temp = x; /* save the value at address x */
x = y; /* put y into x */
y = temp; /* put x into y */
}
int main ()
{
int a = 100;
int b = 200;
cout << "Before swap, value of a :" << a << endl;
cout << "Before swap, value of b :" << b << endl;
swap(a, b);
cout << "After swap, value of a :" << a << endl;
cout << "After swap, value of b :" << b << endl;
return 0;
}

When the above code is put together in a file, compiled and executed, it produces the following
result:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :200
After swap, value of b :100

By default, C++ uses call by value to pass arguments. In general, this means that code within a
function cannot alter the arguments used to call the function.

Const Arguments
In C++, an argument to a function can be declared as const as shown below.

Compiled By B T Chisuwa Page 60


int strlen(const char *p);
int strlen(const char *p);

The qualifier const tells the compiler that the function should not modify the argument. The
compiler will generate an error when this condition is violated. This type of declaration is
significant only when we pass arguments by reference or pointers.

Compiled By B T Chisuwa Page 61


ARRAYS

C++ provides a data structure, the array, which stores a fixed-size sequential collection of
elements of the same type. An array is used to store a collection of data, but it is often more
useful to think of an array as a collection of variables of the same type.

Instead of declaring individual variables, such as number0, number1, ..., and number99, you
declare one array variable such as numbers and use numbers[0], numbers[1], and ...,
numbers[99] to represent individual variables. A specific element in an array is accessed by an
index.

All arrays consist of contiguous memory locations. The lowest address corresponds to the first
element and the highest address to the last element.

Declaring Arrays
To declare an array in C++, the programmer specifies the type of the elements and the number of
elements required by an array as follows:
type arrayName [ arraySize ];

This is called a single-dimension array. The arraySize must be an integer constant greater than
zero and type can be any valid C++ data type. For example, to declare a 10-element array called
balance of type double, use this statement:
double balance[10];

Initializing Arrays:
You can initialize C++ array elements either one by one or using a single statement as follows:
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};

Compiled By B T Chisuwa Page 62


The number of values between braces { } can not be larger than the number of elements that we
declare for the array between square brackets [ ]. Following is an example to assign a single
element of the array:

If you omit the size of the array, an array just big enough to hold the initialization is created.
Therefore, if you write:
double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};

You will create exactly the same array as you did in the previous example.
balance[4] = 50.0;

The above statement assigns element number 5th in the array a value of 50.0. Array with 4th
index will be 5th, i.e., last element because all arrays have 0 as the index of their first element
which is also called base index. Following is the pictorial representaion of the same array we
discussed above:

Accessing Array Elements


An element is accessed by indexing the array name. This is done by placing the index of the
element within square brackets after the name of the array. For example:
double salary = balance[9];

The above statement will take 10th element from the array and assign the value to salary
variable. Following is an example, which will use all the above-mentioned three concepts viz.
declaration, assignment and accessing arrays:

Compiled By B T Chisuwa Page 63


#include <iostream>
#include <iomanip>
using namespace std;
using std::setw;
int main ()
{
int n[ 10 ];
for ( int i = 0; i < 10; i++ )
{
n[ i ] = i + 100;
}
cout << "Element" << setw( 13 ) << "Value" << endl;
for ( int j = 0; j < 10; j++ )
{
cout << setw( 7 )<< j << setw( 13 ) << n[ j ] << endl;
}
return 0;
}

This program makes use of setw() function to format the output. When the above code is
compiled and executed, it produces the following result:
Element Value
0 100
1 101
2 102
3 103
4 104
5 105
6 106
7 107
8 108
9 109

Compiled By B T Chisuwa Page 64


Multi-dimensional arrays
C++ allows multidimensional arrays. Here is the general form of a multidimensional array
declaration:
type name[size1][size2]...[sizeN];

For example, the following declaration creates a three dimensional integer array:
int threedim[5][10][4];

Two-Dimensional Arrays:
The simplest form of the multidimensional array is the two-dimensional array. A two-
dimensional array is, in essence, a list of one-dimensional arrays. To declare a two-dimensional
integer array of size x,y, you would write something as follows:
type arrayName [ x ][ y ];

Where type can be any valid C++ data type and arrayName will be a valid C++ identifier.

A two-dimensional array can be think as a table, which will have x number of rows and y
number of columns. A 2-dimensional array a, which contains three rows and four columns can
be shown as below:

Thus, every element in array a is identified by an element name of the form a[ i ][ j ], where a is
the name of the array, and i and j are the subscripts that uniquely identify each element in a.

Compiled By B T Chisuwa Page 65


Initializing Two-Dimensional Arrays:
Multidimensioned arrays may be initialized by specifying bracketed values for each row.
Following is an array with 3 rows and each row have 4 columns.
int a[3][4] = {
{0, 1, 2, 3} , /* initializers for row indexed by 0 */
{4, 5, 6, 7} , /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};

The nested braces, which indicate the intended row, are optional. The following initialization is
equivalent to previous example:
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

Accessing Two-Dimensional Array Elements:


An element in 2-dimensional array is accessed by using the subscripts ie. row index and column
index of the array. For example:
int val = a[2][3];

The above statement will take 4th element from the 3rd row of the array. You can verify it in the
above digram.
#include <iostream>
using namespace std;
int main ()
{
// an array with 5 rows and 2 columns.
int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
// output each array element's value
for ( int i = 0; i < 5; i++ )
for ( int j = 0; j < 2; j++ )
{
cout << "a[" << i << "][" << j << "]: ";

Compiled By B T Chisuwa Page 66


cout << a[i][j]<< endl;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8

As explained above, you can have arrays with any number of dimensions, although it is likely
that most of the arrays you create will be of one or two dimensions.

Pointer to an array
An array name is a constant pointer to the first element of the array. Therefore, in the
declaration:
double balance[50];

balance is a pointer to &balance[0], which is the address of the first element of the array
balance. Thus, the following program fragment assigns p the address of the first element of
balance:
double *p;
double balance[10];
p = balance;

Compiled By B T Chisuwa Page 67


It is legal to use array names as constant pointers, and vice versa. Therefore, *(balance + 4) is a
legitimate way of accessing the data at balance[4].

Once you store the address of first element in p, you can access array elements using *p, *(p+1),
*(p+2) and so on. Below is the example to show all the concepts discussed above:
#include <iostream>
using namespace std;

int main ()
{
// an array with 5 elements.
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
p = balance;
// output each array element's value
cout << "Array values using pointer " << endl;
for ( int i = 0; i < 5; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
cout << "Array values using balance as address " << endl;
for ( int i = 0; i < 5; i++ )
{
cout << "*(balance + " << i << ") : ";
cout << *(balance + i) << endl;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:

Compiled By B T Chisuwa Page 68


Array values using pointer
*(p + 0) : 1000
*(p + 1) : 2
*(p + 2) : 3.4
*(p + 3) : 17
*(p + 4) : 50
Array values using balance as address
*(balance + 0) : 1000
*(balance + 1) : 2
*(balance + 2) : 3.4
*(balance + 3) : 17
*(balance + 4) : 50

In the above example, p is a pointer to double which means it can store address of a variable of
double type. Once we have address in p, then *p will give us value available at the address stored
in p, as we have shown in the above example.

Passing arrays to functions


C++ does not allow to pass an entire array as an argument to a function. However, You can pass
a pointer to an array by specifying the array's name without an index.

If you want to pass a single-dimension array as an argument in a function, you would have to
declare function formal parameter in one of following three ways and all three declaration
methods produce similar results because each tells the compiler that an integer pointer is going to
be received.

Way-1
Formal parameters as a pointer as follows:

Compiled By B T Chisuwa Page 69


void myFunction(int *param)
{
.
.
.
}

Way-2
Formal parameters as a sized array as follows:
void myFunction(int param[10])
{
.
.
.
}

Way-3
Formal parameters as an unsized array as follows:
void myFunction(int param[])
{
.
.
.
}

Now, consider the following function, which will take an array as an argument along with
another argument and based on the passed arguments, it will return average of the numbers
passed through the array as follows:

Compiled By B T Chisuwa Page 70


double getAverage(int arr[], int size)
{
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i)
{
sum += arr[i];
}
avg = double(sum) / size;
return avg;
}

Now, let us call the above function as follows:


#include <iostream>
using namespace std;
// function declaration:
double getAverage(int arr[], int size);
int main ()
{
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
// pass pointer to the array as an argument.
avg = getAverage( balance, 5 ) ;
// output the returned value
cout << "Average value is: " << avg << endl;
return 0;
}

When the above code is compiled together and executed, it produces the following result:
Average value is: 214.4

Compiled By B T Chisuwa Page 71


As you can see, the length of the array doesn't matter as far as the function is concerned because
C++ performs no bounds checking for the formal parameters.

Return array from functions


C++ does not allow to return an entire array as an argument to a function. However, You can
return a pointer to an array by specifying the array's name without an index.

If you want to return a single-dimension array from a function, you would have to declare a
function returning a pointer as in the following example:
int * myFunction()
{
.
.
.
}

Second point to remember is that C++ does not advocate to return the address of a local variable
to outside of the function so you would have to define the local variable as static variable.

Now, consider the following function, which will generate 10 random numbers and return them
using an array and call this function as follows:
#include <iostream>
#include <ctime>
using namespace std;
// function to generate and return random numbers.
int * getRandom( )
{
static int r[10];
// set the seed
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)

Compiled By B T Chisuwa Page 72


{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// main function to call above defined function.
int main ()
{
// a pointer to an int.
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}

When the above code is compiled together and executed, it produces result something as follows:
624723190
1468735695
807113585
976495677
613357504
1377296355
1530315259
1778906708
1820354158
667126415

Compiled By B T Chisuwa Page 73


*(p + 0) : 624723190
*(p + 1) : 1468735695
*(p + 2) : 807113585
*(p + 3) : 976495677
*(p + 4) : 613357504
*(p + 5) : 1377296355
*(p + 6) : 1530315259
*(p + 7) : 1778906708
*(p + 8) : 1820354158
*(p + 9) : 667126415

Compiled By B T Chisuwa Page 74


STRINGS

C++ provides following two types of string representations:


• The C-style character string.
• The string class type introduced with Standard C++.

The C-Style Character String:


The C-style character string originated within the C language and continues to be supported
within C++. This string is actually a one-dimensional array of characters which is terminated by
a null character '\0'. Thus a null-terminated string contains the characters that comprise the string
followed by a null.

The following declaration and initialization create a string consisting of the word "Hello". To
hold the null character at the end of the array, the size of the character array containing the string
is one more than the number of characters in the word "Hello."
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

If you follow the rule of array initialization, then you can write the above statement as follows:
char greeting[] = "Hello";

Following is the memory presentation of above defined string in C/C++:

Actually, you do not place the null character at the end of a string constant. The C++ compiler
automatically places the '\0' at the end of the string when it initializes the array. Let us try to print
above-mentioned string:
#include <iostream>
using namespace std;
int main ()

Compiled By B T Chisuwa Page 75


{
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << "Greeting message: ";
cout << greeting << endl;
return 0;
}

When the above code is compiled and executed, it produces result something as follows:
Greeting message: Hello

C++ supports a wide range of functions that manipulate null-terminated strings:


S.N. Function & Purpose
1 strcpy(s1, s2);
Copies string s2 into string s1.
2 strcat(s1, s2);
Concatenates string s2 onto the end of string s1.
3 strlen(s1);
Returns the length of string s1.
4 strcmp(s1, s2);
Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2.
5 strchr(s1, ch);
Returns a pointer to the first occurrence of character ch in string s1.
6 strstr(s1, s2);
Returns a pointer to the first occurrence of string s2 in string s1.

Following example makes use of few of the above-mentioned functions:


#include <iostream>
#include <cstring>
using namespace std;
int main ()
{

Compiled By B T Chisuwa Page 76


char str1[10] = "Hello";
char str2[10] = "World";
char str3[10];
int len ;
// copy str1 into str3
strcpy( str3, str1);
cout << "strcpy( str3, str1) : " << str3 << endl;
// concatenates str1 and str2
strcat( str1, str2);
cout << "strcat( str1, str2): " << str1 << endl;
// total lenghth of str1 after concatenation
len = strlen(str1);
cout << "strlen(str1) : " << len << endl;
return 0;
}

When the above code is compiled and executed, it produces result something as follows:
strcpy( str3, str1) : Hello
strcat( str1, str2): HelloWorld
strlen(str1) : 10

The String Class in C++:


The standard C++ library provides a string class type that supports all the operations mentioned
above, additionally much more functionality. We will study this class in C++ Standard Library
but for now let us check following example:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 = "Hello";

Compiled By B T Chisuwa Page 77


string str2 = "World";
string str3;
int len ;
// copy str1 into str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// concatenates str1 and str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// total lenghth of str3 after concatenation
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}

When the above code is compiled and executed, it produces result something as follows:
str3 : Hello
str1 + str2 : HelloWorld
str3.size() : 10

Compiled By B T Chisuwa Page 78


POINTERS

C++ pointers are easy and fun to learn. Some C++ tasks are performed more easily with pointers,
and other C++ tasks, such as dynamic memory allocation, cannot be performed without them.

As you know every variable is a memory location and every memory location has its address
defined which can be accessed using ampersand (&) operator which denotes an address in
memory. Consider the following which will print the address of the variables defined:
#include <iostream>
using namespace std;
int main ()
{
int var1;
char var2[10];
cout << "Address of var1 variable: ";
cout << &var1 << endl;
cout << "Address of var2 variable: ";
cout << &var2 << endl;
return 0;
}

When the above code is compiled and executed, it produces result something as follows:
Address of var1 variable: 0xbfebd5c0
Address of var2 variable: 0xbfebd5b6

What Are Pointers?


A pointer is a variable whose value is the address of another variable. Like any variable or
constant, you must declare a pointer before you can work with it. The general form of a pointer
variable declaration is:
type *var-name;

Compiled By B T Chisuwa Page 79


Here, type is the pointer's base type; it must be a valid C++ type and var-name is the name of
the pointer variable. The asterisk you used to declare a pointer is the same asterisk that you use
for multiplication. However, in this statement the asterisk is being used to designate a variable as
a pointer. Following are the valid pointer declaration:
int *ip; // pointer to an integer
double *dp; // pointer to a double
float *fp; // pointer to a float
char *ch // pointer to character

The actual data type of the value of all pointers, whether integer, float, character, or otherwise, is
the same, a long hexadecimal number that represents a memory address. The only difference
between pointers of different data types is the data type of the variable or constant that the
pointer points to.

Using Pointers in C++:


There are few important operations, which we will do with the pointers very frequently. (a) we
define a pointer variables (b) assign the address of a variable to a pointer and (c) finally access
the value at the address available in the pointer variable. This is done by using unary operator *
that returns the value of the variable located at the address specified by its operand. Following
example makes use of these operations:
#include <iostream>
using namespace std;
int main ()
{
int var = 20; // actual variable declaration.
int *ip; // pointer variable
ip = &var; // store address of var in pointer variable
cout << "Value of var variable: ";
cout << var << endl;
// print the address stored in ip pointer variable
cout << "Address stored in ip variable: ";

Compiled By B T Chisuwa Page 80


cout << ip << endl;
// access the value at the address available in pointer
cout << "Value of *ip variable: ";
cout << *ip << endl;
return 0;
}

When the above code is compiled and executed, it produces result something as follows:
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20

C++ Null Pointers


It is always a good practice to assign the pointer NULL to a pointer variable in case you do not
have exact address to be assigned. This is done at the time of variable declaration. A pointer that
is assigned NULL is called a null pointer.

The NULL pointer is a constant with a value of zero defined in several standard libraries,
including iostream. Consider the following program:
#include <iostream>
using namespace std;
int main ()
{
int *ptr = NULL;
cout << "The value of ptr is " << ptr ;
return 0;
}

When the above code is compiled and executed, it produces the following result:
The value of ptr is 0

Compiled By B T Chisuwa Page 81


On most of the operating systems, programs are not permitted to access memory at address 0
because that memory is reserved by the operating system. However, the memory address 0 has
special significance; it signals that the pointer is not intended to point to an accessible memory
location. But by convention, if a pointer contains the null (zero) value, it is assumed to point to
nothing.

To check for a null pointer you can use an if statement as follows:


if(ptr) // succeeds if p is not null
if(!ptr) // succeeds if p is null

Thus, if all unused pointers are given the null value and you avoid the use of a null pointer, you
can avoid the accidental misuse of an uninitialized pointer. Many times, uninitialized variables
hold some junk values and it becomes difficult to debug the program.

C++ Pointer Arithmetic


As you understood pointer is an address which is a numeric value; therefore, you can perform
arithmetic operations on a pointer just as you can a numeric value. There are four arithmetic
operators that can be used on pointers: ++, --, +, and –

To understand pointer arithmetic, let us consider that ptr is an integer pointer which points to the
address 1000. Assuming 32-bit integers, let us perform the following arithmatic operation on the
pointer:
ptr++

the ptr will point to the location 1004 because each time ptr is incremented, it will point to the
next integer. This operation will move the pointer to next memory location without impacting
actual value at the memory location. If ptr points to a character whose address is 1000, then
above operation will point to the location 1001 because next character will be available at 1001.

Compiled By B T Chisuwa Page 82


Incrementing a Pointer:
We prefer using a pointer in our program instead of an array because the variable pointer can be
incremented, unlike the array name which cannot be incremented because it is a constant pointer.
The following program increments the variable pointer to access each succeeding element of the
array:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
ptr++;
}
return 0;
}

When the above code is compiled and executed, it produces result something as follows:
Address of var[0] = 0xbfa088b0
Value of var[0] = 10
Address of var[1] = 0xbfa088b4
Value of var[1] = 100
Address of var[2] = 0xbfa088b8
Value of var[2] = 200

Compiled By B T Chisuwa Page 83


Decrementing a Pointer:
The same considerations apply to decrementing a pointer, which decreases its value by the
number of bytes of its data type as shown below:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// let us have address of the last element in pointer.
ptr = &var[MAX-1];
for (int i = MAX; i > 0; i--)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// point to the previous location
ptr--;
}
return 0;
}

When the above code is compiled and executed, it produces result something as follows:
Address of var[3] = 0xbfdb70f8
Value of var[3] = 200
Address of var[2] = 0xbfdb70f4
Value of var[2] = 100
Address of var[1] = 0xbfdb70f0
Value of var[1] = 10

Compiled By B T Chisuwa Page 84


Pointer Comparisons
Pointers may be compared by using relational operators, such as ==, <, and >. If p1 and p2 point
to variables that are related to each other, such as elements of the same array, then p1 and p2 can
be meaningfully compared.

The following program modifies the previous example one by incrementing the variable pointer
so long as the address to which it points is either less than or equal to the address of the last
element of the array, which is &var[MAX - 1]:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// let us have address of the first element in pointer.
ptr = var;
int i = 0;
while ( ptr <= &var[MAX - 1] )
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// point to the previous location
ptr++;
i++;
}
return 0;
}

Compiled By B T Chisuwa Page 85


When the above code is compiled and executed, it produces result something as follows:
Address of var[0] = 0xbfce42d0
Value of var[0] = 10
Address of var[1] = 0xbfce42d4
Value of var[1] = 100
Address of var[2] = 0xbfce42d8
Value of var[2] = 200

C++ Pointers vs Arrays


Pointers and arrays are strongly related. In fact, pointers and arrays are interchangeable in many
cases. For example, a pointer that points to the beginning of an array can access that array by
using either pointer arithmetic or array-style indexing. Consider the following program:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
ptr = var;

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


{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
ptr++;
}
return 0;
}

Compiled By B T Chisuwa Page 86


When the above code is compiled and executed, it produces result something as follows:
Address of var[0] = 0xbfa088b0
Value of var[0] = 10
Address of var[1] = 0xbfa088b4
Value of var[1] = 100
Address of var[2] = 0xbfa088b8
Value of var[2] = 200

However, pointers and arrays are not completely interchangeable. For example, consider the
following program:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++)
{
*var = i; // This is a correct syntax
var++; // This is incorrect.
}
return 0;
}

It is perfectly acceptable to apply the pointer operator * to var but it is illegal to modify var
value. The reason for this is that var is a constant that points to the beginning of an array and can
not be used as l-value.

Because an array name generates a pointer constant, it can still be used in pointer-style
expressions, as long as it is not modified. For example, the following is a valid statement that
assigns var[2] the value 500:

Compiled By B T Chisuwa Page 87


*(var + 2) = 500;

Above statement is valid and will compile successfully because var is not changed.

C++ Array of Pointers


Before we understand the concept of array of pointers, let us consider the following example,
which makes use of an array of 3 integers:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++)
{
cout << "Value of var[" << i << "] = ";
cout << var[i] << endl;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

There may be a situation, when we want to maintain an array, which can store pointers to an int
or char or any other data type available. Following is the declaration of an array of pointers to an
integer:
int *ptr[MAX];

Compiled By B T Chisuwa Page 88


This declares ptr as an array of MAX integer pointers. Thus, each element in ptr, now holds a
pointer to an int value. Following example makes use of three integers which will be stored in an
array of pointers as follows:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr[MAX];
for (int i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; // assign the address of integer.
for (int i = 0; i < MAX; i++)
{
cout << "Value of var[" << i << "] = ";
cout << *ptr[i] << endl;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

You can also use an array of pointers to character to store a list of strings as follows:
#include <iostream>
using namespace std;
const int MAX = 4;
int main ()

Compiled By B T Chisuwa Page 89


{
char *names[MAX] = {
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali",
};
for (int i = 0; i < MAX; i++)
{
cout << "Value of names[" << i << "] = ";
cout << names[i] << endl;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali

C++ Pointer to Pointer


A pointer to a pointer is a form of multiple indirection or a chain of pointers. Normally, a pointer
contains the address of a variable. When we define a pointer to a pointer, the first pointer
contains the address of the second pointer, which points to the location that contains the actual
value as shown below.

Compiled By B T Chisuwa Page 90


A variable that is a pointer to a pointer must be declared as such. This is done by placing an
additional asterisk in front of its name. For example, following is the declaration to declare a
pointer to a pointer of type int:
int **var;

When a target value is indirectly pointed to by a pointer to a pointer, accessing that value
requires that the asterisk operator be applied twice, as is shown below in the example:
#include <iostream>
using namespace std;
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
// take the address of var
ptr = &var;
// take the address of ptr using address of operator &
pptr = &ptr;
// take the value using pptr
cout << "Value of var :" << var << endl;
cout << "Value available at *ptr :" << *ptr << endl;
cout << "Value available at **pptr :" << **pptr << endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Value of var :3000
Value available at *ptr :3000
Value available at **pptr :3000

Compiled By B T Chisuwa Page 91


Passing Pointers to Functions
C++ allows you to pass a pointer to a function. To do so, simply declare the function parameter
as a pointer type.

Following a simple example where we pass an unsigned long pointer to a function and change
the value inside the function which reflects back in the calling function:
#include <iostream>
#include <ctime>
using namespace std;
void getSeconds(unsigned long *par);
int main ()
{
unsigned long sec;
getSeconds( &sec );
// print the actual value
cout << "Number of seconds :" << sec << endl;
return 0;
}
void getSeconds(unsigned long *par)
{
// get the current number of seconds
*par = time( NULL );
}

When the above code is compiled and executed, it produces the following result:
Number of seconds :1294450468

The function which can accept a pointer, can also accept an array as shown in the following
example:

Compiled By B T Chisuwa Page 92


#include <iostream>
using namespace std;
// function declaration:
double getAverage(int *arr, int size);
int main ()
{
// an int array with 5 elements.
int balance[5] = {1000, 2, 3, 17, 50}
double avg;
// pass pointer to the array as an argument.
avg = getAverage( balance, 5 ) ;
// output the returned value
cout << "Average value is: " << avg << endl;
return 0;
}
double getAverage(int *arr, int size)
{
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i)
{
sum += arr[i];
}
avg = double(sum) / size;
return avg;
}

When the above code is compiled together and executed, it produces the following result:
Average value is: 214.4

Compiled By B T Chisuwa Page 93


Return Pointer from Functions
As we have seen in last chapter how C++ allows to return an array from a function, similar way
C++ allows you to return a pointer from a function. To do so, you would have to declare a
function returning a pointer as in the following example:
int * myFunction()
{
.
.
.
}

Second point to remember is that, it is not good idea to return the address of a local variable to
outside of the function so you would have to define the local variable as static variable.

Now consider the following function which will generate 10 random numbers and return them
using an array name which represents a pointer ie address of first array element.
#include <iostream>
#include <ctime>
using namespace std;
// function to generate and retrun random numbers.
int * getRandom( )
{
static int r[10];
// set the seed
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;

Compiled By B T Chisuwa Page 94


}
// main function to call above defined function.
int main ()
{
// a pointer to an int.
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}

When the above code is compiled together and executed, it produces result something as follows:
624723190
1468735695
807113585
976495677
613357504
1377296355
1530315259
1778906708
1820354158
667126415
*(p + 0) : 624723190
*(p + 1) : 1468735695
*(p + 2) : 807113585
*(p + 3) : 976495677
*(p + 4) : 613357504

Compiled By B T Chisuwa Page 95


*(p + 5) : 1377296355
*(p + 6) : 1530315259
*(p + 7) : 1778906708
*(p + 8) : 1820354158
*(p + 9) : 667126415

Compiled By B T Chisuwa Page 96


REFERENCES

A reference variable is an alias, that is, another name for an already existing variable. Once a
reference is initialized with a variable, either the variable name or the reference name may be
used to refer to the variable.

C++ References vs Pointers:


References are often confused with pointers but three major differences between references and
pointers are:
• You cannot have NULL references. You must always be able to assume that a reference
is connected to a legitimate piece of storage.
• Once a reference is initialized to an object, it cannot be changed to refer to another object.
Pointers can be pointed to another object at any time.
• A reference must be initialized when it is created. Pointers can be initialized at any time.

Reference Variables
Think of a variable name as a label attached to the variable's location in memory. You can then
think of a reference as a second label attached to that memory location. Therefore, you can
access the contents of the variable through either the original variable name or the reference. For
example, suppose we have the following example:
int i = 17;

We can declare reference variables for i as follows.


int& r = i;

Read the & in these declarations as reference. Thus, read the first declaration as "r is an integer
reference initialized to i" and read the second declaration as "s is a double reference initialized to
d.". Following example makes use of references on int and double:
#include <iostream>
using namespace std;

Compiled By B T Chisuwa Page 97


int main ()
{
// declare simple variables
int i;
double d;
// declare reference variables
int& r = i;
double& s = d;
i = 5;
cout << "Value of i : " << i << endl;
cout << "Value of i reference : " << r << endl;
d = 11.7;
cout << "Value of d : " << d << endl;
cout << "Value of d reference : " << s << endl;
return 0;
}

When the above code is compiled together and executed, it produces the following result:
Value of i : 5
Value of i reference : 5
Value of d : 11.7
Value of d reference : 11.7

A reference variable must be initialised at the time of declaration. This establishes the
correspondence between the reference and the data object which it names. It is important to note
that the initialisation of a reference variable is completely different from assignment to it.

References to Arrays
We can create references to arrays as shown below:
int n[10];
int & x = n[10]; // x is alias for n[10]

Compiled By B T Chisuwa Page 98


The variable x is an alternative to the array element n[10].

References to Literals
We can create references to arrays as shown below:
char & a = ‘\n’; //initialise reference to a literal

The variable a is initialised to the newline constant. This creates a reference to the otherwise
unknown location where the newline constant \n is stored.

The following references are also allowed:


i. int x;
int *p = &x;
int & m = *p;

ii. int & n = 50;

The first set of declarations causes m to refer to x which is pointed to by the pointer p and the
statement in (ii) creates an int object with value 50 and name n.

References are usually used for function argument lists and function return values. So following
are two important subjects related to C++ references which should be clear to a C++
programmer:

References as Parameters
C++ supports passing references as function parameter more safely than parameters.
#include <iostream>
using namespace std;
void swap(int& x, int& y);
int main ()
{
// local variable declaration:
int a = 100;

Compiled By B T Chisuwa Page 99


int b = 200;
cout << "Before swap, value of a :" << a << endl;
cout << "Before swap, value of b :" << b << endl;
/* calling a function to swap the values.*/
swap(a, b);
cout << "After swap, value of a :" << a << endl;
cout << "After swap, value of b :" << b << endl;
return 0;
}
// function definition to swap the values.
void swap(int& x, int& y)
{
int temp;
temp = x; /* save the value at address x */
x = y; /* put y into x */
y = temp; /* put x into y */
return;
}

When the above code is compiled and executed, it produces the following result:
Before swap, value of a :100
Before swap, value of b :200
After swap, value of a :200
After swap, value of b :100

The call by reference mechanism is useful in object-oriented programming because it permits the
manipulation of objects by reference, and eliminates the copying of object parameters back and
forth. It is also important to note that references can be created not only for built-in data types
but also for user defined data types such as structures and classes. References work wonderfully
well with these use-defined data types.

Compiled By B T Chisuwa Page 100


Reference as Return Value
A C++ program can be made easier to read and maintain by using references rather than pointers.
A C++ function can return a reference in a similar way as it returns a pointer.

When a function returns a reference, it returns an implicit pointer to its return value. This way, a
function can be used on the left side of an assignment statement. For example, consider this
simple program:
#include <iostream>
#include <ctime>
using namespace std;
double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};
double& setValues( int i )
{
return vals[i]; // return a reference to the ith element
}
// main function to call above defined function.
int main ()
{
cout << "Value before change" << endl;
for ( int i = 0; i < 5; i++ )
{
cout << "vals[" << i << "] = ";
cout << vals[i] << endl;
}
setValues(1) = 20.23; // change 2nd element
setValues(3) = 70.8; // change 4th element
cout << "Value after change" << endl;
for ( int i = 0; i < 5; i++ )
{
cout << "vals[" << i << "] = ";
cout << vals[i] << endl;

Compiled By B T Chisuwa Page 101


}
return 0;
}

When the above code is compiled together and executed, it produces the following result:
Value before change
vals[0] = 10.1
vals[1] = 12.6
vals[2] = 33.1
vals[3] = 24.1
vals[4] = 50
Value after change
vals[0] = 10.1
vals[1] = 20.23
vals[2] = 33.1
vals[3] = 70.8
vals[4] = 50

When returning a reference, be careful that the object being referred to does not go out of scope.
So it is not legal to return a reference to local var. But you can always return a reference on a
static variable.
int& func() {
int q;
//! return q; // Compile time error
static int x;
return x; // Safe, x lives outside this scope
}

Compiled By B T Chisuwa Page 102


DATE ANDTIME

The C++ standard library does not provide a proper date type. C++ inherits the structs and
functions for date and time manipulation from C. To access date and time related functions and
structures, you would need to include <ctime> header file in your C++ program.

There are four time-related types: clock_t, time_t, size_t, and tm. The types clock_t, size_t and
time_t are capable of representing the system time and date as some sort of integer.

The structure type tm holds the date and time in the form of a C structure having the following
elements:
struct tm {
int tm_sec; // seconds of minutes from 0 to 61
int tm_min; // minutes of hour from 0 to 59
int tm_hour; // hours of day from 0 to 24
int tm_mday; // day of month from 1 to 31
int tm_mon; // month of year from 0 to 11
int tm_year; // year since 1900
int tm_wday; // days since sunday
int tm_yday; // days since January 1st
int tm_isdst; // hours of daylight savings time
}

Following are the important functions, which we use while working with date and time in C or
C++. All these functions are part of standard C and C++ library and you can check their detail
using reference to C++ standard library given below.

Compiled By B T Chisuwa Page 103


SN Function & Purpose
1 time_t time(time_t *time);
This returns the current calendar time of the system in number of seconds elapsed since
January 1, 1970. If the system has no time, .1 is returned.
2 char *ctime(const time_t *time);
This returns a pointer to a string of the form day month year hours:minutes:seconds
year\n\0.
3 struct tm *localtime(const time_t *time);
This returns a pointer to the tm structure representing local time.
4 clock_t clock(void);
This returns a value that approximates the amount of time the calling program has been
running. A value of .1 is returned if the time is not available.
5 char * asctime ( const struct tm * time );
This returns a pointer to a string that contains the information stored in the structure pointed
to by time converted into the form: day month date hours:minutes:seconds year\n\0
6 struct tm *gmtime(const time_t *time);
This returns a pointer to the time in the form of a tm structure. The time is represented in
Coordinated Universal Time (UTC), which is essentially Greenwich Mean Time (GMT).
7 time_t mktime(struct tm *time);
This returns the calendar-time equivalent of the time found in the structure pointed to by
time.
8 double difftime ( time_t time2, time_t time1 );
This function calculates the difference in seconds between time1 and time2.
9 size_t strftime();
This function can be used to format date and time a specific format.

Current date and time:


Consider you want to retrieve the current system date and time, either as a local time or as a
Coordinated Universal Time (UTC). Following is the example to achieve the same:

Compiled By B T Chisuwa Page 104


#include <iostream>
#include <ctime>
using namespace std;
int main( )
{
// current date/time based on current system
time_t now = time(0);
// convert now to string form
char* dt = ctime(&now);
cout << "The local date and time is: " << dt << endl;
// convert now to tm struct for UTC
tm *gmtm = gmtime(&now);
dt = asctime(gmtm);
cout << "The UTC date and time is:"<< dt << endl;
}

When the above code is compiled and executed, it produces following result:
The local date and time is: Sat Jan 8 20:07:41 2011
The UTC date and time is:Sun Jan 9 03:07:41 2011

Format time using struct tm:


The tm structure is very important while working with date and time in either C or C++. This
structure holds the date and time in the form of a C structure as mentioned above. Most of the
time related functions makes use of tm structure. Following is an example which makes use of
various date and time related functions and tm structure:

While using structure in this chapter I'm making an assumption that you have basic
understanding on C structure and how to access structure members using arrow -> operator.

Compiled By B T Chisuwa Page 105


#include <iostream>
#include <ctime>
using namespace std;
int main( )
{
// current date/time based on current system
time_t now = time(0);
cout << "Number of sec since January 1,1970:" << now << endl;
tm *ltm = localtime(&now);
// print various components of tm structure.
cout << "Year: "<< 1900 + ltm->tm_year << endl;
cout << "Month: "<< 1 + ltm->tm_mon<< endl;
cout << "Day: "<< ltm->tm_mday << endl;
cout << "Time: "<< 1 + ltm->tm_hour << ":";
cout << 1 + ltm->tm_min << ":";
cout << 1 + ltm->tm_sec << endl;
}

When the above code is compiled and executed, it produces the following result:
Number of sec since January 1, 1970:1294548238
Year: 2011
Month: 1
Day: 8
Time: 22: 44:59

Compiled By B T Chisuwa Page 106


BASIC INPUT/OUTPUT

C++ I/O occurs in streams, which are sequences of bytes. If bytes flow from a device like a
keyboard, a disk drive, or a network connection, etc., to main memory, this is called input
operation and if bytes flow from main memory to a device like a display screen, a printer, a disk
drive, or a network connection, etc, this is called output operation.

I/O Library Header Files:


There are following header files important to C++ programs:
Header Function and Description
File
<iostream> This file defines the cin, cout, cerr and clog objects, which correspond to the
standard input stream, the standard output stream, the un-buffered standard error
stream and the buffered standard error stream, respectively.
<iomanip> This file declares services useful for performing formatted I/O with so-called
parameterized stream manipulators, such as setw and setprecision.
<fstream> This file declares services for user-controlled file processing. We will discuss
about it in detail in File and Stream related chapter.

The standard input stream (cin):


The predefined object cin is an instance of istream class. The cin object is said to be attached to
the standard input device, which usually is the keyboard. The cin is used in conjunction with the
stream extraction operator, which is written as >> which are two greater than signs as shown in
the following example. The stream extraction operator is then followed by the variable where the
extracted data is stored. For example:
#include <iostream>
using namespace std;
int main( )

Compiled By B T Chisuwa Page 107


{
char name[50];
cout << "Please enter your name: ";
cin >> name;
cout << "Your name is: " << name << endl;
}

When the above code is compiled and executed, it will prompt you to enter a name. You enter a
value and then hit enter to see the result something as follows:
Please enter your name: cplusplus
Your name is: cplusplus

The C++ compiler also determines the data type of the entered value and selects the appropriate
stream extraction operator to extract the value and store it in the given variables.

The stream extraction operator >> may be used more than once in a single statement. To request
more than one datum you can use the following:
cin >> name >> age;

This will be equivalent to the following two statements:


cin >> name;
cin >> age;

cin and strings


The extraction operator can be used on cin to get strings of characters in the same way as with
fundamental data types:
string mystring;
cin>>mystring;

However, cin extraction always considers spaces (whitespaces, tabs, new-line...) as terminating
the value being extracted, and thus extracting a string means to always extract a single word, not
a phrase or an entire sentence.

Compiled By B T Chisuwa Page 108


To get an entire line from cin, there exists a function, called getline, that takes the stream (cin) as
first argument, and the string variable as second. For example:

The standard output stream (cout):


The predefined object cout is an instance of ostream class. The cout object is said to be
"connected to" the standard output device, which usually is the display screen. The cout is used
in conjunction with the stream insertion operator, which is written as << which are two less than
signs as shown in the following example.
#include <iostream>
using namespace std;
int main( )
{
char str[] = "Hello C++";
cout << "Value of str is : " << str << endl;
}

When the above code is compiled and executed, it produces following result:
Value of str is : Hello C++
The C++ compiler also determines the data type of variable to be output and selects the
appropriate stream insertion operator to display the value. The << operator is overloaded to
output data items of built-in types integer, float, double, strings and pointer values.

The insertion operator << may be used more than once in a single statement as shown above and
endl is used to add a new-line at the end of the line.

The standard error stream (cerr):


The predefined object cerr is an instance of ostream class. The cerr object is said to be attached
to the standard error device, which is also a display screen but the object cerr is un-buffered and
each stream insertion to cerr causes its output to appear immediately.

Compiled By B T Chisuwa Page 109


The cerr is also used in conjunction with the stream insertion operator as shown in the following
example.
#include <iostream>
using namespace std;
int main( )
{
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;
}

When the above code is compiled and executed, it produces the following result:
Error message: Unable to read....

The standard log stream (clog):


The predefined object clog is an instance of ostream class. The clog object is said to be attached
to the standard error device, which is also a display screen but the object clog is buffered. This
means that each insertion to clog could cause its output to be held in a buffer until the buffer is
filled or until the buffer is flushed.

The clog is also used in conjunction with the stream insertion operator as shown in the following
example.
#include <iostream>
using namespace std;
int main( )
{
char str[] = "Unable to read....";
clog << "Error message : " << str << endl;
}

When the above code is compiled and executed, it produces the following result:
Error message : Unable to read....

Compiled By B T Chisuwa Page 110


You would not be able to see any difference in cout, cerr and clog with these small examples, but
while writing and executing big programs then difference becomes obvious. So this is good
practice to display error messages using cerr stream and while displaying other log messages
then clog should be used.

Manipulators
Manipulators are operators that are used to format the data display. The most commonly used
manipulators are endl and setw.

endl
The endl manipulator, when used in an output statement, causes a linefeed to be inserted. It has
the same effect as using the newline character “\n”.
#include<iostream>

using namespace std;

int main()
{
cout << "Hello world 1" << endl;
cout << "Hello world 2\n";

return 0;
}

produces
Hello world 1
Hello world 2

setw
- Adjusts the field width for the item about to be printed.
- The setw() manipulator takes an integer argument which is the minimum field width for the
value to be printed.
#include <iostream>
#include <iomanip>

using namespace std;

Compiled By B T Chisuwa Page 111


int main()
{
// A test of setw()

cout << "*" << -17 << "*" << endl;


cout << "*" << setw(6) << -17 << "*" << endl << endl;

cout << "*" << "Hi there!" << "*" << endl;
cout << "*" << setw(20) << "Hi there!" << "*" << endl;
cout << "*" << setw(3) << "Hi there!" << "*" << endl;

return 0;
}

produces
*-17*
* -17*

*Hi there!*
* Hi there!*
*Hi there!*

Note
• The values are right justified in their fields. This can be changed.
• What happens if the value is too big to fit in the field.

Important Points
• The argument given to setw() is a minimum width. If the value needs more space, the
output routines will use as much as is needed.
• This field overflow strategy is different than that used in other programming languages.
Some languages will fill a small field with *'s or #'s. Others will truncate the value. The
philosophy for the C++ standard output is that it's better to have a correct value formatted
poorly than to have a nicely formatted error.
• The default field width is 0.
• Values can be justified in their fields. There are three manipulators for adjusting the
justification: left, right, and internal.

Compiled By B T Chisuwa Page 112


• The default justification is right justification.
• Left - left justify all values in their fields.
• Right - right justify all values in their fields. This is the default justification value.
#include <iostream>
#include <iomanip>

using std::cout;
using std::endl;
using std::setw;
using std::left;
using std::right;

int main()
{
cout << "*" << -17 << "*" << endl;
cout << "*" << setw(6) << -17 << "*" << endl;
cout << left;
cout << "*" << setw(6) << -17 << "*" << endl << endl;

cout << "*" << "Hi there!" << "*" << endl;
cout << "*" << setw(20) << "Hi there!" << "*" << endl;
cout << right;
cout << "*" << setw(20) << "Hi there!" << "*" << endl;

return 0;
}

produces
*-17*
* -17*
*-17 *

*Hi there!*
*Hi there! *
* Hi there!*

• internal- internally justifies numeric values in their fields. Internal justification separates the
sign of a number from its digits. The sign is left justified and the digits are right justified.
This is a useful format in accounting and business programs, but is rarely used in other
applications.

Compiled By B T Chisuwa Page 113


#include <iostream>
#include <iomanip>

using std::cout;
using std::endl;
using std::setw;
using std::internal;

int main()
{
cout << setw(9) << -3.25 << endl;
cout << internal << setw(9) << -3.25 << endl;

return 0;
}

produces
-3.25
- 3.25

Setting Precision:
By default, the floating numbers are printed with six digits after the decimal point. However, we
can specify the number of digits to be displayed after the decimal point while printing the
floating-point numbers. This can be done using the precision() member function as follows:
Cout.precision(d);

Where d is the number of digits to the right of the decimal point. For example, the statements
Cout.precision(3)
Cout << sqrt(2) << “\n”;
Cout << 3.14159 << “\n”;
Cout << 2.50032 << “\n”;

Will produce the following output:


1.141 (truncated)
3.142 (rounded to the nearest cent)
2.5 (no trailing zeros)

Compiled By B T Chisuwa Page 114


Note that, unlike the function setw(), precision() retains the setting in effect until it is reset. That
is why we have only declared only one statement for the precision setting which is used by all
the three outputs.

We can set different values to different precision as follows:

Cout.precision(3);
Cout << sqrt(2) << “\n”;
Cout.precision(5); //Reset the precision
Cout << 3.14159 << “\n”;

Compiled By B T Chisuwa Page 115


DATA STRUCTURES

The C/C++ arrays allow you to define variables that combine several data items of the same kind
but a structure is a collection of variables of different data types under a single name. It is similar
to a class in that, both holds a collection of data of different data types.

In C++, a structure can have both variables and functions as members. It can also declare some
of its members as ‘private’ so that they cannot be accessed directly by the external functions.

Defining a structure in C++


The struct keyword defines a structure type followed by an identifier (name of the structure).
Then inside the curly braces, you can declare one or more members (declare variables inside
curly braces) of that structure. For example:

Here a structure person is defined which has three members: name, age and salary.

At the end of the structure's definition, before the final semicolon, you can specify one or more
structure variables but it is optional. Here is the way you would declare the Person structure:
struct Person
{
char name[50];
int age;
float salary;

Compiled By B T Chisuwa Page 116


}bill;

Note: Remember to end the declaration with a semicolon (;)


Defining a structure variable
Once you declare a structure person as above. You can define a structure variable as:

Here, a structure variable bill is defined which is of type structure Person.

Accessing members of a structure


The members of structure variable are accessed using a member access operator (.) also known
as dot (.) operator.

Suppose, you want to access age of structure variable bill and assign 50 to it. You can perform
this task by using following code below:

Example: C++ Structure


C++ Program to assign data to members of a structure variable and display it
#include <iostream>
using namespace std;

struct Student
{
char regnumber[20];
char fullname[50];
char address[50];
int age;
};

int main()
{
Student s1;
cout << "Enter regnumber: ";

Compiled By B T Chisuwa Page 117


cin.get(s1.regnumber, 20);
cout << "Enter Full name: ";
cin.get(s1.fullname, 50);
cout << "Enter Address: ";
cin.get(s1.address, 50);
cout << "Enter age: ";
cin >> s1.age;

cout << "\nDisplaying Information." << endl;


cout << "Name: " << p1.name << endl;
cout <<"Age: " << p1.age << endl;
cout << "Salary: " << p1.salary;

return 0;
}

Output

Here a structure Person is declared which has three members name, age and salary. Inside
main() function, a structure variable p1 is defined. Then, the user is asked to enter information
and data entered by user is displayed.

Nested Structures
When a structure contains another structure, it is called nested structure. For example, we have
two structures named Address and Employee. To make Address nested to Employee, we have to
define Address structure before and outside Employee structure and create an object of Address
structure inside Employee structure.

Compiled By B T Chisuwa Page 118


Syntax for structure within structure or nested structure
struct structure1
{
----------
----------
};

struct structure2
{
----------
----------
struct structure1 obj;
};

Example for structure within structure or nested structure

#include<iostream.h>

struct Address
{
char HouseNo[25];
char City[25];
char PinCode[25];
};

struct Employee
{
int Id;
char Name[25];
float Salary;
struct Address Add;
};

void main()
{
int i;
Employee E;

cout << "\n\tEnter Employee Id : ";


cin >> E.Id;

Compiled By B T Chisuwa Page 119


cout << "\n\tEnter Employee Name : ";
cin >> E.Name;

cout << "\n\tEnter Employee Salary : ";


cin >> E.Salary;

cout << "\n\tEnter Employee House No : ";


cin >> E.Add.HouseNo;

cout << "\n\tEnter Employee City : ";


cin >> E.Add.City;

cout << "\n\tEnter Employee House No : ";


cin >> E.Add.PinCode;

cout << "\nDetails of Employees";


cout << "\n\tEmployee Id : " << E.Id;
cout << "\n\tEmployee Name : " << E.Name;
cout << "\n\tEmployee Salary : " << E.Salary;
cout << "\n\tEmployee House No : " << E.Add.HouseNo;
cout << "\n\tEmployee City : " << E.Add.City;
cout << "\n\tEmployee House No : " << E.Add.PinCode;

Output:
Enter Employee Id : 101
Enter Employee Name : Suresh
Enter Employee Salary : 45000
Enter Employee House No : 4598/D
Enter Employee City : Delhi
Enter Employee Pin Code : 110056

Details of Employees
Employee Id : 101
Employee Name : Suresh
Employee Salary : 45000
Employee House No : 4598/D
Employee City : Delhi
Employee Pin Code : 110056

Compiled By B T Chisuwa Page 120


Structures as Function Arguments:
You can pass a structure as a function argument in very similar way as you pass any other
variable or pointer. You would access structure variables in the similar way as you have accessed
in the above example:
#include <iostream>
#include <cstring>
using namespace std;

void printBook( struct Books book );

struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};

int main( ) {
Books Book1; // Declare Book1 of type Book
Books Book2; // Declare Book2 of type Book

// book 1 specification
strcpy( Book1.title, "Learn C++ Programming");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Programming");
Book1.book_id = 6495407;

// book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");

Compiled By B T Chisuwa Page 121


strcpy( Book2.subject, "Telecom");
Book2.book_id = 6495700;

// Print Book1 info


printBook( Book1 );

// Print Book2 info


printBook( Book2 );
return 0;
}

void printBook(Books book ) {


cout << "Book title : " << book.title <<endl;
cout << "Book author : " << book.author <<endl;
cout << "Book subject : " << book.subject <<endl;
cout << "Book id : " << book.book_id <<endl;
}

When the above code is compiled and executed, it produces the following result:
Book title : Learn C++ Programming
Book author : Chand Miyan
Book subject : C++ Programming
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700

Compiled By B T Chisuwa Page 122


Pointers to Structures:
You can define pointers to structures in very similar way as you define pointer to any other
variable as follows:
Books *struct_pointer;

Now, you can store the address of a structure variable in the above defined pointer variable. To
find the address of a structure variable, place the & operator before the structure's name as
follows:
struct_pointer = &Book1;

To access the members of a structure using a pointer to that structure, you must use the ->
operator as follows:
struct_pointer->title;

Let us re-write above example using structure pointer, hope this will be easy for you to
understand the concept:
#include <iostream>
#include <cstring>

using namespace std;

struct Books {
char title[50];
char author[50];
char subject[100];
int book_id; };

void printBook(Books *book);

int main( ) {
struct Books Book1; // Declare Book1 of type Book

Compiled By B T Chisuwa Page 123


struct Books Book2; // Declare Book2 of type Book

// Book 1 specification
strcpy( Book1.title, "Learn C++ Programming");
strcpy( Book1.author, "Chand Miyan");
strcpy( Book1.subject, "C++ Programming");
Book1.book_id = 6495407;

// Book 2 specification
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Yakit Singha");
strcpy( Book2.subject, "Telecom");
Book2.book_id = 6495700;

// Print Book1 info, passing address of structure


printBook(&Book1);

// Print Book2 info, passing address of structure


printBook(&Book2);
return 0;
}

// This function accept pointer to structure as parameter.


void printBook(Books *book ) {
cout << "Book title : " << book->title <<endl;
cout << "Book author : " << book->author <<endl;
cout << "Book subject : " << book->subject <<endl;
cout << "Book id : " << book->book_id <<endl;
}

When the above code is compiled and executed, it produces the following result:

Compiled By B T Chisuwa Page 124


Book title : Learn C++ Programming
Book author : Chand Miyan
Book subject : C++ Programming
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700

The typedef Keyword


There is an easier way to define structs or you could "alias" types you create. For example:
typedef struct
{
char title[50];
char author[50];
char subject[100];
int book_id;
}Books;

Now, you can use Books directly to define variables of Books type. Following is the example:
Books Book1, Book2;

You can use typedef keyword for non-structs as well as follows:


typedef long int *pint32;
pint32 x, y, z;

x, y and z are all pointers to long ints

Compiled By B T Chisuwa Page 125


There is very little syntactical difference between structures and classes in C++ and, therefore,
they can be used interchangeably with minor modifications. Since class is a specially introduced
data type in C++, most of the C++ programmers tend to use the structures for holding only data,
and classes to hold both the data and functions.

Note
The only difference between a structure and a class in C++ is that, by default, the members of a
class are private, while, by default, the members of a structure are public.

Compiled By B T Chisuwa Page 126


CLASSES AND OBJECTS

The main purpose of C++ programming is to add object orientation to the C programming
language and classes are the central feature of C++ that supports object-oriented programming
and are often called user-defined types.

Classes are an expanded concept of data structures: like data structures, they can contain data
members, but they can also contain functions as members.

A class is used to specify the form of an object and it combines data representation and methods
for manipulating that data into one neat package. The data and functions within a class are called
members of the class.

C++ Class Definitions:


When you define a class, you define a blueprint for a data type. This doesn't actually define any
data, but it does define what the class name means, that is, what an object of the class will consist
of and what operations can be performed on such an object.

A class definition starts with the keyword class followed by the class name; and the class body,
enclosed by a pair of curly braces. A class definition must be followed either by a semicolon or a
list of declarations. For example, we defined the Box data type using the keyword class as
follows:
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};

The keyword public determines the access attributes of the members of the class that follow it. A
public member can be accessed from outside the class anywhere within the scope of the class

Compiled By B T Chisuwa Page 127


object. You can also specify the members of a class as private or protected which we will
discuss in a sub-section.

Define C++ Objects:


An object is an instantiation of a class. In terms of variables, a class would be the type, and an
object would be the variable.

A class provides the blueprints for objects, so basically an object is created from a class. We
declare objects of a class with exactly the same sort of declaration that we declare variables of
basic types. Following statements declare two objects of class Box:
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box

Both of the objects Box1 and Box2 will have their own copy of data members.

Accessing the Data Members:


The public data members of objects of a class can be accessed using the direct member access
operator (.). Let us try following example to make the things clear:
#include <iostream>
using namespace std;
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};

int main( )
{
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
double volume = 0.0; // Store the volume of a box here

// box 1 specification
Box1.height = 5.0;
Box1.length = 6.0;

Compiled By B T Chisuwa Page 128


Box1.breadth = 7.0;

// box 2 specification
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;

// volume of box 1
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Volume of Box1 : " << volume <<endl;

// volume of box 2
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Volume of Box2 : " << volume <<endl;

return 0;
}

When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560

It is important to note that private and protected members can not be accessed directly using
direct member access operator (.). We will learn how private and protected members can be
accessed.

Classes & Objects in Detail:


So far, you have got very basic idea about C++ Classes and Objects. There are further interesting
concepts related to C++ Classes and Objects which we will discuss in various sub-sections listed
below:
Concept Description
Class member A member function of a class is a function that has its definition or its
functions prototype within the class definition like any other variable.
Class access A class member can be defined as public, private or protected. By default
modifiers members would be assumed as private.
Constructor & A class constructor is a special function in a class that is called when a new
destructor object of the class is created. A destructor is also a special function which is

Compiled By B T Chisuwa Page 129


called when created object is deleted.
C++ copy The copy constructor is a constructor which creates an object by initializing it
constructor with an object of the same class, which has been created previously.
C++ friend A friend function is permitted full access to private and protected members of
functions a class.
C++ inline With an inline function, the compiler tries to expand the code in the body of
functions the function in place of a call to the function.
The this pointer Every object has a special pointer this which points to the object itself.
in C++
Pointer to C++ A pointer to a class is done exactly the same way a pointer to a structure is. In
classes fact a class is really just a structure with functions in it.
Static members Both data members and function members of a class can be declared as static.
of a class

Class Member Functions


A member function of a class is a function that has its definition or its prototype within the class
definition like any other variable. It operates on any object of the class of which it is a member,
and has access to all the members of a class for that object.

Let us take previously defined class to access the members of the class using a member function
instead of directly accessing them:
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
double getVolume(void);// Returns box volume
};

Compiled By B T Chisuwa Page 130


Member functions can be defined within the class definition or separately using scope resolution
operator, ::. Defining a member function within the class definition declares the function inline,
even if you do not use the inline specifier. So either you can define Volume() function as below:
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
double getVolume(void)
{
return length * breadth * height;
}
};

If you like you can define same function outside the class using scope resolution operator, :: as
follows:
double Box::getVolume(void)
{
return length * breadth * height;
}

Here, only important point is that you would have to use class name just before :: operator. A
member function will be called using a dot operator (.) on a object where it will manipulate data
related to that object only as follows:
Box myBox; // Create an object
myBox.getVolume(); // Call member function for the object

Let us put above concepts to set and get the value of different class members in a class:
#include <iostream>
using namespace std;
class Box
{
public:
double length, breadth, height;
// Member functions declaration
double getVolume(void);
void setLength( double len );
void setBreadth( double bre );
void setHeight( double hei );

Compiled By B T Chisuwa Page 131


};
// Member functions definitions
double Box::getVolume(void)
{
return length * breadth * height;
}
void Box::setLength( double len )
{
length = len;
}
void Box::setBreadth( double bre )
{
breadth = bre;
}
void Box::setHeight( double hei )
{
height = hei;
}
int main( )
{
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
double volume = 0.0; // Store the volume of a box here

Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);

Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);

volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;

volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560

Compiled By B T Chisuwa Page 132


Nesting of Member Functions
We just discussed that a member function of a class can be called only by an object of that class
using a dot operator. However, there is an exception to this. A member function can be called by
using its name inside another member function of the same class. This is known as nesting of
member functions. The program below illustrates this feature.
#include <iostream>
using namespace std;

class set
{
int m, n;
public:
void input(void);
void display(void);
int largest(void);
};

int set :: largest(void)


{
if(m>=n)
return m;
else
return n;
}

void set :: input(void)


{
cout << “Input values of m and n” << “\n”;
cin>>m>>n;
}

void set :: display(void)


{
cout << “Largest value = ” << largest() << “\n”; // calling member function
}

int main()
{
set A;
A.input();
A.display();
return 0;
}

Compiled By B T Chisuwa Page 133


The output of the above program would be:
Input values of m and n
25 18
Largest value = 25

Arrays within a Class


The arrays can be used as member variables in a class. The following class definition is valid.
const int size = 10; //provides value for array size

class array
{
int a[size]; // ’a’ is int type array
public:
void setval(void);
void display(void);
};

The array variable a[ ] declared as a private member of the class array can be used in the member
functions, like any other array variable. We can perform any operations on it. For instance, in the
above class definition, the member function setval() sets the values of elements of an array a[ ],
and display() function displays the values. Similarly, we may use other member functions to
perform any other operations on the array values.

Let us consider a shopping list of items for which we place an order with a dealer every month.
The list includes details such as the code number and price of each item. We would like to
perform operations such as adding an item to the list, deleting an item from the list and printing
the total value of the order. The program below shows how these operations are implemented
using a class with arrays as data members.
#include <iostream>
using namespace std;

const m = 50;

class ITEMS
{
int itemCode[m];

Compiled By B T Chisuwa Page 134


float itemPrice[m];
int count;
public:
void CNT(void) {count = 0} // initialises count to 0
void getItem(void);
void displaySum(void);
void remove(void);
void displayItems(void);
};

Void ITEMS :: getItem(void) // assign values to data members of item


{
cout << “Enter item code : ”;
cin >> itemCode[count];

cout << “Enter item cost : ”;


cin>>itemPrice[count];
count++;
}

void ITEMS :: displaySum(void) // display total value of all items


{
float sum = 0;

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


{
Sum = sum + itemPrice[i];
}

cout << “\nTotal value : “ << sum << “\n”;


}

void ITEMS :: remove(void) // delete a specified item


{
int a;
cout << “Enter item code : ”;
cin>> a;

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


{
if(itemCode[i]==a)
{
itemPrice[i]=0;
}
}
}

Compiled By B T Chisuwa Page 135


void ITEMS :: displayItems(void) // displaying items
{
cout << “\nCode Price\n”;

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


{
cout <<”\n” << itemCode[i];
cout << ” ” << itemPrice[i];
}
cout << “\n”;
}

int main()
{
ITEMS order;
order.CNT();
int x;
do // do….while loop
{
cout <<\nYou can do the following;”
<< “Enter appropriate number \n”;
cout << “\n1 : Add an item”;
cout << “\n2 : Display total value”;
cout << “\n3 : Delete an item”;
cout << “\n4 : Display all items”;
cout << “\n5 : Quit”;
cout << “\n\nWhat is your option?”;

cin>>x;

switch(x)
{
case 1 : order.getItem(); break;
case 2 : order.displaySum(); break;
case 3 : order.remove(); break;
case 4 : order.displayItems(); break;
case 5 : break;
default : cout << “Error in input; try again\n”;
}

}while(x!=5); // do….while ends;


return 0;
}

The output of the above program would be

Compiled By B T Chisuwa Page 136


You can do the following; Enter appropriate number
1 : Add an item
2 : Display total value
3 : Delete an item
4 : Display all items
5 : Quit

What is your option? 1


Enter item code : 111
Enter item cost : 100

The program implements all the tasks using a menu-based user interface.

Arrays of Objects
We know that an array can be of any data type including struct. Similarly, we can also have
arrays of variables that are of the type class. Such variables are called arrays of objects. Consider
the following class definition:
class employee
{
char name[30];
float age;
public:
void getdata(void);
void putdata(void);
};

The identifier employee is a user-defined data type and can be used to create objects that relate
to different categories of the employees. Example:
employee manager[3] // array of manager
employee foreman[15] // array of foreman
employee worker[75] // array of worker

The array manager contains three objects(managers), namely, manager[0], manager[1] and
manager[2], of type employee class. Similarly, the foreman array contains 15 objects(foreman)
and the worker array contains 75 objects(workers).

Compiled By B T Chisuwa Page 137


Since an array of objects behaves like any other array, we can use the usual array-accessing
methods to access individual elements, and then the dot member operator to access the member
functions. For example, the statement
manager[i].putdata();

will display the data of the ith element of the array manager. That is, this statement requests the
object manager[i] to invoke the member function putdata().

An array of objects is stored inside the memory in the same way as a multi-dimensional array.
The array manager is represented below. Note that only the space for data items of the objects is
created. Member functions are stored seperately and will be used by all the objects.

Storage of data items of an object array

The program below illustrates the use of object arrays.


#include <iostream>
using namespace std;

class employee
{
char name[30]; //string as class member
float age;
public:

Compiled By B T Chisuwa Page 138


void getdata(void);
void putdata(void);
};

void employee :: getdata(void)


{
cout<< “Enter name: ”;
cin>> name;
cout<< “Enter age: ”;
cin>>age;
}

void employee :: putdata(void)


{
cout<< “Name: ” << name << endl;
cout<< “Age: ” << age << endl;
}

const int size = 3;

int main()
{
employee manager[size];

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


{
cout << “\nDetails of manager” << i+1 << endl;
manager[i].getdata();
}

cout << “\n”;

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


{
cout << “\nManager” << i+1 << endl;
manager[i].putdata();
}

return 0;
}

This being an iteractive program, the input data and the program output are shown below:
Details of manager1
Enter name: xxx
Enter age: 45

Compiled By B T Chisuwa Page 139


Details of manager2
Enter name: yyy
Enter age: 37

Details of manager3
Enter name: zzz
Enter age: 50

Manager1
Name: xxx
Age: 45

Manager2
Name: yyy
Age: 37

Manager3
Name: zzz
Age: 50

Objects as Function Arguments


Like other data type, an object may be used as a function argument. This can be done in two
ways:
• A copy of the entire object is passed to the function.
• Only the address of the object is transferred to the function.

The first method is called pass-by-value. Since a copy of the object is passed to the function, any
changes made to the object inside the function do not affect the object used to call the function.
The second method is called pass-by-reference. When an address of the object is passed, the
called function works directly on the actual object used in the call. This means that any changes
made to the object inside the function will reflect in the actual object. The pass-by-reference
method is more efficient since it requires to pass only the address of the object and not the entire
object.

The program below illustrates the use of objects as function arguments. It performs the addition
of time in the hour and minutes format.

Compiled By B T Chisuwa Page 140


#include <iostream>
using namespace std;

class time
{
int hours;
int minutes;
public:
void gettime(int h, int m)
{
hours = h;
minutes = m;
}

void puttime(void)
{
cout << hours << “ hours and ”;
cout << minutes << “ minutes ” << endl;
}

void sum(time, time); //declaration with objects as arguments


};

void time :: sum(time t1, time t2) // t1, t2 are objects


{
minutes = t1.minutes + t2.minutes;
hours = minutes/60;
minutes = minutes % 60;
hours = hours + t1.hours + t2.hours;
}

int main()
{
time T1, T2, T3;

T1.gettime(2, 45); //get T1


T2.gettime(3, 30); //get T2

T3.sum(T1, T2); // T3 = T1+T2

cout << “T1 = ”; T1.puttime(); // display T1


cout << “T2 = ”; T2.puttime(); // display T2
cout << “T3 = ”; T3.puttime(); // display T3

return 0;
}

Compiled By B T Chisuwa Page 141


The output of the above program would be:
T1 = 2 hours and 45 minutes
T2 = 3 hours and 30 minutes
T3 = 6 hours and 15 minutes

Note
Since the member function sum() is invoked by bthe object T3, with the objects T1 and T2 as
arguments, it can directly access the hours and minutes variables of T3. But, the members of T1
and T2 can be accessed only by using the dot operator (like T1.hours and T1.minutes).
Therefore, inside the function sum(), the variables hours and minutes refer to T3, T1.hours and
T1.minutes refer to T1, and T2.hours and T2.minutes refer to T2.

Figure below illustrates how the members are accessed inside the function sum().

An object can also be passed as an argument to a non-member function. However, such functions
can have access to the public member functions only through the objects passed as arguments to
it. These functions cannot have access to the private data members.

Class Access Modifiers


Data hiding is one of the important features of Object Oriented Programming which allows
preventing the functions of a program to access directly the internal representation of a class
type. The access restriction to the class members is specified by the labeled public, private, and
protected sections within the class body. The keywords public, private, and protected are called
access specifiers.

Compiled By B T Chisuwa Page 142


A class can have multiple public, protected, or private labeled sections. Each section remains in
effect until either another section label or the closing right brace of the class body is seen. The
default access for members and classes is private.
class Base {
public:
// public members go here
protected:
// protected members go here
private:
// private members go here
};

The public members:


A public member is accessible from anywhere outside the class but within a program. You can
set and get the value of public variables without any member function as shown in the following
example:
#include <iostream>
using namespace std;

class Line
{
public:
double length;
void setLength( double len );
double getLength( void );
};

double Line::getLength(void)
{
return length ;
}

void Line::setLength( double len )


{
length = len;
}
int main( )
{
Line line;

Compiled By B T Chisuwa Page 143


line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
// set line length without member function
line.length = 10.0; // OK: because length is public
cout << "Length of line : " << line.length <<endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:

Length of line : 6
Length of line : 10

The private members:


A private member variable or function cannot be accessed, or even viewed from outside the
class. Only the class and friend functions can access private members.

By default all the members of a class would be private, for example in the following class width
is a private member, which means until you label a member, it will be assumed a private
member:
class Box
{
double width;
public:
double length;
void setWidth(double wid );
double getWidth( void );
};
Practically, we define data in private section and related functions in public section so that they
can be called from outside of the class as shown in the following program.
#include <iostream>
using namespace std;
class Box
{
double width;
public:
double length;
void setWidth( double wid );
double getWidth( void );

Compiled By B T Chisuwa Page 144


};
double Box::getWidth(void)
{
return width ;
}
void Box::setWidth( double wid )
{
width = wid;
}

int main( )
{
Box box;
// set box length without member function
box.length = 10.0; // OK: because length is public
cout << "Length of box : " << box.length <<endl;
// set box width without member function
// box.width = 10.0; // Error: because width is private
box.setWidth(10.0); // Use member function to set it.
cout << "Width of box : " << box.getWidth() <<endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Length of box : 10
Width of box : 10

The protected members:


A protected member variable or function is very similar to a private member but it provided one
additional benefit that they can be accessed in child classes, which are called derived classes.

You will learn derived classes and inheritance in next chapter. For now you can check following
example where I have derived one child class SmallBox from a parent class Box.

Following example is similar to above example and here width member will be accessible by
any member function of its derived class SmallBox.
using namespace std;

class Box
{

Compiled By B T Chisuwa Page 145


protected:
double width;
};

class SmallBox:Box // SmallBox is the derived class.


{
public:
void setSmallWidth( double wid );
double getSmallWidth( void );
};

// Member functions of child class


double SmallBox::getSmallWidth(void)
{
return width ;
}

void SmallBox::setSmallWidth( double wid )


{
width = wid;
}

int main( )
{
SmallBox box;
box.setSmallWidth(5.0);
cout << "Width of box : "<< box.getSmallWidth() << endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:

Width of box : 5

C++ Friend Functions


A friend function of a class is defined outside that class' scope but it has the right to access all
private and protected members of the class. Even though the prototypes for friend functions
appear in the class definition, friends are not member functions.

A friend can be a function, function template, or member function, or a class or class template, in
which case the entire class and all of its members are friends.

Compiled By B T Chisuwa Page 146


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

To declare a function as a friend of a class, precede the function prototype in the class definition
with keyword friend as follows:
class Box
{
double width;
public:
double length;
friend void printWidth( Box box);
void setWidth( double wid);
};

Member functions of one class can be friend functions of another class. In such cases, they are
defined using the scope resolution operator as shown below:
class X
{
…..
…...
int fun1(); // member function of X
……
};

class Y{
…..

Compiled By B T Chisuwa Page 147


…..
friend int X::fun1(); // fun1() of X is friend of Y
…..
};

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

C++ Friend Class


To declare all member functions of class ClassTwo as friends of class ClassOne, place a
following declaration in the definition of class ClassOne:
friend class ClassTwo;

Consider the following program:


#include <iostream>
using namespace std;

class Box
{
double width;

public:
friend void printWidth( Box box );
void setWidth( double wid );
};

// Member function definition


void Box::setWidth( double wid )
{
width = wid;
}

// Note: printWidth() is not a member function of any class.


void printWidth( Box box )
{
// Because setWidth() is a friend of Box, it can directly access any member of this class
cout << "Width of box : " << box.width <<endl;
}

Compiled By B T Chisuwa Page 148


int main( )
{
Box box;

box.setWidth(10.0);
printWidth( box );

return 0;
}

When the above code is compiled and executed, it produces the following result:
Width of box : 10

Returning Objects
A function cannot only receive objects as arguments but also can return them. The example
below illustrates how an object can be created (within a function) and returned to another
function.
#include <iostream>
using namespace std;

class complex // x + iy form


{
float x; // real part
float y; // imaginary part
public:
void input(float real, float imag)
{
x = real;
y = imag;
}

friend complex sum(complex, complex);

void show(complex);
};

complex sum(complex c1, complex c2)


{
complex c3; // objects c3 is created

Compiled By B T Chisuwa Page 149


c3.x = c1.x + c2.x;
c3.y = c1.y + c2.y;
return c3; // returns object c3
}

void complex :: show(complex c)


{
cout << c.x << “ + j” << c.y << endl;
}

int main()
{
complex A, B, C;

A.input(3.1 , 5.65);
B.input(2.75 , 1.2);

C = sum(A, B); // C = A + B

cout << “A = ”; A.show(A);


cout << “B = ”; B.show(B);
cout << “C = ”; C.show(C);

return 0;
}

Upon execution, the program would generate the following output:


A = 3.1 + J5.65
B = 2.75 + j1.2
C = 5.85 + j6.85

The program adds two complex numbers A and B to produce a third complex number C and
displays all the three numbers.
Const Member Functions
If a member function does not alter any data in the class, then we may declare it as a const
member function as follows:
void mul(int, int) const;
double get_balance() const;

The qualifier const is appended to the function prototypes (in both declaration and definition).
The compiler will generate an error message if such functions try to alter the data values.

Compiled By B T Chisuwa Page 150


C++ Inline Functions
Inline functions are a lot like a placeholder. Once you define an inline function, using the 'inline'
keyword, whenever you call that function the compiler will replace the function call with the
actual code from the function. Using the inline keyword is simple, just put it before the name of a
function. Then, when you use that function, pretend it is a non-inline function.

A function definition in a class definition is an inline function definition, even without the use of
the inline specifier.

Following is an example, which makes use of inline function to return max of two numbers:
#include <iostream>
using namespace std;

inline int Max(int x, int y)


{
return (x > y)? x : y;
}

int main( )
{
cout << "Max(20,10): " << Max(20,10) << endl;
cout << "Max (0,200): " << Max(0,200) << endl;
cout << "Max (100,1010): " << Max(100,1010) << endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Max (20,10): 20
Max (0,200): 200
Max (100,1010): 1010

Compiled By B T Chisuwa Page 151


The this Pointer in C++
Every object in C++ has access to its own address through an important pointer called this
pointer. Thethis pointer is an implicit parameter to all member functions. Therefore, inside a
member function, this may be used to refer to the invoking object.

Friend functions do not have a this pointer, because friends are not members of a class. Only
member functions have a this pointer.

Let us try the following example to understand the concept of this pointer:
#include <iostream>
using namespace std;

class Box
{
double length, breadth, height;
public:
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
}

double Volume()
{
return length * breadth * height;
}

int compare(Box box)


{
return this->Volume() > box.Volume();
}
};

Compiled By B T Chisuwa Page 152


int main(void)
{
Box Box1(3.3, 1.2, 1.5);
Box Box2(8.5, 6.0, 2.0);

if(Box1.compare(Box2))
{
cout << "Box2 is smaller than Box1" <<endl;
}
else
{
cout << "Box2 is equal to or larger than Box1" <<endl;
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
Constructor called.
Constructor called.
Box2 is equal to or larger than Box1

Pointer to C++ Classes


A pointer to a C++ class is done exactly the same way as a pointer to a structure and to access
members of a pointer to a class you use the member access operator -> operator, just as you do
with pointers to structures. Also as with all pointers, you must initialize the pointer before using
it.

Let us try the following example to understand the concept of pointer to a class:
#include <iostream>
using namespace std;

class Box
{
double length, breadth, height;

public:

Compiled By B T Chisuwa Page 153


Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
}

double Volume()
{
return length * breadth * height;
}
};

int main(void)
{
Box Box1(3.3, 1.2, 1.5);
Box Box2(8.5, 6.0, 2.0);

Box *ptrBox; // Declare pointer to a class.

// Save the address of first object


ptrBox = &Box1;

// Now try to access a member using member access operator


cout << "Volume of Box1: " << ptrBox->Volume() << endl;

// Save the address of first object


ptrBox = &Box2;

// Now try to access a member using member access operator


cout << "Volume of Box2: " << ptrBox->Volume() << endl;

return 0;
}

When the above code is compiled and executed, it produces the following result:
Constructor called.

Compiled By B T Chisuwa Page 154


Constructor called.
Volume of Box1: 5.94
Volume of Box2: 102

Pointers to Members
It is possible to take the address of a member of a class and assign it to a pointer. The address of
a member can be obtained by applying the operator & to a “fully qualified” class member name.
A class member pointer can be declared using the operator ::* with the class name. For example,
given the class
class A
{
private:
int m;
public:
void show();
};

We can define a pointer to the member m as follows:


int A::* ip = &A :: m;

The ip pointer created thus acts like a class member in that it must be invoked with a class
object. In the statement above, the phrase A ::* means “pointer-to-member of A class”. The
phrase &A :: m means the “address of the m member of A class”.

Remember, the following statement is not valid:


int *ip = &m; // won’t work

This is because m is not simply an int type data. It has meaning only when it is associated with
the class to which it belongs. The scope operator must be applied to both the pointer and the
member.

Compiled By B T Chisuwa Page 155


The pointer ip can now be used to access the member m inside member functions (or friend
functions). Let us assume that a is an object of A declared in a member function. We can access
m using the pointer ip as follows:
cout << a.*ip; // display
cout << a.m; // same as above

Now, look at the following code:


ap = &a; // ap is pointer to object a
cout << ap -> *ip; // display m
cout << ap -> m; // same as above

The dereferencing operator ->* is used to access a member when we use pointers to both the
object and the member. The dereferencing operator.* is used when the object itself is used with
the member pointer. Note that *ip is used like a member name.

We can also design pointers to member functions which, then, can be invoked using the
dereferencing operators in the main as shown below:
(object-name .* pointer-to-member function)(10);
(pointer-to-object ->* pointer-to-member function)(10)

The precedence of () is higher than that of .* and ->*, so the parantheses are necessary.

The program below illustrates the use of dereferencing operators to access the class members.
#include <iostream>
using namespace std;

class M
{
int x;
int y;
public:
void set_xy(int a, int b)
{
x = a;
y = b;
}

friend int sum(M m);

Compiled By B T Chisuwa Page 156


};

int sum(M m)
{
int M ::* px = &M :: x;
int M ::* py = &M :: y;
M *pm = &m;
int S = m.*px + pm->*py;
return S;
}

int main()
{
M n;

void (M :: *pf)(int,int) = &M :: set_xy;


(n.*pf)(10,20);
cout << “SUM = ” << sum(n) << endl;

M *op = &n;
(op->*pf)(30,40);
cout << “SUM = ” << sum(n) << endl;

return 0;
}

The output of the above program would be:


sum = 30
sum = 70

Local Classes
Classes can be defined and used inside a function or a block. Such classes are called local
classes. Examples:
void test(int a) // function
{
…..
…..
class student // local class
{
…..
….. // class definition

…..

Compiled By B T Chisuwa Page 157


};
…..
…..
student s1(a); // create student object
….. // use student object
}

Local classes can use global variables (declared above the function) and static variables declared
inside the function but cannot use automatic local variables. The global variables should be used
with the scope operator (::).

There are some restrictions in constructing local classes. They cannot have static data members
and member functions must be defined inside the local classes. Enclosing function cannot access
the private members of a local class. However, we can achieve this by declaring the enclosing
function as a friend.

Static Members of a Class


We can define class members static using static keyword. When we declare a member of a class
as static it means no matter how many objects of the class are created, there is only one copy of
the static member.

A static member is shared by all objects of the class. All static data is initialized to zero when the
first object is created, if no other initialization is present. It is visible only within the class, but its
lifetime is the entire program. We can't put it in the class definition but it can be initialized
outside the class as done in the following example by redeclaring the static variable, using the
scope resolution operator :: to identify which class it belongs to.
Let us try the following example to understand the concept of static data members:
#include <iostream>
using namespace std;

class Box
{
double length, breadth, height;

public:

Compiled By B T Chisuwa Page 158


static int objectCount;

Box(double l=2.0, double b=2.0, double h=2.0)


{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// Increase every time object is created
objectCount++;
}
double Volume()
{
return length * breadth * height;
}
};

// Initialize static member of class Box


int Box::objectCount = 0;

int main(void)
{
Box Box1(3.3, 1.2, 1.5); // Declare box1
Box Box2(8.5, 6.0, 2.0); // Declare box2

// Print total number of objects.


cout << "Total objects: " << Box::objectCount << endl;

return 0;
}

When the above code is compiled and executed, it produces the following result:
Constructor called.
Constructor called.
Total objects: 2

Since static variables are associated with the class itself rather than with any class object, they
are also known as class variables.

Compiled By B T Chisuwa Page 159


Static Function Members:
By declaring a function member as static, you make it independent of any particular object of the
class. A static member function can be called even if no objects of the class exist and the static
functions are accessed using only the class name and the scope resolution operator ::.

A static member function can only access static data member, other static member functions and
any other functions from outside the class.

Static member functions have a class scope and they do not have access to the this pointer of the
class. You could use a static member function to determine whether some objects of the class
have been created or not.

Let us try the following example to understand the concept of static function members:
#include <iostream>
using namespace std;

class Box
{
double length, breadth, height;

public:
static int objectCount;

Box(double l=2.0, double b=2.0, double h=2.0)


{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// Increase every time object is created
objectCount++;
}

double Volume()
{
return length * breadth * height;
}

static int getCount()


{

Compiled By B T Chisuwa Page 160


return objectCount;
}
};

int Box::objectCount = 0;

int main(void)
{
// Print total number of objects before creating object.
cout << "Inital Stage Count: " << Box::getCount() << endl;

Box Box1(3.3, 1.2, 1.5); // Declare box1


Box Box2(8.5, 6.0, 2.0); // Declare box2

// Print total number of objects after creating object.


cout << "Final Stage Count: " << Box::getCount() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2

Compiled By B T Chisuwa Page 161


CONSTRUCTORS AND DESTRUCTORS

The Class Constructor:


A class constructor is a special member function of a class that is executed whenever we create
new objects of that class.

A constructor will have exact same name as the class and it does not have any return type at all,
not even void. Constructors enable an object to initialize itself when it is created. This is known
as automatic initialization of objects. Constructors can be very useful for setting initial values for
certain member variables. It is called constructor because it constructs the values of data
members of the class.

A constructor is declared and defined as follows:

// class with constructor

class integer
{
int m, n;
public:
integer(void); // constructor declared
…..
…..
};

integer :: integer(void) // constructor defined


{
m = 0; n = 0;
}

When a class contains a constructor like the one defined above, it is guaranteed that an object
created by the class will be initialised automatically. For example, the declaration
integer int1; // object int1 created

not only creates the object int1 of type integer but also initialises its data members m and n to
zero. There is no need to write any statement to invoke the constructor function (as we do with
Compiled By B T Chisuwa Page 162
the normal member functions).If a ‘normal’ member function is defined for zero initialisation,
we would need to invoke this function for each of the objects seperately. This would be very
inconvenient, if there are a large number of objects.

A constructor that accepts no parameters is called the default constructor. The default
constructor for class A is A::A(). If no such constructor is defined, then the compiler suppliers a
default constructor. Therefore a statement such as
A a;

Invokes the default constructor of the compiler to create the object a.

The constructor functions have some special characteristics. These are :


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

Remember, when a constructor is declared for a class, initialisation of the class objects becomes
mandatory.

Following example explains the concept of constructor:


#include <iostream>
using namespace std;

class Line
{
public:
Compiled By B T Chisuwa Page 163
void setLength( double len );
double getLength( void );
Line(); // This is the constructor
private:
double length;
};

// Member functions definitions including constructor


Line::Line(void)
{
cout << "Object is being created" << endl;
}

void Line::setLength( double len )


{
length = len;
}

double Line::getLength( void )


{
return length;
}

int main( )
{
Line line;

// set line length


line.setLength(6.0);

cout << "Length of line : " << line.getLength() <<endl;


return 0;
}

When the above code is compiled and executed, it produces the following result:
Object is being created
Length of line : 6

Parameterized Constructor:
The constructor interger(), defined above, initialises the data members of all the objects to zero.
However, in practice it may be necessary to initialise the various data elements of different

Compiled By B T Chisuwa Page 164


objects with different values when they are created. C++ permits us to achieve this objective by
passing arguments to the constructor function when the objects are created. The constructors that
can take arguments are called parameterised constructors.

The constructor integer() may be modified to take arguments as shown below:


class integer
{
int m, n;
public:
integer(int x, int y); // parameterised constructor
…..
…..
};

integer :: integer(int x, int y)


{
m = x; n = y;
}

When a constructor has been parameterised, the object declaration statement such as
integer int1

may not work. We must pass the initial values as arguments to the constructor function when an
object is declared. This can be done in two ways:
• By calling the constructor explicitly.
• By calling the constructor implicitly.

The following declaration illustrates the first method:


integer int1 = integer(0, 100); // explicit call

This statement creates an integer object int1 and passes the values 0 and 100 to it. The second is
implemented as follows:
integer int1(0, 100); // implicit call

This method, sometimes called shorthand method, is used very often as it is shorter, looks better
and easy to implement.

Compiled By B T Chisuwa Page 165


Remember, when the constructor is parameterised, we must provide appropriate arguments for
the constructor. The program below demonstrates the passing of arguments to the constructor
functions.
#include <iostream>
using namespace std;

class integer
{
int m,n;
public:
integer(int, int); // constructor declared

void display(void)
{
cout << “m = ” << m <<endl;
cout << “n = ” << n <<endl;
}
};

integer::integer(int x, int y) // constructor defined


{
m = x; n = y;
}

int main( )
{
integer int1(0, 100); // constructor called implicitly

integer int2 = integer(25, 75); // constructor called explicitly


cout << "\nOBJECT1 " << endl;
int1.display();

cout << "\nOBJECT2 " << endl;


int2.display();

return 0;
}

Compiled By B T Chisuwa Page 166


The program above displays the following output:
Object 1
m=0
n = 100

Object 2
m = 25
n = 75

The constructor functions can also be defined as inline functions. Example:


class integer
{
int m,n;

public:
integer(int x, int y) // Inline constructor
{
m = x; n = y;
}
…..
…..
};

The parameters of a constructor can be of any type except that of the class to which it belongs.
For example,
class A
{
…..
…..
public:
A(A);
};

is illegal.

However, a constructor can accept a reference to its own class as a parameter. Thus, the
statement
class A
{
…..

Compiled By B T Chisuwa Page 167


…..
public:
A(A&);
};

is valid. In such cases, the constructor is called the copy constructor.

Multiple Constructors in a Class


So far we have used two kinds of constructors. They are:
integer(); // No arguments
integer(int, int); // Two arguments

In the first case, the constructor itself supplies the data values and no values are passed by the
calling program. In the second case, the function call passes the appropriate values from main().
C++ permits us to use both these constructors in the same class. For example, we could define a
class as follows:
class integer
{
int m,n;

public:
integer(){m=0; n=0;} // constructor 1
integer(int a, int b)
{m = a; n = b;} // constructor 2
integer(integer & i)
{m = i.m; n = i.n;} // constructor 3
};

This declares three constructors for an integer object. The first constructor receives no
arguments, the second receives two integer arguments and the third receives one integer object
as an argument. For example, the declaration
integer 11;

would automatically invoke the first constructor and set both m and n of 11 to zero. The
statement
integer 12(20, 40);

Compiled By B T Chisuwa Page 168


would call the second constructor which will initialise the data members m and n of 12 to 20 and
40 respectively. Finally, the statement
integer 13(12);

would invoke the third constructor which copies the values of 12 into 13. In other words, it sets
the value of every data element of 13 to the value of the corresponding data element of 12. As
mentioned earlier, such a constructor is called the copy constructor. We learned that the process
of sharing the same name by two or more functions is referred to as function overloading.
Similarly, when more than one constructor function is defined in a class, we say that the
constructor is overloaded.

The program below shows the use of overloaded constructors.


#include <iostream>
using namespace std;

class complex
{
float x, y;
public:
complex(){} // constructor no arg
complex(float a) {x = y = a;} // constructor-one arg
complex(float real, float imag) // constructor-two args
{x = real; y = imag;}

friend complex sum(complex, complex);


friend void show(complex);
};

complex sum(complex c1, complex c2) // friend


{
complex c3;
c3.x = c1.x + c2.x;
c3.y = c1.y + c2.y;
return c3;
}

void show(complex c) // friend


{
cout << c.x << “ + j” << c.y << endl;
}

Compiled By B T Chisuwa Page 169


int main()
{
complex A(2.7, 3.5); // define & initialise
complex B(1.6); // define & initialise
complex C; // define

C = sum(A, B); // sum() is a friend


cout << “A = ”; show(A); // show() is also a friend
cout << “B = ”; show(B);
cout << “C = ”; show(C);

// Another way to give initial values (second method)


complex P,Q,R; // define P, Q, and R

P = complex(2.5, 3.9); // initialise P


Q = complex(1.6, 2.5); // initialise Q
R = sum(P, Q);

cout <<endl;
cout << “P = ”; show(P);
cout << “Q = ”; show(Q);
cout << “R = ”; show(R);

return 0;
}

The output of the program above would be:


A = 2.7 + J3.5
B = 1.6 + J1.6
C = 4.3 + J5.1

P = 2.5 + J3.9
Q = 1.6 + J2.5
R = 4.1 + J6.4

Note
There are three constructors in the class complex. The first constructor, which takes no
arguments, is used to create objects which are not initialised; the second, which takes one
argument, is used to create objects and initialise them; and the third, which takes two arguments,
is also used to create objects and initialise them to specific values. Note that the second method
of initialising values looks better.

Compiled By B T Chisuwa Page 170


Let us look at the first constructor again.
complex(){ }

It contains the empty body and does not do anything. We just stated that this is used to create
objects without any initial values. Remember, we have defined objects in the earlier examples
without using such a constructor. Why do we need this constructor now?. As pointed out earlier,
C++ compiler has an implicit constructor which creates objects, even though it was not defined
in the class.

This works fine as long as we do not use any other constructors in the class. However, once we
define a constructor, we must also define the “do-nothing” implicit constructor. This constructor
will not do anything and is defined just to satisfy the compiler.

Constructors with Default Arguments


It is possible to define constructors with default arguments. For example, the constructor
complex() can be declared as follows:
complex(float real, float imag=0);

Thedefault value of the argument imag is zero. Then, the statement


complex C(5.0);

assigns the value 5.0 to real variable and 0.0 to imag (by default). However, the statement
complex C(2.0, 3.0);

assigns 2.0 to real and 3.0 to imag. The actual parameter, when specified, overrides the default
value. As pointed out earlier, the missing arguments must be the trailing ones.

It is important to distinguish between the default constructor A::A() and the default argument
constructor A::A(int = 0). The default argument constructor can be called with either one
argument or no arguments. When called with no arguments, it becomes a default constructor.
When both these forms are used in a class, it causes ambiguity for a statement such as
A a;

Compiled By B T Chisuwa Page 171


The ambiguity is whether to ‘call’ A::A() or A::A(int = 0).

Dynamic initialisation of Objects


Class objects can be initialised dynamically too. That is to say, the initial value of an object may
be provided during run time. One advantage of dynamic initialisation is that we can provide
various initialisation formats, using overloaded constructors. This provides the flexibility of
using different format of data at run time depending upon the situation.

Consider the long term deposit schemes working in the commercial banks. The banks provide
different interest rates for different schemes as well as for different periods of investment. The
program below illustrates how to use the class variables for holding account details and how to
construct these variables at run time using dynamic initialisation.
#include <iostream>
using namespace std;

class Fixed_deposit
{
long int P_amount; // Principal amount
int Years; // Period of investment
float Rate; // Interest rate
float R_value; // Return value of amount

public:
Fixed_deposit(){}{}
Fixed_deposit(long int p, int y, float r=0.12);
Fixed_deposit(long int p, int y, int r);
void display(void);
};

Fixed_deposit :: Fixed_deposit(long int p, int y, float r)


{
P_amount = p;
Years = y;
Rate = r;
R_value = P_amount;
for(int i = 1; i<=y; i++)
{
R_value = R_value * (1.0 + r);
}
}

Compiled By B T Chisuwa Page 172


Fixed_deposit :: Fixed_deposit(long int p, int y, int r)
{
P_amount = p;
Years = y;
Rate = r;
R_value = P_amount;
for(int i = 1; i<=y; i++)
{
R_value = R_value * (1.0 + float(r)/100);
}
}

void Fixed_deposit :: display(void)


{
cout << “\n”
<< “Principal Amount = ” << P_amount << “\n”
<< “Return Value = ” << R_value << “\n”;
}

int main()
{
Fixed_deposit FD1, FD2, FD3; // deposits created

long int p; // principal amount

int y; // investment period, years


float r; // interest rate, decimal form
int R // interest rate, percent form

cout << “Enter amount, period, interest rate(in percentage)” << “\n”;
cin >> p >> y >> R;
FDI = Fixed_deposit(p,y,R);

cout << “Enter amount, period, interest rate(decimal form)” << “\n”;
cin >> p >> y >> r;
FD2 = Fixed_deposit(p,y,r);

cout << “Enter amount and period” << “\n”;


cin >> p >> y;
FD3 = Fixed_deposit(p,y);

cout << “\nDeposit 1”;


FD1.display();

cout << “\nDeposit 2”;


FD2.display();

Compiled By B T Chisuwa Page 173


cout << “\nDeposit 3”;
FD3.display();

return 0;
}

The output of the program above would be:


Enter amount, period, interest rate(in percentage)
10000 3 18
Enter amount, period, interest rate(decimal form)
10000 3 0.18
Enter amount and period
10000 3

Deposit 1
Principal Amount = 10000
Return Value = 16430.3

Deposit 2
Principal Amount = 10000
Return Value = 16430.3

Deposit 3
Principal Amount = 10000
Return Value = 14049.3

The program uses three overloaded constructors. The parameter values to these constructors are
provided at run time. The user can provide input in one of the following forms:
1. Amount, period and interest in decimal form.
2. Amount, period and interest in percentage form.
3. Amount and period.

Note
Since the constructors are overloaded with the appropriate parameters, the one that matches the
input values is invoked. For example, the second constructor is invoked for the forms (1) and (3),
and the third is invoked for the form (2). Note that, for form (3), the constructor with default
argument is used. Since input to the third parameter is missing, it uses the default value for r.

Compiled By B T Chisuwa Page 174


Dynamic Constructors
The constructors can also be used to allocate memory while creating objects. This will enable the
system to allocate the right amount of memory for each object when the objects are not of the
same size, thus resulting in the saving of memory. Allocation of memory to objects at the time of
their construction is known as dynamic construction of objects. The memory is allocated with the
help of the new operator. The program below shows the use of new, in constructors that are used
to construct strings in objects.
#include <iostream>
#include <string>

using namespace std;

class String
{
char *name;
int length;
public:
String() // constructor -1
{
length = 0;
name = new char[length + 1];
}

String(char *s) // constructor-2


{
length = strlen(s);
name = new char[length + 1]; // one additional character for \0
strcpy(name, s);
}

void display(void)
{
cout << name <<endl;
}

void join(String &a, String &b);


};

void String :: join(String &a, String &b)


{
length = a.length + b.length;
delete name;
name = new char[length + 1]; // dynamic allocation

Compiled By B T Chisuwa Page 175


strcpy(name, a.name);
strcat(name, b.name);
}

int main()
{
char *first = “Josephy ”;
String name1(first), name2(“Louis ”), name3(“Lagrange”), s1,s2;
S1.join(name1, name2);
S2.join(s1, name3);
name1.display();
name2.display();
name3.display();
s1.display();
s2.display();
return 0;
}

The output of the program above would be:


Joseph
Louis
Lagrange
Joseph Louis
Joseph Louis Lagrange

Note
This program uses two constructors. The first is an empty constructor that allows us to declare an
array of strings. The second constructor initialises the length of the string, allocates necessary
space for the string to be stored and creates the string itself. Note that one additional character
space is allocated to hold the end-of-string character ‘\0’.

The member function join() concatenates two strings. It estimates the combined length of the
strings to be joined, allocates memory for the combined string and then creates the same using
the string functions strcpy() and strcat(). Note that in the function join(), length and name are
members of the object that calls the function, while a.length and a.name are members of the
argument object a. The main() function program concatenates three strings into one string. The
output is as shown below:
Joseph Louis Lagrange

Compiled By B T Chisuwa Page 176


Constructing Two-dimensional Arrays
We can construct matrix variables using the class type objects. The example below illustrates
how to construct a matrix of size m x n.
#include <iostream>
using namespace std;

class matrix
{
int **p; // pointer to matrix
int d1, d2; // dimensions

public:
matrix(int x, int y);
void get_element(int i, int j, int value)
{
p[i][j]=value;
}

int & put_element(int i, int j)


{
return p[i][j];
}
};

matrix :: matrix(int x, int y)


{
d1= x;
d2 = y;
p = new int *[d1]; // creates an array pointer

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


{
p[i] = new int[d2]; // creates space for each row
}
}

int main()
{
int m,n;

cout << “Enter size of matrix: ”;


cin >> m >> n;

matrix A(m,n); matrix object A constructed

Compiled By B T Chisuwa Page 177


cout << “Enter matrix elements row by row \n”;

int i, j, value;

for()
{
for()
{
cin >> value;
A.get_element(I,j,value)
}
}

cout << “\n”;


cout << A.put_element(1,2);

return 0;
}

The output of a sample run of the program above is as follows.


Enter size of matrix: 3 4
Enter matrix elements row by row
11 12 13 14
15 16 17 18
19 20 21 22

17

17 is the value of the element (1,2).

The constructor first creates a vector pointer to an int of size d1. Then, it allocates, iteratively an
int type vector of size d2 pointed at by each element p[i]. Thus, space for the elements of a d1 x
d2 matrix is allocated from free store as shown below.

Compiled By B T Chisuwa Page 178


Const Objects
We may create and use constant objects using const keyword before object declaration. For
example, we may create X as a constant object of the class matrix as follows:
const matrix X(m,n); // object X is constant

Any attempt to modify the values of m and n will generate compile-time error. Further, a
constant object can call only const member functions. As we know, a const member is a function
prototype or function definition where the keyword const appears after the function’s signature.

Whenever const objects try to invoke non-const member functions, compiler generates errors.

Using Initialization Lists to Initialize Fields:


In case of parameterized constructor, you can use following syntax to initialize the fields:
Line::Line( double len): length(len)
{
cout << "Object is being created, length = " << len << endl;
}

Above syntax is equal to the following syntax:


Line::Line( double len)
{
cout << "Object is being created, length = " << len << endl;
length = len;

Compiled By B T Chisuwa Page 179


}

If for a class C, you have multiple fields X, Y, Z, etc., to be initialized, then you can use same
syntax and separate the fields by comma as follows:
C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
....
}

C++ Copy Constructor


The copy constructor is a constructor which creates an object by initializing it with an object of
the same class, which has been created previously. The copy constructor is used to:
• Initialize one object from another of the same type.
• Copy an object to pass it as an argument to a function.
• Copy an object to return it from a function.
If a copy constructor is not defined in a class, the compiler itself defines one.If the class has
pointer variables and has some dynamic memory allocations, then it is a must to have a copy
constructor. The process of initialising through a copy constructor is known as copy
initialisation. The most common form of copy constructor is shown here:

classname (const classname &obj) {


// body of constructor
}

Here, obj is a reference to an object that is being used to initialize another object.
#include <iostream>
using namespace std;

class Line
{
int *ptr;

Compiled By B T Chisuwa Page 180


public:
int getLength(void);
Line(int len); // simple constructor
Line(const Line &obj); // copy constructor
~Line(); // destructor
};

Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
// allocate memory for the pointer;
ptr = new int;
*ptr = len;
}

Line::Line(const Line &obj)


{
cout << "Copy constructor allocating ptr." << endl;
ptr = new int;
*ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}

int Line::getLength( void )


{
return *ptr;
}

void display(Line obj)


{
cout << "Length of line : " << obj.getLength() <<endl;
}

int main( )
{

Compiled By B T Chisuwa Page 181


Line line(10);
display(line);

return 0;
}

When the above code is compiled and executed, it produces the following result:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!

Let us see the same example but with a small change to create another object using existing
object of the same type:
#include <iostream>
using namespace std;
class Line
{
public:
int getLength( void );
Line( int len ); // simple constructor
Line( const Line &obj); // copy constructor
~Line(); // destructor
private:
int *ptr;
};
// Member functions definitions including constructor
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
// allocate memory for the pointer;
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj)
{
cout << "Copy constructor allocating ptr." << endl;
ptr = new int;
*ptr = *obj.ptr; // copy the value

Compiled By B T Chisuwa Page 182


}
Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength( void )
{
return *ptr;
}
void display(Line obj)
{
cout << "Length of line : " << obj.getLength() <<endl;
}
// Main function for the program
int main( )
{
Line line1(10);
Line line2 = line1; // This also calls copy constructor
display(line1);
display(line2);
return 0;
}

When the above code is compiled and executed, it produces the following result:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
Freeing memory!

A copy constructor takes a reference to an object of the same class as itself as an argument. Let
us consider another simple example of constructing and using a copy constructor as shown in
program below.
#include <iostream>
using namespace std;

Compiled By B T Chisuwa Page 183


class code
{
int id;
public:
code(){} // constructor
code(int a) {id = a;} // constructor again
code(code & x) // copy constructor
{
id = x.id; // copy in the value
}
void display(void)
{
cout <<id;
}
};

int main()
{
code A(100); // object A is created and initialised
code B(A); // copy constructor called
code C = A; // copy constructor called again

code D; // D is created, not initialised


D = A; // copy constructor not called

cout << “\n id of A: ”; A.display();


cout << “\n id of B: ”; B.display();
cout << “\n id of C: ”; C.display();
cout << “\n id of D: ”; D.display();

return 0;
}

The output of the above program is shown below


id of A: 100
id of B: 100
id of C: 100
id of D: 100

Note
A reference variable has been used as an argument to the copy constructor. We cannot pass the
argument by value to a copy constructor.

Compiled By B T Chisuwa Page 184


The Class Destructor:
A destructor, as the name implies, is used to destroy the objects that have been created by a
constructor. A destructor is a special member function of a class that is executed whenever an
object of its class goes out of scope or whenever the delete expression is applied to a pointer to
the object of that class.

A destructor will have exact same name as the class prefixed with a tilde (~) and it can neither
return a value nor can it take any parameters. Destructor can be very useful for releasing
resources before coming out of the program like closing files, releasing memories etc.

Whenever, new is used to allocate memory in the constructors, we should use delete to free that
memory. For example, the destructor for the matrix class discussed above may be defined as
follows:
matrix :: ~matrix()
{
for(int i=0; i <d1; i++)
{
delete p[i];
delete p;
}
}

This is required because when the pointers to objects go out of scope, a destructor is not called
implicitly.

Following example explains the concept of destructor:


#include <iostream>
using namespace std;

class Line
{
double length;
public:
void setLength( double len );

Compiled By B T Chisuwa Page 185


double getLength( void );
Line(); // This is the constructor declaration
~Line(); // This is the destructor: declaration
};
Line::Line(void)
{
cout << "Object is being created" << endl;
}
Line::~Line(void)
{
cout << "Object is being deleted" << endl;
}
void Line::setLength( double len )
{
length = len;
}
double Line::getLength( void )
{
return length;
}

int main( )
{
Line line;
line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Object is being created
Length of line : 6
Object is being deleted

Compiled By B T Chisuwa Page 186


INHERITANCE

Reusability is yet another important feature of OOP. It is always nice if we could reuse
something that already exists rather than trying to create the same all over again. It would not
only save time and money but also reduce frustration and increase reliability. For instance, the
reuse of a class that has already been tested, debugged and used many times can save us the
effort of developing and testing the same again.

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

The derived class inherits some or all of the traits from the base class. A class can also inherit
properties from more than one class or from more than one level. A derived class with only one
base class, is called single inheritance and one with several base classes is called multiple
inheritance. On the other hand, the traits of one class may be inherited by more than one class.
This process is known as hierarchical inheritance. The mechanism of deriving a class from
another derived class is known as multilevel inheritance. The figure below shows various forms
of inheritance that could be used for writing extensible programs. The direction of arrow
indicates the direction of inheritance. (Some authors show the arrow in opposite direction
meaning “inherited from”.).

Compiled By B T Chisuwa Page 187


Defining Derived Classes:
To define a derived class, we use a class derivation list to specify the base class(es). A
class derivation list names one or more base classes and has the form:
class derived-class: access-specifier/visibility-mode base-class

Where access-specifier is one of public, protected, or private, and base-class is the name of a
previously defined class. If the access-specifier is not used, then it is private by default.

Access Control and Inheritance:


A derived class can access all the non-private members of its base class. Thus base-class
members that should not be accessible to the member functions of derived classes should be
declared private in the base class.

We can summarize the different access types according to who can access them in the following
way:

Compiled By B T Chisuwa Page 188


A derived class inherits all base class methods with the following exceptions:
• Constructors, destructors and copy constructors of the base class.
• Overloaded operators of the base class.
• The friend functions of the base class.

Type of Inheritance:
When deriving a class from a base class, the base class may be inherited through public,
protected or private inheritance. The type of inheritance is specified by the access -specifier.
We hardly use protected or private inheritance but public inheritance is commonly used.
While using different type of inheritance, following rules are applied:

• Public Inheritance: When deriving a class from a public base class, public
members of the base class become public members of the derived class and
protected members of the base class become protected members of the derived
class. A base class's private members are never accessible directly from a derived
class, but can be accessed through calls to the public and protected members of the base
class.

• Protected Inheritance: When deriving from a protected base class, public and
protected members of the base class become protected members of the derived class.

• Private Inheritance: When deriving from a private base class, public and protected
members of the base class become private members of the derived class.

Compiled By B T Chisuwa Page 189


Single Inheritance
Consider a base class Shape and its derived class Rectangle as follows:
#include <iostream>
using namespace std;

// Base class
class Shape
{
protected:
int width;
int height;

public:
void setWidth(int w)
{
width = w;
}

void setHeight(int h)
{
height = h;
}
};

// Derived class
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
};

int main(void)
{
Rectangle Rect;
Rect.setWidth(5);
Rect.setHeight(7);

// Print the area of the object.


cout << "Total area: " << Rect.getArea() << endl;

return 0;
}

Compiled By B T Chisuwa Page 190


When the above code is compiled and executed, it produces the following result:
Total area: 35

Multilevel Inheritance
It is not uncommon that a class is derived from another class as shown below. The class A serves
as a base class for the derived class B, which in turn serves as a base class for the derived class
C. The class B is known as intermediate base class since it provides a link for the inheritance
between A and C. The chain ABC is known as inheritance path.

A derived class with multilevel inheritance is declared as follows:


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

This process can be extended to any number of levels.

Let us consider a simple example. Assume that the test results of a batch of students are stored in
three different classes. Class student stores the roll-number, class test stores the marks obtained
in two subjects and class result contains the total marks obtained in the test. The class result can
inherit the details of the marks obtained in the test and the roll-number of students through
multilevel inheritance. Example:

#include <iostream>
using namespace std;

class student
{
protected:
int roll_number;

public:
void get_number(int);
void put_number(void);
};

Compiled By B T Chisuwa Page 191


void student :: get_number(int a)
{
roll_number = a;
}
void student :: put_number()
{
cout << “Roll Number: ” << roll_number << endl;
}

class test : public student // First level derivation


{
protected:
float sub1;
float sub2;
public:
void get_marks(float, float);
void put_marks(void);
};

void test :: get_marks(float x, float y)


{
sub1 = x;
sub2 = y;
}

void test :: put_marks()


{
cout << “Marks in SUB1 = ” << sub1 << endl;
cout << “Marks in SUB2 = ” << sub2 << endl;
}

class result : public test // Second level derivation


{
float total; // private by default
public:
void display(void);
};

void result :: display(void)


{
total = sub1 + sub2;
put_number();
put_marks();
cout << “Total = ” << total << endl;
}

Compiled By B T Chisuwa Page 192


int main()
{
result student1; // student1 created
student1.get_number(111);
student1.get_marks(75.0 , 59.5);
student1.display();

return 0;
}

The program above displays the following output:


Roll Number: 111
Marks in SUB1 = 75
Marks in SUB2 = 59.5
Total = 134.5

Multiple inheritance
Multiple inheritance is the ability of a class to have more than one base class (super class). The
arguments of the functions may be changed in the derived class. For example, if a function to
calculate area of a four sided shape is inherited then the argument, length can be changed from
data type int in the base class to type double in the derived class.

A C++ class can inherit members from more than one class and here is the extended syntax:

Where access is one of public, protected, or private and would be given for every base class
and they will be separated by comma as shown above. Let us try the following example:

#include <iostream>
using namespace std;

// Base class Shape


class Shape
{
protected:
int width;
int height;

Compiled By B T Chisuwa Page 193


public:
void setWidth(int w)
{
width = w;
}

void setHeight(int h)
{
height = h;
}
};

// Base class PaintCost


class PaintCost
{
public:
int getCost(int area)
{
return area * 70;
}
};

// Derived class
class Rectangle: public Shape, public PaintCost
{
public:
int getArea()
{
return (width * height);
}
};

int main(void)
{
Rectangle Rect;
int area;

Rect.setWidth(5);
Rect.setHeight(7);
Area = Rect.getArea();

// Print the area of the object.


cout << "Total area: " << Rect.getArea() << endl;

// Print the total cost of painting

Compiled By B T Chisuwa Page 194


cout << "Total paint cost: $" << Rect.getCost(area) << endl;

return 0;
}

When the above code is compiled and executed, it produces the following result:
Total area: 35
Total paint cost: $2450

Ambiguity Resolution in Inheritance


Occasionally, we may face a problem in using the multiple inheritance, when a function with the
same name appears in more than one base class. Consider the following two classes.

class M
{
public:
void display(void)
{
cout << “Class M” << endl;
}
};

class N
{
public:
void display(void)
{
cout << “Class N” << endl;
}
};

Which display() function is used by the derived class when we inherit these two classes? We can
solve this problem by defining a named instance within the derived class, using the class
resolution operator with the function as shown below:
class P : public M, public N
{
public:
void display(void) // overrides display() of M and N
{
M :: display();

Compiled By B T Chisuwa Page 195


}
};

We can now use derived class as follows:


int main()
{
P p;
p.display();
}

Ambiguity may also arise in single inheritance applications. For instance, consider the following
situation:
class A
{
public:
void display(void)
{
cout << “A” << endl;
}
};

class B: public A
{
public:
void display(void)
{
cout << “B” << endl;
}
};

In this case, the function in the derived class overrides the inherited function and, therefore, a
simple call to display() by B type object will invoke function defined in B only. However, we
may invoke the function defined in A by using the scope resolution operator to specify the class.
For example:
int main()
{
B b; // derived class object
b.display(); // invokes display() in B
b.A::display(); // invokes display() in A
b.B::display(); // invokes display() in B

Compiled By B T Chisuwa Page 196


return 0;
}

This will produce the following output:


B
A
B

Compiled By B T Chisuwa Page 197


POLYMORPHISM IN C++

The word polymorphism means having many forms. In simple words, we can define
polymorphism as the ability of a message to be displayed in more than one form.

Real life example of polymorphism, a person at a same time can have different characteristic.
Like a man at a same time is a father, a husband, an employee. So a same person can have
different behavior in different situations. This is called polymorphism.

Polymorphism is considered as one of the important features of Object Oriented Programming.

In C++ polymorphism is mainly divided into two types:


• Compile time Polymorphism
• Runtime Polymorphism

Compile time polymorphism


This type of polymorphism is achieved by function overloading or operator overloading. C++
allows you to specify more than one definition for a function name or an operator in the same
scope, which is called function overloading and operator overloading respectively.

When you call an overloaded function or operator, the compiler determines the most
appropriate definition to use by comparing the argument types you used to call the function or
operator with the parameter types specified in the definitions. The process of selecting the most
appropriate overloaded function or operator is called overload resolution.

Function Overloading
Overloading refers to the use of the same thing for different purposes.

Ways to overload a function


1. By changing number of Arguments.
2. By having different types of argument.

Compiled By B T Chisuwa Page 198


1. Number of Arguments different
In this type of function overloading we define two functions with same names but different
number of parameters of the same type. For example, in the below mentioned program we have
made two sum() functions to return sum of two and three integers.
int sum(int x, int y)
{
return x+y;
}

int sum(int x, int y, int z)


{
return x+y+z;
}

Here sum() function is overloaded, to have two and three arguments. Which sum() function will
be called, depends on the number of arguments.
int main()
{
sum(10,20); //sum() with 2 parameters will be called
sum(10,20,30); //sum() with 3 parameters will be called
}

2. Different Datatype of Arguments


In this type of overloading we define two or more functions with same name and same number
of parameters, but the type of parameter is different. For example in this program, we have two
sum() function, first one gets two integer arguments and second one gets two double arguments.
int sum(int x, int y)
{
return x+y;
}

double sum(double x, double y)


{
return x+y;
}
int main()
{
sum(10,20);
sum(10.5, 20.5);
}

Compiled By B T Chisuwa Page 199


Operators overloading in C++:
//Add notes here

Runtime polymorphism:
This type of polymorphism is achieved by Function Overriding.

Function overriding on the other hand occurs when a derived class has a definition for one of
the member functions of the base class. That base function is said to be overridden.

#include <iostream>
using namespace std;

class Parent
{
public:
void print()
{
cout << "The Parent print function was called" << endl;
}
};

class Child : public Parent


{
public:
void print()
{
cout << "The child print function was called" << endl;
}

};

int main()
{
Parent obj1;
Child obj2;

obj1.print();
obj2.print();

return 0;
}
Output:

Compiled By B T Chisuwa Page 200


The Parent print function was called
The child print function was called

Also consider the following example where a base class has been derived by other two classes:
#include <iostream>
using namespace std;

class Shape {
protected:
int width, height;

public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}

int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};

class Rectangle: public Shape{


public:
Rectangle( int a=0, int b=0)
{
Shape(a, b);
}

int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};

class Triangle: public Shape{


public:
Triangle( int a=0, int b=0)
{
Shape(a, b);
}

Compiled By B T Chisuwa Page 201


int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};

int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);

// store the address of Rectangle


shape = &rec;

// call rectangle area.


shape->area();

// store the address of Triangle


shape = &tri;

// call triangle area.


shape->area();

return 0;
}

When the above code is compiled and executed, it produces the following result:
Parent class area
Parent class area

The reason for the incorrect output is that the call of the function area() is being set once by the
compiler as the version defined in the base class. This is called static resolution of the function
call, or static linkage - the function call is fixed before the program is executed. This is also
sometimes called early binding because the area() function is set during the compilation of the
program.

But now, let's make a slight modification in our program and precede the declaration of area() in
the Shape class with the keyword virtual so that it looks like this:

Compiled By B T Chisuwa Page 202


class Shape {
protected:
int width, height;

public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}

virtual int area()


{
cout << "Parent class area :" <<endl;
return 0;
}
};

After this slight modification, when the previous example code is compiled and executed, it
produces the following result:
Rectangle class area
Triangle class area

This time, the compiler looks at the contents of the pointer instead of it's type. Hence, since
addresses of objects of tri and rec classes are stored in *shape, the respective area() function is
called.

As you can see, each of the child classes has a separate implementation for the function area().
This is how polymorphism is generally used. You have different classes with a function of the
same name, and even the same parameters, but with different implementations.

Virtual Functions
A virtual function is a function in a base class that is declared using the keyword virtual.
Defining in a base class a virtual function, with another version in a derived class, signals to the
compiler that we don't want static linkage for this function.

Compiled By B T Chisuwa Page 203


What we do want is the selection of the function to be called at any given point in the program to
be based on the kind of object for which it is called. This sort of operation is referred to as
dynamic linkage, or late binding.

Rules for Virtual Functions


1. They Must be declared in public section of class.
2. Virtual functions cannot be a friend function of another class.
3. Virtual functions should be accessed using pointer or reference of base class type to
achieve run time polymorphism.
4. The prototype of virtual functions should be same in base as well as derived class.
5. They are always defined in base class and overridden in derived class. It is not mandatory
for derived class to override (or re-define the virtual function), in that case base class
version of function is used.
6. A class may have virtual destructor but it cannot have a virtual constructor.

C++ Abstract class


In C++, you can create an abstract class that cannot be instantiated (you cannot create object of
that class). However, you can derive a class from it and instantiate object of the derived class.
Abstract classes are the base class which cannot be instantiated.

A class containing pure virtual function is known as abstract class.

Pure Virtual Function


It's possible that you'd want to include a virtual function in a base class so that it may be
redefined in a derived class to suit the objects of that class, but that there is no meaningful
definition you could give for the function in the base class.

We can change the virtual function area() in the base class to the following:
class Shape {
protected:
int width, height;

Compiled By B T Chisuwa Page 204


public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}

// pure virtual function


virtual int area() = 0;
};

The = 0 tells the compiler that the function has no body and above virtual function will be called
pure virtual function.

Compiled By B T Chisuwa Page 205


DATA ABSTRACTION

Data abstraction refers to, providing only essential information to the outside world and hiding
their background details, i.e., to represent the needed information in program without presenting
the details.

Data abstraction is a programming (and design) technique that relies on the separation of
interface and implementation.

Let's take one real life example of a TV, which you can turn on and off, change the channel,
adjust the volume, and add external components such as speakers, VCRs, and DVD players,
BUT you do not know its internal details, that is, you do not know how it receives signals over
the air or through a cable, how it translates them, and finally displays them on the screen.

Thus, we can say a television clearly separates its internal implementation from its external
interface and you can play with its interfaces like the power button, channel changer, and volume
control without having zero knowledge of its internals.

Now, if we talk in terms of C++ Programming, C++ classes provides great level of data
abstraction. They provide sufficient public methods to the outside world to play with the
functionality of the object and to manipulate object data, i.e., state without actually knowing how
class has been implemented internally.

For example, your program can make a call to the sort() function without knowing what
algorithm the function actually uses to sort the given values. In fact, the underlying
implementation of the sorting functionality could change between releases of the library, and as
long as the interface stays the same, your function call will still work.

Compiled By B T Chisuwa Page 206


In C++, we use classes to define our own abstract data types (ADT). You can use the cout object
of class ostream to stream data to standard output like this:
#include <iostream>
using namespace std;

int main( )
{
cout << "Hello C++" <<endl;
return 0;
}

Here, you don't need to understand how cout displays the text on the user's screen. You need to
only know the public interface and the underlying implementation of cout is free to change.

Access Labels Enforce Abstraction:


In C++, we use access labels to define the abstract interface to the class. A class may contain
zero or more access labels:

• Members defined with a public label are accessible to all parts of the program. The data-
abstraction view of a type is defined by its public members.
• Members defined with a private label are not accessible to code that uses the class. The
private sections hide the implementation from code that uses the type.

There are no restrictions on how often an access label may appear. Each access label specifies
the access level of the succeeding member definitions. The specified access level remains in
effect until the next access label is encountered or the closing right brace of the class body is
seen.

Benefits of Data Abstraction


Data abstraction provides two important advantages:
• Class internals are protected from inadvertent user-level errors, which might corrupt the
state of the object.

Compiled By B T Chisuwa Page 207


• The class implementation may evolve over time in response to changing requirements or
bug reports without requiring change in user-level code.

By defining data members only in the private section of the class, the class author is free to make
changes in the data. If the implementation changes, only the class code needs to be examined to
see what affect the change may have. If data are public, then any function that directly accesses
the data members of the old representation might be broken.

Data Abstraction Example:


Any C++ program where you implement a class with public and private members is an example
of data abstraction. Consider the following example:
#include <iostream>
using namespace std;

class Adder{
public:
// constructor
Adder(int i = 0)
{
total = i;
}

// interface to outside world


void addNum(int number)
{
total += number;
}

// interface to outside world


int getTotal()
{
return total;
};

private:
// hidden data from outside world
int total;
};

int main( )
{

Compiled By B T Chisuwa Page 208


Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;
}

When the above code is compiled and executed, it produces the following result:
Total 60

Above class adds numbers together, and returns the sum. The public members addNum and
getTotal are the interfaces to the outside world and a user needs to know them to use the class.
The private member total is something that the user doesn't need to know about, but is needed
for the class to operate properly.

Designing Strategy:
Abstraction separates code into interface and implementation. So while designing your
component, you must keep interface independent of the implementation so that if you change
underlying implementation then interface would remain intact.

In this case whatever programs are using these interfaces, they would not be impacted and would
just need a recompilation with the latest implementation.

Compiled By B T Chisuwa Page 209


DATA ENCAPSULATION

C++ programs are composed of the following two fundamental elements:


• Program statements (code): This is the part of a program that performs actions and they
are called functions.
• Program data: The data is the information of the program which affected by the
program functions.

Encapsulation is an Object Oriented Programming concept that binds together the data and
functions that manipulate the data, and that keeps both safe from outside interference and misuse.
Data encapsulation led to the important OOP concept of data hiding.

Data encapsulation is a mechanism of bundling the data, and the functions that use them and
data abstraction is a mechanism of exposing only the interfaces and hiding the implementation
details from the user.

C++ supports the properties of encapsulation and data hiding through the creation of user-
defined types, called classes. We already have studied that a class can contain private,
protected and public members. By default, all items defined in a class are private. For example:
class Box
{
double length, breadth, height;

public:
double getVolume(void)
{
return length * breadth * height;
}
};

The variables length, breadth, and height are private. This means that they can be accessed only
by other members of the Box class, and not by any other part of your program. This is one way
encapsulation is achieved.
Compiled By B T Chisuwa Page 210
To make parts of a class public (i.e., accessible to other parts of your program), you must declare
them after the public keyword. All variables or functions defined after the public specifier are
accessible by all other functions in your program.

Making one class a friend of another exposes the implementation details and reduces
encapsulation. The ideal is to keep as many of the details of each class hidden from all other
classes as possible.

Data Encapsulation Example:


Any C++ program where you implement a class with public and private members is an example
of data encapsulation and data abstraction. Consider the following example:
#include <iostream>
using namespace std;
class Adder{
// hidden data from outside world
int total;
public:
Adder(int i = 0)
{
total = i;
}
// interface to outside world
void addNum(int number)
{
total += number;
}
// interface to outside world
int getTotal()
{
return total;
};
};
int main( ) {
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;
}

Compiled By B T Chisuwa Page 211


When the above code is compiled and executed, it produces the following result:
Total 60

Above class adds numbers together, and returns the sum. The public members addNum and
getTotal are the interfaces to the outside world and a user needs to know them to use the class.
The private member total is something that is hidden from the outside world, but is needed for
the class to operate properly.

Designing Strategy:
Most of us have learned through bitter experience to make class members private by default
unless we really need to expose them. That's just good encapsulation.

This wisdom is applied most frequently to data members, but it applies equally to all members,
including virtual functions.

Compiled By B T Chisuwa Page 212


INTERFACES

An interface describes the behavior or capabilities of a C++ class without committing to a


particular implementation of that class.

The C++ interfaces are implemented using abstract classes and these abstract classes should not
be confused with data abstraction which is a concept of keeping implementation details separate
from associated data.

A class is made abstract by declaring at least one of its functions as pure virtual function. A
pure virtual function is specified by placing "= 0" in its declaration as follows:
class Box
{
public:
// pure virtual function
virtual double getVolume() = 0;

private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};

The purpose of an abstract class (often referred to as an ABC) is to provide an appropriate base
class from which other classes can inherit. Abstract classes cannot be used to instantiate objects
and serves only as an interface. Attempting to instantiate an object of an abstract class causes a
compilation error.

Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the virtual
functions, which means that it supports the interface declared by the ABC. Failure to override a
pure virtual function in a derived class, then attempting to instantiate objects of that class, is a
compilation error.

Compiled By B T Chisuwa Page 213


Classes that can be used to instantiate objects are called concrete classes.

Abstract Class Example:


Consider the following example where parent class provides an interface to the base class to
implement a function called getArea():
#include <iostream>
using namespace std;

// Base class
class Shape
{
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;

void setWidth(int w)
{
width = w;
}

void setHeight(int h)
{
height = h;
}

protected:
int width;
int height;
};

// Derived classes
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
};

class Triangle: public Shape


{
public:
int getArea()

Compiled By B T Chisuwa Page 214


{
return (width * height)/2;
}
};

int main(void)
{
Rectangle Rect;
Triangle Tri;

Rect.setWidth(5);
Rect.setHeight(7);

// Print the area of the object.


cout << "Total Rectangle area: " << Rect.getArea() << endl;

Tri.setWidth(5);
Tri.setHeight(7);

// Print the area of the object.


cout << "Total Triangle area: " << Tri.getArea() << endl;

return 0;
}

When the above code is compiled and executed, it produces the following result:
Total Rectangle area: 35
Total Triangle area: 17

You can see how an abstract class defined an interface in terms of getArea() and two other
classes implemented same function but with different algorithm to calculate the area specific to
the shape.

Designing Strategy:
An object-oriented system might use an abstract base class to provide a common and
standardized interface appropriate for all the external applications. Then, through inheritance
from that abstract base class, derived classes are formed that all operate similarly.

The capabilities (i.e., the public functions) offered by the external applications are provided as
pure virtual functions in the abstract base class. The implementations of these pure virtual

Compiled By B T Chisuwa Page 215


functions are provided in the derived classes that correspond to the specific types of the
application.

This architecture also allows new applications to be added to a system easily, even after the
system has been defined.

Compiled By B T Chisuwa Page 216


FILES AND STREAMS

So far, we have been using the iostream standard library, which provides cin and cout methods
for reading from standard input and writing to standard output respectively.

This tutorial will teach you how to read and write from a file. This requires another standard C++
library called fstream, which defines three new data types:
Data Type Description
Ofstream This data type represents the output file stream and is used to create files and to
write information to files.
Ifstream This data type represents the input file stream and is used to read information
from files.
Fstream This data type represents the file stream generally, and has the capabilities of both
ofstream and ifstream which means it can create files, write information to files,
and read information from files.

To perform file processing in C++, header files <iostream> and <fstream> must be included in
your C++ source file.

Opening a File:
A file must be opened before you can read from it or write to it. Either the ofstream or fstream
object may be used to open a file for writing and ifstream object is used to open a file for reading
purpose only.

Following is the standard syntax for open() function, which is a member of fstream, ifstream, and
ofstream objects.
void open(const char *filename, ios::openmode mode);

Compiled By B T Chisuwa Page 217


Here, the first argument specifies the name and location of the file to be opened and the second
argument of the open() member function defines the mode in which the file should be opened.
Mode Flag Description
ios::app Append mode. All output to that file to be appended to the end.
ios::ate Open a file for output and move the read/write control to the end of the file.
ios::in Open a file for reading.
ios::out Open a file for writing.
ios::trunk If the file already exists, its contents will be truncated before opening the file.

You can combine two or more of these values by ORing them together. For example if you want
to open a file in write mode and want to truncate it in case it already exists, following will be the
syntax:
ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );

Similar way, you can open a file for reading and writing purpose as follows:
fstream afile;
afile.open("file.dat", ios::out | ios::in );

Closing a File
When a C++ program terminates, it automatically closes flushes all the streams, release all the
allocated memory and close all the opened files. But it is always a good practice that a
programmer should close all the opened files before program termination.

Following is the standard syntax for close() function, which is a member of fstream, ifstream,
and ofstream objects.
void close();

Writing to a File:
While doing C++ programming, you write information to a file from your program using the
stream insertion operator (<<) just as you use that operator to output information to the screen.
The only difference is that you use an ofstream or fstream object instead of the cout object.

Compiled By B T Chisuwa Page 218


Reading from a File:
You read information from a file into your program using the stream extraction operator (<<)
just as you use that operator to input information from the keyboard. The only difference is that
you use an ifstreamor fstream object instead of the cin object.

Read & Write Example:


Following is the C++ program which opens a file in reading and writing mode. After writing
information inputted by the user to a file named afile.dat, the program reads information from the
file and outputs it onto the screen:
#include <fstream>
#include <iostream>

using namespace std;

int main ()
{
char data[100];

// open a file in write mode.


ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);

// write inputted data into the file.


outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();

// again write inputted data into the file.


outfile << data << endl;

// close the opened file.


outfile.close();

// open a file in read mode.


ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;

Compiled By B T Chisuwa Page 219


// write the data at the screen.
cout << data << endl;

// again read the data from the file and display it.
infile >> data;
cout << data << endl;

// close the opened file.


infile.close();

return 0;
}

When the above code is compiled and executed, it produces following sample input and output:
Writing to the file
Enter your name: Zara
Enter your age: 9
Reading from the file
Zara
9

Above examples make use of additional functions from cin object, like getline() function to read
the line from outside and ignore() function to ignore the extra characters left by previous read
statement.

File Position Pointers:


Both istream and ostream provide member functions for repositioning the file-position pointer.
These member functions are seekg ("seek get") for istream and seekp ("seek put") for ostream.

The argument to seekg and seekp normally is a long integer. A second argument can be specified
to indicate the seek direction. The seek direction can be ios::beg (the default) for positioning
relative to the beginning of a stream, ios::cur for positioning relative to the current position in a
stream or ios::end for positioning relative to the end of a stream.

The file-position pointer is an integer value that specifies the location in the file as a number of
bytes from the file's starting location. Some examples of positioning the "get" file-position
pointer are:

Compiled By B T Chisuwa Page 220


// position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n );
// position n bytes forward in fileObject
fileObject.seekg( n, ios::cur );
// position n bytes back from end of fileObject
fileObject.seekg( n, ios::end );
// position at end of fileObject
fileObject.seekg( 0, ios::end );

Compiled By B T Chisuwa Page 221


ERRORS IN C++

Syntax error
This error occurs due to following reason.
1. Not following the grammatical rules used in declaration of identifier.
2. Not declaring an identifier used in program.
3. Not terminating statement by semicolon.
4. Not providing equal number of opening and closing braces etc.
5. These errors can be rectified by the user as it is displayed while compiling the program.

Logical error
This error won’t be displayed on the screen. However it will lead to display wrong results.
Example: An infinite loop. This error leads to abnormal termination of a program or infinite
loop.

Runtime error
This error occurs while running a program by displaying the message listed below.
1. Division by 0.
2. Overflow
3. Underflow

Compiled By B T Chisuwa Page 222


EXCEPTION HANDLING

An exception is a problem that arises during the execution of a program. A C++ exception is a
response to an exceptional circumstance that arises while a program is running, such as an
attempt to divide by zero.

Exceptions provide a way to transfer control from one part of a program to another. C++
exception handling is built upon three keywords: try, catch, and throw.

• throw: A program throws an exception when a problem shows up. This is done using a
throw keyword.
• catch: A program catches an exception with an exception handler at the place in a
program where you want to handle the problem. The catch keyword indicates the
catching of an exception.
• try: A try block identifies a block of code for which particular exceptions will be
activated. It's followed by one or more catch blocks.

Assuming a block will raise an exception, a method catches an exception using a combination of
thetry and catch keywords. A try/catch block is placed around the code that might generate an
exception. Code within a try/catch block is referred to as protected code, and the syntax for using
try/catch looks like the following:
try {
// protected code
}catch( ExceptionName e1 )
{
// catch block
}catch( ExceptionName e2 )
{
// catch block
}catch( ExceptionName eN )
{
// catch block
}

Compiled By B T Chisuwa Page 223


Throwing Exceptions:
Exceptions can be thrown anywhere within a code block using throw statements. The operand of
the throw statements determines a type for the exception and can be any expression and the type
of the result of the expression determines the type of exception thrown.

Following is an example of throwing an exception when dividing by zero condition occurs:


double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}

Catching Exceptions:
The catch block following the try block catches any exception. You can specify what type of
exception you want to catch and this is determined by the exception declaration that appears in
parentheses following the keyword catch.
try
{
// protected code
}catch( ExceptionName e )
{
// code to handle ExceptionName exception
}

Above code will catch an exception of ExceptionName type. If you want to specify that a catch
block should handle any type of exception that is thrown in a try block, you must put an ellipsis,
..., between the parentheses enclosing the exception declaration as follows:
try
{
// protected code
}catch(...)
{
// code to handle any exception
}

Compiled By B T Chisuwa Page 224


The following is an example, which throws a division by zero exception and we catch it in catch
block.
#include <iostream>
using namespace std;

double division(int a, int b)


{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}

int main ()
{
int x = 50;
int y = 0;
double z = 0;
try
{
z = division(x, y);
cout << z << endl;
}
catch (const char* msg)
{
cerr << msg << endl;
}
return 0;
}

Because we are raising an exception of type const char*, so while catching this exception, we
have to use const char* in catch block. If we compile and run above code, this would produce the
following result:
Division by zero condition!

C++ Standard Exceptions:


C++ provides a list of standard exceptions defined in <exception> which we can use in our
programs. These are arranged in a parent-child class hierarchy shown below:

Compiled By B T Chisuwa Page 225


Here is the small description of each exception mentioned in the above hierarchy:
Exception Description
std::exception An exception and parent class of all the standard C++ exceptions.
std::bad_alloc This can be thrown by new.
std::bad_cast This can be thrown by dynamic_cast.
std::bad_exception This is useful device to handle unexpected exceptions in a C++ program
std::bad_typeid This can be thrown by typeid.
std::logic_error An exception that theoretically can be detected by reading the code.
std::domain_error This is an exception thrown when a mathematically invalid domain is
used
std::invalid_argument This is thrown due to invalid arguments.
std::length_error This is thrown when a too big std::string is created
std::out_of_range This can be thrown by the at method from for example a std::vector and
std::bitset<>::operator[]().
std::runtime_error An exception that theoretically can not be detected by reading the code.
std::overflow_error This is thrown if a mathematical overflow occurs.

Compiled By B T Chisuwa Page 226


std::range_error This is occured when you try to store a value which is out of range.
std::underflow_error This is thrown if a mathematical underflow occurs.

Define New Exceptions:


You can define your own exceptions by inheriting and overriding exception class functionality.
Following is the example, which shows how you can use std::exception class to implement your
own exception in standard way:
#include <iostream>
#include <exception>
using namespace std;
struct MyException : public exception
{
const char * what () const throw ()
{
return "C++ Exception";
}
};
int main()
{
try
{
throw MyException();
}
catch(MyException& e)
{
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
}
catch(std::exception& e)
{
//Other errors
}
}

This would produce the following result:


MyException caught
C++ Exception

Here, what() is a public method provided by exception class and it has been overridden by all the
child exception classes. This returns the cause of an exception.

Compiled By B T Chisuwa Page 227


DYNAMIC MEMORY

Agood understanding of how dynamic memory really works in C++ is essential to becoming a
good C++ programmer. Memory in your C++ program is divided into two parts:
• The stack: All variables declared inside the function will take up memory from the stack.
• The heap: This is unused memory of the program and can be used to allocate the
memory dynamically when program runs.

Many times, you are not aware in advance how much memory you will need to store particular
information in a defined variable and the size of required memory can be determined at run time.

You can allocate memory at run time within the heap for the variable of a given type using a
special operator in C++ which returns the address of the space allocated. This operator is called
new operator.

If you are not in need of dynamically allocated memory anymore, you can use delete operator,
which de-allocates memory previously allocated by new operator.

The new and delete operators:


There is following generic syntax to use new operator to allocate memory dynamically for any
data-type.
new data-type;

Here, data-type could be any built-in data type including an array or any user defined data types
include class or structure. Let us start with built-in data types. For example we can define a
pointer to type double and then request that the memory be allocated at execution time. We can
do this using the new operator with the following statements:
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable

Compiled By B T Chisuwa Page 228


The memory may not have been allocated successfully, if the free store had been used up. So it is
good practice to check if new operator is returning NULL pointer and take appropriate action as
below:
double* pvalue = NULL;
if( !(pvalue = new double ))
{
cout << "Error: out of memory." <<endl;
exit(1);
}

The malloc() function from C, still exists in C++, but it is recommended to avoid using malloc()
function. The main advantage of new over malloc() is that new doesn't just allocate memory, it
constructs objects which is prime purpose of C++.

At any point, when you feel a variable that has been dynamically allocated is not anymore
required, you can free up the memory that it occupies in the free store with the delete operator as
follows:
delete pvalue; // Release memory pointed to by pvalue

Let us put above concepts and form the following example to show how new and delete work:
#include <iostream>
using namespace std;

int main ()
{
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
*pvalue = 29494.99; // Store value at allocated address
cout << "Value of pvalue : " << *pvalue << endl;
delete pvalue; // free up the memory.

return 0;
}

If we compile and run above code, this would produce the following result:
Value of pvalue : 29495

Compiled By B T Chisuwa Page 229


Dynamic Memory Allocation for Arrays:
Consider you want to allocate memory for an array of characters, i.e., string of 20 characters.
Using the same syntax what we have used above we can allocate memory dynamically as shown
below.
char* pvalue = NULL; // Pointer initialized with null
pvalue = new char[20]; // Request memory for the variable

To remove the array that we have just created the statement would look like this:
delete [] pvalue; // Delete array pointed to by pvalue

Following the similar generic syntax of new operator, you can allocat for a multi-dimensional
array as follows:
double** pvalue = NULL; // Pointer initialized with null
pvalue = new double [3][4]; // Allocate memory for a 3x4 array

However, the syntax to release the memory for multi-dimensional array will still remain same as
above:
delete [] pvalue; // Delete array pointed to by pvalue

Dynamic Memory Allocation for Objects:


Objects are no different from simple data types. For example, consider the following code where
we are going to use an array of objects to clarify the concept:
#include <iostream>
using namespace std;

class Box
{
public:
Box() {
cout << "Constructor called!" <<endl;
}
~Box() {
cout << "Destructor called!" <<endl;
}
};

Compiled By B T Chisuwa Page 230


int main( )
{
Box* myBoxArray = new Box[4];
delete [] myBoxArray; // Delete array

return 0;
}

If you were to allocate an array of four Box objects, the Simple constructor would be called four
times and similarly while deleting these objects, destructor will also be called same number of
times.

If we compile and run above code, this would produce the following result:
Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!

Compiled By B T Chisuwa Page 231


NAMESPACES

Consider a situation, when we have two persons with the same name, Zara, in the same class.
Whenever we need to differentiate them definitely we would have to use some additional
information along with their name, like either the area if they live in different area or their
mother or father name, etc.

Same situation can arise in your C++ applications. For example, you might be writing some code
that has a function called xyz() and there is another library available which is also having same
function xyz(). Now the compiler has no way of knowing which version of xyz() function you
are referring to within your code.

A namespace is designed to overcome this difficulty and is used as additional information to


differentiate similar functions, classes, variables etc. with the same name available in different
libraries. Using namespace, you can define the context in which names are defined. In essence, a
namespace defines a scope.

Defining a Namespace:
A namespace definition begins with the keyword namespace followed by the namespace name
as follows:
namespace namespace_name
{
// code declarations
}

To call the namespace-enabled version of either function or variable, prepend the namespace
name as follows:
name::code; // code could be variable or function.

Let us see how namespace scope the entities including variable and functions:

Compiled By B T Chisuwa Page 232


#include <iostream>
using namespace std;

// first name space


namespace first_space{
void func()
{
cout << "Inside first_space" << endl;
}
}

// second name space


namespace second_space
{
void func()
{
cout << "Inside second_space" << endl;
}
}

int main ()
{
// Calls function from first name space.
first_space::func();

// Calls function from second name space.


second_space::func();

return 0;
}

If we compile and run above code, this would produce the following result:
Inside first_space
Inside second_space

The using directive:


You can also avoid prepending of namespaces with the using namespace directive. This
directive tells the compiler that the subsequent code is making use of names in the specified
namespace. The namespace is thus implied for the following code:

Compiled By B T Chisuwa Page 233


#include <iostream>
using namespace std;

// first name space


namespace first_space
{
void func()
{
cout << "Inside first_space" << endl;
}
}

// second name space


namespace second_space
{
void func()
{
cout << "Inside second_space" << endl;
}
}

using namespace first_space;

int main ()
{
// This calls function from first name space.
func();

return 0;
}

If we compile and run above code, this would produce the following result:
Inside first_space

The using directive can also be used to refer to a particular item within a namespace. For
example, if the only part of the std namespace that you intend to use is cout, you can refer to it as
follows:
using std::cout;

Subsequent code can refer to cout without prepending the namespace, but other items in the std
namespace will still need to be explicit as follows:

Compiled By B T Chisuwa Page 234


#include <iostream>
using std::cout;

int main ()
{
cout << "std::endl is used with std!" << std::endl;
return 0;
}

If we compile and run above code, this would produce the following result:
std::endl is used with std!

Names introduced in a using directive obey normal scope rules. The name is visible from the
point of the using directive to the end of the scope in which the directive is found. Entities with
the same name defined in an outer scope are hidden.

Discontiguous Namespaces:
A namespace can be defined in several parts and so a namespace is made up of the sum of its
separately defined parts. The separate parts of a namespace can be spread over multiple files.

So, if one part of the namespace requires a name defined in another file, that name must still be
declared. Writing a following namespace definition either defines a new namespace or adds new
elements to an existing one:
namespace namespace_name {
// code declarations
}

Nested Namespaces:
Namespaces can be nested where you can define one namespace inside another name space as
follows:
namespace namespace_name1 {
// code declarations
namespace namespace_name2 {
// code declarations
}
}

Compiled By B T Chisuwa Page 235


You can access members of nested namespace by using resultion operators as follows:
// to access members of namespace_name2
using namespace namespace_name1::namespace_name2;

// to access members of namespace:name1


using namespace namespace_name1;

In the above statements, if you are using namespace_name1, then it will make elements of
namespace_name2 available in the scope as follows:
#include <iostream>
using namespace std;

// first name space


namespace first_space
{
void func(){
cout << "Inside first_space" << endl;
}

// second name space


namespace second_space{
void func(){
cout << "Inside second_space" << endl;
}
}
}

using namespace first_space::second_space;

int main ()
{
// This calls function from first name space.
func();

return 0;
}

If we compile and run above code, this would produce the following result:
Inside second_space

Compiled By B T Chisuwa Page 236


TEMPLATES

Templates are the foundation of generic programming, which involves writing code in a way that
is independent of any particular type.

C++ has a mechanism called templates to reduce code duplication when supporting numerous
data types. A C++ function or C++ class with functions which operates on integers, float and
double data types can be unified with a single template function or class with functions which is
flexible enough to use all three data types. This mechanism in C++ is called the "Template".

C++ templates fall under the category of "meta-programming" and auto code generation
although one never sees the code generated.

You can use templates to define functions as well as classes, let us see how do they work:

Function Template:
The general form of a template function definition is shown here:
template <class type> ret-type func-name(parameter list)
{
// body of function
}

Here, type is a placeholder name for a data type used by the function. This name can be used
within the function definition.

The following is the example of a function template that returns the maximum of two values:
#include <iostream>
#include <string>

using namespace std;

template <typename T>


inline T const& Max (T const& a, T const& b)

Compiled By B T Chisuwa Page 237


{
return a < b ? b:a;
}

int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;

double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;

return 0;
}

If we compile and run above code, this would produce the following result:
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World

Class Template:
Just as we can define function templates, we can also define class templates. The general form of
a generic class declaration is shown here:
template <class type> class class-name {
.
.
.
}

Here, type is the placeholder type name, which will be specified when a class is instantiated.
You can define more than one generic data type by using a comma-separated list.

Following is the example to define a template class and implement generic methods to calculate
area and perimeter of a rectangle.

Compiled By B T Chisuwa Page 238


#include <iostream>

using namespace std;

template <class T>


class Rectangle{
T length, width;

public:
void setValues()
{
cout<<"Enter Length"<<endl;
cin>>length;
cout<<"Enter Width"<<endl;
cin>>width;
}

T calcArea()
{
return length*width;
}

T calcPerimeter()
{
return 2*(length+width);
}

void display()
{
cout<<"Area is "<< calcArea() <<endl;
cout<<"Perimeter is "<< calcPerimeter() <<endl;
}

};

int main()
{
Rectangle <double> r; // <double> is a Template Argument

r.setValues();
r.display();

return 0;
}

Compiled By B T Chisuwa Page 239


If we compile and run above code, this would produce the following result:
Enter Length
6
Enter Width
8
Area is 48
Perimeter is 28

Compiled By B T Chisuwa Page 240


PREPROCESSOR

The preprocessors are the directives which give instruction to the compiler to preprocess the
information before actual compilation starts.

All preprocessor directives begin with #, and only white-space characters may appear before a
preprocessor directive on a line. Preprocessor directives are not C++ statements, so they do not
end in a semicolon (;).

You already have seen a #include directive in all the examples. This macro is used to include a
header file into the source file.

There are number of preprocessor directives supported by C++ like #include, #define, #if, #else,
#line, etc. Let us see important directives:

The #define Preprocessor:


The #define preprocessor directive creates symbolic constants. The symbolic constant is called a
macro and the general form of the directive is:
#define macro-name replacement-text

When this line appears in a file, all subsequent occurrences of macro in that file will be replaced
by replacement-text before the program is compiled. For example:
#include <iostream>
using namespace std;

#define PI 3.14159

int main ()
{
cout << "Value of PI :" << PI << endl;
return 0;
}

Compiled By B T Chisuwa Page 241


Now, let us do the preprocessing of this code to see the result, assume we have source code file,
so let us compile it with -E option and redirect the result to test.p. Now, if you will check test.p,
it will have lots of information, and at the bottom, you will fine the value replaced as follows:
$gcc -E test.cpp > test.p
...
int main ()
{
cout << "Value of PI :" << 3.14159 << endl;
return 0;
}

Function-Like Macros:
You can use #define to define a macro which will take argument as follows:
#include <iostream>
using namespace std;

#define MIN(a,b) (((a)<(b)) ? a : b)

int main ()
{
int i, j;
i = 100;
j = 30;

cout <<"The minimum is " << MIN(i, j) << endl;


return 0;
}

If we compile and run above code, this would produce the following result:
The minimum is 30

Conditional Compilation:
There are several directives, which can use to compile selectively portions of your program's
source code. This process is called conditional compilation.

The conditional preprocessor construct is much like the if selection structure. Consider the
following preprocessor code:

Compiled By B T Chisuwa Page 242


#ifndef NULL
#define NULL 0
#endif

You can compile a program for debugging purpose and can debugging turn on or off using a
single macro as follows:
#ifdef DEBUG
cerr <<"Variable x = " << x << endl;
#endif

causes the cerr statement to be compiled in the program if the symbolic constant DEBUG has
been defined before directive #ifdef DEBUG. You can use #if 0 statment to comment out a
portion of the program as follows:
#if 0
code prevented from compiling
#endif

Let us try the following example:


#include <iostream>
using namespace std;
#define DEBUG
#define MIN(a,b) (((a)<(b)) ? a : b)

int main ()
{
int i, j;
i = 100;
j = 30;
#ifdef DEBUG
cerr <<"Trace: Inside main function" << endl;
#endif
#if 0
/* This is commented part */
cout << MKSTR(HELLO C++) << endl;
#endif
cout <<"The minimum is " << MIN(i, j) << endl;
#ifdef DEBUG
cerr <<"Trace: Coming out of main function" << endl;
#endif
return 0;
}

Compiled By B T Chisuwa Page 243


If we compile and run above code, this would produce the following result:
Trace: Inside main function
The minimum is 30
Trace: Coming out of main function

The # and ## Operators:


The # and ## preprocessor operators are available in C++ and ANSI/ISO C. The # operator
causes a replacement-text token to be converted to a string surrounded by quotes.

Consider the following macro definition:


#include <iostream>
using namespace std;
#define MKSTR(x) #x
int main ()
{
cout << MKSTR(HELLO C++) << endl;
return 0;
}

If we compile and run above code, this would produce the following result:
HELLO C++

Let us see how it worked. It is simple to understand that the C++ preprocessor turns the line:
cout << MKSTR(HELLO C++) << endl;

into the following line:


cout << "HELLO C++" << endl;

The ## operator is used to concatenate two tokens. Here is an example:


#define CONCAT( x, y ) x ## y

Compiled By B T Chisuwa Page 244


When CONCAT appears in the program, its arguments are concatenated and used to replace the
macro. For example, CONCAT(HELLO, C++) is replaced by "HELLO C++" in the program as
follows.
#include <iostream>
using namespace std;
#define concat(a, b) a ## b
int main()
{
int xy = 100;
cout << concat(x, y);
return 0;
}

If we compile and run above code, this would produce the following result:
100

Let us see how it worked. It is simple to understand that the C++ preprocessor transforms:
cout << concat(x, y);

into the following line:


cout << xy;

Predefined C++ Macros:


C++ provides a number of predefined macros mentioned below:
Macro Description
__LINE__ This contain the current line number of the program when it is being compiled.
__FILE__ This contain the current file name of the program when it is being compiled.
__DATE__ This contains a string of the form month/day/year that is the date of the translation
of the source file into object code.
__TIME__ This contains a string of the form hour:minute:second that is the time at which the
program was compiled.

Let us see an example for all the above macros:

Compiled By B T Chisuwa Page 245


#include <iostream>
using namespace std;
int main ()
{
cout << "Value of __LINE__ : " << __LINE__ << endl;
cout << "Value of __FILE__ : " << __FILE__ << endl;
cout << "Value of __DATE__ : " << __DATE__ << endl;
cout << "Value of __TIME__ : " << __TIME__ << endl;
return 0;
}

If we compile and run above code, this would produce the following result:
Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48

Compiled By B T Chisuwa Page 246


SIGNAL HANDLING

Signals are the interrupts delivered to a process by the operating system which can terminate a
program prematurely. You can generate interrupts by pressing Ctrl+C on a UNIX, LINUX, Mac
OS X or Windows system.

There are signals which can not be caught by the program but there is a following list of signals
which you can catch in your program and can take appropriate actions based on the signal. These
signals are defined in C++ header file <csignal>.

Signal Description
SIGABRT Abnormal termination of the program, such as a call to abort
SIGFPE An erroneous arithmetic operation, such as a divide by zero or an operation
resulting in overflow.
SIGILL Detection of an illegal instruction
SIGINT Receipt of an interactive attention signal.
SIGSEGV An invalid access to storage.
SIGTERM A termination request sent to the program.

The signal() function:


C++ signal-handling library provides function signal to trap unexpected events. Following is the
syntax of the signal() function:
void (*signal (int sig, void (*func)(int)))(int);

Keeping it simple, this function receives two arguments: first argument as an integer which
represents signal number and second argument as a pointer to the signal-handling function.

Compiled By B T Chisuwa Page 247


Let us write a simple C++ program where we will catch SIGINT signal using signal() function.
Whatever signal you want to catch in your program, you must register that signal using signal
function and associate it with a signal handler. Examine the following example:
#include <iostream>
#include <csignal>
using namespace std;

void signalHandler( int signum )


{
cout << "Interrupt signal (" << signum << ") received.\n";
// cleanup and close up stuff here
// terminate program
exit(signum);
}

int main ()
{
// register signal SIGINT and signal handler
signal(SIGINT, signalHandler);
while(1){
cout << "Going to sleep...." << endl;
sleep(1);
}
return 0;
}

When the above code is compiled and executed, it produces the following result:
Going to sleep....
Going to sleep....
Going to sleep....

Now, press Ctrl+c to interrupt the program and you will see that your program will catch the
signal and would come out by printing something as follows:
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

Compiled By B T Chisuwa Page 248


The raise() function:
You can generate signals by function raise(), which takes an integer signal number as an
argument and has the following syntax.
int raise (signal sig);

Here, sig is the signal number to send any of the signals: SIGINT, SIGABRT, SIGFPE, SIGILL,
SIGSEGV, SIGTERM, SIGHUP. Following is the example where we raise a signal internally
using raise() function as follows:
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler( int signum )
{
cout << "Interrupt signal (" << signum << ") received.\n";
// cleanup and close up stuff here
// terminate program
exit(signum);
}
int main ()
{
int i = 0;
// register signal SIGINT and signal handler
signal(SIGINT, signalHandler);
while(++i){
cout << "Going to sleep...." << endl;
if( i == 3 ){
raise( SIGINT);
}
sleep(1);
}
return 0;
}

When the above code is compiled and executed, it produces the following result and would come
out automatically:
Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

Compiled By B T Chisuwa Page 249


Compiled By B T Chisuwa Page 250

You might also like