C++ Tutorial
C++ Tutorial
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.
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.
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:
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.
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.
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
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.
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.
// 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.
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);
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.
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.
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.
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.
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;
}
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;
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.
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++.
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.
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.
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;
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.
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;
// 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
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;
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;
}
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;
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 ()
When the above code is compiled and executed, it produces the following result:
10
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;
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.
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.
When the above code is compiled and executed, it produces the following result:
50
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:
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
Example:
Following is the example to understand this difference:
#include<iostream>
using namespace std;
main()
{
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
Logical Operators:
There are following logical operators supported by C++ language
Assignment Operators:
There are following assignment operators supported by C++ language:
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.
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
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);
}
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.
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;
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.
}
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;
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.
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.
#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
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.
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;
}
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
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
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
Example:
#include <iostream>
using namespace std;
int main ()
{
char grade = 'D';
switch(grade)
{
case 'A' :
cout << "Excellent!" << endl;
break;
case 'B' :
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;
}
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.
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.
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
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.
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 –
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)
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:
int main ()
{
RectangleArea(); // Function Call
return 0;
}
area = length*breadth;
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.
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.
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;
}
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;
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;
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.
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.
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};
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:
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:
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
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.
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};
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 << "]: ";
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;
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:
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.
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:
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:
When the above code is compiled together and executed, it produces the following result:
Average value is: 214.4
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)
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
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";
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 ()
When the above code is compiled and executed, it produces result something as follows:
Greeting message: Hello
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
When the above code is compiled and executed, it produces result something as follows:
str3 : Hello
str1 + str2 : HelloWorld
str3.size() : 10
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
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.
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
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
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.
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.
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
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
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;
}
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:
Above statement is valid and will compile successfully because var is not changed.
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];
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 ()
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
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
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:
When the above code is compiled together and executed, it produces the following result:
Average value is: 214.4
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;
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
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.
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;
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;
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]
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 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;
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.
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;
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
}
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.
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
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.
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
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.
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;
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.
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.
When the above code is compiled and executed, it produces the following result:
Error message: Unable to read....
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....
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>
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>
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.
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.
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”;
Cout.precision(3);
Cout << sqrt(2) << “\n”;
Cout.precision(5); //Reset the precision
Cout << 3.14159 << “\n”;
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.
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;
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:
struct Student
{
char regnumber[20];
char fullname[50];
char address[50];
int age;
};
int main()
{
Student s1;
cout << "Enter regnumber: ";
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.
struct structure2
{
----------
----------
struct structure1 obj;
};
#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;
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
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");
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
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>
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id; };
int main( ) {
struct Books Book1; // Declare Book1 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;
When the above code is compiled and executed, it produces the following result:
Now, you can use Books directly to define variables of Books type. Following is the example:
Books Book1, Book2;
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.
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.
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
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.
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;
// 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.
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
};
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 );
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
class set
{
int m, n;
public:
void input(void);
void display(void);
int largest(void);
};
int main()
{
set A;
A.input();
A.display();
return 0;
}
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];
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”;
}
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).
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.
class employee
{
char name[30]; //string as class member
float age;
public:
int main()
{
employee manager[size];
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
Details of manager3
Enter name: zzz
Enter age: 50
Manager1
Name: xxx
Age: 45
Manager2
Name: yyy
Age: 37
Manager3
Name: zzz
Age: 50
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.
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;
}
int main()
{
time T1, T2, T3;
return 0;
}
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 Line
{
public:
double length;
void setLength( double len );
double getLength( void );
};
double Line::getLength(void)
{
return length ;
}
When the above code is compiled and executed, it produces the following result:
Length of line : 6
Length of line : 10
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 );
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
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
{
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
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.
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{
…..
class Box
{
double width;
public:
friend void printWidth( Box box );
void setWidth( double wid );
};
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;
void show(complex);
};
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
return 0;
}
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.
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;
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
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;
}
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
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:
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);
return 0;
}
When the above code is compiled and executed, it produces the following result:
Constructor called.
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();
};
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”.
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.
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;
}
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;
M *op = &n;
(op->*pf)(30,40);
cout << “SUM = ” << sum(n) << endl;
return 0;
}
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
…..
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.
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:
int main(void)
{
Box Box1(3.3, 1.2, 1.5); // Declare box1
Box Box2(8.5, 6.0, 2.0); // Declare box2
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.
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;
double Volume()
{
return length * breadth * height;
}
int Box::objectCount = 0;
int main(void)
{
// Print total number of objects before creating object.
cout << "Inital Stage Count: " << Box::getCount() << endl;
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.
class integer
{
int m, n;
public:
integer(void); // constructor declared
…..
…..
};
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;
Remember, when a constructor is declared for a class, initialisation of the class objects becomes
mandatory.
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;
};
int main( )
{
Line line;
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
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.
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.
class integer
{
int m,n;
public:
integer(int, int); // constructor declared
void display(void)
{
cout << “m = ” << m <<endl;
cout << “n = ” << n <<endl;
}
};
int main( )
{
integer int1(0, 100); // constructor called implicitly
return 0;
}
Object 2
m = 25
n = 75
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
{
…..
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);
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.
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;}
cout <<endl;
cout << “P = ”; show(P);
cout << “Q = ”; show(Q);
cout << “R = ”; show(R);
return 0;
}
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.
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.
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;
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);
};
int main()
{
Fixed_deposit FD1, FD2, FD3; // deposits created
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);
return 0;
}
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.
class String
{
char *name;
int length;
public:
String() // constructor -1
{
length = 0;
name = new char[length + 1];
}
void display(void)
{
cout << name <<endl;
}
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;
}
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
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 main()
{
int m,n;
int i, j, value;
for()
{
for()
{
cin >> value;
A.get_element(I,j,value)
}
}
return 0;
}
17
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.
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.
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)
{
....
}
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;
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
// allocate memory for the pointer;
ptr = new int;
*ptr = len;
}
Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int main( )
{
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
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;
int main()
{
code A(100); // object A is created and initialised
code B(A); // copy constructor called
code C = A; // copy constructor called again
return 0;
}
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.
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.
class Line
{
double length;
public:
void setLength( double len );
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
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”.).
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.
We can summarize the different access types according to who can access them in the following
way:
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.
// 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);
return 0;
}
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.
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);
};
return 0;
}
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;
void setHeight(int h)
{
height = h;
}
};
// 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();
return 0;
}
When the above code is compiled and executed, it produces the following result:
Total area: 35
Total paint cost: $2450
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();
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
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.
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.
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
}
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;
}
};
};
int main()
{
Parent obj1;
Child obj2;
obj1.print();
obj2.print();
return 0;
}
Output:
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;
}
};
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
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:
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
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.
We can change the virtual function area() in the base class to the following:
class Shape {
protected:
int width, height;
The = 0 tells the compiler that the function has no body and above virtual function will be called
pure virtual function.
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.
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.
• 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.
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.
class Adder{
public:
// constructor
Adder(int i = 0)
{
total = i;
}
private:
// hidden data from outside world
int total;
};
int main( )
{
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.
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.
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.
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.
// 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);
}
};
int main(void)
{
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
Tri.setWidth(5);
Tri.setHeight(7);
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
This architecture also allows new applications to be added to a system easily, even after the
system has been defined.
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);
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.
int main ()
{
char data[100];
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
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.
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:
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
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
}
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
}
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!
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.
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.
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
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
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
class Box
{
public:
Box() {
cout << "Constructor called!" <<endl;
}
~Box() {
cout << "Destructor called!" <<endl;
}
};
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!
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.
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:
int main ()
{
// Calls function from first name space.
first_space::func();
return 0;
}
If we compile and run above code, this would produce the following result:
Inside first_space
Inside 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 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:
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
}
}
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;
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
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>
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.
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;
}
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:
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;
}
Function-Like Macros:
You can use #define to define a macro which will take argument as follows:
#include <iostream>
using namespace std;
int main ()
{
int i, j;
i = 100;
j = 30;
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:
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
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;
}
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;
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);
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
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.
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.
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.
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.