SlideShare a Scribd company logo
1.11. MATHEMATICS 181
24 return 0;
}
✌
✆
Output of above program is
✞
Addition of 5 and 2 is : 7
Subtraction of 5 and 2 is : 3
Multiplication of 5 and 2 is : 10
Division of 5 and 2 is : 2
Modulus of 5 and 2 is : 1
✌
✆
If mathematical expressions are mixed with C++ operators and are directly made to
be put at output stream then their grouping is required. Parentheses are used to group
the scope of expression.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 /*3 + 3 << 1 *
* 6 << 1 *
7 * 6 1 */
/* Here << is considered as a *
9 *C++ insertion operator */
cout << 3 + 3 << 1 << endl ;
11 /*(3 + 3 << 1)*
* (6 << 1) *
13 * 12 */
/* Here << is considered as*
15 *a left shift operator */
cout << (3 + 3 << 1) << endl ;
17 return 0;
}
✌
✆
✞
61
12
✌
✆
182 Array & Pointer
2.1. ARRAY 183
2Array & Pointer
2.1 Array
Arrays in C++ stores data in a single variable name with an index, also known as a
subscript. It is simply a list or ordered grouping for variables of the same type. Arrays
often help a programmer in organize collections of data efficiently and intuitively.
2.1.1 Uni-dimensional Array
Arrays are declared and initialized like
✞
int numbers [6]; // array declared
2 int point [6]={0 , 0, 1, 0, 0, 0}; // array initialized
✌
✆
The brackets ‘[ ]’ identify ‘numbers’ or ‘points’ and the number enclosed in the bracket
indicates the number of elements in the array, i.e. subscripts of the array. An element
of array can be accessed by its index number. In following example, each element of the
array is accessed by its index number.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char ** argv ) {
int ix;
6 short anArray [] = {3, 6, 9, 12, 15};
for (ix = 0; ix < ( sizeof (anArray ) / sizeof ( short)); ++ix) {
8 cout << anArray [ix] << endl ;
}
10 return 0;
}
✌
✆
In the above example, size of array was not explicitly specified. The compiler knows
size of array from the initialized list. The size of ‘anArray’ is ‘5’ because ‘anArray’ has
five elements. Addition of an additional element to the list will increase its size to six.
Static declaration of the size of an array, the array list will be overflow. To overcome this
problem sizeof expression is used as
✞
1 size = sizeof(anArray)/ sizeof(short)
✌
✆
Because of the sizeof expression in for loop, the script is automatically adjusted to this
change. Designated initializer is allow to pick and choose the initialized elements. An
array initialised with ‘[ ]’ is called expandable array. When an array is declared without
184 Array & Pointer
its size, compiler first counts elements of the array and then it grows the array upto a
size so that all the elements can be stored in the array.
✞
1 /* Array with growing size . */
int days [] = {31, 28, 31, 30, 31, 29};
✌
✆
A one dimensional array with variable size can not be declared as shown below:
✞
int i;
2 cin >> i;
int a[i]
✌
✆
The size must be constant. Again, if the array is created with variable size using new
keyword, then it is acceptable.
✞
1 #include <iostream >
using namespace std;
3
int main () {
5 int n, j;
cout << "How may array size : ";
7 cin >> n;
/* Reserve the memory */
9 int *a = new int[n];
for (j = 0; j < n; j++) {
11 a[j] = j*n;
}
13 for (j = 0; j < n; j++) {
cout << a[j] << endl ;
15 }
delete [] a;// Free the memory , required compulsory
17 return 0;
}
✌
✆
✞
0
3
6
✌
✆
2.1.2 Multi-dimensional Array
A multi-dimensional array can be declared and initialized as given below:
✞
1 int two_d [2][3] = {{ 5, 2, 1 },
{ 6, 7, 8 }};
✌
✆
Here [2] represents number of rows and [3] represents number of columns of the two
dimensional array. Multi-dimensional array can be used to add, subtract and product
(either dot or cross) of two vectors or matrices.
2.1. ARRAY 185
✞
#include <iostream >
2 using namespace std;
4 #define X 5
#define Y 5
6
int main (int argc , char ** argv ) {
8 int ix , iy;
10 short anArray[X][Y];
for (ix = 0; ix < X; ++ix) {
12 for (iy = 0; iy < Y; ++iy) {
anArray[ix][ iy] = ix * iy;
14 };
}
16 for (ix = 0; ix < X; ++ix) {
for (iy = 0; iy < Y; ++iy) {
18 cout << anArray [ix][iy] << "t";
};
20 cout << endl ;
}
22 return 0;
}
✌
✆
✞
0 0 0 0 0
0 1 2 3 4
0 2 4 6 8
0 3 6 9 12
0 4 8 12 16
✌
✆
Following is an example of elementwise addition and subtraction of two matrices.
✞
1 #include <iostream >
using namespace std;
3
/* Random number generator between 0 to 10.*/
5 int rand_num (int a, int b) {
return ((a * 97 + b * 21) & 10);
7 }
9 int main (int argc , char ** argv ) {
int i/* row*/,
11 j/* col*/;
int A [3][3]/* First Matrix*/,
13 B[3][3]/* Second Matrix*/ ,
C[3][3]/* Dot Matrix*/;
15 cout << "First Random Matrix is :" << endl ;
/* For each of three rows */
17 for (i = 0; i < 3; i++) {
/* There are three columns.*/
186 Array & Pointer
19 for (j = 0; j < 3; j++) {
/* Assign a random matrix elements .*/
21 A[i][j] = rand_num (i*j, j);
cout << A[i][j] << "t";
23 }
/* Print new line after completion of each row*/
25 cout << endl << endl ;
}
27 cout << "Second Random Matrix is :" << endl ;
/* For each of three rows */
29 for (i = 0; i < 3; i++) {
/* There are three columns.*/
31 for (j = 0; j < 3; j++) {
/* Assign a random matrix elements .*/
33 B[i][j] = rand_num (i, i * j);
cout << B[i][j] << "t";
35 }
/* Print new line after completion of each row*/
37 cout << endl << endl ;
}
39 cout << "Elementwise Addition of Matrices is :" << endl ;
/* For each of three rows */
41 for (i = 0; i < 3; i++) {
/* There are three columns.*/
43 for (j = 0; j < 3; j++) {
/* Add matrices elementwise .*/
45 C[i][j] = A[i][j] + B[i][j];
cout << C[i][j] << "t";
47 }
/* Print new line after completion of each row*/
49 cout << endl << endl ;
}
51 cout << "Elementwise Subtraction of Matrices is :" << endl ;
/* For each of three rows */
53 for (i = 0; i < 3; i++) {
/* There are three columns.*/
55 for (j = 0; j < 3; j++) {
/* Subtract matrices elementwise .*/
57 C[i][j] = A[i][j] - B[i][j];
cout << C[i][j] << "t";
59 }
/* Print new line after completion of each row*/
61 cout << endl << endl ;
}
63 return 0;
}
✌
✆
✞
First Random Matrix is :
0 0 10
0 2 8
0 2 10
2.1. ARRAY 187
Second Random Matrix is :
0 0 0
0 2 10
2 8 2
Elementwise Addition of Matrix is :
0 0 10
0 4 18
2 10 12
Elementwise Subtraction of Matrix is :
0 0 10
0 0 -2
-2 -6 8
✌
✆
Dot product example is
✞
#include <iostream >
2 using namespace std;
4 /* Random number generator between 0 to 10.*/
int rand_num (int a, int b) {
6 return ((a * 97 + b * 21) & 10);
}
8
int main (int argc , char ** argv ) {
10 int i/* row*/,
j/* col*/;
12 int A [3][3]/* First Matrix*/,
B[3][3]/* Second Matrix*/ ,
14 C[3][3]/* Dot Matrix*/;
cout << "First Random Matrix is :" << endl ;
16 /* For each of three rows */
for (i = 0; i < 3; i++) {
18 /* There are three columns.*/
for (j = 0; j < 3; j++) {
20 /* Assign a random matrix elements .*/
A[i][j] = rand_num (i*j, j);
22 cout << A[i][j] << "t";
}
24 /* Print new line after completion of each row*/
cout << endl << endl ;
26 }
cout << "Second Random Matrix is :" << endl ;
28 /* For each of three rows */
for (i = 0; i < 3; i++) {
30 /* There are three columns.*/
for (j = 0; j < 3; j++) {
32 /* Assign a random matrix elements .*/
B[i][j] = rand_num (i, i * j);
34 cout << B[i][j] << "t";
}
36 /* Print new line after completion of each row*/
cout << endl << endl ;
188 Array & Pointer
38 }
cout << "Dot Product of Matrices is :" << endl ;
40 /* For each of three rows */
for (i = 0; i < 3; i++) {
42 /* There are three columns.*/
for (j = 0; j < 3; j++) {
44 /* Subtract matrices elementwise .*/
C[i][j] = A[i][j] * B[i][j];
46 cout << C[i][j] << "t";
}
48 /* Print new line after completion of each row*/
cout << endl << endl ;
50 }
return 0;
52 }
✌
✆
✞
First Random Matrix is :
8 2 2
2 2 0
2 0 8
Second Random Matrix is :
8 8 8
8 2 2
8 2 8
Dot Product Matrix is :
64 16 16
16 4 0
16 0 64
✌
✆
Cross product example is
✞
#include <iostream >
2 #include <cmath >
using namespace std;
4
/* Random number generator between 0 to 10.*/
6 int newseed = 10;
8 int seed (int a) {
newseed = newseed + a;
10 return newseed;
}
12
int rand_num (int a) {
14 seed (a);
return (( newseed * 99991 + 12345) & 10);
16 }
18 int main (int argc , char ** argv ) {
int i/* row*/,
20 j/* col*/;
2.1. ARRAY 189
int A[3]/* First Matrix */,
22 B[3]/* Second Matrix*/,
C[3]/* Vector Matrix*/;
24 cout << "First Random Matrix is :" << endl ;
/* For each of three rows */
26 for (i = 0; i < 3; i++) {
/* There are three columns.*/
28 /* Assign a random matrix elements .*/
A[i] = rand_num (i);
30 cout << A[i] << "t";
}
32 cout << endl ;
cout << "Second Random Matrix is :" << endl ;
34 /* For each of three rows */
for (i = 0; i < 3; i++) {
36 /* There are three columns.*/
/* Assign a random matrix elements .*/
38 B[i] = rand_num (i);
cout << B[i] << "t";
40 }
cout << endl ;
42
cout << "Cross Product of Matrices is :" << endl ;
44 /* For each of three rows */
for (i = 0; i < 3; i++) {
46 /* Subtract matrices elementwise .*/
C[i] = pow(-1, 2 * i)* (A[(i + 1) % 3] * B[(i + 2) % 3] 
48 - B[(i + 1) % 3] * A[(i + 2) % 3]);
cout << C[i] << "t";
50 }
return 0;
52 }
✌
✆
✞
First Random Vector is :
10 2 0
Second Random Vector is :
0 10 8
Cross Product Vector is :
16 -80 100
✌
✆
Array can be passed to a function like
✞
#include <iostream >
2 using namespace std;
4 /*+- Array pointer with **
**| expandable size */
6 void init_array (int a[], int count) {
int i;
8 for (i = 0; i < count; i++)
a[i] = i * 10;
190 Array & Pointer
10 for (i = 0; i < count; i++)
cout << "The a value is " << a[i] << endl ;
12 }
14 int main (int argc , char ** argv ) {
int mydata [10];
16 init_array (mydata , 5);
return 0;
18 }
✌
✆
✞
The a value is 0.
The a value is 10.
The a value is 20.
The a value is 30.
The a value is 40.
✌
✆
For multidimensional array, there is no limit of dimension in C. Here, a four dimensional
matrix is represented by
✞
1 int myData [2][3][2][4]
✌
✆
A new dimension in array declaration is always grouped by curly braces. One dimensional
array has one curly braces, i.e. one row. In two dimensional array, there are two one
dimensional rows both separated by comma (,) operator. These two rows are enclosed by
another curly braces. In three dimensional systems of arrays, two 2-dimensional arrays
are placed one over another. In the following example, two, three and four dimensional
arrays are declared.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int a [2][2] = {
// cols
7 {1, 2}, // row
{5, 6} // row
9 };
int b [2][2][2] = {
11 {
// cols
13 {1, 2}, // row
{5, 6} // row
15 },
{// height
17 {4, 3},
{8, 9}
19 }
};
21 int c [2][2][2][2] = {
{
2.1. ARRAY 191
23 {
// cols
25 {1, 2}, // row
{5, 6} // row
27 },
{// height
29 {1, 2},
{5, 6}
31 }
},
33 {// time
{
35 {4, 1},
{7, 6}
37 },
{
39 {4, 4},
{9, 1}
41 }
}
43 };
int i, j, k, l;
45 cout << "Elements of matrix a are " << endl ;
for (i = 0; i < 2; i++) {
47 for (j = 0; j < 2; j++) {
cout << "Element " << a[i][j] << endl ;
49 }
}
51 cout << "Elements of matrix b are " << endl ;
for (i = 0; i < 2; i++) {
53 for (j = 0; j < 2; j++) {
for (k = 0; k < 2; k++) {
55 cout << "Element " << b[i][j][k] << endl ;
}
57 }
}
59 cout << "Elements of matrix c are " << endl ;
for (i = 0; i < 2; i++) {
61 for (j = 0; j < 2; j++) {
for (k = 0; k < 2; k++) {
63 for (l = 0; l < 2; l++) {
cout << "Element " << c[i][j][k][l] << endl ;
65 }
}
67 }
}
69 return 0;
}
✌
✆
192 Array & Pointer
2.1.3 Array in Function
In a function, an argument is passed as value unless the program needs to alter the
argument. In this case there is requirement that a pointer should be passed to the
function. Arrays can passed to a function as pointers. If an array is passed to the
function, function would have to allocate enough space to hold a copy of the original
array and then copy all the data from the original array to the new array. It is much
quicker to pass the address of the array rather than array itself and have the function
work with the original data. Prototype for the passing of an array to the function is
✞
int sum(int arr [])
✌
✆
C++ compilers do not check the size of the array passed to the function hence for good
programming, the function should know the limits of actions on the array. This is why a
new parameter of array size as ‘n’ is passed to the function as
✞
1 int sum(int arr[], int n)
✌
✆
The name of an array is address of first element hence array name passed as argument to
the function should be matching argument and a pointer. In this context int arr[] is same
as the int * arr. In case of multi-dimensional array, first bracket in the multidimensional
array may be empty or not empty but other bracket should contains a valid integer for
the size of the array dimension.
✞
1 #include <iostream >
using namespace std;
3 #define ROWS 3
#define COLS 4
5 int sum(int rows , int cols , int ar [][ COLS ]);
7 int main (void ) {
int i, j;
9 int varr [ROWS ][ COLS ];
for (i = 0; i < ROWS ; i++)
11 for (j = 0; j < COLS ; j++)
varr [i][j] = i * j + j;
13 cout << "3x4 Array n";
cout << "Sum of all elements " << sum(ROWS , COLS , varr );
15 return 0;
}
17
int sum(int rows , int cols , int ar [][ COLS ]) {
19 int r;
int c;
21 int tot = 0;
for (r = 0; r < rows ; r++)
23 for (c = 0; c < cols ; c++)
tot += ar[r][c];
25 return tot;
}
✌
✆
2.1. ARRAY 193
✞
3x4 Array
Sum of all elements 36
✌
✆
2.1.4 Return Array From Function
C++ allows to return an array from a function. To return single dimension array, we
create a function with pointer. See the example below:
✞
#include <iostream >
2 #include <ctime >
using namespace std;
4
int * getArray () {
6 static int a[5];
8 for (int i = 0; i < 5; ++i) {
a[i] = i * 2;
10 }
return a;
12 }
14 int main (int argc , char *argv []) {
int *p;
16
p = getArray ();
18
for (int i = 0; i < 5; i++) {
20 cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl ;
22 }
24 return 0;
}
✌
✆
✞
*(p + 0) : 0
*(p + 1) : 2
*(p + 2) : 4
*(p + 3) : 6
*(p + 4) : 8
✌
✆
2.1.5 String As Array
String is defined as array of characters. C++ allows a character array to be represented
by a character string with a null terminating character which is automatically added at
the end of character array instead of a list of characters. Example of string array is shown
below.
194 Array & Pointer
✞
1 char string [] = {’A’, ’p’, ’p’, ’l’, ’e’, ’S’, ’0 ’};
✌
✆
Normal size of a string array is controlled at initialization of the string array. An string
array stores elements upto its declared length. Excess elements are ignored and skipped.
In following example only ten characters will be stored in the string array ‘mystr’.
✞
1 char mystr [10] = "Apple is red.";
✌
✆
It is convenient to let the compiler determine the array size. If anyone omits the size of
array at the time of array declaration and initialization, the compiler itself determines the
size for supplied string. In following example, compiler set the string length of thirteen
characters.
✞
1 char mystr[] = "Apple is red.";
✌
✆
A pointer-to-string method may also be used for string declaration and initialization. In
pointer notation, above example will be looked like
✞
1 const char *ptrstr = "Merkkijono ";
✌
✆
Both declarations amount to saying that ‘ptrstr’ is a pointer to the indicated string.
‘ptrstr’ string variable declared as array or as pointer, both are same but only pointer
version can be used with increment operator. To create an extra long string, string is
splitted into multiple sections, by closing the first section with a quote, and recommencing
the string on the next line (also starting and ending in a quote):
✞
1 char string [] = "This is a very , very long "
"string that requires two lines.";
✌
✆
Full example is given below:
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
char ch;
6 char string[] = "Two lines "
"string.";
8 int i = 0;
while (string[i] != ’0’) {
10 ch = string[i];
cout << ch;
12 i++;
}
14 return 0;
}
✌
✆
✞
T.w.o. .l.i.n.e.s. .s.t.r.i.n.g...
✌
✆
2.1. ARRAY 195
When an array is declared and initialized with characters, there must be a terminating
null character. Otherwise there shall be garbage output. For example following syntax
has no terminating null character. It is not in standard format.
✞
1 char a[10];
a[0]= ’a’;
3 a[1]= ’r’;
a[2]= ’u’;
✌
✆
In above method, a null terminator is added as its last element. Now, the string array is
initialized in standard format.
✞
char a[10];
2 a[0]= ’a’;
a[1]= ’r’;
4 a[2]= ’u’;
a[3]= ’0’;
✌
✆
See following two examples, in which string is terminating without and with null termi-
nating character. First example gives garbage output (see below).
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 char a[10];
a[0] = ’a’;
7 a[1] = ’r’;
a[2] = ’u’;
9 cout << a;
return 0;
11 }
✌
✆
✞
<garbage output >
✌
✆
In this second example, string is terminated with null character. This example gives
output what we required.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 char a[10];
a[0] = ’a’;
7 a[1] = ’r’;
a[2] = ’u’;
9 a[3] = ’0’;
cout << a;
11 return 0;
}
✌
✆
196 Array & Pointer
✞
aru
✌
✆
Static array size should be larger than one to the required size of the array to store data.
For example, to store one byte data, array size should be two. Similarly, for storing n
bytes data, array size should be at least n + 1.
2.1.6 Size of Array
C++ features two kinds of arrays: static (compile-time, fixed size) and dynamic (allocated
at run-time). The length of a dynamic array cannot be acquired from the array itself -
its length must be stored elsewhere. The size of array is computed as
✞
1 int length = sizeof(<array name >) / sizeof(<array element >);
✌
✆
Preprocessor ways for array length is defined as
✞
1 #define ARRAY_LENGTH (A) (sizeof(A) / sizeof(A[0]) )
✌
✆
Arrays become pointers when passed as a parameter to a function. Thus, the length of
an array parameter may not require directly. A dedicated length parameter is required.
An example is given below.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 const char *fruit[2] = {"apples", "oranges"};
7 /* Length of the array by dividing *
*the size of all elements by the*
9 *size of the first element. */
11 int length = sizeof (fruit) / sizeof (fruit[0]) ;
13 cout << length;
15 return 0;
}
✌
✆
✞
2
✌
✆
In above example, length of the array is obtained by dividing the size of all elements
(found with sizeof (fruit)) by the size of the first element. Note that since the array
elements are pointers to null-terminated character arrays, the size of the first element is
actually the size of the pointer type - not the length of the string. This size, regardless
of the type being pointed to, is 8 bytes, 4 bytes, or 2 bytes on 64-bit, 32-bit, or 16-bit
platforms respectively. Pointer can be used for variable size array as shown in example
below.
2.2. POINTER 197
✞
1 #include <iostream >
using namespace std;
3 /* Variable size array.*/
char *name ;
5
int main (int argc , char *argv []) {
7 name = "My School!!";
int i = 0;
9 while (name [i] != ’0’) {
cout << name [i] << endl ;
11 i++;
}
13 return 0;
}
✌
✆
✞
M
y
S
c
h
o
o
l
!
!
✌
✆
2.2 Pointer
A pointer is a simple variable that stores address (the location in memory) of a value
in memory rather than storing data itself. There are four fundamental things for the
pointers:
1. How to declare them.
2. How to assign them.
3. How to reference the value to which the pointer points, i.e value finding also known
as dereferencing.
4. How they relate to arrays.
Two important rules of the pointer must be remembered. These are:
1. A variable name with prefixed by ampersand (&) defines the address of the variable
and therefore points to the variable.
2. A pointer with prefixed by asterisk (*) refers to the value of the variable pointed-by
the pointer.
198 Array & Pointer
An array name is also an address of the first element of the array. Assume, ‘arr’ is an
array as relation geven below:
✞
arr == &arr [0];
✌
✆
Here both ‘arr’ and ‘&arr[0]’ represent to the memory address of first element of the same
array. A pointer can points to any element of an array, if the pointer is assigned address of
that element. In the following example, pointer ‘x’ points to the address of first element
of tha array ‘i’.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 int i[5] = {10, 20, 30, 40, 50};
int *x = &i[0]; /* Points to first element.*/
7 cout << *x;
return 0;
9 }
✌
✆
0
10
1
20
2
30
3
40
4
50
i[]:
x
The output of above program shall be
✞
10
✌
✆
If above example is modified as given below, then the pointer ‘x’ points to the 3rd
element of the array ‘i’.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 int i[5] = {10, 20, 30, 40, 50};
int *x = &i[2]; /* Points to third element.*/
7 cout << *x;
return 0;
9 }
✌
✆
0
10
1
20
2
30
3
40
4
50
i[]:
x
2.2. POINTER 199
The output of above program shall be
✞
30
✌
✆
If an intger is pointed by a pointer-to-char variable, then this variable can points to
the address of each byte of the integer variable (integer variable is 4 bytes long).
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 /* 1000 D = 1111101001 B*/
int i = 1001;
7 /* Pointer casting from integer to character .*/
char *x = (char *) &i;
9 /* Little endian is x[0]=11101001 B*
*Big endian is x[1]=00000011 B*
11 *Big endian x[2]= x[3]=00000000 B*/
/* Print little endian x[0]*/
13 cout << (int) x[0] << endl ;
return 0;
15 }
✌
✆
x[3] x[2] x[1] x[0]
i:
x
00000000 00000000 00000011 11101001
Output of above program is
✞
-23
✌
✆
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 /* 1000 D = 1111101001 B*/
int i = 1001;
7 /* Pointer casting from integer to character .*/
char *x = (char *) &i;
9 /* Little endian is x[0]=11101001 B*
*Big endian is x[1]=00000011 B*
11 *Big endian x[2]= x[3]=00000000 B*/
/* Print big endian x[1]*/
13 cout << (int) x[1] << endl ;
return 0;
15 }
✌
✆
200 Array & Pointer
x[3] x[2] x[1] x[0]
i:
x
00000000 00000000 00000011 11101001
Output of above program is
✞
3
✌
✆
2.2.1 Declaring Pointers
In C, pointers are declared as shown in following syntax.
✞
1 long *var1 , var2 ;
int **p3;
✌
✆
In these syntax, line 1 declares ‘var1’ as a pointer to a long and ‘var2’ as a long and not
a pointer to a long. In line 2, ‘p3’ is declared as a pointer to a pointer to an int. In C++,
a pointer is declared as shown in the following syntax.
✞
int * A;
2 int * ptrA , ptrB ;
✌
✆
Here ‘A’, ‘ptrA’ are pionter to integer while ‘ptrB’ is an ordinary integer. See an example
given below:
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char ** argv ) {
int i;
6 int* p, j;
p = &i; /* valid for best practice */
8 i = 10; /*i is now 10 */
*p = 20; /* valid*/
10 j = 5;
/* prints 20*/
12 cout << "i is " << i << endl ;
cout << "i is " << *p << endl ;
14 /* prints 5*/
cout << "j is " << j << endl ;
16 return 0;
}
✌
✆
✞
i is 20
i is 20
j is 5
✌
✆
2.2. POINTER 201
1
0x49
2
0x50
3
0x51
4
0x52
5
0x53
6
0x54
7
0x55
int *p = &i
i
&i
Pointer types are often used as parameters to function calls.
✞
1 int MyFunction ( struct MyStruct *pStruct );
✌
✆
In the above syntax, it is explained that how to declare a function which uses a pointer as
an argument. Since C++ passes function arguments by value, in order to allow a function
to modify a value from the calling routine, a pointer to the value must be passed. Pointer-
to-Structure is also used as function arguments even when nothing in the struct will be
modified in the function. This is done to avoid copying the complete contents of the
structure onto the stack. A simple example is
✞
1 #include <iostream >
/* time .h C library in C++ header as ctime*/
3 #include <ctime >
using namespace std;
5
void getSeconds (unsigned long *par);
7
int main (int argc , char ** argv []) {
9 unsigned long sec;
getSeconds (& sec);
11 cout << "Number of seconds since 01 Jan 1970 : " << sec;
return 0;
13 }
15 void getSeconds (unsigned long *par) {
*par = time (NULL );
17 return;
}
✌
✆
✞
Number of seconds: 1420616845
✌
✆
2.2.2 Pointer to Member
A member of a structure or class or a namespace are also accessible via pointers. A pointer
to member shall not point to a static member of a class, i.e. a member with reference
type. “pointer to member” is distinct from the type “pointer”, therefore, a pointer to
member is declared only by the pointer to member declarator syntax, and never by the
pointer declarator syntax.
✞
1 int X::* i = &X::a; // pointer to member method
int *i = &a; // pointer declarator method
✌
✆
202 Array & Pointer
See the example below:
✞
#include <cstdlib >
2 #include <iostream >
using namespace std;
4
struct X {
6 int a;
};
8
int main (int argc , char ** argv ) {
10 /* Declare member function i as pointer *
*to the original member a of the struct*/
12 int X::* i = &X::a;
X x;
14 x.*i = 10;
cout << x.*i;
16 return 0;
}
✌
✆
✞
10
✌
✆
2.2.3 Pointer Address
Pointers are used to point the memory address where data is stored. A pointer size is
determined by the pointer data type. For example if pointer is character type then size
of pointer is one byte. The pointer increment is one byte long. For example,
✞
1 string *ptr= new string [8];
✌
✆
and pointer ‘ptr’ points to memory address 0×00 then ‘ptr++’ points to the memory
address 0×01 as shown in the following figure.
d
0x00
e
0x01
f
0x02
g
0x03
h
0x04
i
0x05
j
0x06
k
0x07
Bytes
ptr ptr++
*ptr (*ptr)++
Again ‘*ptr’ points to the character ‘d’ at the memory address pointed by the pointer
‘ptr’. To get the next character ‘e’, dereference is done as ‘(*ptr)++’. Similarly, if pointer
is integer type as declared below:
✞
1 int *ptr= new int [10];
✌
✆
2.2. POINTER 203
then size of ‘ptr’ is 4 bytes. Now, if pointer ‘prt’ points to the memory address 0×00 then
‘ptr++’ points to the memory address 0×04 as shown in the figure given below:
xxxx
0x00
xxxx
0x01
xxxx
0x02
xxxx
0x03
yyyy
0x04
yyyy
0x05
yyyy
0x06
yyyy
0x07
Bytes
ptr ptr++
*ptr (*ptr)++
Again ‘*ptr’ points to the integer value at the memory address pointed by the pointer
‘ptr’. To get the next integer value, dereference is done as ‘(*ptr)++’. Remember that
precedence of ‘++’ symbol is higher to asterisk (*) symbol. This is why to scope of
asterisk (*) is changed by using parenthesis.
2.2.4 Assigning Values to Pointers
To assign address of a variable to a pointer, unary operator ‘&’, also known as ‘address
of’ operator is used as shown in the following syntax.
✞
1 /*An interger variable that have *
*null value stored in memory. */
3 int myInt;
/* Pointer that addresses to an integer value.*/
5 int * ptr;
/* Address to the pointer where *
7 *myInt value is stores in memory.*/
ptr = &myInt;
✌
✆
Here, ‘ptr’ is referencing to ‘myInt’ now. Pointers can also be assign the address of
dynamically allocated memory. See the following example.
✞
#include <iostream >
2 using namespace std;
4 int j, k;
int * ptr;
6
int main (int argc , char ** argv ) {
8 j = 1;
k = 2;
10 ptr = &k;
cout << "j = " << j << ". It stored at " << (void *) &j << endl ;
12 cout << "k = " << k << ". It stored at " << (void *) &k << endl ;
cout << "‘ptr’ = " << ptr << ". It stored at "
14 << (void *) &ptr << endl ;
cout << "Value of the integer pointed -by ‘ptr’ is " << *ptr <<
endl ;
16 return 0;
204 Array & Pointer
}
✌
✆
✞
j has value 1 and stored at 0x403100
k has value 2 and stored at 0x403120
‘ptr ’ has value 0x403120 and stored at 0x403110
Value of the integer pointed -by ‘ptr ’ is 2
✌
✆
Assigning a value to a pointer requires specialization. In C++, it is best practice that
first assign the address of a value to the pointer. We can retrieve the value from the
address by dereferencing it using asterisk (‘*’);
✞
int * j;
2 int k = 5;
j = &k/* Valid & good practice .*/
✌
✆
See the example
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int * j;
int k = 15;
7 j = &k; /* valid & good practice */
cout << "j is : " << *j;
9 return 0;
}
✌
✆
✞
j is : 15
✌
✆
Assigning a value to a pointer directly causes errors in the C++ program. Therefore, it
is not assumed a good practice. Sometimes, confusion creates a bad way for assignment
of a value to a pointer as shown below:
✞
1 int * j;
*j = 5;/* Invalid & very bad practice .*/
✌
✆
It is as we try to assign a value to an uninitialized pointer. A pointer points to the
location (address) where value is stored. Pointer does not store value itself. So, pointer
does not know where value is stored. If we try to do so, the program either may crash or
it damaged to the system.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char ** argv ) {
int i;
6 int *p;
p = &i; /* valid for best practice */
2.2. POINTER 205
8 i = 10; /*i is now 10 */
*p = 20; /* valid*/
10 /* prints 20*/
cout << "i is " << i << endl ;
12 cout << "i is " << *p << endl ;
return 0;
14 }
✌
✆
✞
i is 20
i is 20
✌
✆
When we create a pointer in C++, the computer allocates memory to hold an address,
but it does not allocate memory to hold the data to which the address points. Space for
data is created by another step. If we omit the step required to create space for data
attracts the errors.
✞
int * i;
2 *i = 10;
✌
✆
Here, i is a pointer but it point to nothing. Therefore, code failed to assign an address to
i. See the example below, which will failed to give desired output.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char ** argv ) {
int* p;
6 *p = 5;
cout << "p is " << *p << endl ;
8 return 0;
}
✌
✆
In C++, memory for pointer is allocated by new operator. To allocate memory for integer
we use the syntax like
✞
1 int * j = new int;
✌
✆
We tell to operator new for what data type we want in memory. It finds a block of the
correct size and returns the address of the block. A practical example is given below:
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int *j = new int;
*j = 5; /* valid & good practice */
7 cout << "j is : " << *j;
return 0;
9 }
✌
✆
206 Array & Pointer
✞
j is : 5
✌
✆
Each allocated memory by new operator only should be freed by delete operator. It is
used as
✞
1 int *j = new int;/* Create & reserve memory space*/
delete j; /* Free memory space*/
✌
✆
The use of delete operator as given below is illegal.
✞
int i = 5;
2 int *j = &i;
delete j; /* illegal */
✌
✆
2.2.5 Pointer Dereferencing (Value Finding)
To access a value to which a pointer points, the asterisk (‘*’) operator is used. An-
other operator, the ‘−>’ (Indirection) operator is used in conjunction with pointers to
structures. Here’s a short example.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int i;
int *p; // Pointer type int *
7 p = &i; // p now points to i
i = 10; // i is now 10
9 *p = 20; // i is now 20!!
/* prints "20" */
11 cout << "i is " << i << endl ;
/* "20"! dereferencing -p is the same as i!*/
13 cout << "i is " << *p << endl ;
return 0;
15 }
✌
✆
✞
i is 20
i is 20
✌
✆
2.2.6 Addition of Pointers
A pointer when dereferences, retrieves the value at the address pointed by the pointer.
If the value at pointer address is an integer then we can add another integer value to it.
When an integer value is addedd to the pointer then old addres of the pointer is changed
into new address. Difference between new address and old address is equal to the pointer
data type. In the following example, we retrieve the pointer value and add 1 to in function
‘increment()’.
2.2. POINTER 207
✞
#include <iostream >
2 using namespace std;
4 void increment (int *p) {
*p = *p + 1; /* Add one to p */
6 }
8 int main (int argc , char ** argv ) {
int i = 20;
10 /* i value is 20 */
cout << "i is " << i << endl ;
12 /* Pass interger to increment function as pointer */
increment (&i);
14 /* Print the value 21*/
cout << "i is " << i << endl ;
16 return 0;
}
✌
✆
✞
i is 20
i is 21
✌
✆
The value of a pointer is the address of the object to which it points. The address of a
large object, such as type double variable, typically is the address of the first byte of the
object. Applying the * operator to a pointer yields the value stored in the pointed-to
object. Adding 1 to the pointer increases its value by the size, in bytes, of the pointed-to
type.
2.2.7 Pointers and Arrays
If we have to use pointer for an array, then we use new operator to create a dynamic
array of specific size. The valid types of dynamic allocation of array memory space are
shown below:
✞
int * i = new int [10];/* 40 bytes space for 10 elements */
2 string * str = new string [10];/*10 bytes string.*/
✌
✆
new operator returns the address of the first element of the block. We should free the
allocated memory space by delete operator when program does not need it. Single block
of memory should be created and freed like
✞
int * i = new int; /* Single byte memory space*/
2 delete i; /* Free the allocated memory space*/
✌
✆
A dynamic array memory space should be created and freed like
✞
int * i = new int [10]; /*10 block memory */
2 delete [] i; /* Free memory allocated for array*/
✌
✆
208 Array & Pointer
Here ‘[]’ between delete operator and variable ‘i’ tells the program that it should free the
whole array, not just the element pointed to by the pointer.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char ** argv ) {
int * mk = new int [10];
6 *mk = 65874859;
cout << *mk << endl ;
8 delete [] mk;
return 0;
10 }
✌
✆
✞
65874859
✌
✆
To add a value to a pointer we can use ‘*’ (asterisk) operator as well as array element
method to the dynamically allocated array as shown in following example.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int * mk = new int [5];
int i;
7 for (i = 0; i < 5; i++) {
mk[i] = i;
9 }
for (i = 0; i < 5; i++) {
11 cout << mk[i] << endl ;
}
13 delete [] mk;
return 0;
15 }
✌
✆
✞
0
1
2
3
4
✌
✆
If we want to add and retrieve values to dynamically allocated memory by using pointer
then initial pointer location must be restored to get the actual stored values. See the
example below:
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int * mk = new int [5];
2.2. POINTER 209
int i;
7 for (i = 0; i < 5; i++) {
*mk = i; // assign value at pointer location
9 mk ++; // increase pointer location by one
}
11 mk = mk -5; // Restore the initial position of the pointer.
for (i = 0; i < 5; i++) {
13 cout << *mk << endl ;
mk ++;
15 }
delete [] mk;
17 return 0;
}
✌
✆
✞
0
1
2
3
4
✌
✆
Pointer arithmetic can be used to increment the pointer position and retrieval of the value
stored at that address.
✞
1 #include <iostream >
#include <string >
3 using namespace std;
5 int main (int argc , char ** argv ) {
int * mk = new int [5];
7 int i;
for (i = 0; i < 5; i++) {
9 mk[i] = i;
}
11 for (i = 0; i < 5; i++) {
cout << *(mk + i) << "t" << (mk [0] + i) << endl ;
13 }
delete [] mk;
15 return 0;
}
✌
✆
✞
0 0
1 1
2 2
3 3
4 4
✌
✆
Pointers to Arrays
An array can be initialized by using any of the following methods:
210 Array & Pointer
✞
1 int myArr [3] = {a, b, c};
int * arrPtr = myArr; /* name of an array = address */
3 int * arrPtr = &myArr[0]; /*or use address operator */
✌
✆
First line in above syntax is initialization of an array. In second line, ‘arrPtr’ is a pointer
to the array ‘myArr’. In third line, ‘arrPtr’ points to the address of first element of the
array ‘myArr’. See the following example, in which both methods are used to assign the
same array to two different pointers by two different methods.
✞
1 #include <iostream >
#include <string >
3 using namespace std;
5 int main (int argc , char ** argv ) {
double Marks[3] = {120.0 , 200.0 , 150.0};
7 /* Here are two ways to get the address of an array*/
double * p1 = Marks; /* name of an array = address */
9 double * p2 = &Marks [0]; /*or use address operator */
// with array element
11 cout << "p1 = " << p1 << ", *p1 = " << *p1 << endl ;
cout << "p2 = " << p2 << ", *p2 = " << *p2 << endl ;
13 p1 = p1 + 1;
p2 = p2 + 1;
15 cout << "Add 1 to the p1 & p2 pointers : n";
cout << "p1 = " << p1 << ", *p1 = " << *p1 << endl ;
17 cout << "p2 = " << p2 << ", *p2 = " << *p2 << endl ;
p1 = p1 + 1;
19 p2 = p2 + 1;
cout << "Add 1 to the p1 & p2 pointers : n";
21 cout << "p1 = " << p1 << ", *p1 = " << *p1 << endl ;
cout << "p2 = " << p2 << ", *p2 = " << *p2 << endl ;
23 return 0;
}
✌
✆
✞
p1 = 0x22 ff40, *p1 = 120
p2 = 0x22 ff40, *p2 = 120
Add 1 to the p1 & p2 pointers :
p1 = 0x22 ff48, *p1 = 200
p2 = 0x22 ff48, *p2 = 200
Add 1 to the p1 & p2 pointers :
p1 = 0x22 ff50, *p1 = 150
p2 = 0x22 ff50, *p2 = 150
✌
✆
Pointers as Function Argument
Pointers can also be used as function arguments in C++. Function prototype with pointer
argument is shown below:
✞
int myFunc(int* a);
✌
✆
2.2. POINTER 211
When we call this function, we use ‘&’ (address of) symbol to pass the address of a
variable not the value of the variable as function argument. The function is called like
✞
1 int i=10; // variable i with assigned value 10
myFunc(&i); // pass address of i to function myFunc
✌
✆
By this way, pointer ‘a’ is assigned the address of the function parameter ‘i’. In following
example, a sum function takes two integer values as pointer and return their sum as
integer. The call of sum function uses addresses of the two integer values by using address-
of symbol (‘&’).
✞
#include <iostream >
2 using namespace std;
4 /*pass -by -value as pointers to a & b to sum()*/
int sum(int* a, int* b) {
6 int f;
/* Passed values as a and b.*
8 *They can be changed here .*/
f = *a + *b;
10 return f;
}
12
int main (int argc , char *argv []) {
14 int i = 2, j = 3, g;
/* Pass address of i and j to sum *
16 *function not values of i and j */
g = sum (&i, &j);
18 cout << "Sum of " << 2 << ", " << 3 << " is " << g;
return 0;
20 }
✌
✆
✞
Sum of 2, 3 is 5
✌
✆
00000010 00000011
0xaa 0xbb
i j
g = sum(&i, &j);
212 Array & Pointer
00000010 00000011
0xaa 0xbb
i j
int sum(int* a, int* b) {}
A pointer function can also be used as function argument, generally called function
callback. See the example
✞
1 #include <iostream >
using namespace std;
3
int getSum(int i, int j, int (* PrintLabel )(int , int)) {
5 cout << "Sum of " << i << " and " << j << " is ";
cout << PrintLabel (i, j);
7 }
9 int PrintLabel (int x, int y) {
return (x + y);
11 }
13 int main (int argc , char *argv []) {
15 getSum (2, 4, PrintLabel );
return 0;
17 }
✌
✆
✞
Sum of 2 and 4 is 6
✌
✆
Address as Function Argument
Address of can also be used as function argument in C++. Function prototype with
address of argument is as:
✞
1 int myFunc(int& a);
✌
✆
Here, int& passes a reference to the function. When we call this function, we just pass
the variables as argument. The function call should be like
✞
1 int i=10;
myFunc(i);
✌
✆
In following example, a sum function takes addresses of two arguments and return their
sum as integer. The function call of this sum function uses variables as function argu-
ments.
2.2. POINTER 213
✞
#include <iostream >
2 using namespace std;
4 /*pass -by -value as address of a & b to sum()*/
int sum(int& a, int& b) {
6 int f;
/* Passed values as a and b.*
8 *They can be changed here .*/
f = a + b;
10 return f;
}
12
int main (int argc , char *argv []) {
14 int i = 2, j = 3, g;
/* Sum function with arguments i and j*/
16 g = sum(i, j);
cout << "Sum of " << 2 << ", " << 3 << " is " << g;
18 return 0;
}
✌
✆
✞
Sum of 2, 3 is 5
✌
✆
2.2.8 Constant Pointers
A pointer may be declared as constant by using const keyword.
✞
1 int i = 5;
const int *p = &i;
3 //Or
int const *p = &i;
✌
✆
There are two cases, (i) where a pointer pointed to constant data (pointee) and pointee
can not be changed, and (b) where constant pointer (address) can not be changed. The
usual pointer-pointee relation are given below:
✞
#include <iostream >
2 using namespace std;
4 int main () {
int i = 2;
6 int j = 3;
int *k = &j; // k points to j and *k is 3
8 cout << *k << endl ;
j = 6; // Now both j and *k are 6
10 cout << j << " " << *k << endl ;
*k = 7; // j and *k are 7. Pointee changes
12 cout << j << " " << *k << endl ;
k = &i; // k points to i. *k is 2. Pointer changes
14 cout << i << " " << *k << endl ;
214 Array & Pointer
*k = 8; // i and *k are 8 now. Pointee changes
16 cout << i << " " << *k << endl ;
return 0;
18 }
✌
✆
✞
3
6 6
7 7
2 2
8 8
✌
✆
Now the const keyword is used as shown in modified example. There are errors shows by
the compiler.
✞
1 #include <iostream >
using namespace std;
3
int main () {
5 int i = 2;
const int j = 3;
7 const int *k = &j;
j = 6; // Error! assignment of read -only variable ’j’
9 *k = 7; // Error! assignment of read -only location ’* k’
k = &i; // k points to i. *k is 2. Pointer changes
11 *k = 8; // Error! assignment of read -only location ’* k’
return 0;
13 }
✌
✆
Here, code line
✞
1 //+--Pointee type , i.e. constant pointee
//|
3 const int *k = &j;
✌
✆
1
0x49
2
0x50
3
0x51
4
0x52
5
0x53
6
0x54
7
0x55
const int *k = &j
j
&j
(const) j
represents that ‘k’ is a non constant type pointer and the value to which it is pointing
is constant type. Therefore, value of ‘j’ can not be changed while address of ‘k’ can be
changed.
✞
1 #include <iostream >
using namespace std;
2.2. POINTER 215
3
int main () {
5 int i = 2;
const int j = 3;
7 const int *k = &j;
// int const *k = &j; // Or state
9 cout << "Address of k is " << k << endl ;
k = &i; // k points to i. *k is 2. Pointer changes
11 cout << "New address of k is " << k << endl ;
//
13 cout << "i : " << i << ", k : " << *k << endl ;
return 0;
15 }
✌
✆
✞
Address of k is 0x22ff44
New address of k is 0x22 ff48
i : 2, k : 2
✌
✆
Similarly, if
✞
1 // +--Pointer type , i.e. constant pointer
// |
3 int * const k = &j;
✌
✆
then, pointer becomes constant while value of pointee can be changed. Notice the position
of asterisk (*) not the const keyword.
1
0x49
2
0x50
3
0x51
4
0x52
5
0x53
6
0x54
7
0x55
int * const k = &j
(const) *k
j
&j
✞
1 #include <iostream >
using namespace std;
3
int main () {
5 int i = 2;
int j = 3;
7 int * const k = &j;
cout << "Address of k is " << k << endl ;
9 cout << "Old values - j : " << j << ", k : " << *k << endl ;
j = 5; // k points to i. *k is 2. Pointer changes
11 cout << "New values - j : " << j << ", k : " << *k << endl ;
//k = &i;// Error! assignment of read -only variable ’k’
13 return 0;
}
✌
✆
216 Array & Pointer
✞
Address of k is 0x22ff44
Old values - j : 3, k : 3
New values - j : 5, k : 5
✌
✆
The change in the position of the asterisk (*) and keyword const changes the pointer and
pointee type. The general representation is
✞
1 int n = 5;
int * p = &n; // non -const -Pointer to non -const -Pointee
3 const int * p = &n; // non -const -Pointer to const - Pointee
int * const p = &n; // const -Pointer to non -const - Pointee
5 const int * const p = &n; // const -Pointer to const -Pointee
✌
✆
2.2.9 Pointers to Function
A pointer to function is defined as
✞
1 void (*fp)();
✌
✆
This function has no return value and no arguments (i.e. parameters). Here parentheses
( ) is used to encapsulate asterisk and function name. The reason is that parentheses
operator, ( ), has higher precedence than that of dereferencing operator (*). Hence for
pointer-to-function variable, dereferencing of function is grouped by parentheses. Exam-
ple for pointer-to-function is given below.
✞
1 #include <iostream >
3 using namespace std;
5 void myFunc () {
cout << "Function is called ..." << endl ;
7 }
9 int main (int argc , char *argv []) {
void (*r)();
11 r = myFunc;
(*r)();
13 return 0;
}
✌
✆
✞
Function is called ...
✌
✆
A pointer to a function is possible in C++. This type of function may accepts arguments
as pointers. The return value from the function is pointed by the function itself. In
following example, a pointer-to-function is used.
✞
1 #include <iostream >
using namespace std;
2.2. POINTER 217
3
int* f(int* x) {
5 (*x)++;
return x;
7 }
9 int main (int argc , char *argv []) {
int a = 1;
11 cout << f(&a) << endl ;
cout << *f(&a) << endl ;
13 return 0;
}
✌
✆
✞
0x22ff5c
3
✌
✆
Sometimes pointer-to-function returns the pointer to local variable. It is not considered
a good practice. Compiler shows warning when we do so. It should be avoid in program-
ming.
2.2.10 Pointer Arithmetic
In normal mathematics numbers are used for addition, subtraction, division and multipli-
cation etc. A pointer to an integer has different behavior to the integer. This is why, in
pointer arithmetic, we have to arrange or conform the pointers so that they can behave in
properly. A pointer-to-variable always points to the address where value of the variable
is stored. This is why direct arithmetic of the pointers is of the arithmetic of the address
rather than the values stored at the addresses. For example, we have to create an array
of 2 element size (cells). Store a value in first cell. Retrieve the value and increment it
by one. In the following example, we implement the solution as given below:
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
int i [10];
6 int* a = i;
cout << "a is " << (long ) a << endl ;
8 a++;
cout << "a++ is " << (long ) a << endl ;
10 return 0;
}
✌
✆
✞
a is 2293556
a++ is 2293560
✌
✆
In above example, the increment operator adds 4 to the address of pointer-to-integer
variable ‘a’ rather that its value. This is why, we need proper confer to the pointer to
218 Array & Pointer
the desired result. In the following example, we uses proper way of pointe and get the
desired result.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
int i [2]={1}; /*1st=1, 2nd=0*/
6 int* a = i;
cout << "a is " << *a << endl ;
8 *a++; /* Increment to pointer index*
*and get value which is 0 */
10 cout << "a++ is " << *a << endl ;
return 0;
12 }
✌
✆
✞
a is 1
a++ is 0
✌
✆
The result is not as we sought in result. Above code is again modified as given below:
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
int i [2]={1}; /*1st=1, 2nd=0*/
6 int* a = i;
cout << "a is " << *a << endl ;
8 (*a)++; /* Increment to value of a*/
cout << "a++ is " << *a << endl ;
10 return 0;
}
✌
✆
✞
a is 1
a++ is 2
✌
✆
This is the result what we sought in our problem. Similarly, in following example, we use
pointers in simple arithmetic.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
int a = 9, b = 5;
6 int* i = &a;
int* j = &b;
8 cout << "Sum of i, j is " << (*i + *j) << endl ;
cout << "Subtraction of i, j is " << (*i - *j) << endl ;
10 cout << "Division of i, j is " << (*i / *j) << endl ;
cout << "Multiplication of i, j is " << (*i * *j) << endl ;
2.2. POINTER 219
12 return 0;
}
✌
✆
✞
Sum of i, j is 14
Subtraction of i, j is 4
Division of i, j is 1
Multiplication of i, j is 45
✌
✆
220 Accessing System Files
3.1. STREAM & BUFFER 221
3Accessing System Files
Standard Input-Output and access of files is a main part of computer programming. In
this chapter we shall discuss the importance and methodology of accessing system and
user define files.
3.1 Stream & Buffer
3.1.1 File Stream
fstream is a header which includes the objects for reading a file or writing a file. It is just
a file stream. Operations on the open file are performed by the objects/member functions
of the fstream class.
3.1.2 File Buffer
filebuf is a stream buffer that is used to read from a file or write to a file. It is constructed
without association, these objects are associated to a file by calling its member open. Once
open, all input/output operations performed on the object are reflected in the associated
file. rdbuf () reads the file at once completely and put it in read buffer stream. See the
example below:
✞
#include <fstream >
2 #include <iostream >
using namespace std;
4
int main (int argc , char * argv []) {
6 ifstream inF("a.txt");
cout << inF.rdbuf();
8 return 0;
}
✌
✆
streambuf is a stream buffer and is an object in charge of performing the reading and
writing operations of the stream object it is associated with. The stream delegates all
such operations to its associated stream buffer object, which is an intermediary between
the stream and its controlled input and output sequences.
3.2 Accessing Files
Files are named memory locations where data is stored in text or binary form. Each
file that exists in the disk can be accessed, read and write if it is not specially granted
restricted permissions. Users may create, access, update and delete a file by using C++
program.
222 Accessing System Files
3.2.1 Open A File
A file in C++ can be opened in read, write, truncate or append mode. The flags used to
open a file are given in following table.
Flags Meaning
ios::in Opens an input file without truncating the existing file. (ifstream)
ios::ate Opens an existing file and seeks the end.
ios::out Opens an output file. By default, ios::trunc is implied. (ofstream)
ios::app Opens an output file for appending data.
ios::nocreate Opens a file only if it already exists.
ios::noreplace Opens a file only if it does not exist.
ios::trunc Opens a file in truncate mode.
ios::binary Opens a file in binary mode. Default is text mode.
Table 3.1: File opening mode.
To open a file, one can either call open on the file stream or, more commonly, use the
constructor. One can also supply an open mode to further control the file stream. For
reading-writing of the file, ‘fstream’ header file is used.
✞
1 #include <fstream >
using namespace std;
3
int main (int argc , char *argv []) {
5 ofstream file1;
7 file1.open ("file1.txt", ios:: app);
file1 << "Appended data .n";
9
ofstream file2("file2.txt");
11 file2 << "Replace data .n";
13 return 0;
}
✌
✆
Each file opened must be closed by using function close(). On unsuccessful, a flag is set in
the stream object. The flag status is checked by good(), bad() or fail() member functions,
which return a boolean value. The stream object doesn’t throw any exceptions in such a
situation, hence manual status check is required.
✞
#include <iostream >
2 #include <fstream >
using namespace std;
4
3.2. ACCESSING FILES 223
int main (int argc , char *argv []) {
6
/* Try to open non -exist file xyz.txt.*
8 *fstream does not show any errors. */
ifstream file1;
10 file1.open ("zyz.txt", ios::in);
12 /*To check whether a xyz.txt is really*
*opened or not , we use good () object.*/
14 cout << file1.good (); /* Returns 0*/
cout << endl ;
16
/* Try to open existing file a.txt. */
18 ifstream file2;
file2.open ("a.txt", ios::in);
20
/*To check whether a a.txt is really *
22 *opened or not , we use good () object.*/
cout << file2.good (); /* Returns 1*/
24 }
✌
✆
✞
0
1
✌
✆
fail() tries to read the next character from the input stream. If it fails to read the next
character due to EOF, it returns true otherwise it returns false.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char ** argv ) {
char name ;
6 cout << "Enter the name : ";
cin.get(name );
8 while (cin.fail () == false) {
cout << name << endl ;
10 cin.get(name );
}
12 return 0;
}
✌
✆
3.2.2 Read File Data
While reading a file, input from the in-stream is assigned to a string variable, until the
file or in-stream does not reach to EOF pitfall or until an error does not occur. getline()
function is used for this purpose.
✞
1 #include <fstream >
#include <string >
224 Accessing System Files
3 #include <iostream >
using namespace std;
5
int main (int argc , char ** argv ) {
7 /* Line number counter */
int linecount = 0;
9 string line ;
/* Open input file */
11 ifstream inFile("file1.txt");
/*If input file is successfully opened.*/
13 if (inFile) {
/* Read line by line of text file . *
15 *until end of file is not found. */
while (getline(inFile , line )) {
17 /* Print the line number and line */
cout << linecount << ": " << line << ’n’;
19 /* Increment the line number */
linecount ++;
21 }
}
23 /* Close input file .*/
inFile.close();
25 return 0;
}
✌
✆
We can also read a file byte by byte as the method given below:
✞
#include <fstream >
2 #include <string >
#include <iostream >
4 using namespace std;
6 int main (int argc , char ** argv ) {
ifstream is("file1.txt");
8
char c;
10 while (is.get(c))
cout << c << endl ;
12
is.close();
14
return 0;
16 }
✌
✆
To check whether the file has been reached to its end, eof () member function is used as
shown in the syntax given below.
✞
if (infile.eof()) break
✌
✆
3.2. ACCESSING FILES 225
Infile Stream
ifstream operator is used to open an input file stream. It is always followed by input
stream name. A file name is argument of the input stream name. To use this operator,
header file ‘fstream’ is required. Syntax of ifstream is given as
✞
1 ifstream <stream name >("<file name >");
✌
✆
An example is given below:
✞
1 #include <string >
#include <fstream >
3 using namespace std;
5 int main (int argc , char *argv []) {
/* Open a file stream to read */
7 ifstream f1("a.txt");
ofstream f2("b.txt");
9 string s;
while (getline(f1 , s))
11 f2 << s << "n";
}
✌
✆
On execution, we shall get desired result.
3.2.3 Write File Data
The data of user is stored in memory as data file. To write a file in memory, data is first
transfer to out stream buffer and them it is flushed into the memory.
Outfile Stream
ofstream operator is used to open an output file stream. This is member of fstream (file
stream) class. It is always followed by output stream name. A file name is argument of
the output stream name. To use this operator, header file ‘fstream’ is required. Syntax
of ofstream is given as
✞
ofstream <stream name >("<file name >");
✌
✆
An example is given below:
✞
1 #include <string >
#include <fstream >
3 using namespace std;
5 int main (int argc , char *argv []) {
ifstream f1("a.txt");
7 /* Open a file stream to write*/
ofstream f2("b.txt");
9 string s;
while (getline(f1 , s))
226 Accessing System Files
11 f2 << s << "n";
f1.close();
13 f2.close()’
return 0;
15 }
✌
✆
On execution, we shall get desired result. Concatenation of the strings is allowed in C++
by using operator ‘+=’. See the example below:
✞
1 #include <string >
#include <fstream >
3 #include <iostream >
using namespace std;
5
int main (int argc , char *argv []) {
7 ifstream f1("a.txt");
/* Open a file stream to write*/
9 ofstream f2("b.txt");
string s, line ;
11 while (getline(f1 , s))
line += s + "n";
13 f2 << line ;
cout << line ;
15 }
✌
✆
3.2.4 File As Function Argument
A input or output file stream allows to pass a file pointer to a function as its argument.
The syntax of argument is like
✞
1 ifstream & <arg name > // for input file stream
ofstream & <arg name > // for output file stream
✌
✆
In the following example, out file stream is passed to function argument and contents are
written in the out file.
✞
#include <iostream >
2 #include <fstream >
using namespace std;
4
void PassToFunc (ofstream &f, int n) {
6 f << n;
}
8
int main () {
10 ofstream f1("b.txt");
PassToFunc (f1 , 10);
12 return 0;
}
✌
✆
It creates a file “b.txt” in which integer 10 is written.
3.2. ACCESSING FILES 227
3.2.5 File Position
We can access the location of file pointer by using tellp() for an out stream (ostream) and
tellg() for an in stream (istream). seekp return the stream position (streampos) of an out
stream (ostream) and seekg() returns the stream position of an in stream (istream). seekp
and seekg() takes two arguments. First is number of byte, either positive or negative value
and second is direction. The seek directions are
Flags Meaning
ios::beg From the beginning of stream.
ios::cur From the current position of stream.
ios::end From the end of stream.
Table 3.2: Seek Directions.
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
(1)
fp
(2)
fp.seekp(-8, ios::cur)
(3)
fp
(4)
Figure 3.1: Change in location of file pointer from current file pointer location.
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
(1)
fp
(2)
fp.seekp(-8, ios::end)
(3)
fp
(4)
Figure 3.2: Change in location of file pointer from the end of file location.
228 Accessing System Files
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
(1)
fp
(2)
fp.seekp(10, ios::beg)
(3)
fp
(4)
Figure 3.3: Change in location of file pointer from the beginning of file location.
In following example, a file ‘a.txt’ is read and file pointer is set after 10bytes using
seekg() function from the beginning of the file. The current position of the in file stream
is return by using function tellg() function.
✞
1 #include <fstream >
#include <iostream >
3 using namespace std;
5 int main (int argc , char * argv []) {
/* Open in file */
7 ifstream inf("a.txt");
/* Set file pointer after 10 bytes*
9 *from beginning of current file */
inf.seekg(10, ios:: cur);
11 /* Get current position of file pointer */
cout << inf.tellg();
13 return 0;
}
✌
✆
✞
10
✌
✆
In following example, we set the file pointer after 10 bytes from the end of the file location.
✞
1 #include <fstream >
#include <iostream >
3 using namespace std;
5 int main (int argc , char * argv []) {
/* Open in file */
7 ifstream inf("a.txt");
/* Set file pointer after -10 bytes*
9 *from the end of the current file */
inf.seekg(-10, ios:: end);
11 /* Get current position of file pointer */
cout << inf.tellg();
3.3. DATA STRUCTURES 229
13 return 0;
}
✌
✆
✞
228
✌
✆
For output stream, seekp() and tellp() functions are used.
✞
1 #include <fstream >
#include <iostream >
3 using namespace std;
5 int main (int argc , char * argv []) {
/* Open out file */
7 ofstream outf ("b.txt");
/* Set file pointer after 11 bytes*
9 *from beginning of current file */
outf . seekp(11, ios:: beg);
11 /* Get current position of file pointer */
cout << outf .tellp();
13 return 0;
}
✌
✆
✞
11
✌
✆
We can write something after the specific position in the current out file by using ‘<<’
operator.
✞
1 #include <fstream >
#include <iostream >
3 using namespace std;
5 int main (int argc , char * argv []) {
ofstream outf ("b.txt");
7 outf . seekp(11, ios:: beg);
outf << "This is my file ";
9 return 0;
}
✌
✆
3.3 Data Structures
A data structure (struct) contains multiple pieces of data. Each piece of data (called a
“member”) can be accessed by using a group of instance of structure, followed by a ‘.’
(ie dot), then the name of the member (another way to access a member is using the
member operator ‘−>’ for pointers.). The member variables of data structure can be of
any data-type or can be an array or a pointer.
230 Accessing System Files
3.3.1 Struct
A data structure contains multiple pieces of data. One defines a data structure using the
struct keyword. For example,
✞
struct <mystruct >{
2 int <int_member >;
double <double_member >;
4 char <string_member [25] >;
} <variable >;
✌
✆
‘variable’ is an instance of ‘mystruct’. One can omit it from the end of the struct decla-
ration and declare it later using:
✞
1 struct <mystruct > <variable >;
✌
✆
It is often common practice to make a type synonym so we don’t have to type struct
‘mystruct’ all the time. The struct itself has no name (by the absence of a name on the
first line), but it is aliased as ‘mystruct’. Then you can use
✞
1 <mystruct > <variable >;
✌
✆
We can add or read data in structure by just using ‘dot’ symbol as
✞
1 struct student {
int id;
3 char *name ;
float perc ;
5 } st;
st.id =1;/* use of dot symbol between instance name and struct
element.*/
✌
✆
After creating an instance of structre, instance reserves the memory bytes equal to the
sum of size of all members. See the figure given below:
a b c d e f g h i j
st
id name perc
Here is working example of struct function:
✞
#include <iostream >
2 using namespace std;
4 struct student {
int id;
6 char *name ;
float perc ;
8 } st , st1 , st2;
3.3. DATA STRUCTURES 231
10 int main (int argc , char *argv []) {
st.id = 1;
12 st1.name = "Arun Umrao";
st2.perc = 90.5;
14 cout << "Id is: " << st.id << endl ;
cout << "Name is: " << st1.name << endl ;
16 cout << "perc is: " << st2.perc << endl ;
return 0;
18 }
✌
✆
✞
Id is: 1
Name is: Arun Umrao
perc is: 90.5
✌
✆
Another simple example is given below.
✞
1 #include <iostream >
using namespace std;
3
struct data {
5 int val;
float b;
7 };
9 int main (int argc , char *argv []) {
struct data s;
11 s.val = 12;
s.b = 3.14159;
13 cout << "The val field in s is:" << s.val << endl ;
return 0;
15 }
✌
✆
✞
The val field in s is: 12
✌
✆
Pointer can be also used in structure. An instance of a structure ‘data’ using a pointer is
declared as
✞
1 data *<variable >;
✌
✆
Member values of the structure declared with pointer are initialized or accessed by using
operator −
>. See the following syntax, in which a structure ‘Func’ is declared by using a
pointer and its member values are set by using operator −
>.
✞
1 struct Func {
int val;
3 float fl;
};
5 struct Func *b;
b->val = 3491;
✌
✆
232 Accessing System Files
st st++
val fl
A working example is
✞
#include <iostream >
2 using namespace std;
4 struct Func {
int val;
6 float fl;
};
8
int main (int argc , char *argv []) {
10 /* Func struct required for pointer */
struct Func a;
12 /* this is a pointer to a struct Func */
struct Func *b;
14 b->val = 3491;
cout << "The value of b is " << b->val << endl ;
16 return 0;
}
✌
✆
✞
The value of b is 3491.
✌
✆
A struct data can also be passed to a function by using address of procedure. See the
example below in which data struct is passed to function ‘Plantation’.
✞
1 #include <iostream >
using namespace std;
3
/* Data structure */
5 struct Data {
int Trees;
7 int Plants;
};
9
/* function Plantation with data structure as pointer */
11 void Plantation (struct Data *f) {
f->Trees = 10;
13 f->Plants = 20;
}
15
int main (int argc , char *argv []) {
17 /* Struct data structure */
struct Data Bio;
19 /* Pass address ‘Bio ’ into struct ‘Data ’ as pointer */
Plantation (& Bio);
3.3. DATA STRUCTURES 233
21 cout << "Trees : " << Bio.Trees << endl ; /* prints "10" */
cout << "Plants : " << Bio.Plants << endl ; /* prints "20" */
23 return 0;
}
✌
✆
✞
Trees : 10
Plants : 20
✌
✆
A constant pointer, once holds an address cannot change to the new address. It means a
constant pointer, if already pointing to an address, cannot point to a new address.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
char ch = ’A’;
6 char cH = ’B’;
8 char * const ptr = &ch; // A constant pointer
ptr = &cH; // Illegal way of pointer .
10
return 0;
12 }
✌
✆
In case of pointer to structure, if the things on the left of the ‘.’ (dot) or ‘−
>’ operator is
qualified (with ‘const’ or ‘volatile’) then the result is also has those qualifiers associated
with it. In the following example, when the pointer points to a qualified type the result
got is also qualified.
✞
#include <iostream >
2 using namespace std;
4 struct myStruct {
int i;
6 };
8 int main (int argc , char *argv []) {
/* Initialisation of structures . */
10 struct myStruct *Ptr , s_item;
/* Initialisation of structures of constant qualifier . */
12 const struct myStruct *s_Ptr;
/* Set the item value.*/
14 s_item.i = 1; /* OK */
/* Assigning new pointer .*/
16 Ptr = &s_item;
Ptr ->i += 2; /* OK */
18 /* Constant qualified pointer.*/
s_Ptr = &s_item;
20 s_Ptr ->i = 0; /* Not OK to point constant type qualifier . */
return 0;
234 Accessing System Files
22 }
✌
✆
A structure can also be initialized at the starting of program if structure is defined as
✞
struct employee {
2 int no;
int sex;
4 int age;
};
6 struct employee EmpNo={<int >, <int >, <int >};
✌
✆
The following example clears the initialization of the structure.
✞
#include <iostream >
2 using namespace std;
4 struct employee {
int no;
6 int sex;
int age;
8 };
10 int main (int argc , char *argv []) {
struct employee EmpNo = {10, 1, 15}; /* Initializing structure */
12 cout << EmpNo.no << endl << EmpNo.sex << endl << EmpNo.age;
return 0;
14 }
✌
✆
Nested Structure
When a loop is declared inside another loop then the inner loop is called nested loop.
✞
for (;;) {
2 for (;;) /* Nested for loop */
}
✌
✆
Similarly, when a structure is declared inside another structure then it is called nested
structure. Nested structure can be declared by using either normal variable or pointer.
In following example, a nested structure is declared and declared by simple variable.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5
/* date structure */
7 struct date {
int day;
9 int month;
int year ;
3.3. DATA STRUCTURES 235
11 };
13 /* variety structure */
struct variety {/* Upper level structure */
15 char *name ;
/* Nested structure . Declared by normal variable . *
17 * Element of the structure are accessed by dot (.)*/
struct date date ; /* Lower level structure as normal
variable .*/
19 } tr; /* Structure declared as normal variable . *
* Elements can be accessed by (.) symbol.*/
21
/* Accessing structure elements by using synopsis like
23 * up_level_struct (.) up_level_elem
* or
25 * up_level_struct (.) low_level_struct (.) low_level_elem */
tr.name = "A";
27 tr.date .day = 10;
cout << "Name : " << tr.name << endl ;
29 cout << "day : " << tr.date .day << endl ;
return 0;
31 }
✌
✆
✞
Name : A
day : 10
✌
✆
In simple variable type declaration of structure, elements are accesses by using dot (.).
Using of pointer symbol (−>) throws the errors. In above example, ‘name’ and ‘date’ are
elements of the ‘variety’ structure.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
6 /* date structure */
struct date {
8 int day;
int month;
10 int year ;
};
12
/* variety structure */
14 struct variety {/* Upper level structure */
char *name ;
16 /* Nested structure . Declared by normal variable . *
* Element of the structure are accessed by dot (.)*/
18 struct date date ; /* Lower level structure as normal
variable .*/
} tr; /* Structure declared as normal variable . *
20 * Elements can be accessed by (.) symbol.*/
236 Accessing System Files
22 /* Accessing structure elements by using synopsis like
* up_level_struct (.) up_level_elem
24 * or
* up_level_struct (.) low_level_struct (.) low_level_elem */
26 tr.name = "A";
tr.date .day = 10;
28 /* Following line throws errors. Reason is that we are trying*
*to access the element by pointer symbol (->) even though *
30 *the structure ‘tr ’ is declared here as normal variable . */
tr ->date .month = 11;
32 cout << "Name : " << tr.name << endl ;
cout << "day : " << tr.date .day << endl ;
34 return 0;
}
✌
✆
By other way, we can use pointer method to assign one structure inside other structure.
In pointer method, elements are accessed by using pointer symbol (−>) and dot (.).
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5
/* date structure */
7 struct date {
int day;
9 int month;
int year ;
11 };
13 /* variety structure */
struct variety {/* Upper level structure */
15 char *name ;
/* Nested structure . Declared by normal variable . *
17 * Element of the structure can accessed by dot (.)*/
struct date date ; /* Lower level structure as normal
variable .*/
19 } *tr; /* Structure declared as pointer variable . *
* Elements can be accessed by (->) symbol.*/
21 /* Accessing structure elements by using synopsis like
* up_level_struct (->) up_level_elem
23 * or
* up_level_struct (->) low_level_struct (.) low_level_elem */
25 tr ->name = "A";
tr ->date .day = 10;
27 cout << "Name : " << tr ->name << endl ;
cout << "day : " << tr ->date .day << endl ;
29 return 0;
}
✌
✆
3.3. DATA STRUCTURES 237
✞
Name : A
day : 10
✌
✆
Again, indirect membership operator or structure pointer operator (−>) is not used in
the level or element of the structure declared as normal variable.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
6 /* date structure */
struct date {
8 int day;
int month;
10 int year ;
};
12
/* variety structure */
14 struct variety {/* upper level structure */
char *name ;
16 /* Nested structure . Declared by normal variable . *
* Element of the structure are accessed by dot (.)*/
18 struct date date ; /* Lower level structure as normal
variable .*/
} *tr; /* Structure declared as pointer variable .*
20 * Elements are accessed by (->) symbol. */
/* Following lines throw errors. We are trying here to access *
22 *the elements of structure ‘date ’ by pointer symbol (->) while*
*the structure ‘date ’ is declared here as normal variable .
*/
24 tr ->date ->day = 10;
tr.date ->day = 10;
26 return 0;
}
✌
✆
But the lower level elements can also be accessed by using pointer symbol (−>) if lower
level structure is also declared as pointer level.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5
/* date structure */
7 struct date {
int day;
9 int month;
int year ;
11 };
238 Accessing System Files
13 /* variety structure */
struct variety {/* upper level structure */
15 char *name ;
/* Nested structure . Declared as pointer variable .*
17 * Element of the structure can accessed by (->) */
struct date *date ; /* Lower level structure as normal
variable .*/
19 } *tr; /* Structure declared as pointer variable . *
* Elements can be accessed by (->) symbol.*/
21 cout << "Date & Month :" << endl ;
/* Accessing structure elements by using synopsis like
23 * up_level_struct (->) up_level_elem
* or
25 * up_level_struct (->) low_level_struct (->) low_level_elem */
tr ->date ->day = 10;
27 tr ->date ->month = 10;
cout << "Day : " << (tr ->date ->day) << endl ;
29 cout << "Month : " << (tr ->date -> month) << endl ;
return 0;
31 }
✌
✆
✞
Date & Month :
Day : 10
Month : 10
✌
✆
In above examples, it is clarified that, elements of structures declared as variable type are
accessed by using dot (.) and elements of structure declared as pointer type are accessed
by using indirect membership operator or structure pointer operator (-¿).
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5
/* date structure */
7 struct date {
int day;
9 int month;
int year ;
11 };
13 /* variety structure */
struct variety {/* up_level_struct (uls)*/
15 char *name ;
/* Nested structure . Declared as pointer variable .*
17 * Element of the structure are accessed by (->). */
struct date *date ; /* Lower level structure as normal
variable .*/
19 } tr; /* Structure declared as normal variable .*
* Elements can be accessed by dot (.). */
21
3.3. DATA STRUCTURES 239
/* Accessing structure elements by using synopsis like
23 * up_level_struct (.) up_level_elem
* or
25 * up_level_struct (.) low_level_struct (->) low_level_elem */
tr.date ->day = 10;
27 tr.date ->month = 10;
cout << "Day : " << (tr.date ->day) << endl ;
29 cout << "Month : " << (tr.date -> month) << endl ;
return 0;
31 }
✌
✆
✞
Day : 10
Month : 10
✌
✆
Linked List
See the followomg prototype for the definition of a structure:
✞
struct list_Elem {
2 int data ;
struct list_Elem *ele_Ptr ; /* Element is structure itself.*/
4 };
✌
✆
In this prototype, element of structure is structure itself. It is forbidden in the structure
definition. But in fact it only contains a pointer to itself. It is allowed as by the time
the compiler reaches the pointer declaration it already knows that there is such a thing
as a ‘struct list Elem’ so the declaration is permitted. In fact, it is possible to make a
incomplete declaration of a structure by saying
✞
struct list_Elem ;
✌
✆
at some point before the full declaration. This will allow the declaration of pointers before
the full declaration is seen. It is also important in the case of cross-referencing structures
where each must contain a pointer to the other, as shown in the following example.
✞
1 struct s_1; /* Incomplete type */
3 struct s_2 {
int something ;
5 struct s_1 *sp;
};
7
struct s_1 { /* Full declaration */
9 float something ;
struct s_2 *sp;
11 };
✌
✆
This illustrates the need for incomplete types. It also illustrates an important thing about
the names of structure members: they inhabit a name-space per structure, so element
240 Accessing System Files
names can be the same in different structures without causing any problems. Incomplete
types may only be used where the size of the structure isn’t needed yet. A full declaration
must have been given by the time that the size is used. The later full declaration mustn’t
be in an inner block because then it becomes a new declaration of a different structure.
✞
1 struct x; /* Incomplete type */
3 /* valid uses of the tag */
struct x *p, func (void );
5
void f1(void ) {
7 struct x {
int i;
9 }; /* redeclaration ! */
}
11
/* full declaration now */
13 struct x {
float f;
15 } s_x;
17 void f2(void ) {
/* valid statements */
19 p = &s_x;
*p = func ();
21 s_x = func ();
}
23
struct x func (void ) {
25 struct x tmp;
tmp.f = 0;
27 return (tmp);
}
✌
✆
The other principal way to get incomplete types is to declare arrays without specifying
their size and their type is incomplete until a later declaration provides the missing
information:
✞
int ar []; /* incomplete type */
2 int ar [5]; /* completes the type */
✌
✆
If you try that out, it will only work if the declarations are outside any blocks (external
declarations), but that’s for other reasons. There were three elements linked into the list,
which could have been built like this:
✞
struct list_Elem {
2 int data ;
struct list_Elem *pointer ;
4 } ar [3];
6 int main (int argc , char *argv []) {
3.3. DATA STRUCTURES 241
ar [0]. data = 5;
8 ar [0]. pointer = &ar [1];
ar [1]. data = 99;
10 ar [1]. pointer = &ar [2];
ar [2]. data = -7;
12 ar [2]. pointer = 0; /* mark end of list */
return (0);
14 }
✌
✆
and the contents of the list can be printed in two ways. The array can be traversed in
order of index, or the pointers can be used as in the following example.
✞
#include <iostream >
2 using namespace std;
4 struct list_Elem {
int data ;
6 struct list_Elem *pointer ;
} ar [3];
8
int main (int argc , char *argv []) {
10
struct list_Elem *lp;
12
ar [0]. data = 5;
14 ar [0]. pointer = &ar [1];
ar [1]. data = 99;
16 ar [1]. pointer = &ar [2];
ar [2]. data = -7;
18 ar [2]. pointer = 0; /* mark end of list */
20 /* follow pointers */
lp = ar;
22 while (lp) {
cout << "contents " << lp ->data << endl ;
24 lp = lp ->pointer ;
}
26 return 0;
}
✌
✆
✞
contents 5
contents 99
contents -7
✌
✆
Structure As Arguments
A structure can also passed to a function as shown in the example below:
✞
1 #include <iostream >
using namespace std;
242 Accessing System Files
3
#define TREE_NUM 50
5
/* Structure for garden tree length.*/
7 struct g_len {
char gardens[TREE_NUM ];
9 double t_len_1;
double t_len_2;
11 };
13 /* Structure passed to the function .*/
double sum(struct g_len val) {
15 return (val.t_len_1 + val.t_len_2 );
}
17
int main (int argc , char *argv []) {
19 /* Initialized the structure .*/
struct g_len sbi = {
21 "G DELHI",
6524.12 ,
23 9458.87
};
25 double s=sum(sbi);
cout << "Tree length is " << s << endl ;
27 return 0;
}
✌
✆
✞
Tree length is 15982.99 m.
✌
✆
3.3.2 Enumerate
In C++, enumerations are created by explicit definitions, which use the enum keyword
and are reminiscent of struct and union definitions. Point of declaration of enum is that
point of the program body, where, enum list is started. See example below.
✞
1 #include <iostream >
using namespace std;
3
enum {
5 /*0*/ /*1*/ /*2*/
TRUE , FALSE , NO
7 } b = NO;
9 int main (int argc , char ** argv ) {
cout << "bool : " << b << endl ;
11 return 0;
}
✌
✆
3.3. DATA STRUCTURES 243
✞
bool : 2
✌
✆
C also allows the programmer to choose the values of the enumeration constants explicitly,
even without type.
✞
1 #include <iostream >
using namespace std;
3
enum {
5 TRUE = 0, FALSE = 1, NO = 10
} b = NO;
7
int main (int argc , char ** argv ) {
9 cout << "bool : " << b << endl ;
return 0;
11 }
✌
✆
✞
bool : 10
✌
✆
In enumerate the values are assigned successively. If any enum key is set to a specific
value then next enum key has value one larger than its preceding enum key if its value is
not set.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5
enum COLORS {
7 BLUE , /* Index value 0*/
GREEN = 3, /* Index value 3*/
9 YELLOW , /* Index value 4*/
RED = 2, /* Index value 2*/
11 BLACK /* Index value 3*/
};
13 cout << "The colors are:n";
cout << BLUE << endl ; /*0*/
15 cout << YELLOW << endl ; /*4*/
cout << BLACK << endl ; /*3*/
17
return 0;
19 }
✌
✆
✞
The colors are:
0
4
3
✌
✆
244 Accessing System Files
3.3.3 Union
The definition of a union is similar to that of a struct. The difference between the two
is that in a struct, the members occupy different areas of memory, but in a union, the
members occupy the same area of memory. Thus, in the following type, for example:
✞
union {
2 int i;
double d;
4 } u;
✌
✆
The programmer can access either ‘u.i’ or ‘u.d’, but not both at the same time. Since ‘u.i’
and ‘u.d’ occupy the same area of memory, modifying one modifies the value of the other,
sometimes in unpredictable ways. The size of a union is the size of its largest member.
A simple example is
✞
#include <iostream >
2 #include <string >
using namespace std;
4
union Data {
6 int i;
float f;
8 char str [50];
};
10
int main (int argc , char ** argv ) {
12 union Data data ;
data .i = 10;
14 data .f = 220.5;
string str("C Programming ");
16 str.copy (data .str , str.length());
data .str[str.length ()]=’0’;
18 cout << "data .i : " << data .i << endl ;
cout << "data .f : " << data .f << endl ;
20 cout << "data .str : " << data .str << endl ;
return 0;
22 }
✌
✆
✞
data .i : 1917853763
data .f : 4.12236 e+30
data .str : C Programming
✌
✆
A constructor and destructor member function can also be declared inside the union.
union has few restrictions like
1. A union cannot have virtual functions, members of reference type and base classes.
It cannot be used as a base class.
2. If a union has a member with a user-defined constructor, a copy operation, a move
operation, or a destructor, then that special function is deleted for that union; that
is, it cannot be used for an object of the union type.
3.4. MEMORY MANAGEMENT 245
3. At most one member of a union can have an in-class initializer.
3.4 Memory Management
3.4.1 Create Memory Space
If there is requirement of a few bytes of memory to store data then we allocate memory
space by using simple variables. But in case of array, string and stacks where addition
of data is not static a dynamic memory allocation is required. Arrays, strings and stack
stores non-counting data when a program is in run thus the memory size should be
expanded when a new data is added. Allocation of memory while program is in run
is called dynamic memory allocation. To create a dynamic memory space, we use new
keyword for this purpose. Its syntax is
✞
1 int *i = new int [10];/*A block of ten integers .*/
int *j = new int (10) ; /* Heap allocation for 10 integers .*/
✌
✆
The new returns the address of first element of the array to the pointer ‘i’. Each time a
dynamic memory is created, must be freed before exit from the program by using delete
keyword.
✞
delete i;
✌
✆
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int *i = new int [5];
int j;
7 for (j = 0; j < 5; j++) {
i[j] = j;
9 }
11 for (j = 0; j < 5; j++) {
cout << i[j] << endl ;
13 }
delete i;
15 return 0;
}
✌
✆
✞
0
1
2
3
4
✌
✆
246 Accessing System Files
3.4.2 Delete Memory Space
Each memory heap created dynamically by new operator must be freed by using delete
keyword.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char ** argv ) {
5 int *i = new int [5]; // Create space for 5 integers
delete i; // Clear the space
7 return 0;
}
✌
✆
3.4.3 Placement Memory Space
new() operator is used to place a memory space over the given buffer stack. For example,
‘b’ is declared as a buffer of two element. The new() operator
✞
int b[2];
2 /* Create memory space and filled with 5*/
int *i = new(b) int (5);
✌
✆
places a memory space over buffer and puts the integer value ‘5’. The address of this
element is assigned to variable ‘i’. Similarly,
✞
1 int *i = new(b + sizeof (int)) int (6);
✌
✆
puts the integer value ‘6’ over the buffer at memory location 4 bytes (size of integer)
ahead to the address of buffer ‘b’. See the example below:
✞
1 #include <iostream >
using namespace std;
3
int main () {
5 int b[2];
int *i = new(b) int (5);
7 int *j = new (b + sizeof (int)) int (6);
cout << *i << endl ;
9 cout << *j << endl ;
return 0;
11 }
✌
✆
✞
5
6
✌
✆
Placements are not deallocated by using delete keyword.
3.5. STACK 247
3.5 Stack
C++ has a ‘stack’ library which deals with all stack related activities. An stack is initiated
as
✞
stack <int > myStack; /* For integer stack*/
2 stack <float > myStack; /* For float stack*/
stack <string > myStack; /* For string stack*/
✌
✆
Stack is based on the Last In First Out (LIFO) principle. The last element inserted by
push() function returns at first by pop() function.
3.5.1 Empty Stack
empty() function tells whether a stack is empty or non empty. If stack is empty then it
returns true otherwise returns false.
✞
1 #include <iostream >
#include <stack >
3 using namespace std;
5 int main (int argc , char ** argv ) {
stack <int > myStack;
7 myStack .push (10) ;
cout << myStack.empty() << endl ; /* Returns 0*/
9 myStack .pop();
cout << myStack.empty() << endl ; /* Returns 1*/
11 return 0;
}
✌
✆
✞
0
1
✌
✆
3.5.2 Size of Stack
size() function returns the size of the stack.
✞
#include <iostream >
2 #include <stack >
using namespace std;
4
int main (int argc , char ** argv ) {
6 stack <int > myStack;
myStack .push (10) ;
8 myStack .push (11) ;
myStack .push (12) ;
10 cout << "Size of stack : ";
cout << myStack.size () << endl ; /* Returns 3*/
12 myStack .pop();
248 Accessing System Files
cout << "Size of stack : ";
14 cout << myStack.size () << endl ; /* Returns 2*/
return 0;
16 }
✌
✆
✞
Size of stack : 3
Size of stack : 2
✌
✆
3.5.3 Get Top Element
top() returns the reference of topmost element of the stack. This function can replace the
top most element or can do arithmetic on it if arithmetic operator is used.
✞
#include <iostream >
2 #include <stack >
using namespace std;
4
int main (int argc , char ** argv ) {
6 stack <int > myStack;
myStack .push (10) ;
8 myStack .push (11) ;
myStack .push (12) ;
10 cout << "Size of stack before top () is : ";
cout << myStack.size () << endl ; /* Returns 3*/
12 myStack .top() = 10;
cout << "Size of stack after top () is : ";
14 cout << myStack.size () << endl ;/* Returns 3*/
cout << "Top stack is : ";
16 cout << myStack.top () << endl ; /* Returns 10*/
myStack .top() -= 7;
18 cout << "Top stack is : ";
cout << myStack.top () << endl ; /* Returns 3*/
20 return 0;
}
✌
✆
✞
Size of stack before top () is : 3
Size of stack after top () is : 3
Top stack is : 10
Top stack is : 3
✌
✆
3.5.4 Add Element at Top
push function is used to add an element into the stack. Its syntax is
✞
<stack name >. push (<value >);
✌
✆
3.5. STACK 249
✞
1 #include <iostream >
#include <stack >
3 using namespace std;
5 int main (int argc , char ** argv ) {
stack <int > myStack;
7 myStack .push (10) ;
myStack .push (11) ;
9 myStack .push (12) ;
cout << "Top element is : ";
11 cout << myStack.top () << endl ; /* Returns 12*/
return 0;
13 }
✌
✆
✞
Top element is : 12
✌
✆
3.5.5 Remove Top Element
pop is used to remove the top of the element of a stack. It is used as
✞
1 <stack name >. pop();
✌
✆
✞
1 #include <iostream >
#include <stack >
3 using namespace std;
5 int main (int argc , char ** argv ) {
stack <int > myStack;
7 myStack .push (10) ;
myStack .push (11) ;
9 myStack .push (12) ;
cout << "Top element is : ";
11 cout << myStack.top () << endl ; /* Returns 12*/
myStack .pop(); /* Remove top most element */
13 cout << "Top element is : ";
cout << myStack.top () << endl ; /* Returns 11*/
15 return 0;
}
✌
✆
✞
Top element is : 12
Top element is : 11
✌
✆
250 OOP in C++
4.1. STRUCTURES 251
4OOP in C++
4.1 Structures
In Object Oriented Programming, a structure is required. A struct is like a class except
for the default access. C++ also support the C like structure. Structures are also allow
Operator Overloading. A struct is defined as
✞
struct myStructType /*: inheritances */ {
2 public:
<public memters >
4 protected :
<protected members >
6 private :
<private members >
8 } myStructName ;
✌
✆
public members are accessed from anywhere by declaring structure object and calling
public member. private members are accessed within the structure definition only, i.e.
by member classes or member functions defined within the parent structure. protected
members are accessible in the class or through derived classes. An object of type ‘myS-
tructType’ is declared as
✞
myStructType <object name >;
✌
✆
The simplest example of the struct is the structure for the coordinate point. A point
structure is defined and initialized as
✞
1 struct Point {
double x, y;
3 };
✌
✆
In this definition of structure, there are two members named as x and y. We can set the
values to the member of this structure as
✞
1 struct Point blank;
blank.x = 3.0;
3 blank.y = 4.0;
✌
✆
We can read the values of an instance variable using the same syntax we used to write
them:
✞
1 int x = blank.x;
✌
✆
See the example below:
252 OOP in C++
✞
1 #include <iostream >
using namespace std;
3
struct Point {
5 double x, y;
};
7
int main (int argc , char *argv []) {
9 struct Point point;
point.x = 1;
11 point.y = 1.5;
cout << "x is " << point.x << " and y is " << point.y;
13 return 0;
}
✌
✆
✞
x is 1 and y is 1.5
✌
✆
The detailed explanation is given in struct section. Size of struct is equal to the sum of
sizes of its all variables.
✞
1 #include <iostream >
using namespace std;
3
struct A {
5 int i [30]; /*30 X 4= 120 bytes*/
int j [20]; /*20 X 4= 80 bytes*/
7 };/* Total size is 200 bytes*/
9 int main (int argc , char *argv []) {
cout << "sizeof struct A = " << sizeof (A)
11 << " bytes" << endl ;
return 0;
13 }
✌
✆
✞
sizeof struct A = 200 bytes
✌
✆
struct can also holds the member function inside them. A member function inside the
struct is modified by using operator ‘::’. The member function is accessed by calling struct
and its member function. See the example below:
✞
1 #include <iostream >
using namespace std;
3
struct A {
5 void g();/* declaring member function */
};
7
/* Accessing the member function g()*
9 *of structure A and modifing to it*/
4.1. STRUCTURES 253
void A::g() {
11 cout << "Sturcture A" << endl ;
}
13
int main (int argc , char *argv []) {
15 /* Declare and initialized struct A*/
struct A a;
17 /* Call to memeber function g()*/
a.g();
19 return 0;
}
✌
✆
✞
Sturcture A
✌
✆
Pointer can also be used in argument of a member function. A child structure alongwith
its members can also be defined inside the parent structure. See the example below:
✞
1 #include <iostream >
using namespace std;
3
struct A {
5 /* declaring member function *
*with pointer type argument */
7 void g(int* x);
9 struct B {
void h();
11 };
};
13
/* Accessing the member function g()*
15 *of structure A and modifing to it*/
void A::g(int* x) {
17 cout << "Sturcture A" << endl ;
cout << "x is " << *x << endl ;
19 }
21 void A::B::h() {
cout << "Nested struct !!";
23 }
25 int main (int argc , char *argv []) {
struct A a;
27 int i = 12;
a.g(&i);
29 struct A::B b;
b.h();
31 return 0;
}
✌
✆
254 OOP in C++
✞
Sturcture A
x is 12
Sturcture A
x is -12
✌
✆
Following example has a nested struct model. The nested model has member function
h(). Function definition of this member function is defined outside the structure by using
operator ‘::’.
✞
#include <iostream >
2 using namespace std;
4 /* Outer parent structure */
struct A {
6 void g(int* x);
8 /* Nested child structure */
struct B {
10 void h();
};
12 };
14 void A::g(int* x) {
cout << "Sturcture A" << endl ;
16 cout << "x is " << *x << endl ;
}
18
/* Accessing function of nested child B *
20 *structure and defining its definitions .*/
void A::B::h() {
22 cout << "Nested struct !!";
}
24
int main (int argc , char *argv []) {
26 struct A a;
int i = 12;
28 a.g(&i);
struct A::B b;
30 b.h();
return 0;
32 }
✌
✆
✞
Sturcture A
x is 12
Nested struct !!
✌
✆
4.2. CLASSES 255
4.2 Classes
Classes are used to create user defined types which includes the set of functions. An
instance of a class is called an object and programs can contain any number of classes.
As with other types, object types are case-sensitive. A class can have both, the data
members and the function members associated with it. A class is defined by:
✞
1 class MyClass {
/* public , protected and private *
3 * variables /constants /functions */
};
✌
✆
An object of MyClass class is declared as shown in the following syntax.
✞
MyClass object;
✌
✆
By default, all class members are initially private unless they are declared as pro-
tected or public. A class is like a container which contains is all members.
✞
1 class MyClass {
int x;// integer variable x
3 void f(){}// function with definition
};
✌
✆
MyClass
x void f()
Figure 4.1: Fields/Members of a class.
Remember that the memory arrangement of the class object is in different form. Non-
virtual functions do not reflects in memory arrangement. (See Virtual Function Table
(VFT) for details.) The object of a class can not access to private data members of own
class but they can be accessed from within the class.
✞
#include <iostream >
2 using namespace std;
4 class A {
int x = 1;
6 public:
int y = 2;
8 void X(){
256 OOP in C++
cout << x << endl ;
10 }
};
12
int main () {
14 A *a = new A();
// cout << a->x;// Error!! accessing private member
16 cout << a->y << endl ;
a->X(); // Return the value of private A::x
18 return 0;
}
✌
✆
✞
2
1
✌
✆
A
x=1 y=2 X()
a (object of A)
x=1 y=2 X()
In first part of above figure, all data members of the class ‘A’ are shown. In second part
of above figure, object of class ‘A’ can not access private member ‘x’ directly but it can
access to it via member function ‘X()’. If object of a class is declared twice then each
object is created at different location of memory address. See in the example given below:
✞
#include <iostream >
2 using namespace std;
4 class Address {
int HNo;
6 int BlockNo ;
public:
8 void getLocality ();
void getDistrict ();
10 void getState ();
int pin;
12 };
14 int main () {
Address A, B;
16 cout << "Memory Address of object A is " << &A << endl ;
cout << "Memory Address of object B is " << &B << endl ;
18 return 0;
4.2. CLASSES 257
}
✌
✆
✞
Memory Address of object A is 0x22ff 54
Memory Address of object B is 0x22ff 48
✌
✆
Object ‘B’
int A::HNo;
0x22ff48
int A::BlockNo;
0x22ff4C
int A::pin;
0x22ff50
Object ‘A’
int B::HNo;
0x22ff54
int B::BlockNo;
0x22ff58
int B::pin;
0x22ff5C
Figure 4.2: Memory representation of object “Address B” and “Address A”.
4.2.1 Abstract Class
An abstract class, a type of C++ class, is designed for specific use as a base class. A
abstract class is that class which contains at least one pure virtual function by inheriting
or by defining. See the following syntax:
✞
class myClass {
2 public:
virtual void func ();// virtual function
4 virtual void funcn() = 0;// pure virtual function
};
✌
✆
Here, function myClass::func is a pure virtual function. A function is said to be declared
with definition, it function is followed by curly braces as shown below:
✞
1 int func ();// Declaration without definition
int func () {} // Declaration with definition
✌
✆
A function declaration can not have both, i.e. a pure specifier and functions’ definition
as shown below:
✞
class myClass {
2 public:
virtual void func () {}= 0; // Invalid , compile time error
4 // virtual void func1() =0 {}; // Valid
};
✌
✆
In above example, compiler shall show the error. An abstract class can not be declared
as a parameter type or a function return type or the type of an explicit conversion or
an object of an abstract class. However, pointers and references to an abstract class
258 OOP in C++
are acceptable. A derived class is abstract class unless its each inherited or owned pure
virtual function is not overriden.
✞
1 class myClass { // abstract base class
public:
3 virtual void func () = 0;// pure virtual function
};
5
class myDerivedClass : public myClass {// Not an abstract class
7 void func ();// Virtual function is overriden here
};
✌
✆
Instances can not be created for the abstract base class. Therefore, a class derived from
an abstract base class will also be abstract class unless and instance of such derived class
can not be created.
✞
#include <iostream >
2 using namespace std;
4 class myClass { // abstract class
public:
6 virtual void func () = 0; // pure virtual function
};
8
class myDerivedClass : public myClass {// abstract class
10 void newfunc ();
};
12
int main (int argc , char *argv []) {
14 myDerivedClass myObj;// Not allowed
return 0;
16 }
✌
✆
The compiler will not allow the declaration of object myObj because myDerivedClass is
an abstract class. It inherited the pure virtual function func() from myClass. To create
the instances of derived class, we need to override each pure virtual function of the derived
class as well as of its inherited base class. Above codes are modified as given in the below
example:
✞
#include <iostream >
2 using namespace std;
4 class myClass { // abstract class
public:
6 virtual void func () = 0;
};
8
class myDerivedClass : public myClass {// Not an abstract class
10 void func ();//As virtual function is overriden
};
12
4.2. CLASSES 259
int main (int argc , char *argv []) {
14 myDerivedClass myObj; // allowed
return 0;
16 }
✌
✆
The compiler, here allows the declaration of object myObj as myDerivedClass::func()
overrides the inherited pure virtual function myClass::func(). A compiler issues a warning
for the calling of a pure virtual function directly, but not if it is called indirectly. An
example of abstract class and derived class is given below:
✞
#include <iostream >
2 using namespace std;
4 class B{// abstract base class
public:
6 virtual void show () = 0;
};
8
class D: public B{// Derived class not abstract class as
10 // show () is overrided here
public:
12 void show () { cout << "In Derived n"; }
};
14
int main (void ){
16 /* Create object of class D and cast it for class B. Same
members *
*of class D shall be overrided by non -virtual member of class
B.*/
18 B *bp = new D();
/* Here the virtual function show () in base class does *
20 *not override to the show () function of derived class.*/
bp ->show ();
22 return 0;
}
✌
✆
✞
In Derived
✌
✆
4.2.2 Friend Class
Friend classes or functions can be declared within a class template. When a template is
instantiated, the names of its friends are treated as if the specialization had been explicitly
declared at its point of initialization. Friendship is not mutual. If a class A is friend of
B, then B doesnt become friend of A automatically. Friendship is not inherited. See the
example below in which, class B is friend of class A.
✞
1 #include <iostream >
using namespace std;
3
260 OOP in C++
class A {
5 int a, b;
public:
7
A(int i, int j) : a(i), b(j) {
9 }
friend class B; // class B as Friend of class A
11 };
13 class B {
public:
15
int dispSum (A& x) {
17 /* Since class B is friend of class A, hence *
*private members of A are accessible here . */
19 return x.a + x.b;
}
21 };
23 int main () {
A a(2, 3);
25 B b;
cout << b.dispSum(a);
27 return 0;
}
✌
✆
✞
5
✌
✆
As with non-template classes, the names of name-space-scope friend functions of a class
template specialization are not visible during an ordinary lookup unless explicitly declared
at name-space scope. If a friend declaration in a non-local class first declares a class or
function, the friend class or function is a member of the innermost enclosing name-space.
✞
1 #include <iostream >
using namespace std;
3
namespace myNameSpace {
5
class myClass {
7 // myNameSpace :: func is a friend
friend void func (myClass);
9 };
// myNameSpace :: func is not visible here
11 myClass myClassObj ;
13 void func (myClass) {
/* definition */
15 } // func () is defined and known to be a friend
}
17
using myNameSpace :: myClassObj ;
4.2. CLASSES 261
19
int main (int argc , char *argv []) {
21 myNameSpace :: func (myClassObj ); // OK
myNameSpace :: myClass :: func (myClassObj );// error
23 /* func () is not a member of myNameSpace :: myClass */
25 return 0;
}
✌
✆
In this example, function func() can only be called through namespace myNameSpace
using the call
✞
myNameSpace :: func (myClassObj )
✌
✆
Attempting to call function func() through class myClass using the
✞
1 myNameSpace :: myClass :: func (myClassObj );
✌
✆
call results in a compile-time error. Since the friend declaration first occurs in a non-local
class, the friend function is a member of the innermost enclosing name-space and may
only be accessed through that name-space.
4.2.3 Nested Class
A nested class is a class which is declared in another enclosing class. A nested class is
a member of outer class. It has same rights as other members of the outer class have.
The members of an enclosing class have no special access to members of a nested class.
General rules of a class are obeyed for accessing of member of the class.
✞
1 #include <iostream >
using namespace std;
3
/* Outer class */
5 class myOuter {
public:
7
/* start of inner Nested class declaration */
9 class myInnerNested {
private :
11 int s;
public:
13
void myFunction (int a, int b) {
15 s = a + b;
}
17
void show () {
19 cout << "Sum of two numbers is " << s;
}
21 };
};
262 OOP in C++
23
int main (int argc , char ** argv ) {
25 myOuter :: myInnerNested NC;
NC.myFunction (2, 3);
27 NC.show ();
return 0;
29 }
✌
✆
✞
Sum of two numbers is 5
✌
✆
In the above example, class members, variable ‘s’ and ‘myFunction()’ & ‘show()’ functions
are declared as public. Therefore, these two functions can be assessed as object of the
class. See another example:
✞
1 #include <iostream >
using namespace std;
3
/* Outer class */
5 class myOuter {
public:
7 int x;
9 /* start of inner Nested class declaration */
class myInnerNested {
11 public:
13 void myFunction () {
myOuter e;
15 cout << e.x;
}
17 };
};
19
int main (int argc , char ** argv ) {
21 myOuter OC;
OC.x = 2;
23 myOuter :: myInnerNested NC;
NC.myFunction ();
25 return 0;
}
✌
✆
✞
2
✌
✆
Another example, similar to above one.
✞
1 #include <iostream >
using namespace std;
3
/* Outer class*/
5 class OuterClass {
4.2. CLASSES 263
public:
7 int x;
public:
9 /* Public inner class*/
class InnerClass {
11 public:
/* Public function func inside inner class*/
13 void func (OuterClass * p, int i) {
/* Access public variable of outer class*/
15 p->x = i;
}
17 };
};
19
int main (int argc , char ** argv ) {
21 /* Create object for outer class*/
OuterClass *oc = new OuterClass ();
23 /* Create object for inner class*/
OuterClass :: InnerClass ic;
25 /* Call function func of inner class*/
ic.func (oc , 10);
27 /* Get the value of variable x*/
cout << oc ->x;
29 return 0;
}
✌
✆
✞
10
✌
✆
A base class (say ‘Point’), can also be nested by creating its instances inside other base
class (‘say Vector’). In this case, fields of the ‘Vector’ class are ‘Point’ class. See the
syntax given below:
✞
1 class Point{
public:
3 double x,y;
};
5 class Vector{
public:
7 Point init , final;
};
✌
✆
The fields of ‘Point’ class and ‘Vector’ class are looked like
264 OOP in C++
Point
x y
Vector
Point (init)
x y
Point (final)
x y
The creation of instances of the ‘Vector’ class also creates the instances of‘ Point’ class
as ‘init’ and ‘final’.
✞
Vector vec;
✌
✆
vec (Instance of Vector)
init (Instance of Point)
x y
final (Instance of Point)
x y
4.2. CLASSES 265
4.2.4 Derived Class
Derived class is one which is created from the base class by inhering the data members
of the base class. The derived class may contain additional data members or may access
only to the data member of base class. A derived class is created like
✞
1 class <BaseClassName >;
class <DerivedClassName > : <access type > <BaseClassName >;
✌
✆
Here, access type shall be one of the keywords private, protected and public that defines
the scope of inherited class for the derived class. The function defined in base class can
be overloaded in derived class. See the example below:
✞
#include <iostream >
2 using namespace std;
4 class BaseClass {
protected :
6 int m;
public:
8
BaseClass (int i) {
10 m = i;
}
12
/* print() function in base class*/
14 void print() {
cout << m << " ";
16 }
};
18
/* Derived Class with protected inherited to base class*/
20 class DerivedClass : protected BaseClass {
double n;
22 public:
24 DerivedClass (int i, double d) : BaseClass (i), n(d) {
}
26
/* Class initialization with default values of i and d*/
28 // DerivedClass (int i=2, double j=3) : BaseClass (i), n(j) { }
30 /* print() function of base class is overloaded here .*/
void print() {
32 cout << m << " ";
}
34
void print(DerivedClass &a) {
36 cout << a.m << " " << a.n << " ";
}
38 };
266 OOP in C++
40 int main () {
DerivedClass dc(20, 30.5);
42 dc.print();
dc.print(dc);
44 return 0;
}
✌
✆
✞
20 20 30.5
✌
✆
The derived class has following properties:
1. Derived class inherits all data members of all base classes. Access to private data
members of a class from the object of that class is not allowed. Derived class can add
own data members.
✞
1 class myClassB {
public:
3 int x; // Base class member variable
int myFuncB () {
5 } // Base class member function
};
7
class myClassD : public myClassB {
9 public:
int y; // Derived class member variable
11 int myFuncD () {
} // Derived class member function
13 };
✌
✆
In above classes, all members are public, therefore, all public members of class myClassB
are inherited and accessed by object of class myClassD as shown in following figure.
myClassB
int x;
int myFuncB();
myClassD;
int x;
int myFuncB();
int y;
int myFuncD();
But private data members of base class are inherited by the derived class, but they
can not be accessed by the object of derived class. This is why, in memory allocation to
the object of derived class, private members of the base class share memory space. See
the following example.
✞
1 #include <iostream >
using namespace std;
4.2. CLASSES 267
3
class myClassB {
5 int x; // Base class member variable
public:
7
int myFuncB () {
9 } // Base class member function
};
11
class myClassD : public myClassB {
13 int y; // Derived class member variable
public:
15
int myFuncD () {
17 } // Derived class member function
};
19
int main () {
21 cout << sizeof (myClassD );
return 0;
23 }
✌
✆
✞
8
✌
✆
Memory allocation of a class is not based on its structure. Non-virtual functions do not
get share in memory space of the object of a class. The memory allocation of base class
and derived class are given in below figure.
myClassB
int x
4 bytes
myClassD
int x
4 bytes
int y
4 bytes
2. Derived class inherits all member functions of all base classes. They may override
a member function of any base class by redefining it with the same signature. Derived
class may overload a member function of any base class by redefining it with the same
name but different signature. Derived class does not inherit the friend member function
of any base class.
✞
1 #include <iostream >
using namespace std;
3
class myClassB {
5 public:
int x = 10; // Base class member variable
268 OOP in C++
7
static void fB() {
9 cout << "fB" << endl ;
}// Base class static member function
11
friend void gB() {
13 cout << "gB" << endl ;
}// Base class friend member function
15
void hB() {
17 cout << "hB" << endl ;
} // Base class member function
19 };
21 class myClassD : public myClassB {
int y = 20; // Derived class member variable
23 public:
25 void fD() {
cout << "fD" << endl ;
27 } // Derived class member function
};
29
int main () {
31 myClassD D;
cout << D.x << endl ;
33 D.fB();
//D.gB (); // Error!! accessing to friend myClassB ::gB()
35 D.hB();
D.fD();
37 return 0;
}
✌
✆
✞
10
fB
hB
fD
✌
✆
The member function of base class and derived class are shown in the following figure.
4.2. CLASSES 269
myClassB
int x;
static void fB();
friend void gB();
void hB();
myClassD
int x;
static void fB();
void hB();
int y;
void fD();
In above figure, those members of base class, which are inherited by the derived class
but have no access to them either by object method or from within the derived class, are
not shown. Those members which are accessed from within the derived class are shown
in above figure.
3. Derived class cannot access private members of any base class but they have access
to the protected members of any base class.
✞
#include <iostream >
2 using namespace std;
4 class myClassB {
int x = 10; // Base class private member variable
6
void privF() {
8 cout << "privF" << endl ;
}// Base class private member function
10 public:
12 static void fB() {
cout << "fB" << endl ;
14 }// Base class static member function
16 void gB() {
cout << "gB" << endl ;
18 } // Base class member function
};
20
class myClassD : public myClassB {
22 int y = 20; // Derived class private member variable
public:
24
void fD() {
26 cout << "fD" << endl ;
} // Derived class member function
28 };
30 int main () {
270 OOP in C++
myClassD D;
32 // cout << D.x << endl ; // Error!! accessing to private
myClassB ::x
D.fB();
34 //D.privF()(); // Error!! accessing to private
myClassB :: privF()
//D.y(); // Error!! accessing to private myClassD ::y
36 D.fD();
return 0;
38 }
✌
✆
✞
fB
fD
✌
✆
The member function of base class and derived class are shown in the following figure.
myClassB
int x;
void privF();
static void fB();
void gB();
myClassD
static void fB();
void gB();
int y;
void fD();
In above figure, those members of base class, which are inherited by the derived class
but have no access to them either by object method or from within the derived class, are
not shown. Those members which are accessed from within the derived class are shown
in above figure.
4. First, a constructor of the derived class must call all constructors of the base
classes to construct the base class instances of the derived class. Base class constructors
are called in listing order. The destructor of the derived class must call the destructors
of the base classes to destruct the base class instances of the Derived class. Derived class
layout contains instances of each base class.
✞
class Point {
2 public:
double x, y;
4 };
6 class Vector {
public:
8 Point init , final;
};
✌
✆
The creation of instances of the ‘Vector’ class also creates the instances of‘ Point’ class
as ‘init’ and ‘final’.
4.2. CLASSES 271
✞
1 Vector vec;
✌
✆
vec (Instance of Vector)
init (Instance of Point)
x y
final (Instance of Point)
x y
5. Derived class layout contains instances of each base class. Derived class layout will
have data members of its own. C++ does not guarantee the relative position of the base
class instances and derived class members. See the previous ‘Point’ and ‘Vector’ classes:
✞
1 class Point {
public:
3 double x, y;
};
5
class Vector {
7 public:
Point init , final;
9 int z;
};
✌
✆
The creation of instances of the ‘Vector’ class also creates the instances of‘ Point’ class
as ‘init’ and ‘final’.
✞
Vector vec;
✌
✆
272 OOP in C++
vec (Instance of Vector)
z
init (Instance of Point)
x y
final (Instance of Point)
x y
4.2.5 Polymorphic Class
Any class containing a virtual member function (by definition or by inheritance, pure
or non-pure) is called a Polymorphic Type. A hierarchy may be polymorphic or non-
polymorphic. A non-polymorphic hierarchy has little value.
✞
1 Class B{
public:
3 virtual void fB() =0;
};
5 class D : public B{
public:
7 void fD(){}
}
✌
✆
In above syntax, both, base class and derived class are polymorphic classes.
4.2.6 Data Abstraction
A fundamental concept of Object Oriented (OO) programming is that an object should
not expose any of its implementation details. The class, by design, allows to hide how
the class is implemented.
✞
#include <iostream >
2 #include <iomanip >
using namespace std;
4
class Add {
6 public:
int a = 10;
8 int b = 20;
10 int add () const {
return a + b;
4.2. CLASSES 273
12 }
};
14
int main (int argc , char *argv []) {
16 Add myAdd;
cout << "Addition is " << myAdd.add() << endl ;
18 return 0;
}
✌
✆
✞
Addition is 30
✌
✆
The keywords like private, public, and protected affect the permissions of the members,
where members are either variables or functions or classes etc.
Public Member Public members declared or defined within the public section can be
accessed freely anywhere a declared object is in scope.
✞
1 #include <iostream >
#include <iomanip >
3 using namespace std;
5 class Add {
public:
7 /* Public member. Accessible from any where.*/
int add(int a, int b) const {
9 return a + b;
}
11 };
13 int main (int argc , char *argv []) {
Add myAdd;
15 cout << "Addition is " << myAdd.add(1, 2) << endl ;
return 0;
17 }
✌
✆
✞
Addition is 3
✌
✆
Private Member Members defined declared and defined withing the scope of private
are called private members. They are only accessible within the class which is defining
them and from friend classes. Friend classes are usually the domain of member variables
and helper functions.
✞
1 #include <iostream >
using namespace std;
3
class myClass {
5 public:
int x;
7
274 OOP in C++
/* Public member. Accessible from any where.*/
9 getSum(int a, int b) {
/* Access to private member ’add’*/
11 add(a, b);
}
13 private:
/* here ’add ’() is declared as private member.*
15 *Accessible within the declaring class only .*/
int add(int a, int b);
17
};
19
/* Defining the ‘add’ private member function .*/
21 myClass :: add(int a, int b) {
return a + b;
23 }
25 int main (int argc , char ** argv ) {
myClass *oc = new myClass ();
27 cout << oc ->getSum(2, 3);
return 0;
29 }
✌
✆
✞
5
✌
✆
Protected Member Members declared or defined within the scope of protected are
protected member. It has a special meaning to inheritance, protected members are ac-
cessible in the class that defines them and in classes that inherit from that base class or
friends of it.
4.2.7 Data Hiding
Encapsulation is a process of object oriented programming, in which sensitive information
stored in object’s members are hidden by declaring members as private or protected. In
encapsulation, variables and data flow is visible but not accessible to user from outside
the class. See the example given below:
✞
1 class MyClass {
public:
3 // Public members of class
private:
5 // Members are visible but are still private ( encapsulated )
int x;
7 int y;
};
✌
✆
In data hiding we are unable to know, what is a user accessing via members. Data hiding
is accomplished by using a void pointer or a forward declared struct pointer as the class
data. See the example given below:
4.2. CLASSES 275
✞
class MyClass {
2 public:
// Public members of class
4 private:
struct hiddenData ;
6 // User cannot see what ’h_data’ is in this class (hidden)
hiddenData * h_data;
8 };
✌
✆
4.2.8 Inheritance
Inheritance is a property that describes a relationship between two (or more) types or
classes or objects. It is possible to derive one class from another class or even several
classes. A base class is a class that is created with the intention of deriving other classes
from it. A child class is a class that is derived from another class, i.e. from parent class.
In dynamic type of class, values for the class function are passed by user.
✞
#include <iostream >
2 #include <iomanip >
using namespace std;
4
class MyClass {
6 protected :
int age;
8 public:
10 void Age(int i) {
this ->age = i;
12 cout << age;
}
14 };
16 int main (int argc , char *argv []) {
18 MyClass *a = new MyClass ();
a->Age (10) ;
20
return 0;
22 }
✌
✆
✞
10
✌
✆
By using the colon ‘:’ we can inherit the members of an existing class by new derived
class. See the example below:
✞
1 #include <iostream >
#include <iomanip >
3 using namespace std;
276 OOP in C++
5 class MyClass {
protected :
7 int age;
public:
9
void Age(int i) {
11 this ->age = i;
cout << age;
13 }
};
15 /* Inheritance to MyClass by using colon (:)*
*Inheritance is as <base > : <parent > type */
17 class NewMyClass : public MyClass {};
19 int main (int argc , char *argv []) {
21 NewMyClass *a = new NewMyClass ();
a->Age (10) ;
23
return 0;
25 }
✌
✆
✞
10
✌
✆
A class can also be inherited to other class with new variables and functions. See the
example below:
✞
1 #include <iostream >
#include <iomanip >
3 using namespace std;
5 class MyClass {
protected :
7 int age;
public:
9
void Age(int i) {
11 this ->age = i;
cout << age << endl ;
13 }
};
15
/*By inheritance , we can access MyClass *
17 *via NewMyClass class as shown below. */
class NewMyClass : public MyClass {
19 int gen;
public:
21
void Gender() {
23 this ->gen = 1;
4.2. CLASSES 277
cout << gen << endl ;
25 }
27 };
29 int main (int argc , char *argv []) {
31 NewMyClass *a = new NewMyClass ();
a->Age (10) ;
33 a->Gender ();
return 0;
35 }
✌
✆
✞
10
1
✌
✆
In above example, the newly created class NewMyClass has been inherited from the
MyClass class. Therefore, all the methods and properties (variables) from the MyClass
class are available to the newly created class. Comma is used to use multiple classes to be
inheritate. Calling of constructors directly is forbidden, but by the method shown below,
we can call parent constructor.
✞
ChildClass :: ChildClass (int a, int b) : ParentClass (a, b){
2 <statements for child construction >
}
✌
✆
See the example below:
✞
1 #include <iostream >
using namespace std;
3
class myClass {
5 const int i;
public:
7 myClass (int j);
void getOutPut ();
9 };
11 myClass :: myClass(int j) : i(j) {
}
13
void myClass :: getOutPut () {
15 cout << "Output is " << i << endl ;
}
17
int main (int argc , char *argv []) {
19 myClass Func1(1) , Func2 (2), Func3 (3);
Func1.getOutPut ();
21 Func2.getOutPut ();
Func3.getOutPut ();
278 OOP in C++
23 return 0;
}
✌
✆
✞
Output is 1
Output is 2
Output is 3
✌
✆
In inheritance, derived class can access only public and protected members of the base
class. Private members of the base class can not be accessed from derived class.
Type of Inheritance
There are three types of inheritance. (i) public inheritance, (ii) protected inheritance and
(iii) private inheritance.
Public Inheritance When we derive a class from a public type 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. The private
members of base class can not be accessed by derived class directly, but they can be
accessed from the members of the base class.
✞
1 #include <iostream >
using namespace std;
3
class A {
5 public:
int a;
7 };
9 /* Public type inheritance of class A */
class B : public A {
11 public:
void display () { cout << a << endl ; };
13 };
15 int main () {
B b;
17 b.a=10;
b.display ();
19 return 0;
}
✌
✆
✞
10
✌
✆
4.2. CLASSES 279
Inheritance to Base Class by Derived
Class
Data Members
of Base Class
public protected private
public public protected private
protected protected protected private
private private private private
Access to Data Members of Base Class
for Derived Class
Table 4.1: Visibility of data members of base class when it is inherited by derived class
as public, protected and private.
Protected Inheritance When deriving a new class from a protected base class, public
and protected members of the base class become protected members of the derived class.
✞
1 #include <iostream >
using namespace std;
3
class B {
5 protected :
int b;
7 public:
9 void set_b(int y) {
b = y;
11 };
};
13
/* Public type inheritance of class B*/
15 class D : public B {
public:
17
void display () {
19 cout << b << endl ;
};
21 };
23 int main () {
D d;
25 d.set_b (4);
d.display ();
27 return 0;
280 OOP in C++
}
✌
✆
✞
4
✌
✆
Another example is :
✞
1 #include <iostream >
using namespace std;
3
class A {
5 protected :
int a;
7 public:
9 void set_a(int x) {
a = x;
11 };
};
13
class B {
15 protected :
int b;
17 public:
19 void set_b(int y) {
b = y;
21 };
};
23
/* Public type inheritance of class A & B*/
25 class D : public A, public B {
public:
27
void display () {
29 cout << a * b << endl ;
};
31 };
33 int main () {
D d;
35 d.set_a (3);
d.set_b (4);
37 d.display ();
return 0;
39 }
✌
✆
✞
12
✌
✆
Private Inheritance When deriving a new class from a private base class, public and
protected members of the base class become private members of the derived class. Private
4.2. CLASSES 281
inheritance is not used in standard programming practices. But it is required when we
want to access protected or private members of base class from derived class.
✞
1 #include <iostream >
using namespace std;
3
class A {
5 int n;
protected :
7
A(int i) : n(i) { }
9 virtual int get() = 0;
virtual void print() = 0;
11 };
13 int A:: get () {
return n;
15 }
17 class B : private A {
public:
19 // Constructor to initialize A::n
B(int i) : A(i) { }
21
// Override get() function to return A::n
23 int get () {
A:: get();
25 };
27 // Print the value of A::n
void print() {
29 cout << get() << endl ;
}
31 };
33 int main () {
B *p = new B(10) ;
35 p->print();
return 0;
37 }
✌
✆
✞
10
✌
✆
Private members of a class can be accessed from unrelated class by making friend to
unrelated class with the class. See the example below:
✞
1 #include <iostream >
using namespace std;
3
class A {
5 int a, b;
282 OOP in C++
public:
7
A(int i, int j) : a(i), b(j) {
9 }
friend class B; // class B as Friend of class A
11 };
13 class B {
public:
15
void disp (A& x) {
17 /* Since class B is friend of class A, hence *
*private members of A are accessible here . */
19 cout << x.a << " " << x.b;
}
21 };
23 int main () {
A a(2, 3);
25 B b;
b.disp (a);
27 return 0;
}
✌
✆
✞
2 3
✌
✆
Multiple Inheritance
Multiple inheritance allows the construction of classes that inherit from more than one
type or class. This contrasts with single inheritance, where a class will only inherit from
one type or class. Syntax of the multiple inheritance is given below:
✞
1 class A{
<statements >
3 }
class B{
5 <statements >
}
7 class MultiInherit : public A, public B{
<statements >
9 };
✌
✆
In above syntax, MultiInherit class inherited to two classes, i.e. class A and class B. See
the example below, in which data members of base classes, i.e. class MyClassA and class
MyClassB are inherited by derived class NewMyClass. Here inheritence is public type for
both base classes.
✞
1 #include <iostream >
using namespace std;
4.2. CLASSES 283
3
class MyClassA {
5 protected :
int age;
7 public:
9 void Age(int i) {
this ->age = i;
11 cout << age << endl ;
}
13 };
15 class MyClassB {
protected :
17 int income;
public:
19
void Income(int i) {
21 this ->income = i;
cout << income << endl ;
23 }
};
25
/*By inheritance , we can access MyClass *
27 *via NewMyClass class as shown below: */
class NewMyClass : public MyClassA , public MyClassB {
29 int gen;
public:
31
void Gender() {
33 this ->gen = 1;
cout << gen << endl ;
35 }
37 };
39 int main (int argc , char *argv []) {
41 NewMyClass *a = new NewMyClass ();
a->Age (10) ;
43 a->Income (15000);
a->Gender ();
45 return 0;
}
✌
✆
✞
10
15000
1
✌
✆
If a derived class inherited to base class then it also inherited to all its members including
public variables, functions and classes. If derived class redefines the members of base class
284 OOP in C++
then it overrides to that member of the base class and redefined member is associated to
the object of derived class. See the examples given below, in which derived class inherited
to the member function ‘sum()’ of base class and adds new function ‘mul()’ as its member
function.
✞
1 #include <iostream >
using namespace std;
3
class mA {
5 public:
7 int sum(int i, int j) {
return (i + j);
9 }//A:: sum()
}; // class mA
11
class mB : public mA {
13 public:
15 int mul(int i, int j) {
return (i * j);
17 }//mB :: mul()
}; // class mB inherited to mA
19
int main () {
21
mA a; // Declared class object a
23 mB b; // Declared class object b
cout << a.sum(2, 3) << endl ; // A:: sum()
25 cout << b.sum(2, 3) << endl ; // A:: sum(), inherited
cout << b.mul(2, 3) << endl ; // B:: mul(), added
27 return 0;
}
✌
✆
✞
5
5
6
✌
✆
Second example is given below, in which derived class overrides to the member function
‘sum()’ of base class.
✞
1 #include <iostream >
using namespace std;
3
class mA {
5 public:
7 int sum(int i, int j) {
return (i + j);
9 }//A:: sum()
}; // class mA
4.2. CLASSES 285
11
class mB : public mA {
13 public:
15 int sum(int i, int j) {
return (1 + i + j);
17 }// function is redefined , it override to mA:: sum ()
// now member of the class mB is as mB:: sum()
19 }; // class mB inherited to mA
21 int main () {
23 mA a; // Declared class object a
mB b; // Declared class object b
25 cout << a.sum(2, 3) << endl ; // A:: sum()
cout << b.sum(2, 3) << endl ; // B:: sum()
27 return 0;
}
✌
✆
✞
5
6
✌
✆
Class Constructors
In class-based object-oriented programming, a constructor inside a class is a subroutine
call to create an object of the class. Constructors that can take at least one argument are
termed as parameterized constructors. A constructor is used to initialize the intial values
of class members or used to update the intial values of the class members. For example:
✞
class myClass {
2 int x, y;
public:
4 // Non -Parameterized constructor Or class declaration
myClass ();
6
// Parameterized constructor Or class declaration
8 myClass (int a, int b);
};
10
// Body definition of Non -parameterized constructor
12 myClass :: myClass () {}
14 // Body definition of parameterized constructor
myClass :: myClass(int a, int b){
16 x = a;
y = b;
18 }
✌
✆
286 OOP in C++
When an object is declared in a parameterized constructor, the initial values have to be
passed as arguments to the constructor function. A constructor has no return type and
it’s name is name of the class. The constructors can be called explicitly or implicitly.
✞
myClass e = myClass (0, 50); // Explicit call
2 //Or
myClass e(0, 50); // Implicit call
✌
✆
If the programmer does not supply a constructor for an instantiable class, most languages
will provide a default constructor with default parameter values.
✞
1 class student {
public:
3 int a, b;
// default constructor with default values
5 student (a=0, b=0);
};
✌
✆
See the example below:
✞
#include <iostream >
2 using namespace std;
4 class MyClass {
private:
6 int i, j;
public:
8
/* Class constructor with default values. It inherited *
10 /*to variables i and j. And assigning values to them . */
MyClass (int a = 2, int b = 3) : i(a), j(b) { //i=a and j=b
12 cout << "i : " << i << ", j : " << j << endl ;
}
14 };
16 int main (int argc , char *argv []) {
MyClass f1;
18 MyClass f2 (0);
MyClass f3(5, 6);
20 return 0;
}
✌
✆
✞
i : 2, j : 3
i : 0, j : 3
i : 5, j : 6
✌
✆
Class Destructors
A derived class object may be created by using pointer method. The object must be
destroyed when object is not being used. In OOP, a destructor is automatically invoked
4.2. CLASSES 287
when the object is destroyed. During object construction, object acquires some resources,
allocates reserved memory spaces etc during its lifetime. Class destructor frees these
resources and/or deregister them from other entities which may keep referencing to it.
To destroy the object explicitly, delete operator is used. See the example below:
✞
1 #include <iostream >
3 using namespace std;
5 class B{
public:
7 B() { cout << "B Constructed n"; }
~B() { cout << "B Destructed n"; }
9 };
class D : public B {
11 int n;
public:
13 D() { cout << "D Constructed n"; }
~D() { cout << "D Destructed n"; }
15 };
17 int main () {
// B *d= new D() ;// May use this method
19
// Or , begin of second method
21 D *d= new D();
B *b =d;
23 // End of second method
25 delete b;
return 0;
27 }
✌
✆
✞
B Constructed
D Constructed
B Destructed
✌
✆
In above example, base class destructor is not destructed. The reason is that, derived
class object is created and cast into base class by using pointer, and base class destructor
is not virtual. So, to delete base class constructor, destructor of the base class should be
virtual. See the modified form of above example:
✞
1 #include <iostream >
3 using namespace std;
5 class B{
public:
7 B() { cout << "B Constructed n"; }
virtual ~B() { cout << "B Destructed n"; }
9 };
288 OOP in C++
class D : public B {
11 int n;
public:
13 D() { cout << "D Constructed n"; }
~D() { cout << "D Destructed n"; }
15 };
17 int main () {
// B *d= new D() ;// May use this method
19
// Or , begin of second method
21 D *d= new D();
B *b =d;
23 // End of second method
25 delete b;
return 0;
27 }
✌
✆
✞
B Constructed
D Constructed
D Destructed
B Destructed
✌
✆
Base class constructors are always constructed first, followed by derived class constructors.
Destruction will be in reverse order, i.e. derived class destructor destructed first, followed
by base class. See the example given below:
✞
#include <iostream >
2 using namespace std;
4 class B {
int i;
6 public:
8 B(int d) : i(d) {
cout << "B::B(int);" << endl ;
10 }
12 ~B() { /* No need it to be a virtual as derived *
* class object , D d(1,2) is not a pointer */
14 cout << "B::~B(): " << i << endl ;
}
16 };
18 class D : public B {
int j;
20 public:
22 D(int d, int e) : j(d), B(e) {
cout << "D::D(int);" << endl ;
4.2. CLASSES 289
24 }
26 ~D() {
cout << "D::~D(): " << j << endl ;
28 }
};
30
int main () {
32 D d(1, 2);// with default call -by -values 1 and 2
return 0;
34 }
✌
✆
✞
B::B(int);
D::D(int);
D::~D(): 1
B::~B(): 2
✌
✆
In above example, when we create class object by calling
✞
D d(1, 2)
✌
✆
The base class constructor is called first. So, “B::B(int);” is printed in output. After that,
the derived class constructor is called and there is output “D::D(int)”. The destructors
are called automatically, therefore, first derived class destructor is called and after that
base class destructor is called. This is why, the result output is “D:: D(): 1” and “B:: B():
2” in the ordered sequence.
Named Constructors
Named constructors require static member functions. Named constructors is the name
given to functions used to create an object of a class without (directly) using its con-
structors. Constructors are either private or protected and clients have access only to
the public static functions. The static functions are called “named constructors” as each
unique way of creating an object has a different intuitive name. See the example below:
✞
1 #include <iostream >
using namespace std;
3
class myClass {
5 public:
7 static myClass createMyClass1 () {
return myClass (0);
9 } /* Named constructor */
11 static myClass createMyClass2 () {
return myClass (1);
13 }/* Named constructor */
protected :
15 myClass (int n);
290 OOP in C++
};
17
int main (int argc , char *argv []) {
19 myClass g1 = myClass :: createMyClass1 (); /* Using named
constructor */
myClass g2 = myClass (0); /* Without named constructor */
21 return 0;
}
✌
✆
Without using the named constructor in the above class, it is difficult to convey the
meaning of what myClass(0) and myClass(1) means.
Copy Constructor
The purpose of the copy constructor is to allow the programmer to perform the same
instructions as the assignment operator with the special case of knowing that the caller
is initializing/constructing rather than an copying. The most common form of copy
constructor is shown below:
✞
<class name > (const <class name > &<obj >) {
2 <body of constructor >
}
✌
✆
Example is
✞
1 #include <iostream >
using namespace std;
3
class myClass {
5 int x;
int y;
7 public:
myClass (int i, int j) : x(i), y(j) {
9 }
11 myClass (const myClass &c) : x(c.x), y(c.y) {
}
13
~myClass () {
15 }
17 void print() {
cout << "x : " << x << ", y : " << y << endl ;
19 }
};
21
int main (int argc , char *argv []) {
23 /* Object c is created for myClass class*/
myClass c(1, 2) , // Constructor - myClass(int , int)
25 // Now value of x is set 1 and y is set 2
c1(c), // Copy Constructor - myClass (const myClass &)
4.2. CLASSES 291
27 c2= c; // Copy Constructor - myClass (const myClass &)
c.print();
29 c1.print();
c2.print();
31 return 0;
}
✌
✆
✞
x : 1, y : 2
x : 1, y : 2
x : 1, y : 2
✌
✆
Copy Constructor is needed for initializing the data members of a UDT from an existing
value.
Function Constructors
A constructor is a special member function that is called whenever a new instance of a
class is created. The constructor is declared much like a normal member function but it
will share the name of the class and it has no return value. Constructors are responsible
for the run-time setup necessary for the class operation. Constructor has arguments and
they can also be overloaded.
✞
1 class MyClass {
public:
3 /* Default function constructure */
MyClass ();
5 /* Function overload constructure */
MyClass (int a, int b);
7
private:
9 int x;
int y;
11 };
✌
✆
Default Constructors A default constructor is one which can be called with no argu-
ments. To create an array of objects of a class type, the class must have an accessible
default constructor.
Overloaded Constructors When an object of a class is instantiated, the class writer can
provide various constructors each with a different purpose. A large class would have many
data members, some of which may or may not be defined when an object is instantiated.
Constructor Initialization Lists Constructor initialization lists are the only way to
initialize data members and base classes with a non-default constructor.
292 OOP in C++
Constructor Type Declaration
A default constructor X()
A copy constructor X(const X&)
A copy assignment X& operator=(const X&)
A move constructor X(X&&)
A move assignment X& operator=(X&&)
A destructor ∼X()
Table 4.2: Copy, move and delete constructors of a class ‘X’.
Compiler provides default constructor and default free destructor if user does not provide
constructor or destructor. Objects of a class are initialized by the constructors.
Function Destructors
Destructors are declared as any normal member functions but will share the same name
as the Class. Destructor’s name is preceded with a “˜”. It does not have arguments and
can’t be overloaded. Destructors are called whenever an Object of the Class is destroyed.
A destructor function of a constructor function is declared as
✞
1 class X{
void myFunc(int i);/* Constructor */
3 ~myFunc (); /* Destructor */
}
✌
✆
A destructor function does not require any arguments. A constructor and destructor
member functions of a class ‘X’ are called as
✞
X:: myFunc(i);/* Calling of constructor function */
2 X::~ myFunc ();/* Calling of destructor function */
✌
✆
If function destructor is not provided by the user, then compiler automatically provides
default free destructor.
Friend Function
A function declared inside a class as friend when defined outside the scope of the class
has full right to access all private and protected members of that class. Friend functions
are prototypes inside the class but they are not member functions of that class. A friend
can be a function, function template, or member function, or a class or class template. A
friend function are defined as
✞
class myClass {
2 double width;
public:
4 friend void getWidth (myClass mc);
4.2. CLASSES 293
};
✌
✆
See the example below:
✞
1 #include <iostream >
using namespace std;
3
class myClass {
5 double width;
public:
7 /* Declaration function getWidth () as friend*/
friend void getWidth (myClass mc);
9 void setWidth (double wd);
};
11
/* Set ‘width’ from public function .*/
13 void myClass :: setWidth ( double v) {
width = v;
15 }
17 /* Access value of ‘width’ from friend function .*/
void getWidth (myClass mc) {
19 cout << mc.width;
}
21
int main (int argc , char *argv []) {
23 myClass mc;
cout << "Setting width to 10.2 " << endl ;
25 mc.setWidth (10.2);
cout << "Printing width : ";
27 getWidth (mc);
return 0;
29 }
✌
✆
✞
Setting width to 10.2
Printing width : 10.2
✌
✆
4.2.9 Data Members
Data members are declared in the same way as a global or function variable. It is a part
of the class definition. They stores information for the class and usually are hidden.
The this Pointer Member The this keyword acts as a pointer to the class being
referenced. It acts like any other pointer. It can not be changed. It is only accessible
within non-static member functions of a class, union or struct, and is not available in
static member functions.
✞
#include <iostream >
2 using namespace std;
294 OOP in C++
4 class MyClass {
protected :
6 int age;
public:
8
void setAge(int i) {
10 this ->age = i;
}
12
void getAge() {
14 cout << age << endl ;
}
16 };
18 int main (int argc , char *argv []) {
20 MyClass *a = new MyClass ();
a->setAge (10) ;
22 a->getAge ();
return 0;
24 }
✌
✆
✞
10
✌
✆
Static Data Member The static specifier in a data member, is shared by all instances
of the owner class and derived classes. To use static data members, data member is
declared as static and initialized outside the class declaration, at file scope. When data
member is used in a class, all instances of that class share one copy of the variable.
✞
1 #include <iostream >
using namespace std;
3
class MyClass {
5 public:
7 MyClass () {
++i;
9 cout << "Created " << i << " instances of classn";
}
11 private:
static int i;
13 };
15 /* Allocate memory for i, and initialize it */
int MyClass ::i = 0;
17
int main (int argc , char *argv []) {
19 // MyClass f1 , f2 , f3;
//Or
21 MyClass f1;
4.2. CLASSES 295
MyClass f2;
23 MyClass f3;
return 0;
25 }
✌
✆
✞
Created 1 instances of class
Created 2 instances of class
Created 3 instances of class
✌
✆
In the example above, the static class variable iNumMyClass is shared between all three
instances of the MyClass class (f1, f2 and f3) and keeps count upward by one when the
class MyClass has been instantiated. See another example:
✞
1 #include <iostream >
using namespace std;
3
class Address {
5 static int HNo;
public:
7 void getHNo();
};
9 int Address :: HNo = 10;
11 void Address :: getHNo() {
cout << "House No is " << HNo << endl ;
13 }
15 int main () {
Address A;
17 A.getHNo ();
return 0;
19 }
✌
✆
✞
House No is 10
✌
✆
4.2.10 Class Members
Class members are those variable, functions and classes which are defined inside the class.
The class members operate on any object of the class of which they are member. Class
members have access to all other members of a class for that object. For example in the
following syntax, three different types of members are defined here.
✞
1 class myClass {
int x; // Variable Member
3 double y; // Variable Member
int sum (); // Function Member
5 class XYZ{}// Class Member
}
✌
✆
296 OOP in C++
Members of member functions can be defined inside the class or separately outside the
class by using scope resolution operator, i.e. ‘::’. See the example given below:
✞
#include <iostream >
2 using namespace std;
4 /* Declaration of new class*/
class MyClass {
6 public:
/* Public interger variable x*/
8 int x;
/* Prototype of member function doubleIt ().*
10 *Only declaration of the member function .*/
int doubleIt ();
12 };
14 /* Defining the member function outside the class as *
*its member function of the class using :: operator .*/
16 int MyClass :: doubleIt () {
cout << 2 * x;
18 }
20 int main (int argc , char *argv []) {
/* Defining of class object.*/
22 MyClass c;
/* Accessing class member as object */
24 c.x = 2;
c.doubleIt ();
26 return 0;
}
✌
✆
Defining a member function within the class declares the function inline, even when inline
specifier is not used. A member function is called by using a dot operator (.) on a object.
See the example given below:
✞
1 #include <iostream >
using namespace std;
3
class MyClass {
5 public:
int x;
7
int doubleIt () {
9 return 2 * x;
}
11 };
13 int main (int argc , char *argv []) {
/* Object of MyClass is created.*/
15 MyClass c;
/* Accessing member function of the class by using object*/
17 c.x = 2;
4.2. CLASSES 297
cout << c.doubleIt ();
19 return 0;
}
✌
✆
✞
4
✌
✆
Object inside the main() function can also be created by using pointer method as shown
in the following example.
✞
1 #include <iostream >
using namespace std;
3
class MyClass {
5 public:
int x;
7
int doubleIt () {
9 return 2 * x;
}
11 };
13 int main (int argc , char *argv []) {
/* Object of MyClass is created.*/
15 MyClass *c = new MyClass ();
/* Accessing member function of the class by using object*/
17 c->x = 2;
cout << c->doubleIt ();
19 return 0;
}
✌
✆
Member functions can be used to interact with data contained within user defined types.
Function prototypes are declared within the class definition. Function outside of the class
definition uses the scope resolution operator “::”. This scope resolution operator allows
to define the functions somewhere else. In case of the class and member function are
defined separately, the header file which contains the class definition is named same as
the class name. For example, assume a project, which is named as MyClass, then header
file should be named like MyClass.h. It contains the class definition.
✞
#ifndef MyClass_H
2 #define MyClass_H
4 class MyClass {
public:
6 /* Default function constructure . In other words *
*declaring function prototype without definitions .*/
8 void MyFunc();
/* Function overload constructure */
10 int MyFunc(int a, int b);
int Add(int g, int h);
12
298 OOP in C++
private:
14 int x;
int y;
16 };
18 #endif
✌
✆
The member functions are defined outside the class definition in MyClass.cpp file. The
scope operator is used to put the scope of function definitions inside the class. See the
file script below:
✞
#include "MyClass.h"
2
/* Definition of member function MyFunc () of MyClass class*/
4 void MyClass :: MyFunc() {
x = 5;
6 y = 10;
}
8
/* Definition of member function MyFunc () of MyClass class*/
10 int MyClass :: MyFunc(int a, int b) {
x = a;
12 y = b;
}
14
/* Definition of member function Add() of MyClass class*/
16 int MyClass :: Add(int g, int h) {
x = h + g*x;
18 y = g + h*y;
}
✌
✆
Access to Protected Member
Protected members of a class are accessible from the derived class, if they are accessed
from withing the definition of derived class. A derived class is derived from a main class
by using inherit operator ‘:’ (colon).
✞
1 #include <iostream >
using namespace std;
3
/* Main class*/
5 class myClass {
protected :
7 int num;
};
9
/* Derived class with access permission *
11 *to member function of the main class */
class myDerivedClass : public myClass {
13 public:
4.2. CLASSES 299
15 void printNum () {
num = 10;
17 cout << num << endl ;
}
19 };
21 main (int argc , char *argv []) {
myDerivedClass * c = new myDerivedClass ();
23 c->printNum ();
}
✌
✆
✞
10
✌
✆
Access to Virtual Function
The access control applied to virtual functions is determined by the type used to make
the function call. Overriding declarations of the function do not affect the access control
for a given type (See the abstract classes section for details).
Mutables
A constant data member is not changeable even in a non-constant object. A mutable
data member is changeable in a constant object. A data member is made mutable by
using mutable keyword. mutable is applicable only to data members and not to variables.
Reference data members, static data members and const data members cannot be declared
as mutable. If a data member is declared mutable, then it is legal to assign a value to it
from a const member function.
✞
1 #include <iostream >
using namespace std;
3
class MyClass {
5 int x;
mutable int y;
7 public:
9 /* Set value of x and y by initialization */
MyClass (int m, int mm) : x(m), y(mm) {
11 }
13 int getX () const {
return x;
15 }
17 void setX (int i) { // Not OK
x = i;
19 }
300 OOP in C++
21 int getY () const {
return y;
23 }
25 void setY (int i) const {
y = i;
27 } // Okay to change mutable
};
29
int main () {
31 const MyClass mC(1, 2);// Initialized MyClass object
cout << mC.getX () << endl ;
33 // mC.setX (3); // Error to invoke
cout << mC.getY () << endl ;
35 mC.setY (4);
return 0;
37 }
✌
✆
✞
1
2
✌
✆
Static Data Member
A static data member is associated with class not with object. It is shared by all the
objects of a class. It should need to be defined outside the class scope (in addition to the
declaration within the class scope) to avoid linker error.
✞
class Y {
2 static int armLen; // Static data member
public:
4 int i;
}
6 /* static variable of class Y must be initialize here .*/
int X::Y:: armLen = 10;
✌
✆
It must be initialized in a source file and should constructed before main() starts and
destructed after main() ends. It may be private or public type. It can be accessed with
the class-name followed by the scope resolution operator (::) or as a member of any object
of the class. It virtually eliminates any need for global variables in OOPs environment.
✞
1 #include <iostream >
using namespace std;
3
namespace X {
5 class Y {/* class namespace */
public:
7 static int armLen; // Static data member
};
9 int i;
4.2. CLASSES 301
}
11 /* static variable of class Y must be initialize here .*/
int X::Y:: armLen = 10;
13
int main (int argc , char *argv []) {
15 /* Calling of class namespace .*/
cout << "Arm length is " << (X::Y:: armLen);
17 return 0;
}
✌
✆
✞
Arm length is 10
✌
✆
The static data member does not have this pointer. It can not access or invoke non-static
data members or member functions respectively. It can not be declared as constant and
can not be exists with a non-static version of the same function.
4.2.11 This Pointer
The address of the calling object is stored in a special pointer called the this pointer.
The this pointer holds the memory address of the current object. The this is a constant
pointer. It can not be modified by user. The this pointer is automatically supplied every
time you call a non-static member function of a class. Within any member function, this
pointer exists and that it holds the address of the current object.
✞
1 #include <iostream >
using namespace std;
3
class Address {
5 int HNo;
public:
7 void setHNo(int);
int getHNo ();
9 };
11 void Address :: setHNo(int i) {
(* this ).HNo = i;
13 }
15 int Address :: getHNo() {
return (* this ).HNo;
17 }
19 int main () {
Address A;
21 A.setHNo (10) ;
cout << "House No is " << A.getHNo () << endl ;
23 return 0;
}
✌
✆
302 OOP in C++
✞
House No is 10
✌
✆
In above example, the parentheses are required with ‘(*this).HNo’ as only this is a pointer.
Otherwise, ‘this.HNo’ is considered as a pointer. The this pointer is also used as pointer-
to-member operator as shown in the following example.
✞
1 #include <iostream >
using namespace std;
3
class Address {
5 int HNo;
public:
7 void setHNo(int);
int getHNo ();
9 };
11 void Address :: setHNo(int i) {
this ->HNo = i;
13 }
15 int Address :: getHNo() {
return this ->HNo;
17 }
19 int main () {
Address A;
21 A.setHNo (10) ;
cout << "House No is " << A.getHNo () << endl ;
23 return 0;
}
✌
✆
✞
House No is 10
✌
✆
The this pointer differentiate an object’s field and a local variable with the same identifier.
✞
1 #include <iostream >
using namespace std;
3
class Address {
5 int HNo;
public:
7 void setHNo(int);
int getHNo ();
9 };
11 void Address :: setHNo(int HNo) {
this ->HNo = HNo; // Object field left side
13 // and local variable at right side .
}
15
4.2. CLASSES 303
int Address :: getHNo() {
17 return this ->HNo;
}
19
int main () {
21 Address A;
A.setHNo (10) ;
23 cout << "House No is " << A.getHNo () << endl ;
return 0;
25 }
✌
✆
✞
House No is 10
✌
✆
The this pointer can access to static member variables of a class but it can not be used
with static member functions.
✞
1 #include <iostream >
using namespace std;
3
class Address {
5 static int HNo; // static variable
public:
7 void setHNo(int);
int getHNo ();
9 };
int Address :: HNo = 0;
11
void Address :: setHNo(int HNo) {
13 this ->HNo = HNo;// can access to HNo member of class
}
15
int Address :: getHNo() {
17 return this ->HNo;
}
19
int main () {
21 Address A;
A.setHNo (10) ;
23 cout << "House No is " << A.getHNo () << endl ;
return 0;
25 }
✌
✆
✞
House No is 10
✌
✆
In above example, variable ‘HNo’ is static type and it can be accessed via this point. But
following code failed to compile as a member function is declared as static.
✞
1 #include <iostream >
using namespace std;
3
304 OOP in C++
class Address {
5 int HNo;
public:
7 void setHNo(int);
static int getHNo(); // Static member function
9 };
11 void Address :: setHNo(int HNo) {
this ->HNo = HNo;
13 }
15 int Address :: getHNo() {
return this ->HNo; // Error! ’this ’ is unavailable
17 // for static member functions
}
19
int main () {
21 Address A;
A.setHNo (10) ;
23 cout << "House No is " << A.getHNo () << endl ;
return 0;
25 }
✌
✆
4.2.12 Operator Overloading
Every operator is associated with an operator function that defines its behavior. For
example, a + b is related to operator function as
✞
1 operator +(a, b)
//Or
3 a.operator +(b)
✌
✆
Similarly, a = b is related to operator function as
✞
1 operator =(a, b)
✌
✆
c = a + b is related to operator function as
✞
1 operator =(c, operator +(a, b))
✌
✆
+ Overloading
C++ provides way to overload built-in operators. Overloaded operators are functions
with special names followed by the keyword operator and the symbol for the operator
being defined. An overloaded operator has a return type and a parameter list. For
example, the syntax
✞
1 className operator +(<data -type > className )
✌
✆
4.2. CLASSES 305
declares the addition operator that can be used to add two className objects and returns
final className object. Most overloaded operators may be defined as ordinary non-
member functions or as class member functions. In case we define above function as
non-member function of a class then we would have to pass two arguments for each
operand as follows:
✞
1 className operator +(<data -type > className , <data -type > className )
✌
✆
Following is the example to show the concept of operator over loading using a member
function. Here an object is passed as an argument whose properties will be accessed using
this object, the object which will call this operator can be accessed using this operator
as explained below:
✞
1 #include <iostream >
using namespace std;
3
class myClass { // Declaration of a class
5 public:
// The result member function
7 double getRes(void ) {
return x;
9 }
// Member function setting value of x
11 void setX (double v) {
x = v;
13 }
// operator class
15 myClass operator +( myClass X) {
myClass Y;
17 Y.x = x + X.x;
return Y;
19 }
21 private:
double x;
23 };
25 int main (int argc , char *argv []) {
myClass X1;
27 X1.setX (1.0);
myClass X2;
29 X2.setX (2.0);
myClass X3;
31 X3 = X1 + X2;
cout << X3.getRes();
33 return 0;
}
✌
✆
✞
3
✌
✆
Unary operators like + + a and a + + can be overloaded as
306 OOP in C++
✞
1 operator ++(a); // ++a
//Or
3 a.operator ++() ; // ++a
✌
✆
and
✞
1 operator ++(a, int); // a++
✌
✆
respectively. The operators, like ‘::’ (scope resolution), ‘.’ (member access), ‘.*’ (member
access through pointer to member), sizeof, ‘**’, <>, &| and ‘?:’ (ternary conditional)
cannot be overloaded. Operators other than above listed can be overloaded. The opera-
tors ‘&’, ‘&&‘, ‘||’, and ‘,’ (comma) lose their special properties on operator overloading.
Example of copy-assignment-operator is given below:
✞
1 #include <iostream >
using namespace std;
3
class Complex {
5 int real ;
int imag ;
7
public:
9
Complex (int a = 0, int b = 0) : real (a), imag (b) {
11 }
// Write function header and body for the copy -assignment
operator
13
Complex & operator =( const Complex &t) {
15 real = t.real ;
imag = t.imag ;
17 }
19 void print() {
cout << real << "+i" << imag ;
21 }
};
23
int main () {
25 Complex t1(2, 3);
Complex t3;
27 t3 = t1; // Using copy -assignment operator
t3.print();
29
return 0;
31 }
✌
✆
✞
2+i3
✌
✆
4.2. CLASSES 307
<< Overloading
The operator << is also known as output operator, insertion operator and bitwise left
shift operator. Output operator is a part of ostream object declared inside the header file
‘iostream’. This operator accepts two arguments, one the address where output is placed
and second the data to be placed at output address. The output operator is overloaded
as
✞
1 ostream& operator <<(ostream &, <datatype >);
✌
✆
The datatype may be an integer, a float or double value or a string or a class.
✞
1 #include <iostream >
using namespace std;
3
class AgeMrk {
5 private:
int Age;
7 double Marks;
public:
9 friend ostream& operator <<( ostream &, const AgeMrk &);
AgeMrk(int , double); // constructor should be same
11 // name as of the class
};
13
AgeMrk:: AgeMrk(int age , double mk) {
15 Age = age;
Marks = mk;
17 }
19 ostream& operator <<( ostream & out , const AgeMrk& amk) {
out << "Age : " << amk.Age <<
21 " Marks : " << amk.Marks << endl ;
return out;
23 }
25 int main () {
AgeMrk AgeMrk(10, 150.00) ;
27 cout << AgeMrk;
return 0;
29 }
✌
✆
✞
Age : 10 Marks : 150
✌
✆
>> Overloading
The operator >> is also known as input operator, extraction operator and bitwise right
shift operator. Input operator is a part of istream object declared inside the header
file ‘iostream’. This operator accepts two arguments, one the address from where input
308 OOP in C++
is extracted or receive and second the data to be accept from the address. The input
operator is overloaded as
✞
1 istream& operator >>(istream &, <data >);
✌
✆
The datatype may be an integer, a float or double value or a string or a class.
✞
1 #include <iostream >
using namespace std;
3
class AgeMrk {
5 private:
int Age;
7 double Marks;
public:
9 friend ostream& operator <<( ostream &, const AgeMrk &);
friend istream& operator >>( istream &, AgeMrk&);
11 AgeMrk(int , double); // constructor should be same
// name as of the class
13 };
15 AgeMrk:: AgeMrk(int age , double mk) {
Age = age;
17 Marks = mk;
}
19
ostream& operator <<( ostream & out , const AgeMrk& amk) {
21 out << "Age : " << amk.Age <<
" Marks : " << amk.Marks << endl ;
23 return out;
}
25
istream& operator >>( istream & in , AgeMrk& amk) {
27 cout << endl ; // to clear the buffer
cout << "Enter Age ";
29 in >> amk.Age;
cout << "Marks ";
31 in >> amk.Marks;
return in;
33 }
35 int main () {
AgeMrk AgeMrk(0, 0);
37 cin >> AgeMrk;
cout << AgeMrk;
39 return 0;
}
✌
✆
✞
Enter Age 12
Marks 250
Age : 12 Marks : 250
✌
✆
4.2. CLASSES 309
++, - - Overloading
++ and - - are incremental and decrement operators. ++ and - - may be used as prefix
or postfix to a given variable. For example,
✞
1 i++; // post fixed increment operator
++i; // pre fixed increment operator
3 i--; // post fixed decrement operator
--i; // pre fixed decrement operator .
✌
✆
The increment operator overloading is done by using operator keyword as shown below
✞
operator ++() ;
✌
✆
In the following example, use of ++ operator overloading is explained.
✞
1 #include <iostream >
using namespace std;
3
class AgeMrk {
5 private:
int Age;
7 double Marks;
public:
9 friend ostream& operator <<( ostream &, const AgeMrk &);
AgeMrk(int , double); // constructor should be same
11 // name as of the class
AgeMrk& operator ++() ;
13 };
15 ostream& operator <<( ostream & out , const AgeMrk& amk) {
out << "Age : " << amk.Age <<
17 " Marks : " << amk.Marks << endl ;
return out;
19 }
21 AgeMrk:: AgeMrk(int ag , double mk) {
Age = ag;
23 Marks = mk;
}
25
AgeMrk& AgeMrk :: operator ++() {
27 ++ Age;
++ Marks;
29 return *this ;
}
31
int main () {
33 AgeMrk AgeMrk(10, 20);
cout << ++ AgeMrk;
35 return 0;
}
✌
✆
310 OOP in C++
✞
Age : 11 Marks : 21
✌
✆
The decrement operator overloading is done by using operator keyword as shown below
✞
1 operator --();
✌
✆
In the following example, use of - - operator overloading is explained.
✞
1 #include <iostream >
using namespace std;
3
class AgeMrk {
5 private:
int Age;
7 double Marks;
public:
9 friend ostream& operator <<( ostream &, const AgeMrk &);
AgeMrk(int , double); // constructor should be same
11 // name as of the class
AgeMrk& operator --() ;
13 };
15 ostream& operator <<( ostream & out , const AgeMrk& amk) {
out << "Age : " << amk.Age <<
17 " Marks : " << amk.Marks << endl ;
return out;
19 }
21 AgeMrk:: AgeMrk(int ag , double mk) {
Age = ag;
23 Marks = mk;
}
25
AgeMrk& AgeMrk :: operator --() {
27 --Age;
--Marks;
29 return *this ;
}
31
int main () {
33 AgeMrk AgeMark (11, 25);
cout << --AgeMark;
35 return 0;
}
✌
✆
✞
Age : 10 Marks : 24
✌
✆
4.2. CLASSES 311
[] Overloading
The opereator [] is used for array. For example, ‘int myA[10]’ represents an array of 10
integer element size. The [] operator can be overloaded for adding additional capabilities,
i.e. checking whether the array is overfloaded, or there is no element in the array etc. []
operator is overloaded by using operator keyword.
✞
1 <data type > &operator [](< parameters >)
✌
✆
See the following example.
✞
1 #include <iostream >
using namespace std;
3 const int SIZE = 10;
5 class myArr {
private :
7 int mArr [SIZE ]; // mArr of size 10
9 public:
myArr() { // constructor
11 register int i;
for(i = 0; i < SIZE ; i++) {
13 mArr [i] = i;
}
15 }
17 int &operator []( int i) { // overload [] operator
if( i > SIZE ) {
19 cout << "Index out of bounds" <<endl ;
return mArr [0];
21 }
return mArr [i];
23 }
};
25
int main () {
27 myArr A;
29 cout << "Value of A[2] : " << A[2] <<endl ;
cout << "Value of A[5] : " << A[5]<< endl ;
31 cout << "Value of A[12] : " << A[12]<< endl ;
33 return 0;
}
✌
✆
✞
Value of A[2] : 2
Value of A[5] : 5
Index out of bounds
Value of A[12] : 0
✌
✆
312 OOP in C++
4.2.13 Function Overloading
Member functions can be overloaded. Multiple member functions can exist with the
same name on the same scope, but must have different signatures, i.e. input arguments,
members etc. Constructors and other class member functions, except the destructor, can
be overloaded.
4.3 Object
Class is mere a blueprint or a template. They do not assign the value or create storage.
Objects are instances of class, which holds the data variables declared in class. Member
functions work on these class objects. Objects are initialised by using Constructors. If
object is failed to be created, Destructors is automatically called to release the memory
reserved by the object.
✞
#include <iostream >
2 using namespace std;
4 class MyClass {
public:
6 int x;
};
8 int main (int argc , char *argv []){
/* Object c is created for MyClass class*/
10 MyClass c;
c.x=2;
12 return 0;
}
✌
✆
The class object can also be created by using default value as shown in the following
example. Here, class is derived inside itself.
✞
1 #include <iostream >
using namespace std;
3
class MyClass {
5 int x;
int y;
7 public:
int z;
9 /* Initialize x and y data members *
* data members of the other class *
11 * are initialized by class calling */
MyClass (int i, int j) : x(i), y(j) {
13 cout << "x : " << x << ", y : " << y << endl ;
}
15 };
17 int main (int argc , char *argv []) {
/* Object c is created for MyClass class*/
4.3. OBJECT 313
19 MyClass c(1, 2); // Now value of x is set 1 and y is set 2
c.z = 2;
21 cout << "z : " << c.z << endl ;
return 0;
23 }
✌
✆
✞
x : 1, y : 2
z : 2
✌
✆
In the following example, data members of derived MyClass and inherited YourClass
are initialized by using derived class MyClass class and inherited YourClass privately by
MyClass class.
✞
#include <iostream >
2 using namespace std;
4 class YourClass {
public:
6 int k;
/* Initialize k data member of own class. */
8 YourClass (int f) : k(f) {
}
10 };
12 /* Inherit YourClass as private */
class MyClass : private YourClass {
14 int x;
int y;
16 public:
int z;
18
/* Initialize x and y data members of own class. *
20 * And k data member of inherited YourClass class.*/
MyClass (int i, int j, int k) : x(i), y(j), YourClass (k) {
22 cout << "x : " << x << ", y : " << y ;
cout << ", k : " << YourClass ::k << endl ;
24 }
};
26
int main (int argc , char *argv []) {
28 /* Object c is created for MyClass class*/
MyClass c(1, 2, 3); // Now value of x is set 1 and y is set 2
30 c.z = 2;
cout << "z : " << c.z << endl ;
32 return 0;
}
✌
✆
✞
x : 1, y : 2, k : 3
z : 2
✌
✆
314 OOP in C++
4.3.1 Casting
Casting is performed when a value (variable) of one data type is used in place of other
data type or to convert the type of an object, expression, function argument, or return
value to another type. It does not need any argument and does not has return type.
For example, to put the value of integer data type variable at double data type variable,
casting is performed as
✞
int i=2; // integer data type variable declared & initialized
2 double j=2; // double data type variable declared & initialized
double k=j/i; // integer i is casted as double and used
✌
✆
In C++, there are two types of castings, (i) implicit casting and (ii) explicit casting.
✞
1 int i=2; // integer data type variable declared & initialized
double j=i; // implicit casting
3 double k=( double) i; // explicit casting or forced casting
✌
✆
In casting, data of one data type is converted into data of other data type. Therefore,
there is loss of data. For example, if double data type is casted as integer data type, then
compiler shows warning.
✞
1 double i = 2.0; // double data type variable declared & initialized
int j = i; /* warning !! as double (8 bytes size ) is casted to *
3 *integer (4 bytes size ). Possible loss of data */
✌
✆
In case of referencing, implicit casting results in error, while explicit casting is acceptable.
✞
1 int i = 2; // integer data type variable declared & initialized
double j = 2.5; // double data type variable declared & initialized
3 double *k = &j; // explicit casting or forced casting
i = k; // error!! invalid conversion from ’double*’ to ’int’
5 i = (int) k;// explicit casting , acceptable
✌
✆
Implicit casting in unrelated classes is not permitted, while forced casting is accepted.
✞
1 class mA {
public:
3 int i;
}; // class mA
5
class mB {
7 public:
double d;
9 }; // class mB not related to mA
mA a;
11 mB b;
a = b; // error
13 a = (mA)b; // error
b = a; // error
15 b = (mB)a; // error
p = q; // error
4.3. OBJECT 315
17 q = p; // error
mA *p = &a; //OK , referencing instances of class mA
19 mB *q = &b; //OK , referencing instances of class mB
p = (mA*)&b; // OK , Forced casting of class mB into class mA with
reference
21 q = (mB*)&a; // OK , Forced casting of class mA into class mB with
reference
✌
✆
But force casting returns weird result. See the example below:
✞
1 #include <iostream >
using namespace std;
3
class mA {
5 public:
int i = 2;
7 }; // class mA
9 class mB {
public:
11 double d = 2.5;
}; // class mB not related to mA
13
int main () {
15 mA a;
mB b;
17 mA *p = &a; // class object
mB *q = &b; // class object
19 cout << p->i << " " << q->d << endl ;
p = (mA*) & b; // Forced casting
21 q = (mB*) & a; // Forced casting
cout << p->i << " " << q->d << endl ;
23 return 0;
}
✌
✆
✞
2 2.5
0 5.28382e-308
✌
✆
In hierarchy, casting is permitted with limited sense. There are two ways of casting in
hierarchical casting, (i) upward casting and (ii) downward casting. In upward casting,
derived class is casted into base class and in downward casting, base class is casted into
derived class. Downward casting is not permitted.
✞
#include <iostream >
2 using namespace std;
4 class mA {
public:
6 int i;
}; // class mA
316 OOP in C++
8
class mB : public mA {
10 public:
double d;
12 }; // class mB inherited to mA
14 int main () {
16 mA *a = 0;
mB *b = 0;
18 a = b; // OK , upward casting
b = a; // NOT OK , downward casting , error!! invalid conversion
20 return 0;
}
✌
✆
4.3.2 Binding
A class object is created by two ways, (i) static type and (ii) dynamic type. Static type of
the object is declared for the object while codes are written. The compiler sees the static
type objects. The dynamic type of the object is determined by the type of the object to
which it currently refers. Compiler does not sees the dynamic objects.
✞
1 #include <iostream >
using namespace std;
3
class mA {
5 public:
int i;
7 }; // class mA
9 class mB : public mA {
public:
11 double d;
}; // class mB inherited to mA
13
int main () {
15
mA *a; // Declared class object a as pointer
17 a = new mB; // Static type of a = mA
// Dynamic type of a = mB
19 return 0;
}
✌
✆
Static binding (i.e. early binding) is done at compile-time. Normal function calls, over-
loaded function calls, and overloaded operators are examples of static binding. Dynamic
binding (i.e. late binding) is done at run-time. Function pointers, Virtual functions are
examples of late binding. Binding is decided by the type of pointer if member functions
of the classes are not virtual. See the examples given below:
✞
#include <iostream >
4.3. OBJECT 317
2 using namespace std;
4 class mA {
public:
6
int sum(int i, int j) {
8 return (i + j);
}
10 }; // class mA
12 class mB : public mA {
public:
14
int sum(int i, int j) {
16 return (1 + i + j);
}
18 }; // class mB inherited to mA
20 int main () {
22 mA a; // Declared class object a
mB b; // Declared class object b
24 mA *p; // Declared class object b as pointer
p = &a;
26 cout << p->sum(2, 3) << endl ; // A:: sum()
p = &b;
28 cout << p->sum(2, 3) << endl ; // A:: sum()
return 0;
30 }
✌
✆
✞
5
5
✌
✆
Similarly, Binding is decided by the type of object if member functions of the base class
are virtual. Example for dynamic binding is given below:
✞
#include <iostream >
2 using namespace std;
4 class mA {
public:
6
virtual int sum(int i, int j) {
8 return (i + j);
}
10 }; // class mA
12 class mB : public mA {
public:
14
virtual int sum(int i, int j) {
318 OOP in C++
16 return (i + j + 1);
}
18 }; // class mB inherited to mA
20 int main () {
22 mA a; // Declared class object a
mB b; // Declared class object b
24 mA *p; // Declared class object b as pointer
p = &a;
26 cout << p->sum(2, 3) << endl ; // A:: sum()
p = &b;
28 cout << p->sum(2, 3) << endl ; // B:: sum()
return 0;
30 }
✌
✆
✞
5
6
✌
✆
From the above example, it is clear that dynamic binding is possible only for pointer and
reference data types and for member functions that are declared as virtual in the base
class. If a member function is declared as virtual, it can be overridden in the derived class.
If a member function is not virtual and it is re-defined in the derived class then the latter
definition hides the former one. A derived class non-virtual member function overriding
to a virtual member function of a base class is always virtual. A virtual member function
of derived class overriding to the non-virtual member function of base class is always
virtual. Virtual functions can be overrided by non-virtual function with same signature.
✞
#include <iostream >
2 using namespace std;
4 class mA {
public:
6
int sum(int i, int j) {
8 return (i + j);
}
10 }; // class mA
12 class mB : public mA {
public:
14
virtual int sum(int i, int j) {
16 return (i + j + 1);
}
18 }; // class mB inherited to mA
20 int main () {
mA a;
22 cout << a.sum(2, 3) << endl ; // B:: sum()
4.3. OBJECT 319
mB b;
24 cout << b.sum(2, 3) << endl ; // B:: sum()
return 0;
26 }
✌
✆
✞
5
6
✌
✆
The VTF of the class B shall be looked like
Object of mB
VFT
VFT
mB::sum(int, int)
0
The definition of override and overload has a bit differences. A function that is rede-
fined in derived class with or without same signature is known as overriding. Overloading
word is used when a function is redefined with different number of parameters or with
different signature. For example,
✞
class B {
2 protected :
int var;
4 public:
void print() {
6 cout << var << endl ;
}
8 };
10 class D : protected B {
double dvar ;
12 public:
14 void print() {// overriding to base print()
cout << var << " ";
16 }
18 void print(D& a) {// overriding and overloading to base print()
cout << a.var << " " << a.dvar << " ";
20 }
};
✌
✆
The ‘print()’ function is overriding and overloading in the derived class to the function
‘print()’ of base class.
4.3.3 Cast Operators
In C++ there are four types of cast operators:
320 OOP in C++
const cast
It is used like
✞
1 const_cast <new type >(< expression >)
✌
✆
It overrides const and/or volatile data-types. It does not allow to change the value. Only
const cast may be used to cast away (remove) const-ness or volatility.
✞
1 #include <iostream >
using namespace std;
3
class B {
5 int j;
public:
7 // Constructor of class B
9 B(int i) : j(i) {
}
11 // Get the value of j
13 void get() const {
cout << j << endl ;
15 }
// Set the value of j
17
void set(int i) {
19 j = i;
}
21 };
// print string
23 void print(char * str) {
cout << str << endl ;
25 }
27 int main () {
// Constant character string
29 const char * c = "sample text ";
print(const_cast <char *> (c));
31 // Create instance for class B by pas -by -value method
const B b(1);
33 // Call the get() function
b.get ();
35 // Cast class B to class B&
const_cast <B&> (b).set (5);
37 // Call the get() function
b.get ();
39 return 0;
}
✌
✆
✞
sample text
4.3. OBJECT 321
1
5
✌
✆
static cast
It is used like
✞
1 static_cast <new type >(< expression >)
✌
✆
It performs a non-polymorphic cast. It is used in computation of changed values either
by implicitly or user defined. Following is an example in which, a variable of double data
type is casted into integer data type.
✞
1 #include <iostream >
using namespace std;
3
int main () {
5 int i = 2;
double d = 3.7;
7 i = (int) d;
cout << i << endl ;
9 /* static_cast converts the variable d into int *
*data type and assigns the result to variable i*/
11 i = static_cast <int > (d);
cout << i << endl ;
13
return 0;
15 }
✌
✆
✞
3
3
✌
✆
Classes can also be cast from one class type to other class type. See the example given
below:
✞
#include <iostream >
2 using namespace std;
4 class A {};
6 class B : public A {};
8 int main () {
A a;
10 B b;
// Up cast , derived class in casts as base class
12 A *p = &b; // implicit -- okay
p = static_cast <A*> (&b); // static_cast -- okay
14 p = (A*) &b; //OK as it is explicit
322 OOP in C++
// Down cast , base class in casts as derived class
16 B *q = &a; // error as it is implicit
q = static_cast <B*> (&a); // static_cast -- okay
18 q = (B*) & a; // OK as it is explicit
return 0;
20 }
✌
✆
In hierarchy, static cast, implicit cast and explicit cast are allowed in upward casting as
shown in the code lines
✞
A a;
2 B b;
// Up cast , derived class in casts as base class
4 A *p = &b; // implicit -- okay
p = static_cast <A*> (&b); // static_cast -- okay
6 p = (A*) &b; //OK as it is explicit
✌
✆
While implicit cast in downward casting is not allowed.
✞
A a;
2 B b;
// Down cast , derived class in casts as base class
4 B *q = &a; // error as it is implicit
q = static_cast <B*> (&a); // static_cast -- okay
6 q = (B*) & a; // OK as it is explicit
✌
✆
Unrelated classes are those classes which do not inherited to each other. For example
✞
class A{};
2 class B{};
✌
✆
both are unrelated as they do not inherited mutually. Consider the example as given below
for unrelated classes in which class B is casted from class A by constructor method.
✞
#include <iostream >
2 using namespace std;
4 class A {
int i;
6 public:
// create constructor for class A
8 A(int ai) : i(ai) {
}
10
// return value of i
12 int get () const {
return i;
14 }
};
16
class B {
4.3. OBJECT 323
18 int i;
public:
20 // create constructor for class B
B(int ai) : i(ai) {
22 }
24 // return value of i
int get () const {
26 return i;
}
28
/* matching function conversion of *
30 *class A to class B, i.e. A ==> B*/
B(const A&) { }// conversion from A (constructor )
32 };
34 int main () {
A a(1);
36 B b(2);
/* static conversion of class *
38 *A to class B, i.e. A ==> B */
const B &r = static_cast <B> (a);
40 cout << a.get() << endl ;
cout << b.get() << endl ;
42 cout << r.get() << endl ;
return 0;
44 }
✌
✆
✞
1
2
2293744
✌
✆
In static casting, a matching function for conversion of class A to class B, i.e. A ⇒ B
shall be defined inside the class B. Similarly, integers is cast into class B as shown in the
following example:
✞
1 #include <iostream >
using namespace std;
3
class A { };
5
class B {
7 int i = 1;
public:
9
// return value of i
11 int get () const {
return i;
13 }
15 /* matching function conversion of *
324 OOP in C++
*int i to class B, i.e. i ==> B*/
17 B(int ai = 1) {
}
19 };
21 int main () {
int i;
23 B b;
/* static conversion of integer*
25 *i to class B, i.e. i ==> B */
const B &r = static_cast <B> (i);
27 cout << b.get() << endl ;
cout << r.get() << endl ;
29 return 0;
}
✌
✆
✞
1
1
✌
✆
To cast a class into an integer data type, the integer is overloaded by using keyword
operator as shown in the following example.
✞
#include <iostream >
2 using namespace std;
4 class A {
};
6
class B {
8 int i;
public:
10 // create constructor for class B
B(int ai) : i(ai) {
12 }
14 // return value of i
int get () const {
16 return i;
}
18
/* matching function conversion of *
20 *class A to integer , i.e. i ==> B*/
operator int() {
22 }
};
24
int main () {
26 int i = 2;
B b(2);
28 /* static conversion of class *
*B to integer i, i.e. B ==> i */
4.3. OBJECT 325
30 const B &r = static_cast <int > (b);
cout << b.get() << endl ;
32 cout << r.get() << endl ;
return 0;
34 }
✌
✆
✞
2
2293584
✌
✆
The keyword operator may also be used with classes as shown in the following example
in which class B is casted to class A by type-cast method.
✞
#include <iostream >
2 using namespace std;
4 class A {
int i;
6 public:
8 // create constructor for class A with default value 3
A(int ai = 3) : i(ai) {
10 cout << ai << endl ;
}
12 };
14 class B {
public:
16 // conversion to A (type -cast operator )
operator A() {
18 return A();
}
20 };
22 int main () {
B b;
24 /* static conversion of class *
*B to class A, i.e. B ==> A */
26 const A &r = static_cast <A> (b); // B:: operator A()
return 0;
28 }
✌
✆
✞
3
✌
✆
In static casting, it can be explicitly call a single-argument constructor or a conversion
operator to handle the casting between two unrelated classes.
✞
1 #include <iostream >
using namespace std;
3
class A {
326 OOP in C++
5 int i;
public:
7 A(int ai) : i(ai) { }
int get () const {
9 return i;
}
11 };
13 class B {
int i;
15 public:
B(int ai) : i(ai) { }
17 int get () const {
return i;
19 }
/* conversion from A (assignment ) *
21 * to a single -argument constructor */
B(A& a) : i(a.get()) {}
23 // conversion to A (type -cast operator )
operator A(){return A(i);}
25 };
27 int main () {
int i=2;
29 A a(2);
B b(3);
31 const B &r = static_cast <B> (a);
cout << a.get() << ":";
33 cout << r.get() << ":";
return 0;
35 }
✌
✆
✞
2:2:
✌
✆
reinterpret cast
It is used like
✞
1 reinterpret_cast <new type >(< expression >)
✌
✆
It casts between unrelated pointer types or pointer and integer. It does not perform
computation yet reinterprets value. It can convert any class object pointer to any other
class object pointer.
✞
1 #include <iostream >
using namespace std;
3 int main (){
5 float a = 12;
int b = *reinterpret_cast <int*>(& a);
4.3. OBJECT 327
7 cout << b;
return 0;
9 }
✌
✆
✞
1094713344
✌
✆
In above example, reinterpret cast takes the address of ‘a’, reinterpret it into an int* and
get back an int* that points to ‘a’. Deference value is returned to pointer as integer value.
The float value of ‘a’ is recast as integer. This is why, the output in above example is not
12 as desired.
dynamic cast
It is used like
✞
1 dynamic_cast <new type >(< expression >)
✌
✆
It performs a run-time cast that verifies the validity of the cast. It also performs pre-
defined computation, sets null or throws exception. Dynamic cast can only be used with
pointers and references to the classes (or with void*). Its purpose is to ensure that the
result of the type conversion points to a valid complete object of the destination pointer
type.
✞
1 #include <iostream >
using namespace std;
3
class B {
5 public:
7 virtual void func () {
}
9 };
11 class D : public B {
};
13
int main () {
15 B b;
D *d = dynamic_cast <D*> (b);// Error !! Source is not a pointer
17 //D *d = dynamic_cast <D*> (&b);// Allowed
if (d != NULL )
19 cout << 1;
else
21 cout << "Error";
return 0;
23 }
✌
✆
This naturally includes pointer upcast, implicit conversion and downcast of polymorphic
classes iff the pointed object is a valid complete object of the target type. If the pointed
object is not a valid complete object of the target type, dynamic cast returns a null
328 OOP in C++
pointer. If dynamic cast is used to convert to a reference type and the conversion is not
possible, an exception of type bad cast is thrown.
✞
1 #include <iostream >
using namespace std;
3
class B {
5 };
7 class D : public B {
};
9
int main () {
11 B *b = new D;
/* Conversion of base class to*
13 *derived class , ie down cast */
D *d = dynamic_cast <D*> (b);
15 if (d != NULL )
cout << 1;
17 else
cout << "Error!!";
19 return 0;
}
✌
✆
In above example, there is error as we try to downcast and base class has no virtual
function (ie downcast without polymorphism). In the following example, base class is
added a virtual function and in this case downcast conversion by dynamic cast is possible.
✞
#include <iostream >
2 using namespace std;
4 class B {
public:
6
virtual void func () {
8 }
};
10
class D : public B {
12 };
14 int main () {
B *b = new D;
16 D *d = dynamic_cast <D*> (b);
if (d != NULL )
18 cout << 1;
else
20 cout << "Error";
return 0;
22 }
✌
✆
4.4. TEMPLATES 329
✞
1
✌
✆
4.4 Templates
Assume functions with same name but of different signatures as given below:
✞
1 int myFunc(int x){
return x;
3 }
double myFunc(double x){
5 return x;
}
✌
✆
These functions have a unique structure as given below:
✞
<return type > <function name >(< parameter type > <var >){
2 <statements >
}
✌
✆
A template is a class or a function that serves the above purpose. A template for above
functions has syntax like
✞
1 template <class T> // T stands for any type
T myFunc(T x){
3 return x;
}
✌
✆
In above example, the less than and greater than symbol after the template keyword are
internal part of program structure and they can not be replaced. The class type, i.e.
datatype is represented by ‘T’ and it is automatically selected by the compiler according
to the parameter datatype. The ‘class type’ are int, double, class, string, array etc.
✞
#include <iostream >
2 using namespace std;
4 template <class T>
T myFunc(T x) {
6 return x;
}
8
int main () {
10 double x = 10.12;
cout << myFunc(x) << endl ;
12 int y = 10.12;
cout << myFunc(y) << endl ;
14 return 0;
}
✌
✆
330 OOP in C++
✞
10.12
10
✌
✆
Templates can be overloaded.
✞
template <class T>
2 T myFunc(T x){
return x;
4 }
template <class T> // Overloaded
6 T myFunc(T x, T y){
return x+y;
8 }
✌
✆
✞
#include <iostream >
2 using namespace std;
4 template <class T>
T myFunc(T x) {
6 return x;
}
8
template <class T>
10 T myFunc(T x, T y) {
return x + y;
12 }
14 int main () {
cout << myFunc (10.12) << endl ;
16 cout << myFunc(10, 20) << endl ;
return 0;
18 }
✌
✆
✞
10.12
30
✌
✆
The data qualifiers can be used accordingly as and when required. See the example below:
✞
#include <iostream >
2 using namespace std;
4 template <typename T>
T const &Max(T const &a, T const &b) {
6 return a < b ? b : a;
}
8
int main (int argc , char *argv []) {
10 cout << "Max(45, 74) : " << Max(45, 74) << endl ;
return 0;
4.4. TEMPLATES 331
12 }
✌
✆
✞
Max(45, 74) : 74
✌
✆
This program shall run similar to the following one:
✞
1 #include <iostream >
using namespace std;
3
template <typename T>
5 T Max(T a, T b) {
return a < b ? b : a;
7 }
9 int main (int argc , char *argv []) {
cout << "Max(45, 74) : " << Max(45, 74) << endl ;
11 return 0;
}
✌
✆
✞
Max(45, 74) : 74
✌
✆
For a template class, template keyword tells the compiler that the class definition that
follows will manipulate one or more unspecified types. At the time the actual class code
is generated from the template, those types must be specified so that the compiler can
substitute them. A template class is declared as
✞
1 template < class class_name >//< and > are part of program
class <class name > {
3 T <variable >;
public:
5 T <statements >;
};
✌
✆
See the example below:
✞
#include <iostream >
2 using namespace std;
4 template < class T=int , class U=int >
class Test {
6 T x; U y;
public:
8 Test (T t, U u): x(t), y(u) { }
void display () { cout << x << "," << y << endl ;}
10 };
int main () {
12 Test <char , char >b(’a’, ’b’);
b.display ();
14 Test < >c(’a’, 12.9);
c.display ();
332 Miscellaneous
16 return 0;
}
✌
✆
✞
a,b
97,12
✌
✆
✞
#include <iostream >
2 using namespace std;
template <class T> void display(T x) {
4 cout << x << " ";
}
6
template <class T, class U> void display (T x, U y) {
8 cout << x << " " << y << endl ;
}
10 int main () {
double d=1.5;
12 int i=2;
char c=’a’;
14 display (c);
display (i, d);
16 display (c, d);
return 0;
18 }
✌
✆
✞
a 2 1.5
a 1.5
✌
✆
5.1. ERRORS 333
5Miscellaneous
5.1 Errors
A program written by a programmer should be in order of the rules of the programming
language. If any code line of code is outside of the set rules of the languages, compiler
shows errors specifying the position of code line and type of error.
5.1.1 Exception Handling
An exception is a problem that arises during the execution of a program. A C++ excep-
tion arises when a non-acceptable event is created. For example, division of a number by
zero is not acceptable. At this case, C++ throws an exception. C++ has an exception
class in standard library. We can write a user defined exception by overriding exception
class. To handle an exception, there are three keywords, throw, catch and try.
throw A program throws an exception when a problem shows up using throw keyword.
The throws value is catched by following catch keyword.
catch A program catches an exception with an exception handler. It is done by catch
keyword.
try A try block identifies a block of code for which particular exceptions will be
activated. Each try block should be followed by at least catch block.
✞
try{
2 <statements >
}catch(<exception name > <handle >){
4 <statements >
}
✌
✆
Exceptions is throw from anywhere within a code block using throw statements. For
example
✞
1 void myFunc () {
<condition >
3 throw <message / message id >;
}
✌
✆
Each exception is catched in catch block. Each catch block should be preceded by try
block.
✞
try{
2 <statements >
}catch(<exception name > <handle >){
334 Miscellaneous
4 <statements >
}
✌
✆
✞
1 #include <iostream >
using namespace std;
3
int main () {
5 char c = ’c’;
try {
7 cout << "Try & throw c" << endl ;
throw c;
9 } catch (char c) {
cout << "Caught " << c << endl ;
11 }
13 return 0;
}
✌
✆
✞
Try & throw c
Caught c
✌
✆
The catch block following the try block catches any exception. Codes which handle any
exception should be inside the catch block. Each throw is catched by the following catch
block.
✞
#include <iostream >
2 using namespace std;
4 int main () {
try {
6 try {
throw 78.9; // throw 1
8 } catch (int n) {// catch throw 1
cout << "Locally Handle " << ’n’;
10 throw; // throw 2
}
12 } catch (int n) {// catch throw 2
cout << "Handle in the outer loop " << ’n’;
14 } catch (...) {
cout << "default ";
16 return 0;
}
18 return 0;
}
✌
✆
✞
Locally Handle
Handle in the outer loop
✌
✆
5.1. ERRORS 335
C++ has a list of standard exceptions defined in ‘exception’ class. The list of exceptions
is given in following table:
Exception Description
std::exception An exception and parent class of all the standard
C++ exceptions.
std::bad alloc An exception thrown by new.
std::bad cast An exception thrown by dynamic cast.
std::bad exception It handles the unpredictable exceptions.
std::bad typeid An exception thrown by type id.
std::logic error An exception that is detected by reading the codes.
std::domain error An exception thrown when a mathematically invalid
domain is used.
std::invalid argument An exception thrown due to invalid arguments.
std::length error An exception thrown when a too big string is created.
std::out of range It is thrown when a vector or list is used.
std::runtime error An exception that can not be detected by reading
the codes.
std::overflow error This is thrown if a mathematical overflow occurs.
std::range error Exception, occurs when out of range value is stored.
std::underflow error This is thrown if a mathematical underflow occurs.
We can also create our own exception by inheriting and overriding ‘exception’ class.
User defined exception are declared as
✞
struct <exception name > : public exception {
2 const char * <excep member func > const throw () {
return <thrown message >;
4 }
};
✌
✆
The example of the user defined exception is given below:
✞
1 #include <iostream >
/* Standard exception header file .*/
3 #include <exception >
using namespace std;
5
struct DivByZero : public exception {
7
const char * noDiv() const throw () {
336 Miscellaneous
9 return "Division by zero is not acceptable !!";
}
11 };
13 int main (int argc , char ** argv ) {
try {
15 /* Throw the user defined exception */
throw DivByZero ();
17 } catch (DivByZero & ex) {/* Catch the exception */
/* Show what we caught.*/
19 cout << "Division exception caught!!" << endl ;
/* Show what system thrown*/
21 cout << ex.noDiv() << endl ;
}
23 }
✌
✆
✞
Division exception caught !!
Division by zero is not acceptable !!
✌
✆
We can raise the exceptions through the function call. The raised exception is caught by
catch clause.
✞
#include <iostream >
2 #include <exception >
using namespace std;
4
class myExc : public exception {//
6
virtual const char * what () const throw() {
8 return "Divide By Zero ";
}
10 };
12 class DivideByZero {
public:
14 int num , den;
DivideByZero (int a = 0, int b = 0) : num(a), den(b) {}
16 int divide(int num , int den){
if (den == 0) {
18 throw myExc();
}
20 return (num / den);
}
22 };
24 int main () {
26 DivideByZero d;
28 try {
d.divide(1, 0);
5.1. ERRORS 337
30 }catch (exception & e) {
cout << e.what () << endl ;
32 }
34 return 0;
}
✌
✆
Multiple catches for same try function can be used. See the example below:
✞
1 #include <iostream >
using namespace std;
3
void myFunction (int test ) {
5 try {
if (test )
7 throw test ;
else
9 throw "Value is zero ";
}
11
catch (int i) {
13 cout << "CaughtOne ";
}
15
catch (const char *str) {
17 cout << "CaughtString ";
}
19 }
int main () {
21 myFunction (-3);
myFunction (0);
23 return 0;
}
✌
✆
✞
CaughtOne CaughtStrin
✌
✆
5.1.2 Error Type
In a programming language, errors are classified as :
Compile Time Error A compile time error is the error which arises when a compiler
compiles the program. Compile time errors are mostly related to syntax, procedure and
functions.
Run Time Error Run time error is the error which arises when a program run. A
program which stores the time stamp or time validity shown the run time error if the
program is run after expiry of the time.
Logical or Semantic Error This type of error arises in the program when it runs
successfully but suffers mismanagement in memory and stack logic. For example, if an
338 Miscellaneous
array is of size n and programmer tries to put the n + 1 elements then program shows
errors.
5.1.3 Exception Specification
C++ provides a syntax which helps users to diagnose errors and exceptions thrown by a
function. This syntax is throw. A function can be defined with throw as given below:
✞
1 <func type > <func name > throw(<exp func 1>, <exp func 2>, ...) ;
✌
✆
Without throw, the above function is purely a traditional function without throwing any
exception. See example below:
✞
1 #include <iostream >
using namespace std;
3
class Up {
5 };
7 class Down {
};
9
void callFunc (int i) throw (Up , Down ) {
11 switch (i) {
case 1: throw Up ();
13 break;
case 2: throw Down ();
15 break;
}
17 }
19 int main (int argc , char ** argv ) {
for (int i = 1; i <= 3; i++) {
21 try {
callFunc (i);
23 } catch (Up) {
cout << i << ": Up caught" << endl ;
25 } catch (Down ) {
cout << i << ": Down caught" << endl ;
27 }
}
29 return 0;
}
✌
✆
✞
1: Up caught
2: Down caught
✌
✆
The classes Up and Down are created solely to throw as exceptions. Often exception
classes can hold additional information for depth querying.
5.2. WRAPPING C & C++ 339
✞
#include <iostream >
2 using namespace std;
4 class Up {
public:
6
virtual void what () {
8 cout << "UP" << endl ;
}
10 };
12 class Down {
public:
14
virtual void what () {
16 cout << "DOWN " << endl ;
}
18 };
20 void callFunc (int i) throw (Up , Down ) {
switch (i) {
22 case 1: throw Up ();
break;
24 case 2: throw Down ();
break;
26 }
}
28
int main (int argc , char ** argv ) {
30 for (int i = 1; i <= 3; i++) {
try {
32 callFunc (i);
} catch (Up up) {
34 up.what ();
} catch (Down down ) {
36 down .what ();
}
38 }
return 0;
40 }
✌
✆
✞
UP
DOWN
✌
✆
5.2 Wrapping C & C++
extern keyword is used to link external files in C++ program. To link a .h header file in
C++. we declared extern function as
340 Miscellaneous
✞
extern "C"{
2 #include <math .h>
}
✌
✆
See the example below:
✞
1 #include <iostream >
using namespace std;
3
extern "C"{
5 #include <math .h>
}
7 int main (int argc , char ** argv ) {
cout << sin (3.14) << endl ;
9 return 0;
}
✌
✆
✞
0.00159265
✌
✆
We can also link the multiple languages single by single or in nested form by using extern
keyword.
✞
1 extern "C" {
void myF(); /* C linkage */
3 extern "C++" {
void myG(); /* C++ linkage */
5 extern "C" void myH(); /* C linkage */
}
7 void m(); /* C linkage */
}
✌
✆
IT is common requirement of calling C functions from C++. In thies case, C function
should be defined as extern “C”. Otherwise, the linker won’t be able to locate the C
function. To make a header suitable for both C and C++ compilers, all the declarations
are put inside extern “C” brackets, but the C compiler does not recognize this syntax.
Every C++ compiler predefined the macro cplusplus, so we can use that macro to guard
the C++ syntax :
✞
#ifdef __cplusplus /* Begin definition */
2 extern "C" { /* extern C begin */
#endif
4 <body of header statement >
#ifdef __cplusplus
6 } /* extern C closed */
#endif /* End definition */
✌
✆
See the example
✞
1 #include <iostream >
5.3. CODING STYLE 341
using namespace std;
3
#ifdef __cplusplus
5 extern "C" {
#endif
7 #include <math .h>
#ifdef __cplusplus
9 }
#endif
11
int main (int argc , char ** argv ) {
13 cout << sin (3.14) << endl ;
return 0;
15 }
✌
✆
✞
0.00159265
✌
✆
We can access the C++ code from C. See the example below:
✞
1 #include <iostream >
using namespace std;
3
extern "C" int print(int i, double d) {
5 cout << "i = " << i << ", d = " << d << endl ;
}
7
int main (int argc , char ** argv ) {
9 print(3, 14.2);
return 0;
11 }
✌
✆
✞
i = 3, d = 14.2
✌
✆
5.3 Coding Style
5.3.1 Reserved Keyword
There are some keywords which are solely reserved for internal use by C++. They can
not be redefined by programmer. These keywords also can not be overloaded. The list of
reserved keywords is given in below table.
342 Miscellaneous
and compl export namespace return try char16 t
and eq const extern new short typedef char32 t
asm const cast false not signed typeid constexpr
auto continue float not eq sizeof typename decltype
bitand default for operator static union noexcept
bitor delete friend or static cast unsigned nullptr
bool do goto or eq struct using static assert
break double if private switch virtual thread local
case dynamic cast inline protected template void wchar t
catch else int public this volatile while
char enum long register throw alignas xor
class explicit mutable reinterpret cast true alignof xor eq
Operator
Type Id The typeid operator allows the type of an object to be determined at run
time. The result of typeid is a
✞
1 const type_info &
✌
✆
The value is a reference to a type info object that represents either the type-id or the type
of the expression, depending on which form of typeid is used. The typeid operator does
not work with managed types (abstract declarators or instances). The typeid operator
does a run-time check when applied to an l-value of a polymorphic class type, where the
true type of the object cannot be determined by the static information provided. Such
cases are:
1. A reference to a class
2. A pointer, dereferenced with *
3. A sub-scripted pointer (i.e. [ ])
✞
1 #include <iostream >
#include <typeinfo >
3 using namespace std;
5 class A {
public:
7
virtual ~A() {
9 }
};
11
class B : public A {
13 };
15 int main () {
A a;
5.3. CODING STYLE 343
17 A *b = new A();
cout << typeid (a).name () << ": " << typeid (&a).name () << endl ;
19 cout << typeid (b).name () << ": " << typeid (*b).name () << endl ;
return 0;
21 }
✌
✆
✞
1A: P1A
P1A: 1A
✌
✆
constexpr
decltype
nullptr
thread local
this
typename
5.3.2 Case Sensitivity
C++ identifiers are case sensitive i.e. myname, MYNAME, and MyName are the names
of three different objects. Some linkers may map external identifiers to a single case,
although this is uncommon in most modern linkers. See the following example, in which
two variables ‘y’ and ‘Y’ are declared and initialized. They are treated as two different
variables and can be accessed differently.
✞
#include <iostream >
2 using namespace std;
4 int main (int argc , char *argv []) {
// Declare a variable y
6 int y = 1;
// Declare a variable Y
8 int Y = 2;
cout << "y is " << y << " and Y is " << Y;
10 return 0;
}
✌
✆
✞
y is 1 and Y is 2
✌
✆
5.3.3 Commenting
Commenting inside the C++ code is a beautiful feature of C++ language. It provides the
utility for writing managed codes. Commenting occurs within the C++ codes. It may be
of a single line or can span in multiple lines. There are two way of commenting. First is
344 C++ Standards
single line commenting which started with ‘//’. Anything written in the line started with
‘//’ are skipped by the C++ compilers. Presence of another ‘//’ in the same line does
not end the single line comment. Second method is multiline commenting. Text starting
with the token ‘/*’ are treated as a comments and ignored. The multiline comments are
ended at next token ‘*/’.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 // Declare a variable // as y
int y;
7 /* <-- given expression *
*y = (5 + 3 - 4) % 2 *
9 *is computed in steps*
*y = (8 - 4) % 2 *
11 *y = 4 % 2 = 0 -->*/
y = (5 + 3 - 4) % 2;
13 cout << "Result is : << y;
return 0;
15 }
✌
✆
✞
Result is : 0
✌
✆
6.1. C++14 345
6C++ Standards
6.1 C++14
C++11 allowed lambda functions to deduce the return type based on the type of the
expression given to the return statement. C++14 provides this ability to all functions.
To induce return type deduction, the function must be declared with auto as the return
type, but without the trailing return type specifier in C++11:
✞
1 auto DeduceReturnType (); /* Return type to be determined */
✌
✆
If there are multiple return expressions then they all must be deduce the same type.
Recursion can be used to a function of this type, but the recursive call must happen after
at least one return statement in the definition of the function:
✞
1 auto myF(int i) {
if (i == 1){
3 return i; /* return type deduced as int*/
}else {
5 /* Good & OK as there is prior return*/
return myF(i-1)+i;
7 }
}
✌
✆
✞
#include <iostream >
2 using namespace std;
4 int myF(int i) {
if (i == 1) {
6 return i; /* return type deduced as int*/
} else {
8 /* Good & OK as there is prior return*/
return myF(i - 1) + i;
10 }
}
12
int main (int argc , char *argv []) {
14 cout << "myF (1) = " << myF (1) << endl ;
cout << "myF (2) = " << myF (2) << endl ;
16 cout << "myF (3) = " << myF (3) << endl ;
return 0;
18 }
✌
✆
346 C++ Standards
✞
myF (1) = 1
myF (2) = 3
myF (3) = 6
✌
✆
✞
1 auto myF(int i) {
if (i == 1){
3 /* Bad & Not OK as there is no prior return */
return myF(i-1)+i;
5 }else {
return i; /* return type deduced as int*/
7 }
}
✌
✆
✞
#include <iostream >
2 using namespace std;
4 int myF(int i) {
if (i == 1) {
6 /* Bad & Not OK as there is no prior return */
return myF(i - 1) + i;
8 } else {
return i; /* return type deduced as int*/
10 }
}
12
int main (int argc , char *argv []) {
14 cout << "myF (1) = " << myF (1) << endl ;
cout << "myF (2) = " << myF (2) << endl ;
16 cout << "myF (3) = " << myF (3) << endl ;
return 0;
18 }
✌
✆
✞
myF (1) = 1
myF (2) = 2
myF (3) = 3
✌
✆
Before C++14, only functions, classes or type aliases could be templates. In C++14, we
can create the variables as templates.
✞
1 template < typename T>
constexpr T pi = T (3.141592653589793238462643383);
✌
✆
Numeric literals in C++14 can be specified in binary form. The syntax uses the prefixes
0b or 0B.
✞
#include <iostream >
2 using namespace std;
6.1. C++14 347
4 int main (int argc , char *argv []) {
int i = 0b1000;
6 cout << i << endl ;
return 0;
8 }
✌
✆
✞
8
✌
✆
Hexadecimal form of assignment of number to a variable is given in following example.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 int i = 0x1000;
cout << i << endl ;
7 return 0;
}
✌
✆
✞
4096
✌
✆
Octal form of assignment of number to a variable is given in following example.
✞
1 #include <iostream >
using namespace std;
3
int main (int argc , char *argv []) {
5 int i = 01000;
cout << i << endl ;
7 return 0;
}
✌
✆
✞
512
✌
✆
In C++14, the single-quote character may be used arbitrarily as a digit separator in
numeric literals, both integer literals and floating point literals. In C++11, lambda
function parameters need to be declared with concrete types. C++14 allows lambda
function parameters to be declared with the auto type specifier.
✞
1 auto lambda = []( auto x, auto y) {return x + y;};
✌
✆
As for auto type deduction, generic lambdas follow the rules of template argument de-
duction.
✞
1 struct unnamed_lambda {
template <typename T, typename U>
3 auto operator ()(T x, U y) const { return x + y;}
};
5 auto lambda = unnamed_lambda {};
✌
✆
348 C++ Standards
The deprecated attribute allows marking an entity deprecated, which shows warning at
the time of code compilation. C++14 extends to allow fetching from a tuple by type
instead of by index. If the tuple has more than one element of the type, a compile-time
error results:
✞
1 tuple <string , string , int > t("foo", "bar", 7);
int i = get <int >(t); /* i == 7 */
3 int j = get <2>(t); /* Same as before: j == 7 */
/* Compile -time error due to ambiguity */
5 string s = get <string >(t);
✌
✆

More Related Content

PDF
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
PDF
c programming
PDF
c programming
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
PPTX
Unit 3
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
c programming
c programming
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Unit 3
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...

What's hot (20)

PDF
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
DOC
C tech questions
PPTX
C++ Pointers
DOCX
C interview question answer 2
PDF
C++ L05-Functions
PDF
Recursion to iteration automation.
PPT
Fp201 unit5 1
PDF
C++ L07-Struct
PDF
C++ L06-Pointers
PDF
C++ L04-Array+String
PDF
Array notes
PDF
C++ L03-Control Structure
PDF
Container adapters
PDF
Stl algorithm-Basic types
PDF
C++ Programming - 11th Study
DOCX
Arrry structure Stacks in data structure
PPTX
functions of C++
PDF
C++ L01-Variables
PDF
C++ L08-Classes Part1
PDF
Polymorphism
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
C tech questions
C++ Pointers
C interview question answer 2
C++ L05-Functions
Recursion to iteration automation.
Fp201 unit5 1
C++ L07-Struct
C++ L06-Pointers
C++ L04-Array+String
Array notes
C++ L03-Control Structure
Container adapters
Stl algorithm-Basic types
C++ Programming - 11th Study
Arrry structure Stacks in data structure
functions of C++
C++ L01-Variables
C++ L08-Classes Part1
Polymorphism
Ad

Similar to Introduction to cpp (c++) (20)

PPT
Lecture#5-Arrays-oral patholohu hfFoP.ppt
PDF
C++ Nested loops, matrix and fuctions.pdf
PDF
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...
PPT
Lecture#8 introduction to array with examples c++
PPTX
week14Pointers_II. pointers pemrograman dasar C++.pptx
PPT
Arrays
PDF
C++ practical
PPTX
Computer Programming for Engineers Spring 2023Lab 8 - Pointers.pptx
PDF
PPS SSSSHHEHESHSHEHHEHAKAKHEHE12131415.pdf
PPTX
Dynamic Objects,Pointer to function,Array & Pointer,Character String Processing
PDF
a) Write the recursive function in C++ to sort a set of data using M.pdf
DOC
Oops lab manual2
PPTX
2- Dimensional Arrays
PPTX
Lecture 9_Classes.pptx
PPTX
Lab 13
PPTX
C++ lectures all chapters in one slide.pptx
DOCX
C++ file
DOCX
C++ file
DOCX
#include stdafx.h using namespace std; #include stdlib.h.docx
PPT
Arrays in c programing. practicals and .ppt
Lecture#5-Arrays-oral patholohu hfFoP.ppt
C++ Nested loops, matrix and fuctions.pdf
booksoncprogramminglanguage-anintroductiontobeginnersbyarunumrao4-21101016591...
Lecture#8 introduction to array with examples c++
week14Pointers_II. pointers pemrograman dasar C++.pptx
Arrays
C++ practical
Computer Programming for Engineers Spring 2023Lab 8 - Pointers.pptx
PPS SSSSHHEHESHSHEHHEHAKAKHEHE12131415.pdf
Dynamic Objects,Pointer to function,Array & Pointer,Character String Processing
a) Write the recursive function in C++ to sort a set of data using M.pdf
Oops lab manual2
2- Dimensional Arrays
Lecture 9_Classes.pptx
Lab 13
C++ lectures all chapters in one slide.pptx
C++ file
C++ file
#include stdafx.h using namespace std; #include stdlib.h.docx
Arrays in c programing. practicals and .ppt
Ad

More from Arun Umrao (20)

PDF
maths_practice_sheet_28.12.23 (copy).pdf
PDF
Function Analysis v.2
PDF
Average value by integral method
PDF
Xcos simulation
PDF
Work and energy
PDF
Units of physical quantities
PDF
Scilab help book 2 of 2
PDF
Scilab help book 1 of 2
PDF
Notes of Java
PDF
Modelica programming help book
PDF
Measurements and errors
PDF
Linear motion for k12 students
PDF
Gnu octave help book 02 of 02
PDF
Gnu octave help book 01 of 02
PDF
Fortran programming help book
PDF
Force and its application for k12 students
PDF
Electric field for k12 student
PDF
Dictionary of physics
PDF
Decreasing and increasing function
PDF
Circular motion
maths_practice_sheet_28.12.23 (copy).pdf
Function Analysis v.2
Average value by integral method
Xcos simulation
Work and energy
Units of physical quantities
Scilab help book 2 of 2
Scilab help book 1 of 2
Notes of Java
Modelica programming help book
Measurements and errors
Linear motion for k12 students
Gnu octave help book 02 of 02
Gnu octave help book 01 of 02
Fortran programming help book
Force and its application for k12 students
Electric field for k12 student
Dictionary of physics
Decreasing and increasing function
Circular motion

Recently uploaded (20)

PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
ai tools demonstartion for schools and inter college
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
System and Network Administraation Chapter 3
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
history of c programming in notes for students .pptx
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
medical staffing services at VALiNTRY
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
top salesforce developer skills in 2025.pdf
PDF
Nekopoi APK 2025 free lastest update
Which alternative to Crystal Reports is best for small or large businesses.pdf
VVF-Customer-Presentation2025-Ver1.9.pptx
Design an Analysis of Algorithms I-SECS-1021-03
Odoo Companies in India – Driving Business Transformation.pdf
ai tools demonstartion for schools and inter college
Navsoft: AI-Powered Business Solutions & Custom Software Development
System and Network Administraation Chapter 3
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
history of c programming in notes for students .pptx
Upgrade and Innovation Strategies for SAP ERP Customers
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Internet Downloader Manager (IDM) Crack 6.42 Build 41
medical staffing services at VALiNTRY
How to Choose the Right IT Partner for Your Business in Malaysia
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
top salesforce developer skills in 2025.pdf
Nekopoi APK 2025 free lastest update

Introduction to cpp (c++)

  • 1. 1.11. MATHEMATICS 181 24 return 0; } ✌ ✆ Output of above program is ✞ Addition of 5 and 2 is : 7 Subtraction of 5 and 2 is : 3 Multiplication of 5 and 2 is : 10 Division of 5 and 2 is : 2 Modulus of 5 and 2 is : 1 ✌ ✆ If mathematical expressions are mixed with C++ operators and are directly made to be put at output stream then their grouping is required. Parentheses are used to group the scope of expression. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 /*3 + 3 << 1 * * 6 << 1 * 7 * 6 1 */ /* Here << is considered as a * 9 *C++ insertion operator */ cout << 3 + 3 << 1 << endl ; 11 /*(3 + 3 << 1)* * (6 << 1) * 13 * 12 */ /* Here << is considered as* 15 *a left shift operator */ cout << (3 + 3 << 1) << endl ; 17 return 0; } ✌ ✆ ✞ 61 12 ✌ ✆
  • 2. 182 Array & Pointer
  • 3. 2.1. ARRAY 183 2Array & Pointer 2.1 Array Arrays in C++ stores data in a single variable name with an index, also known as a subscript. It is simply a list or ordered grouping for variables of the same type. Arrays often help a programmer in organize collections of data efficiently and intuitively. 2.1.1 Uni-dimensional Array Arrays are declared and initialized like ✞ int numbers [6]; // array declared 2 int point [6]={0 , 0, 1, 0, 0, 0}; // array initialized ✌ ✆ The brackets ‘[ ]’ identify ‘numbers’ or ‘points’ and the number enclosed in the bracket indicates the number of elements in the array, i.e. subscripts of the array. An element of array can be accessed by its index number. In following example, each element of the array is accessed by its index number. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char ** argv ) { int ix; 6 short anArray [] = {3, 6, 9, 12, 15}; for (ix = 0; ix < ( sizeof (anArray ) / sizeof ( short)); ++ix) { 8 cout << anArray [ix] << endl ; } 10 return 0; } ✌ ✆ In the above example, size of array was not explicitly specified. The compiler knows size of array from the initialized list. The size of ‘anArray’ is ‘5’ because ‘anArray’ has five elements. Addition of an additional element to the list will increase its size to six. Static declaration of the size of an array, the array list will be overflow. To overcome this problem sizeof expression is used as ✞ 1 size = sizeof(anArray)/ sizeof(short) ✌ ✆ Because of the sizeof expression in for loop, the script is automatically adjusted to this change. Designated initializer is allow to pick and choose the initialized elements. An array initialised with ‘[ ]’ is called expandable array. When an array is declared without
  • 4. 184 Array & Pointer its size, compiler first counts elements of the array and then it grows the array upto a size so that all the elements can be stored in the array. ✞ 1 /* Array with growing size . */ int days [] = {31, 28, 31, 30, 31, 29}; ✌ ✆ A one dimensional array with variable size can not be declared as shown below: ✞ int i; 2 cin >> i; int a[i] ✌ ✆ The size must be constant. Again, if the array is created with variable size using new keyword, then it is acceptable. ✞ 1 #include <iostream > using namespace std; 3 int main () { 5 int n, j; cout << "How may array size : "; 7 cin >> n; /* Reserve the memory */ 9 int *a = new int[n]; for (j = 0; j < n; j++) { 11 a[j] = j*n; } 13 for (j = 0; j < n; j++) { cout << a[j] << endl ; 15 } delete [] a;// Free the memory , required compulsory 17 return 0; } ✌ ✆ ✞ 0 3 6 ✌ ✆ 2.1.2 Multi-dimensional Array A multi-dimensional array can be declared and initialized as given below: ✞ 1 int two_d [2][3] = {{ 5, 2, 1 }, { 6, 7, 8 }}; ✌ ✆ Here [2] represents number of rows and [3] represents number of columns of the two dimensional array. Multi-dimensional array can be used to add, subtract and product (either dot or cross) of two vectors or matrices.
  • 5. 2.1. ARRAY 185 ✞ #include <iostream > 2 using namespace std; 4 #define X 5 #define Y 5 6 int main (int argc , char ** argv ) { 8 int ix , iy; 10 short anArray[X][Y]; for (ix = 0; ix < X; ++ix) { 12 for (iy = 0; iy < Y; ++iy) { anArray[ix][ iy] = ix * iy; 14 }; } 16 for (ix = 0; ix < X; ++ix) { for (iy = 0; iy < Y; ++iy) { 18 cout << anArray [ix][iy] << "t"; }; 20 cout << endl ; } 22 return 0; } ✌ ✆ ✞ 0 0 0 0 0 0 1 2 3 4 0 2 4 6 8 0 3 6 9 12 0 4 8 12 16 ✌ ✆ Following is an example of elementwise addition and subtraction of two matrices. ✞ 1 #include <iostream > using namespace std; 3 /* Random number generator between 0 to 10.*/ 5 int rand_num (int a, int b) { return ((a * 97 + b * 21) & 10); 7 } 9 int main (int argc , char ** argv ) { int i/* row*/, 11 j/* col*/; int A [3][3]/* First Matrix*/, 13 B[3][3]/* Second Matrix*/ , C[3][3]/* Dot Matrix*/; 15 cout << "First Random Matrix is :" << endl ; /* For each of three rows */ 17 for (i = 0; i < 3; i++) { /* There are three columns.*/
  • 6. 186 Array & Pointer 19 for (j = 0; j < 3; j++) { /* Assign a random matrix elements .*/ 21 A[i][j] = rand_num (i*j, j); cout << A[i][j] << "t"; 23 } /* Print new line after completion of each row*/ 25 cout << endl << endl ; } 27 cout << "Second Random Matrix is :" << endl ; /* For each of three rows */ 29 for (i = 0; i < 3; i++) { /* There are three columns.*/ 31 for (j = 0; j < 3; j++) { /* Assign a random matrix elements .*/ 33 B[i][j] = rand_num (i, i * j); cout << B[i][j] << "t"; 35 } /* Print new line after completion of each row*/ 37 cout << endl << endl ; } 39 cout << "Elementwise Addition of Matrices is :" << endl ; /* For each of three rows */ 41 for (i = 0; i < 3; i++) { /* There are three columns.*/ 43 for (j = 0; j < 3; j++) { /* Add matrices elementwise .*/ 45 C[i][j] = A[i][j] + B[i][j]; cout << C[i][j] << "t"; 47 } /* Print new line after completion of each row*/ 49 cout << endl << endl ; } 51 cout << "Elementwise Subtraction of Matrices is :" << endl ; /* For each of three rows */ 53 for (i = 0; i < 3; i++) { /* There are three columns.*/ 55 for (j = 0; j < 3; j++) { /* Subtract matrices elementwise .*/ 57 C[i][j] = A[i][j] - B[i][j]; cout << C[i][j] << "t"; 59 } /* Print new line after completion of each row*/ 61 cout << endl << endl ; } 63 return 0; } ✌ ✆ ✞ First Random Matrix is : 0 0 10 0 2 8 0 2 10
  • 7. 2.1. ARRAY 187 Second Random Matrix is : 0 0 0 0 2 10 2 8 2 Elementwise Addition of Matrix is : 0 0 10 0 4 18 2 10 12 Elementwise Subtraction of Matrix is : 0 0 10 0 0 -2 -2 -6 8 ✌ ✆ Dot product example is ✞ #include <iostream > 2 using namespace std; 4 /* Random number generator between 0 to 10.*/ int rand_num (int a, int b) { 6 return ((a * 97 + b * 21) & 10); } 8 int main (int argc , char ** argv ) { 10 int i/* row*/, j/* col*/; 12 int A [3][3]/* First Matrix*/, B[3][3]/* Second Matrix*/ , 14 C[3][3]/* Dot Matrix*/; cout << "First Random Matrix is :" << endl ; 16 /* For each of three rows */ for (i = 0; i < 3; i++) { 18 /* There are three columns.*/ for (j = 0; j < 3; j++) { 20 /* Assign a random matrix elements .*/ A[i][j] = rand_num (i*j, j); 22 cout << A[i][j] << "t"; } 24 /* Print new line after completion of each row*/ cout << endl << endl ; 26 } cout << "Second Random Matrix is :" << endl ; 28 /* For each of three rows */ for (i = 0; i < 3; i++) { 30 /* There are three columns.*/ for (j = 0; j < 3; j++) { 32 /* Assign a random matrix elements .*/ B[i][j] = rand_num (i, i * j); 34 cout << B[i][j] << "t"; } 36 /* Print new line after completion of each row*/ cout << endl << endl ;
  • 8. 188 Array & Pointer 38 } cout << "Dot Product of Matrices is :" << endl ; 40 /* For each of three rows */ for (i = 0; i < 3; i++) { 42 /* There are three columns.*/ for (j = 0; j < 3; j++) { 44 /* Subtract matrices elementwise .*/ C[i][j] = A[i][j] * B[i][j]; 46 cout << C[i][j] << "t"; } 48 /* Print new line after completion of each row*/ cout << endl << endl ; 50 } return 0; 52 } ✌ ✆ ✞ First Random Matrix is : 8 2 2 2 2 0 2 0 8 Second Random Matrix is : 8 8 8 8 2 2 8 2 8 Dot Product Matrix is : 64 16 16 16 4 0 16 0 64 ✌ ✆ Cross product example is ✞ #include <iostream > 2 #include <cmath > using namespace std; 4 /* Random number generator between 0 to 10.*/ 6 int newseed = 10; 8 int seed (int a) { newseed = newseed + a; 10 return newseed; } 12 int rand_num (int a) { 14 seed (a); return (( newseed * 99991 + 12345) & 10); 16 } 18 int main (int argc , char ** argv ) { int i/* row*/, 20 j/* col*/;
  • 9. 2.1. ARRAY 189 int A[3]/* First Matrix */, 22 B[3]/* Second Matrix*/, C[3]/* Vector Matrix*/; 24 cout << "First Random Matrix is :" << endl ; /* For each of three rows */ 26 for (i = 0; i < 3; i++) { /* There are three columns.*/ 28 /* Assign a random matrix elements .*/ A[i] = rand_num (i); 30 cout << A[i] << "t"; } 32 cout << endl ; cout << "Second Random Matrix is :" << endl ; 34 /* For each of three rows */ for (i = 0; i < 3; i++) { 36 /* There are three columns.*/ /* Assign a random matrix elements .*/ 38 B[i] = rand_num (i); cout << B[i] << "t"; 40 } cout << endl ; 42 cout << "Cross Product of Matrices is :" << endl ; 44 /* For each of three rows */ for (i = 0; i < 3; i++) { 46 /* Subtract matrices elementwise .*/ C[i] = pow(-1, 2 * i)* (A[(i + 1) % 3] * B[(i + 2) % 3] 48 - B[(i + 1) % 3] * A[(i + 2) % 3]); cout << C[i] << "t"; 50 } return 0; 52 } ✌ ✆ ✞ First Random Vector is : 10 2 0 Second Random Vector is : 0 10 8 Cross Product Vector is : 16 -80 100 ✌ ✆ Array can be passed to a function like ✞ #include <iostream > 2 using namespace std; 4 /*+- Array pointer with ** **| expandable size */ 6 void init_array (int a[], int count) { int i; 8 for (i = 0; i < count; i++) a[i] = i * 10;
  • 10. 190 Array & Pointer 10 for (i = 0; i < count; i++) cout << "The a value is " << a[i] << endl ; 12 } 14 int main (int argc , char ** argv ) { int mydata [10]; 16 init_array (mydata , 5); return 0; 18 } ✌ ✆ ✞ The a value is 0. The a value is 10. The a value is 20. The a value is 30. The a value is 40. ✌ ✆ For multidimensional array, there is no limit of dimension in C. Here, a four dimensional matrix is represented by ✞ 1 int myData [2][3][2][4] ✌ ✆ A new dimension in array declaration is always grouped by curly braces. One dimensional array has one curly braces, i.e. one row. In two dimensional array, there are two one dimensional rows both separated by comma (,) operator. These two rows are enclosed by another curly braces. In three dimensional systems of arrays, two 2-dimensional arrays are placed one over another. In the following example, two, three and four dimensional arrays are declared. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int a [2][2] = { // cols 7 {1, 2}, // row {5, 6} // row 9 }; int b [2][2][2] = { 11 { // cols 13 {1, 2}, // row {5, 6} // row 15 }, {// height 17 {4, 3}, {8, 9} 19 } }; 21 int c [2][2][2][2] = { {
  • 11. 2.1. ARRAY 191 23 { // cols 25 {1, 2}, // row {5, 6} // row 27 }, {// height 29 {1, 2}, {5, 6} 31 } }, 33 {// time { 35 {4, 1}, {7, 6} 37 }, { 39 {4, 4}, {9, 1} 41 } } 43 }; int i, j, k, l; 45 cout << "Elements of matrix a are " << endl ; for (i = 0; i < 2; i++) { 47 for (j = 0; j < 2; j++) { cout << "Element " << a[i][j] << endl ; 49 } } 51 cout << "Elements of matrix b are " << endl ; for (i = 0; i < 2; i++) { 53 for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { 55 cout << "Element " << b[i][j][k] << endl ; } 57 } } 59 cout << "Elements of matrix c are " << endl ; for (i = 0; i < 2; i++) { 61 for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { 63 for (l = 0; l < 2; l++) { cout << "Element " << c[i][j][k][l] << endl ; 65 } } 67 } } 69 return 0; } ✌ ✆
  • 12. 192 Array & Pointer 2.1.3 Array in Function In a function, an argument is passed as value unless the program needs to alter the argument. In this case there is requirement that a pointer should be passed to the function. Arrays can passed to a function as pointers. If an array is passed to the function, function would have to allocate enough space to hold a copy of the original array and then copy all the data from the original array to the new array. It is much quicker to pass the address of the array rather than array itself and have the function work with the original data. Prototype for the passing of an array to the function is ✞ int sum(int arr []) ✌ ✆ C++ compilers do not check the size of the array passed to the function hence for good programming, the function should know the limits of actions on the array. This is why a new parameter of array size as ‘n’ is passed to the function as ✞ 1 int sum(int arr[], int n) ✌ ✆ The name of an array is address of first element hence array name passed as argument to the function should be matching argument and a pointer. In this context int arr[] is same as the int * arr. In case of multi-dimensional array, first bracket in the multidimensional array may be empty or not empty but other bracket should contains a valid integer for the size of the array dimension. ✞ 1 #include <iostream > using namespace std; 3 #define ROWS 3 #define COLS 4 5 int sum(int rows , int cols , int ar [][ COLS ]); 7 int main (void ) { int i, j; 9 int varr [ROWS ][ COLS ]; for (i = 0; i < ROWS ; i++) 11 for (j = 0; j < COLS ; j++) varr [i][j] = i * j + j; 13 cout << "3x4 Array n"; cout << "Sum of all elements " << sum(ROWS , COLS , varr ); 15 return 0; } 17 int sum(int rows , int cols , int ar [][ COLS ]) { 19 int r; int c; 21 int tot = 0; for (r = 0; r < rows ; r++) 23 for (c = 0; c < cols ; c++) tot += ar[r][c]; 25 return tot; } ✌ ✆
  • 13. 2.1. ARRAY 193 ✞ 3x4 Array Sum of all elements 36 ✌ ✆ 2.1.4 Return Array From Function C++ allows to return an array from a function. To return single dimension array, we create a function with pointer. See the example below: ✞ #include <iostream > 2 #include <ctime > using namespace std; 4 int * getArray () { 6 static int a[5]; 8 for (int i = 0; i < 5; ++i) { a[i] = i * 2; 10 } return a; 12 } 14 int main (int argc , char *argv []) { int *p; 16 p = getArray (); 18 for (int i = 0; i < 5; i++) { 20 cout << "*(p + " << i << ") : "; cout << *(p + i) << endl ; 22 } 24 return 0; } ✌ ✆ ✞ *(p + 0) : 0 *(p + 1) : 2 *(p + 2) : 4 *(p + 3) : 6 *(p + 4) : 8 ✌ ✆ 2.1.5 String As Array String is defined as array of characters. C++ allows a character array to be represented by a character string with a null terminating character which is automatically added at the end of character array instead of a list of characters. Example of string array is shown below.
  • 14. 194 Array & Pointer ✞ 1 char string [] = {’A’, ’p’, ’p’, ’l’, ’e’, ’S’, ’0 ’}; ✌ ✆ Normal size of a string array is controlled at initialization of the string array. An string array stores elements upto its declared length. Excess elements are ignored and skipped. In following example only ten characters will be stored in the string array ‘mystr’. ✞ 1 char mystr [10] = "Apple is red."; ✌ ✆ It is convenient to let the compiler determine the array size. If anyone omits the size of array at the time of array declaration and initialization, the compiler itself determines the size for supplied string. In following example, compiler set the string length of thirteen characters. ✞ 1 char mystr[] = "Apple is red."; ✌ ✆ A pointer-to-string method may also be used for string declaration and initialization. In pointer notation, above example will be looked like ✞ 1 const char *ptrstr = "Merkkijono "; ✌ ✆ Both declarations amount to saying that ‘ptrstr’ is a pointer to the indicated string. ‘ptrstr’ string variable declared as array or as pointer, both are same but only pointer version can be used with increment operator. To create an extra long string, string is splitted into multiple sections, by closing the first section with a quote, and recommencing the string on the next line (also starting and ending in a quote): ✞ 1 char string [] = "This is a very , very long " "string that requires two lines."; ✌ ✆ Full example is given below: ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { char ch; 6 char string[] = "Two lines " "string."; 8 int i = 0; while (string[i] != ’0’) { 10 ch = string[i]; cout << ch; 12 i++; } 14 return 0; } ✌ ✆ ✞ T.w.o. .l.i.n.e.s. .s.t.r.i.n.g... ✌ ✆
  • 15. 2.1. ARRAY 195 When an array is declared and initialized with characters, there must be a terminating null character. Otherwise there shall be garbage output. For example following syntax has no terminating null character. It is not in standard format. ✞ 1 char a[10]; a[0]= ’a’; 3 a[1]= ’r’; a[2]= ’u’; ✌ ✆ In above method, a null terminator is added as its last element. Now, the string array is initialized in standard format. ✞ char a[10]; 2 a[0]= ’a’; a[1]= ’r’; 4 a[2]= ’u’; a[3]= ’0’; ✌ ✆ See following two examples, in which string is terminating without and with null termi- nating character. First example gives garbage output (see below). ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 char a[10]; a[0] = ’a’; 7 a[1] = ’r’; a[2] = ’u’; 9 cout << a; return 0; 11 } ✌ ✆ ✞ <garbage output > ✌ ✆ In this second example, string is terminated with null character. This example gives output what we required. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 char a[10]; a[0] = ’a’; 7 a[1] = ’r’; a[2] = ’u’; 9 a[3] = ’0’; cout << a; 11 return 0; } ✌ ✆
  • 16. 196 Array & Pointer ✞ aru ✌ ✆ Static array size should be larger than one to the required size of the array to store data. For example, to store one byte data, array size should be two. Similarly, for storing n bytes data, array size should be at least n + 1. 2.1.6 Size of Array C++ features two kinds of arrays: static (compile-time, fixed size) and dynamic (allocated at run-time). The length of a dynamic array cannot be acquired from the array itself - its length must be stored elsewhere. The size of array is computed as ✞ 1 int length = sizeof(<array name >) / sizeof(<array element >); ✌ ✆ Preprocessor ways for array length is defined as ✞ 1 #define ARRAY_LENGTH (A) (sizeof(A) / sizeof(A[0]) ) ✌ ✆ Arrays become pointers when passed as a parameter to a function. Thus, the length of an array parameter may not require directly. A dedicated length parameter is required. An example is given below. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 const char *fruit[2] = {"apples", "oranges"}; 7 /* Length of the array by dividing * *the size of all elements by the* 9 *size of the first element. */ 11 int length = sizeof (fruit) / sizeof (fruit[0]) ; 13 cout << length; 15 return 0; } ✌ ✆ ✞ 2 ✌ ✆ In above example, length of the array is obtained by dividing the size of all elements (found with sizeof (fruit)) by the size of the first element. Note that since the array elements are pointers to null-terminated character arrays, the size of the first element is actually the size of the pointer type - not the length of the string. This size, regardless of the type being pointed to, is 8 bytes, 4 bytes, or 2 bytes on 64-bit, 32-bit, or 16-bit platforms respectively. Pointer can be used for variable size array as shown in example below.
  • 17. 2.2. POINTER 197 ✞ 1 #include <iostream > using namespace std; 3 /* Variable size array.*/ char *name ; 5 int main (int argc , char *argv []) { 7 name = "My School!!"; int i = 0; 9 while (name [i] != ’0’) { cout << name [i] << endl ; 11 i++; } 13 return 0; } ✌ ✆ ✞ M y S c h o o l ! ! ✌ ✆ 2.2 Pointer A pointer is a simple variable that stores address (the location in memory) of a value in memory rather than storing data itself. There are four fundamental things for the pointers: 1. How to declare them. 2. How to assign them. 3. How to reference the value to which the pointer points, i.e value finding also known as dereferencing. 4. How they relate to arrays. Two important rules of the pointer must be remembered. These are: 1. A variable name with prefixed by ampersand (&) defines the address of the variable and therefore points to the variable. 2. A pointer with prefixed by asterisk (*) refers to the value of the variable pointed-by the pointer.
  • 18. 198 Array & Pointer An array name is also an address of the first element of the array. Assume, ‘arr’ is an array as relation geven below: ✞ arr == &arr [0]; ✌ ✆ Here both ‘arr’ and ‘&arr[0]’ represent to the memory address of first element of the same array. A pointer can points to any element of an array, if the pointer is assigned address of that element. In the following example, pointer ‘x’ points to the address of first element of tha array ‘i’. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 int i[5] = {10, 20, 30, 40, 50}; int *x = &i[0]; /* Points to first element.*/ 7 cout << *x; return 0; 9 } ✌ ✆ 0 10 1 20 2 30 3 40 4 50 i[]: x The output of above program shall be ✞ 10 ✌ ✆ If above example is modified as given below, then the pointer ‘x’ points to the 3rd element of the array ‘i’. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 int i[5] = {10, 20, 30, 40, 50}; int *x = &i[2]; /* Points to third element.*/ 7 cout << *x; return 0; 9 } ✌ ✆ 0 10 1 20 2 30 3 40 4 50 i[]: x
  • 19. 2.2. POINTER 199 The output of above program shall be ✞ 30 ✌ ✆ If an intger is pointed by a pointer-to-char variable, then this variable can points to the address of each byte of the integer variable (integer variable is 4 bytes long). ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 /* 1000 D = 1111101001 B*/ int i = 1001; 7 /* Pointer casting from integer to character .*/ char *x = (char *) &i; 9 /* Little endian is x[0]=11101001 B* *Big endian is x[1]=00000011 B* 11 *Big endian x[2]= x[3]=00000000 B*/ /* Print little endian x[0]*/ 13 cout << (int) x[0] << endl ; return 0; 15 } ✌ ✆ x[3] x[2] x[1] x[0] i: x 00000000 00000000 00000011 11101001 Output of above program is ✞ -23 ✌ ✆ ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 /* 1000 D = 1111101001 B*/ int i = 1001; 7 /* Pointer casting from integer to character .*/ char *x = (char *) &i; 9 /* Little endian is x[0]=11101001 B* *Big endian is x[1]=00000011 B* 11 *Big endian x[2]= x[3]=00000000 B*/ /* Print big endian x[1]*/ 13 cout << (int) x[1] << endl ; return 0; 15 } ✌ ✆
  • 20. 200 Array & Pointer x[3] x[2] x[1] x[0] i: x 00000000 00000000 00000011 11101001 Output of above program is ✞ 3 ✌ ✆ 2.2.1 Declaring Pointers In C, pointers are declared as shown in following syntax. ✞ 1 long *var1 , var2 ; int **p3; ✌ ✆ In these syntax, line 1 declares ‘var1’ as a pointer to a long and ‘var2’ as a long and not a pointer to a long. In line 2, ‘p3’ is declared as a pointer to a pointer to an int. In C++, a pointer is declared as shown in the following syntax. ✞ int * A; 2 int * ptrA , ptrB ; ✌ ✆ Here ‘A’, ‘ptrA’ are pionter to integer while ‘ptrB’ is an ordinary integer. See an example given below: ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char ** argv ) { int i; 6 int* p, j; p = &i; /* valid for best practice */ 8 i = 10; /*i is now 10 */ *p = 20; /* valid*/ 10 j = 5; /* prints 20*/ 12 cout << "i is " << i << endl ; cout << "i is " << *p << endl ; 14 /* prints 5*/ cout << "j is " << j << endl ; 16 return 0; } ✌ ✆ ✞ i is 20 i is 20 j is 5 ✌ ✆
  • 21. 2.2. POINTER 201 1 0x49 2 0x50 3 0x51 4 0x52 5 0x53 6 0x54 7 0x55 int *p = &i i &i Pointer types are often used as parameters to function calls. ✞ 1 int MyFunction ( struct MyStruct *pStruct ); ✌ ✆ In the above syntax, it is explained that how to declare a function which uses a pointer as an argument. Since C++ passes function arguments by value, in order to allow a function to modify a value from the calling routine, a pointer to the value must be passed. Pointer- to-Structure is also used as function arguments even when nothing in the struct will be modified in the function. This is done to avoid copying the complete contents of the structure onto the stack. A simple example is ✞ 1 #include <iostream > /* time .h C library in C++ header as ctime*/ 3 #include <ctime > using namespace std; 5 void getSeconds (unsigned long *par); 7 int main (int argc , char ** argv []) { 9 unsigned long sec; getSeconds (& sec); 11 cout << "Number of seconds since 01 Jan 1970 : " << sec; return 0; 13 } 15 void getSeconds (unsigned long *par) { *par = time (NULL ); 17 return; } ✌ ✆ ✞ Number of seconds: 1420616845 ✌ ✆ 2.2.2 Pointer to Member A member of a structure or class or a namespace are also accessible via pointers. A pointer to member shall not point to a static member of a class, i.e. a member with reference type. “pointer to member” is distinct from the type “pointer”, therefore, a pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer declarator syntax. ✞ 1 int X::* i = &X::a; // pointer to member method int *i = &a; // pointer declarator method ✌ ✆
  • 22. 202 Array & Pointer See the example below: ✞ #include <cstdlib > 2 #include <iostream > using namespace std; 4 struct X { 6 int a; }; 8 int main (int argc , char ** argv ) { 10 /* Declare member function i as pointer * *to the original member a of the struct*/ 12 int X::* i = &X::a; X x; 14 x.*i = 10; cout << x.*i; 16 return 0; } ✌ ✆ ✞ 10 ✌ ✆ 2.2.3 Pointer Address Pointers are used to point the memory address where data is stored. A pointer size is determined by the pointer data type. For example if pointer is character type then size of pointer is one byte. The pointer increment is one byte long. For example, ✞ 1 string *ptr= new string [8]; ✌ ✆ and pointer ‘ptr’ points to memory address 0×00 then ‘ptr++’ points to the memory address 0×01 as shown in the following figure. d 0x00 e 0x01 f 0x02 g 0x03 h 0x04 i 0x05 j 0x06 k 0x07 Bytes ptr ptr++ *ptr (*ptr)++ Again ‘*ptr’ points to the character ‘d’ at the memory address pointed by the pointer ‘ptr’. To get the next character ‘e’, dereference is done as ‘(*ptr)++’. Similarly, if pointer is integer type as declared below: ✞ 1 int *ptr= new int [10]; ✌ ✆
  • 23. 2.2. POINTER 203 then size of ‘ptr’ is 4 bytes. Now, if pointer ‘prt’ points to the memory address 0×00 then ‘ptr++’ points to the memory address 0×04 as shown in the figure given below: xxxx 0x00 xxxx 0x01 xxxx 0x02 xxxx 0x03 yyyy 0x04 yyyy 0x05 yyyy 0x06 yyyy 0x07 Bytes ptr ptr++ *ptr (*ptr)++ Again ‘*ptr’ points to the integer value at the memory address pointed by the pointer ‘ptr’. To get the next integer value, dereference is done as ‘(*ptr)++’. Remember that precedence of ‘++’ symbol is higher to asterisk (*) symbol. This is why to scope of asterisk (*) is changed by using parenthesis. 2.2.4 Assigning Values to Pointers To assign address of a variable to a pointer, unary operator ‘&’, also known as ‘address of’ operator is used as shown in the following syntax. ✞ 1 /*An interger variable that have * *null value stored in memory. */ 3 int myInt; /* Pointer that addresses to an integer value.*/ 5 int * ptr; /* Address to the pointer where * 7 *myInt value is stores in memory.*/ ptr = &myInt; ✌ ✆ Here, ‘ptr’ is referencing to ‘myInt’ now. Pointers can also be assign the address of dynamically allocated memory. See the following example. ✞ #include <iostream > 2 using namespace std; 4 int j, k; int * ptr; 6 int main (int argc , char ** argv ) { 8 j = 1; k = 2; 10 ptr = &k; cout << "j = " << j << ". It stored at " << (void *) &j << endl ; 12 cout << "k = " << k << ". It stored at " << (void *) &k << endl ; cout << "‘ptr’ = " << ptr << ". It stored at " 14 << (void *) &ptr << endl ; cout << "Value of the integer pointed -by ‘ptr’ is " << *ptr << endl ; 16 return 0;
  • 24. 204 Array & Pointer } ✌ ✆ ✞ j has value 1 and stored at 0x403100 k has value 2 and stored at 0x403120 ‘ptr ’ has value 0x403120 and stored at 0x403110 Value of the integer pointed -by ‘ptr ’ is 2 ✌ ✆ Assigning a value to a pointer requires specialization. In C++, it is best practice that first assign the address of a value to the pointer. We can retrieve the value from the address by dereferencing it using asterisk (‘*’); ✞ int * j; 2 int k = 5; j = &k/* Valid & good practice .*/ ✌ ✆ See the example ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int * j; int k = 15; 7 j = &k; /* valid & good practice */ cout << "j is : " << *j; 9 return 0; } ✌ ✆ ✞ j is : 15 ✌ ✆ Assigning a value to a pointer directly causes errors in the C++ program. Therefore, it is not assumed a good practice. Sometimes, confusion creates a bad way for assignment of a value to a pointer as shown below: ✞ 1 int * j; *j = 5;/* Invalid & very bad practice .*/ ✌ ✆ It is as we try to assign a value to an uninitialized pointer. A pointer points to the location (address) where value is stored. Pointer does not store value itself. So, pointer does not know where value is stored. If we try to do so, the program either may crash or it damaged to the system. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char ** argv ) { int i; 6 int *p; p = &i; /* valid for best practice */
  • 25. 2.2. POINTER 205 8 i = 10; /*i is now 10 */ *p = 20; /* valid*/ 10 /* prints 20*/ cout << "i is " << i << endl ; 12 cout << "i is " << *p << endl ; return 0; 14 } ✌ ✆ ✞ i is 20 i is 20 ✌ ✆ When we create a pointer in C++, the computer allocates memory to hold an address, but it does not allocate memory to hold the data to which the address points. Space for data is created by another step. If we omit the step required to create space for data attracts the errors. ✞ int * i; 2 *i = 10; ✌ ✆ Here, i is a pointer but it point to nothing. Therefore, code failed to assign an address to i. See the example below, which will failed to give desired output. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char ** argv ) { int* p; 6 *p = 5; cout << "p is " << *p << endl ; 8 return 0; } ✌ ✆ In C++, memory for pointer is allocated by new operator. To allocate memory for integer we use the syntax like ✞ 1 int * j = new int; ✌ ✆ We tell to operator new for what data type we want in memory. It finds a block of the correct size and returns the address of the block. A practical example is given below: ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int *j = new int; *j = 5; /* valid & good practice */ 7 cout << "j is : " << *j; return 0; 9 } ✌ ✆
  • 26. 206 Array & Pointer ✞ j is : 5 ✌ ✆ Each allocated memory by new operator only should be freed by delete operator. It is used as ✞ 1 int *j = new int;/* Create & reserve memory space*/ delete j; /* Free memory space*/ ✌ ✆ The use of delete operator as given below is illegal. ✞ int i = 5; 2 int *j = &i; delete j; /* illegal */ ✌ ✆ 2.2.5 Pointer Dereferencing (Value Finding) To access a value to which a pointer points, the asterisk (‘*’) operator is used. An- other operator, the ‘−>’ (Indirection) operator is used in conjunction with pointers to structures. Here’s a short example. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int i; int *p; // Pointer type int * 7 p = &i; // p now points to i i = 10; // i is now 10 9 *p = 20; // i is now 20!! /* prints "20" */ 11 cout << "i is " << i << endl ; /* "20"! dereferencing -p is the same as i!*/ 13 cout << "i is " << *p << endl ; return 0; 15 } ✌ ✆ ✞ i is 20 i is 20 ✌ ✆ 2.2.6 Addition of Pointers A pointer when dereferences, retrieves the value at the address pointed by the pointer. If the value at pointer address is an integer then we can add another integer value to it. When an integer value is addedd to the pointer then old addres of the pointer is changed into new address. Difference between new address and old address is equal to the pointer data type. In the following example, we retrieve the pointer value and add 1 to in function ‘increment()’.
  • 27. 2.2. POINTER 207 ✞ #include <iostream > 2 using namespace std; 4 void increment (int *p) { *p = *p + 1; /* Add one to p */ 6 } 8 int main (int argc , char ** argv ) { int i = 20; 10 /* i value is 20 */ cout << "i is " << i << endl ; 12 /* Pass interger to increment function as pointer */ increment (&i); 14 /* Print the value 21*/ cout << "i is " << i << endl ; 16 return 0; } ✌ ✆ ✞ i is 20 i is 21 ✌ ✆ The value of a pointer is the address of the object to which it points. The address of a large object, such as type double variable, typically is the address of the first byte of the object. Applying the * operator to a pointer yields the value stored in the pointed-to object. Adding 1 to the pointer increases its value by the size, in bytes, of the pointed-to type. 2.2.7 Pointers and Arrays If we have to use pointer for an array, then we use new operator to create a dynamic array of specific size. The valid types of dynamic allocation of array memory space are shown below: ✞ int * i = new int [10];/* 40 bytes space for 10 elements */ 2 string * str = new string [10];/*10 bytes string.*/ ✌ ✆ new operator returns the address of the first element of the block. We should free the allocated memory space by delete operator when program does not need it. Single block of memory should be created and freed like ✞ int * i = new int; /* Single byte memory space*/ 2 delete i; /* Free the allocated memory space*/ ✌ ✆ A dynamic array memory space should be created and freed like ✞ int * i = new int [10]; /*10 block memory */ 2 delete [] i; /* Free memory allocated for array*/ ✌ ✆
  • 28. 208 Array & Pointer Here ‘[]’ between delete operator and variable ‘i’ tells the program that it should free the whole array, not just the element pointed to by the pointer. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char ** argv ) { int * mk = new int [10]; 6 *mk = 65874859; cout << *mk << endl ; 8 delete [] mk; return 0; 10 } ✌ ✆ ✞ 65874859 ✌ ✆ To add a value to a pointer we can use ‘*’ (asterisk) operator as well as array element method to the dynamically allocated array as shown in following example. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int * mk = new int [5]; int i; 7 for (i = 0; i < 5; i++) { mk[i] = i; 9 } for (i = 0; i < 5; i++) { 11 cout << mk[i] << endl ; } 13 delete [] mk; return 0; 15 } ✌ ✆ ✞ 0 1 2 3 4 ✌ ✆ If we want to add and retrieve values to dynamically allocated memory by using pointer then initial pointer location must be restored to get the actual stored values. See the example below: ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int * mk = new int [5];
  • 29. 2.2. POINTER 209 int i; 7 for (i = 0; i < 5; i++) { *mk = i; // assign value at pointer location 9 mk ++; // increase pointer location by one } 11 mk = mk -5; // Restore the initial position of the pointer. for (i = 0; i < 5; i++) { 13 cout << *mk << endl ; mk ++; 15 } delete [] mk; 17 return 0; } ✌ ✆ ✞ 0 1 2 3 4 ✌ ✆ Pointer arithmetic can be used to increment the pointer position and retrieval of the value stored at that address. ✞ 1 #include <iostream > #include <string > 3 using namespace std; 5 int main (int argc , char ** argv ) { int * mk = new int [5]; 7 int i; for (i = 0; i < 5; i++) { 9 mk[i] = i; } 11 for (i = 0; i < 5; i++) { cout << *(mk + i) << "t" << (mk [0] + i) << endl ; 13 } delete [] mk; 15 return 0; } ✌ ✆ ✞ 0 0 1 1 2 2 3 3 4 4 ✌ ✆ Pointers to Arrays An array can be initialized by using any of the following methods:
  • 30. 210 Array & Pointer ✞ 1 int myArr [3] = {a, b, c}; int * arrPtr = myArr; /* name of an array = address */ 3 int * arrPtr = &myArr[0]; /*or use address operator */ ✌ ✆ First line in above syntax is initialization of an array. In second line, ‘arrPtr’ is a pointer to the array ‘myArr’. In third line, ‘arrPtr’ points to the address of first element of the array ‘myArr’. See the following example, in which both methods are used to assign the same array to two different pointers by two different methods. ✞ 1 #include <iostream > #include <string > 3 using namespace std; 5 int main (int argc , char ** argv ) { double Marks[3] = {120.0 , 200.0 , 150.0}; 7 /* Here are two ways to get the address of an array*/ double * p1 = Marks; /* name of an array = address */ 9 double * p2 = &Marks [0]; /*or use address operator */ // with array element 11 cout << "p1 = " << p1 << ", *p1 = " << *p1 << endl ; cout << "p2 = " << p2 << ", *p2 = " << *p2 << endl ; 13 p1 = p1 + 1; p2 = p2 + 1; 15 cout << "Add 1 to the p1 & p2 pointers : n"; cout << "p1 = " << p1 << ", *p1 = " << *p1 << endl ; 17 cout << "p2 = " << p2 << ", *p2 = " << *p2 << endl ; p1 = p1 + 1; 19 p2 = p2 + 1; cout << "Add 1 to the p1 & p2 pointers : n"; 21 cout << "p1 = " << p1 << ", *p1 = " << *p1 << endl ; cout << "p2 = " << p2 << ", *p2 = " << *p2 << endl ; 23 return 0; } ✌ ✆ ✞ p1 = 0x22 ff40, *p1 = 120 p2 = 0x22 ff40, *p2 = 120 Add 1 to the p1 & p2 pointers : p1 = 0x22 ff48, *p1 = 200 p2 = 0x22 ff48, *p2 = 200 Add 1 to the p1 & p2 pointers : p1 = 0x22 ff50, *p1 = 150 p2 = 0x22 ff50, *p2 = 150 ✌ ✆ Pointers as Function Argument Pointers can also be used as function arguments in C++. Function prototype with pointer argument is shown below: ✞ int myFunc(int* a); ✌ ✆
  • 31. 2.2. POINTER 211 When we call this function, we use ‘&’ (address of) symbol to pass the address of a variable not the value of the variable as function argument. The function is called like ✞ 1 int i=10; // variable i with assigned value 10 myFunc(&i); // pass address of i to function myFunc ✌ ✆ By this way, pointer ‘a’ is assigned the address of the function parameter ‘i’. In following example, a sum function takes two integer values as pointer and return their sum as integer. The call of sum function uses addresses of the two integer values by using address- of symbol (‘&’). ✞ #include <iostream > 2 using namespace std; 4 /*pass -by -value as pointers to a & b to sum()*/ int sum(int* a, int* b) { 6 int f; /* Passed values as a and b.* 8 *They can be changed here .*/ f = *a + *b; 10 return f; } 12 int main (int argc , char *argv []) { 14 int i = 2, j = 3, g; /* Pass address of i and j to sum * 16 *function not values of i and j */ g = sum (&i, &j); 18 cout << "Sum of " << 2 << ", " << 3 << " is " << g; return 0; 20 } ✌ ✆ ✞ Sum of 2, 3 is 5 ✌ ✆ 00000010 00000011 0xaa 0xbb i j g = sum(&i, &j);
  • 32. 212 Array & Pointer 00000010 00000011 0xaa 0xbb i j int sum(int* a, int* b) {} A pointer function can also be used as function argument, generally called function callback. See the example ✞ 1 #include <iostream > using namespace std; 3 int getSum(int i, int j, int (* PrintLabel )(int , int)) { 5 cout << "Sum of " << i << " and " << j << " is "; cout << PrintLabel (i, j); 7 } 9 int PrintLabel (int x, int y) { return (x + y); 11 } 13 int main (int argc , char *argv []) { 15 getSum (2, 4, PrintLabel ); return 0; 17 } ✌ ✆ ✞ Sum of 2 and 4 is 6 ✌ ✆ Address as Function Argument Address of can also be used as function argument in C++. Function prototype with address of argument is as: ✞ 1 int myFunc(int& a); ✌ ✆ Here, int& passes a reference to the function. When we call this function, we just pass the variables as argument. The function call should be like ✞ 1 int i=10; myFunc(i); ✌ ✆ In following example, a sum function takes addresses of two arguments and return their sum as integer. The function call of this sum function uses variables as function argu- ments.
  • 33. 2.2. POINTER 213 ✞ #include <iostream > 2 using namespace std; 4 /*pass -by -value as address of a & b to sum()*/ int sum(int& a, int& b) { 6 int f; /* Passed values as a and b.* 8 *They can be changed here .*/ f = a + b; 10 return f; } 12 int main (int argc , char *argv []) { 14 int i = 2, j = 3, g; /* Sum function with arguments i and j*/ 16 g = sum(i, j); cout << "Sum of " << 2 << ", " << 3 << " is " << g; 18 return 0; } ✌ ✆ ✞ Sum of 2, 3 is 5 ✌ ✆ 2.2.8 Constant Pointers A pointer may be declared as constant by using const keyword. ✞ 1 int i = 5; const int *p = &i; 3 //Or int const *p = &i; ✌ ✆ There are two cases, (i) where a pointer pointed to constant data (pointee) and pointee can not be changed, and (b) where constant pointer (address) can not be changed. The usual pointer-pointee relation are given below: ✞ #include <iostream > 2 using namespace std; 4 int main () { int i = 2; 6 int j = 3; int *k = &j; // k points to j and *k is 3 8 cout << *k << endl ; j = 6; // Now both j and *k are 6 10 cout << j << " " << *k << endl ; *k = 7; // j and *k are 7. Pointee changes 12 cout << j << " " << *k << endl ; k = &i; // k points to i. *k is 2. Pointer changes 14 cout << i << " " << *k << endl ;
  • 34. 214 Array & Pointer *k = 8; // i and *k are 8 now. Pointee changes 16 cout << i << " " << *k << endl ; return 0; 18 } ✌ ✆ ✞ 3 6 6 7 7 2 2 8 8 ✌ ✆ Now the const keyword is used as shown in modified example. There are errors shows by the compiler. ✞ 1 #include <iostream > using namespace std; 3 int main () { 5 int i = 2; const int j = 3; 7 const int *k = &j; j = 6; // Error! assignment of read -only variable ’j’ 9 *k = 7; // Error! assignment of read -only location ’* k’ k = &i; // k points to i. *k is 2. Pointer changes 11 *k = 8; // Error! assignment of read -only location ’* k’ return 0; 13 } ✌ ✆ Here, code line ✞ 1 //+--Pointee type , i.e. constant pointee //| 3 const int *k = &j; ✌ ✆ 1 0x49 2 0x50 3 0x51 4 0x52 5 0x53 6 0x54 7 0x55 const int *k = &j j &j (const) j represents that ‘k’ is a non constant type pointer and the value to which it is pointing is constant type. Therefore, value of ‘j’ can not be changed while address of ‘k’ can be changed. ✞ 1 #include <iostream > using namespace std;
  • 35. 2.2. POINTER 215 3 int main () { 5 int i = 2; const int j = 3; 7 const int *k = &j; // int const *k = &j; // Or state 9 cout << "Address of k is " << k << endl ; k = &i; // k points to i. *k is 2. Pointer changes 11 cout << "New address of k is " << k << endl ; // 13 cout << "i : " << i << ", k : " << *k << endl ; return 0; 15 } ✌ ✆ ✞ Address of k is 0x22ff44 New address of k is 0x22 ff48 i : 2, k : 2 ✌ ✆ Similarly, if ✞ 1 // +--Pointer type , i.e. constant pointer // | 3 int * const k = &j; ✌ ✆ then, pointer becomes constant while value of pointee can be changed. Notice the position of asterisk (*) not the const keyword. 1 0x49 2 0x50 3 0x51 4 0x52 5 0x53 6 0x54 7 0x55 int * const k = &j (const) *k j &j ✞ 1 #include <iostream > using namespace std; 3 int main () { 5 int i = 2; int j = 3; 7 int * const k = &j; cout << "Address of k is " << k << endl ; 9 cout << "Old values - j : " << j << ", k : " << *k << endl ; j = 5; // k points to i. *k is 2. Pointer changes 11 cout << "New values - j : " << j << ", k : " << *k << endl ; //k = &i;// Error! assignment of read -only variable ’k’ 13 return 0; } ✌ ✆
  • 36. 216 Array & Pointer ✞ Address of k is 0x22ff44 Old values - j : 3, k : 3 New values - j : 5, k : 5 ✌ ✆ The change in the position of the asterisk (*) and keyword const changes the pointer and pointee type. The general representation is ✞ 1 int n = 5; int * p = &n; // non -const -Pointer to non -const -Pointee 3 const int * p = &n; // non -const -Pointer to const - Pointee int * const p = &n; // const -Pointer to non -const - Pointee 5 const int * const p = &n; // const -Pointer to const -Pointee ✌ ✆ 2.2.9 Pointers to Function A pointer to function is defined as ✞ 1 void (*fp)(); ✌ ✆ This function has no return value and no arguments (i.e. parameters). Here parentheses ( ) is used to encapsulate asterisk and function name. The reason is that parentheses operator, ( ), has higher precedence than that of dereferencing operator (*). Hence for pointer-to-function variable, dereferencing of function is grouped by parentheses. Exam- ple for pointer-to-function is given below. ✞ 1 #include <iostream > 3 using namespace std; 5 void myFunc () { cout << "Function is called ..." << endl ; 7 } 9 int main (int argc , char *argv []) { void (*r)(); 11 r = myFunc; (*r)(); 13 return 0; } ✌ ✆ ✞ Function is called ... ✌ ✆ A pointer to a function is possible in C++. This type of function may accepts arguments as pointers. The return value from the function is pointed by the function itself. In following example, a pointer-to-function is used. ✞ 1 #include <iostream > using namespace std;
  • 37. 2.2. POINTER 217 3 int* f(int* x) { 5 (*x)++; return x; 7 } 9 int main (int argc , char *argv []) { int a = 1; 11 cout << f(&a) << endl ; cout << *f(&a) << endl ; 13 return 0; } ✌ ✆ ✞ 0x22ff5c 3 ✌ ✆ Sometimes pointer-to-function returns the pointer to local variable. It is not considered a good practice. Compiler shows warning when we do so. It should be avoid in program- ming. 2.2.10 Pointer Arithmetic In normal mathematics numbers are used for addition, subtraction, division and multipli- cation etc. A pointer to an integer has different behavior to the integer. This is why, in pointer arithmetic, we have to arrange or conform the pointers so that they can behave in properly. A pointer-to-variable always points to the address where value of the variable is stored. This is why direct arithmetic of the pointers is of the arithmetic of the address rather than the values stored at the addresses. For example, we have to create an array of 2 element size (cells). Store a value in first cell. Retrieve the value and increment it by one. In the following example, we implement the solution as given below: ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { int i [10]; 6 int* a = i; cout << "a is " << (long ) a << endl ; 8 a++; cout << "a++ is " << (long ) a << endl ; 10 return 0; } ✌ ✆ ✞ a is 2293556 a++ is 2293560 ✌ ✆ In above example, the increment operator adds 4 to the address of pointer-to-integer variable ‘a’ rather that its value. This is why, we need proper confer to the pointer to
  • 38. 218 Array & Pointer the desired result. In the following example, we uses proper way of pointe and get the desired result. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { int i [2]={1}; /*1st=1, 2nd=0*/ 6 int* a = i; cout << "a is " << *a << endl ; 8 *a++; /* Increment to pointer index* *and get value which is 0 */ 10 cout << "a++ is " << *a << endl ; return 0; 12 } ✌ ✆ ✞ a is 1 a++ is 0 ✌ ✆ The result is not as we sought in result. Above code is again modified as given below: ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { int i [2]={1}; /*1st=1, 2nd=0*/ 6 int* a = i; cout << "a is " << *a << endl ; 8 (*a)++; /* Increment to value of a*/ cout << "a++ is " << *a << endl ; 10 return 0; } ✌ ✆ ✞ a is 1 a++ is 2 ✌ ✆ This is the result what we sought in our problem. Similarly, in following example, we use pointers in simple arithmetic. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { int a = 9, b = 5; 6 int* i = &a; int* j = &b; 8 cout << "Sum of i, j is " << (*i + *j) << endl ; cout << "Subtraction of i, j is " << (*i - *j) << endl ; 10 cout << "Division of i, j is " << (*i / *j) << endl ; cout << "Multiplication of i, j is " << (*i * *j) << endl ;
  • 39. 2.2. POINTER 219 12 return 0; } ✌ ✆ ✞ Sum of i, j is 14 Subtraction of i, j is 4 Division of i, j is 1 Multiplication of i, j is 45 ✌ ✆
  • 41. 3.1. STREAM & BUFFER 221 3Accessing System Files Standard Input-Output and access of files is a main part of computer programming. In this chapter we shall discuss the importance and methodology of accessing system and user define files. 3.1 Stream & Buffer 3.1.1 File Stream fstream is a header which includes the objects for reading a file or writing a file. It is just a file stream. Operations on the open file are performed by the objects/member functions of the fstream class. 3.1.2 File Buffer filebuf is a stream buffer that is used to read from a file or write to a file. It is constructed without association, these objects are associated to a file by calling its member open. Once open, all input/output operations performed on the object are reflected in the associated file. rdbuf () reads the file at once completely and put it in read buffer stream. See the example below: ✞ #include <fstream > 2 #include <iostream > using namespace std; 4 int main (int argc , char * argv []) { 6 ifstream inF("a.txt"); cout << inF.rdbuf(); 8 return 0; } ✌ ✆ streambuf is a stream buffer and is an object in charge of performing the reading and writing operations of the stream object it is associated with. The stream delegates all such operations to its associated stream buffer object, which is an intermediary between the stream and its controlled input and output sequences. 3.2 Accessing Files Files are named memory locations where data is stored in text or binary form. Each file that exists in the disk can be accessed, read and write if it is not specially granted restricted permissions. Users may create, access, update and delete a file by using C++ program.
  • 42. 222 Accessing System Files 3.2.1 Open A File A file in C++ can be opened in read, write, truncate or append mode. The flags used to open a file are given in following table. Flags Meaning ios::in Opens an input file without truncating the existing file. (ifstream) ios::ate Opens an existing file and seeks the end. ios::out Opens an output file. By default, ios::trunc is implied. (ofstream) ios::app Opens an output file for appending data. ios::nocreate Opens a file only if it already exists. ios::noreplace Opens a file only if it does not exist. ios::trunc Opens a file in truncate mode. ios::binary Opens a file in binary mode. Default is text mode. Table 3.1: File opening mode. To open a file, one can either call open on the file stream or, more commonly, use the constructor. One can also supply an open mode to further control the file stream. For reading-writing of the file, ‘fstream’ header file is used. ✞ 1 #include <fstream > using namespace std; 3 int main (int argc , char *argv []) { 5 ofstream file1; 7 file1.open ("file1.txt", ios:: app); file1 << "Appended data .n"; 9 ofstream file2("file2.txt"); 11 file2 << "Replace data .n"; 13 return 0; } ✌ ✆ Each file opened must be closed by using function close(). On unsuccessful, a flag is set in the stream object. The flag status is checked by good(), bad() or fail() member functions, which return a boolean value. The stream object doesn’t throw any exceptions in such a situation, hence manual status check is required. ✞ #include <iostream > 2 #include <fstream > using namespace std; 4
  • 43. 3.2. ACCESSING FILES 223 int main (int argc , char *argv []) { 6 /* Try to open non -exist file xyz.txt.* 8 *fstream does not show any errors. */ ifstream file1; 10 file1.open ("zyz.txt", ios::in); 12 /*To check whether a xyz.txt is really* *opened or not , we use good () object.*/ 14 cout << file1.good (); /* Returns 0*/ cout << endl ; 16 /* Try to open existing file a.txt. */ 18 ifstream file2; file2.open ("a.txt", ios::in); 20 /*To check whether a a.txt is really * 22 *opened or not , we use good () object.*/ cout << file2.good (); /* Returns 1*/ 24 } ✌ ✆ ✞ 0 1 ✌ ✆ fail() tries to read the next character from the input stream. If it fails to read the next character due to EOF, it returns true otherwise it returns false. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char ** argv ) { char name ; 6 cout << "Enter the name : "; cin.get(name ); 8 while (cin.fail () == false) { cout << name << endl ; 10 cin.get(name ); } 12 return 0; } ✌ ✆ 3.2.2 Read File Data While reading a file, input from the in-stream is assigned to a string variable, until the file or in-stream does not reach to EOF pitfall or until an error does not occur. getline() function is used for this purpose. ✞ 1 #include <fstream > #include <string >
  • 44. 224 Accessing System Files 3 #include <iostream > using namespace std; 5 int main (int argc , char ** argv ) { 7 /* Line number counter */ int linecount = 0; 9 string line ; /* Open input file */ 11 ifstream inFile("file1.txt"); /*If input file is successfully opened.*/ 13 if (inFile) { /* Read line by line of text file . * 15 *until end of file is not found. */ while (getline(inFile , line )) { 17 /* Print the line number and line */ cout << linecount << ": " << line << ’n’; 19 /* Increment the line number */ linecount ++; 21 } } 23 /* Close input file .*/ inFile.close(); 25 return 0; } ✌ ✆ We can also read a file byte by byte as the method given below: ✞ #include <fstream > 2 #include <string > #include <iostream > 4 using namespace std; 6 int main (int argc , char ** argv ) { ifstream is("file1.txt"); 8 char c; 10 while (is.get(c)) cout << c << endl ; 12 is.close(); 14 return 0; 16 } ✌ ✆ To check whether the file has been reached to its end, eof () member function is used as shown in the syntax given below. ✞ if (infile.eof()) break ✌ ✆
  • 45. 3.2. ACCESSING FILES 225 Infile Stream ifstream operator is used to open an input file stream. It is always followed by input stream name. A file name is argument of the input stream name. To use this operator, header file ‘fstream’ is required. Syntax of ifstream is given as ✞ 1 ifstream <stream name >("<file name >"); ✌ ✆ An example is given below: ✞ 1 #include <string > #include <fstream > 3 using namespace std; 5 int main (int argc , char *argv []) { /* Open a file stream to read */ 7 ifstream f1("a.txt"); ofstream f2("b.txt"); 9 string s; while (getline(f1 , s)) 11 f2 << s << "n"; } ✌ ✆ On execution, we shall get desired result. 3.2.3 Write File Data The data of user is stored in memory as data file. To write a file in memory, data is first transfer to out stream buffer and them it is flushed into the memory. Outfile Stream ofstream operator is used to open an output file stream. This is member of fstream (file stream) class. It is always followed by output stream name. A file name is argument of the output stream name. To use this operator, header file ‘fstream’ is required. Syntax of ofstream is given as ✞ ofstream <stream name >("<file name >"); ✌ ✆ An example is given below: ✞ 1 #include <string > #include <fstream > 3 using namespace std; 5 int main (int argc , char *argv []) { ifstream f1("a.txt"); 7 /* Open a file stream to write*/ ofstream f2("b.txt"); 9 string s; while (getline(f1 , s))
  • 46. 226 Accessing System Files 11 f2 << s << "n"; f1.close(); 13 f2.close()’ return 0; 15 } ✌ ✆ On execution, we shall get desired result. Concatenation of the strings is allowed in C++ by using operator ‘+=’. See the example below: ✞ 1 #include <string > #include <fstream > 3 #include <iostream > using namespace std; 5 int main (int argc , char *argv []) { 7 ifstream f1("a.txt"); /* Open a file stream to write*/ 9 ofstream f2("b.txt"); string s, line ; 11 while (getline(f1 , s)) line += s + "n"; 13 f2 << line ; cout << line ; 15 } ✌ ✆ 3.2.4 File As Function Argument A input or output file stream allows to pass a file pointer to a function as its argument. The syntax of argument is like ✞ 1 ifstream & <arg name > // for input file stream ofstream & <arg name > // for output file stream ✌ ✆ In the following example, out file stream is passed to function argument and contents are written in the out file. ✞ #include <iostream > 2 #include <fstream > using namespace std; 4 void PassToFunc (ofstream &f, int n) { 6 f << n; } 8 int main () { 10 ofstream f1("b.txt"); PassToFunc (f1 , 10); 12 return 0; } ✌ ✆ It creates a file “b.txt” in which integer 10 is written.
  • 47. 3.2. ACCESSING FILES 227 3.2.5 File Position We can access the location of file pointer by using tellp() for an out stream (ostream) and tellg() for an in stream (istream). seekp return the stream position (streampos) of an out stream (ostream) and seekg() returns the stream position of an in stream (istream). seekp and seekg() takes two arguments. First is number of byte, either positive or negative value and second is direction. The seek directions are Flags Meaning ios::beg From the beginning of stream. ios::cur From the current position of stream. ios::end From the end of stream. Table 3.2: Seek Directions. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 (1) fp (2) fp.seekp(-8, ios::cur) (3) fp (4) Figure 3.1: Change in location of file pointer from current file pointer location. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 (1) fp (2) fp.seekp(-8, ios::end) (3) fp (4) Figure 3.2: Change in location of file pointer from the end of file location.
  • 48. 228 Accessing System Files 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 (1) fp (2) fp.seekp(10, ios::beg) (3) fp (4) Figure 3.3: Change in location of file pointer from the beginning of file location. In following example, a file ‘a.txt’ is read and file pointer is set after 10bytes using seekg() function from the beginning of the file. The current position of the in file stream is return by using function tellg() function. ✞ 1 #include <fstream > #include <iostream > 3 using namespace std; 5 int main (int argc , char * argv []) { /* Open in file */ 7 ifstream inf("a.txt"); /* Set file pointer after 10 bytes* 9 *from beginning of current file */ inf.seekg(10, ios:: cur); 11 /* Get current position of file pointer */ cout << inf.tellg(); 13 return 0; } ✌ ✆ ✞ 10 ✌ ✆ In following example, we set the file pointer after 10 bytes from the end of the file location. ✞ 1 #include <fstream > #include <iostream > 3 using namespace std; 5 int main (int argc , char * argv []) { /* Open in file */ 7 ifstream inf("a.txt"); /* Set file pointer after -10 bytes* 9 *from the end of the current file */ inf.seekg(-10, ios:: end); 11 /* Get current position of file pointer */ cout << inf.tellg();
  • 49. 3.3. DATA STRUCTURES 229 13 return 0; } ✌ ✆ ✞ 228 ✌ ✆ For output stream, seekp() and tellp() functions are used. ✞ 1 #include <fstream > #include <iostream > 3 using namespace std; 5 int main (int argc , char * argv []) { /* Open out file */ 7 ofstream outf ("b.txt"); /* Set file pointer after 11 bytes* 9 *from beginning of current file */ outf . seekp(11, ios:: beg); 11 /* Get current position of file pointer */ cout << outf .tellp(); 13 return 0; } ✌ ✆ ✞ 11 ✌ ✆ We can write something after the specific position in the current out file by using ‘<<’ operator. ✞ 1 #include <fstream > #include <iostream > 3 using namespace std; 5 int main (int argc , char * argv []) { ofstream outf ("b.txt"); 7 outf . seekp(11, ios:: beg); outf << "This is my file "; 9 return 0; } ✌ ✆ 3.3 Data Structures A data structure (struct) contains multiple pieces of data. Each piece of data (called a “member”) can be accessed by using a group of instance of structure, followed by a ‘.’ (ie dot), then the name of the member (another way to access a member is using the member operator ‘−>’ for pointers.). The member variables of data structure can be of any data-type or can be an array or a pointer.
  • 50. 230 Accessing System Files 3.3.1 Struct A data structure contains multiple pieces of data. One defines a data structure using the struct keyword. For example, ✞ struct <mystruct >{ 2 int <int_member >; double <double_member >; 4 char <string_member [25] >; } <variable >; ✌ ✆ ‘variable’ is an instance of ‘mystruct’. One can omit it from the end of the struct decla- ration and declare it later using: ✞ 1 struct <mystruct > <variable >; ✌ ✆ It is often common practice to make a type synonym so we don’t have to type struct ‘mystruct’ all the time. The struct itself has no name (by the absence of a name on the first line), but it is aliased as ‘mystruct’. Then you can use ✞ 1 <mystruct > <variable >; ✌ ✆ We can add or read data in structure by just using ‘dot’ symbol as ✞ 1 struct student { int id; 3 char *name ; float perc ; 5 } st; st.id =1;/* use of dot symbol between instance name and struct element.*/ ✌ ✆ After creating an instance of structre, instance reserves the memory bytes equal to the sum of size of all members. See the figure given below: a b c d e f g h i j st id name perc Here is working example of struct function: ✞ #include <iostream > 2 using namespace std; 4 struct student { int id; 6 char *name ; float perc ; 8 } st , st1 , st2;
  • 51. 3.3. DATA STRUCTURES 231 10 int main (int argc , char *argv []) { st.id = 1; 12 st1.name = "Arun Umrao"; st2.perc = 90.5; 14 cout << "Id is: " << st.id << endl ; cout << "Name is: " << st1.name << endl ; 16 cout << "perc is: " << st2.perc << endl ; return 0; 18 } ✌ ✆ ✞ Id is: 1 Name is: Arun Umrao perc is: 90.5 ✌ ✆ Another simple example is given below. ✞ 1 #include <iostream > using namespace std; 3 struct data { 5 int val; float b; 7 }; 9 int main (int argc , char *argv []) { struct data s; 11 s.val = 12; s.b = 3.14159; 13 cout << "The val field in s is:" << s.val << endl ; return 0; 15 } ✌ ✆ ✞ The val field in s is: 12 ✌ ✆ Pointer can be also used in structure. An instance of a structure ‘data’ using a pointer is declared as ✞ 1 data *<variable >; ✌ ✆ Member values of the structure declared with pointer are initialized or accessed by using operator − >. See the following syntax, in which a structure ‘Func’ is declared by using a pointer and its member values are set by using operator − >. ✞ 1 struct Func { int val; 3 float fl; }; 5 struct Func *b; b->val = 3491; ✌ ✆
  • 52. 232 Accessing System Files st st++ val fl A working example is ✞ #include <iostream > 2 using namespace std; 4 struct Func { int val; 6 float fl; }; 8 int main (int argc , char *argv []) { 10 /* Func struct required for pointer */ struct Func a; 12 /* this is a pointer to a struct Func */ struct Func *b; 14 b->val = 3491; cout << "The value of b is " << b->val << endl ; 16 return 0; } ✌ ✆ ✞ The value of b is 3491. ✌ ✆ A struct data can also be passed to a function by using address of procedure. See the example below in which data struct is passed to function ‘Plantation’. ✞ 1 #include <iostream > using namespace std; 3 /* Data structure */ 5 struct Data { int Trees; 7 int Plants; }; 9 /* function Plantation with data structure as pointer */ 11 void Plantation (struct Data *f) { f->Trees = 10; 13 f->Plants = 20; } 15 int main (int argc , char *argv []) { 17 /* Struct data structure */ struct Data Bio; 19 /* Pass address ‘Bio ’ into struct ‘Data ’ as pointer */ Plantation (& Bio);
  • 53. 3.3. DATA STRUCTURES 233 21 cout << "Trees : " << Bio.Trees << endl ; /* prints "10" */ cout << "Plants : " << Bio.Plants << endl ; /* prints "20" */ 23 return 0; } ✌ ✆ ✞ Trees : 10 Plants : 20 ✌ ✆ A constant pointer, once holds an address cannot change to the new address. It means a constant pointer, if already pointing to an address, cannot point to a new address. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { char ch = ’A’; 6 char cH = ’B’; 8 char * const ptr = &ch; // A constant pointer ptr = &cH; // Illegal way of pointer . 10 return 0; 12 } ✌ ✆ In case of pointer to structure, if the things on the left of the ‘.’ (dot) or ‘− >’ operator is qualified (with ‘const’ or ‘volatile’) then the result is also has those qualifiers associated with it. In the following example, when the pointer points to a qualified type the result got is also qualified. ✞ #include <iostream > 2 using namespace std; 4 struct myStruct { int i; 6 }; 8 int main (int argc , char *argv []) { /* Initialisation of structures . */ 10 struct myStruct *Ptr , s_item; /* Initialisation of structures of constant qualifier . */ 12 const struct myStruct *s_Ptr; /* Set the item value.*/ 14 s_item.i = 1; /* OK */ /* Assigning new pointer .*/ 16 Ptr = &s_item; Ptr ->i += 2; /* OK */ 18 /* Constant qualified pointer.*/ s_Ptr = &s_item; 20 s_Ptr ->i = 0; /* Not OK to point constant type qualifier . */ return 0;
  • 54. 234 Accessing System Files 22 } ✌ ✆ A structure can also be initialized at the starting of program if structure is defined as ✞ struct employee { 2 int no; int sex; 4 int age; }; 6 struct employee EmpNo={<int >, <int >, <int >}; ✌ ✆ The following example clears the initialization of the structure. ✞ #include <iostream > 2 using namespace std; 4 struct employee { int no; 6 int sex; int age; 8 }; 10 int main (int argc , char *argv []) { struct employee EmpNo = {10, 1, 15}; /* Initializing structure */ 12 cout << EmpNo.no << endl << EmpNo.sex << endl << EmpNo.age; return 0; 14 } ✌ ✆ Nested Structure When a loop is declared inside another loop then the inner loop is called nested loop. ✞ for (;;) { 2 for (;;) /* Nested for loop */ } ✌ ✆ Similarly, when a structure is declared inside another structure then it is called nested structure. Nested structure can be declared by using either normal variable or pointer. In following example, a nested structure is declared and declared by simple variable. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 /* date structure */ 7 struct date { int day; 9 int month; int year ;
  • 55. 3.3. DATA STRUCTURES 235 11 }; 13 /* variety structure */ struct variety {/* Upper level structure */ 15 char *name ; /* Nested structure . Declared by normal variable . * 17 * Element of the structure are accessed by dot (.)*/ struct date date ; /* Lower level structure as normal variable .*/ 19 } tr; /* Structure declared as normal variable . * * Elements can be accessed by (.) symbol.*/ 21 /* Accessing structure elements by using synopsis like 23 * up_level_struct (.) up_level_elem * or 25 * up_level_struct (.) low_level_struct (.) low_level_elem */ tr.name = "A"; 27 tr.date .day = 10; cout << "Name : " << tr.name << endl ; 29 cout << "day : " << tr.date .day << endl ; return 0; 31 } ✌ ✆ ✞ Name : A day : 10 ✌ ✆ In simple variable type declaration of structure, elements are accesses by using dot (.). Using of pointer symbol (−>) throws the errors. In above example, ‘name’ and ‘date’ are elements of the ‘variety’ structure. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { 6 /* date structure */ struct date { 8 int day; int month; 10 int year ; }; 12 /* variety structure */ 14 struct variety {/* Upper level structure */ char *name ; 16 /* Nested structure . Declared by normal variable . * * Element of the structure are accessed by dot (.)*/ 18 struct date date ; /* Lower level structure as normal variable .*/ } tr; /* Structure declared as normal variable . * 20 * Elements can be accessed by (.) symbol.*/
  • 56. 236 Accessing System Files 22 /* Accessing structure elements by using synopsis like * up_level_struct (.) up_level_elem 24 * or * up_level_struct (.) low_level_struct (.) low_level_elem */ 26 tr.name = "A"; tr.date .day = 10; 28 /* Following line throws errors. Reason is that we are trying* *to access the element by pointer symbol (->) even though * 30 *the structure ‘tr ’ is declared here as normal variable . */ tr ->date .month = 11; 32 cout << "Name : " << tr.name << endl ; cout << "day : " << tr.date .day << endl ; 34 return 0; } ✌ ✆ By other way, we can use pointer method to assign one structure inside other structure. In pointer method, elements are accessed by using pointer symbol (−>) and dot (.). ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 /* date structure */ 7 struct date { int day; 9 int month; int year ; 11 }; 13 /* variety structure */ struct variety {/* Upper level structure */ 15 char *name ; /* Nested structure . Declared by normal variable . * 17 * Element of the structure can accessed by dot (.)*/ struct date date ; /* Lower level structure as normal variable .*/ 19 } *tr; /* Structure declared as pointer variable . * * Elements can be accessed by (->) symbol.*/ 21 /* Accessing structure elements by using synopsis like * up_level_struct (->) up_level_elem 23 * or * up_level_struct (->) low_level_struct (.) low_level_elem */ 25 tr ->name = "A"; tr ->date .day = 10; 27 cout << "Name : " << tr ->name << endl ; cout << "day : " << tr ->date .day << endl ; 29 return 0; } ✌ ✆
  • 57. 3.3. DATA STRUCTURES 237 ✞ Name : A day : 10 ✌ ✆ Again, indirect membership operator or structure pointer operator (−>) is not used in the level or element of the structure declared as normal variable. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { 6 /* date structure */ struct date { 8 int day; int month; 10 int year ; }; 12 /* variety structure */ 14 struct variety {/* upper level structure */ char *name ; 16 /* Nested structure . Declared by normal variable . * * Element of the structure are accessed by dot (.)*/ 18 struct date date ; /* Lower level structure as normal variable .*/ } *tr; /* Structure declared as pointer variable .* 20 * Elements are accessed by (->) symbol. */ /* Following lines throw errors. We are trying here to access * 22 *the elements of structure ‘date ’ by pointer symbol (->) while* *the structure ‘date ’ is declared here as normal variable . */ 24 tr ->date ->day = 10; tr.date ->day = 10; 26 return 0; } ✌ ✆ But the lower level elements can also be accessed by using pointer symbol (−>) if lower level structure is also declared as pointer level. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 /* date structure */ 7 struct date { int day; 9 int month; int year ; 11 };
  • 58. 238 Accessing System Files 13 /* variety structure */ struct variety {/* upper level structure */ 15 char *name ; /* Nested structure . Declared as pointer variable .* 17 * Element of the structure can accessed by (->) */ struct date *date ; /* Lower level structure as normal variable .*/ 19 } *tr; /* Structure declared as pointer variable . * * Elements can be accessed by (->) symbol.*/ 21 cout << "Date & Month :" << endl ; /* Accessing structure elements by using synopsis like 23 * up_level_struct (->) up_level_elem * or 25 * up_level_struct (->) low_level_struct (->) low_level_elem */ tr ->date ->day = 10; 27 tr ->date ->month = 10; cout << "Day : " << (tr ->date ->day) << endl ; 29 cout << "Month : " << (tr ->date -> month) << endl ; return 0; 31 } ✌ ✆ ✞ Date & Month : Day : 10 Month : 10 ✌ ✆ In above examples, it is clarified that, elements of structures declared as variable type are accessed by using dot (.) and elements of structure declared as pointer type are accessed by using indirect membership operator or structure pointer operator (-¿). ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 /* date structure */ 7 struct date { int day; 9 int month; int year ; 11 }; 13 /* variety structure */ struct variety {/* up_level_struct (uls)*/ 15 char *name ; /* Nested structure . Declared as pointer variable .* 17 * Element of the structure are accessed by (->). */ struct date *date ; /* Lower level structure as normal variable .*/ 19 } tr; /* Structure declared as normal variable .* * Elements can be accessed by dot (.). */ 21
  • 59. 3.3. DATA STRUCTURES 239 /* Accessing structure elements by using synopsis like 23 * up_level_struct (.) up_level_elem * or 25 * up_level_struct (.) low_level_struct (->) low_level_elem */ tr.date ->day = 10; 27 tr.date ->month = 10; cout << "Day : " << (tr.date ->day) << endl ; 29 cout << "Month : " << (tr.date -> month) << endl ; return 0; 31 } ✌ ✆ ✞ Day : 10 Month : 10 ✌ ✆ Linked List See the followomg prototype for the definition of a structure: ✞ struct list_Elem { 2 int data ; struct list_Elem *ele_Ptr ; /* Element is structure itself.*/ 4 }; ✌ ✆ In this prototype, element of structure is structure itself. It is forbidden in the structure definition. But in fact it only contains a pointer to itself. It is allowed as by the time the compiler reaches the pointer declaration it already knows that there is such a thing as a ‘struct list Elem’ so the declaration is permitted. In fact, it is possible to make a incomplete declaration of a structure by saying ✞ struct list_Elem ; ✌ ✆ at some point before the full declaration. This will allow the declaration of pointers before the full declaration is seen. It is also important in the case of cross-referencing structures where each must contain a pointer to the other, as shown in the following example. ✞ 1 struct s_1; /* Incomplete type */ 3 struct s_2 { int something ; 5 struct s_1 *sp; }; 7 struct s_1 { /* Full declaration */ 9 float something ; struct s_2 *sp; 11 }; ✌ ✆ This illustrates the need for incomplete types. It also illustrates an important thing about the names of structure members: they inhabit a name-space per structure, so element
  • 60. 240 Accessing System Files names can be the same in different structures without causing any problems. Incomplete types may only be used where the size of the structure isn’t needed yet. A full declaration must have been given by the time that the size is used. The later full declaration mustn’t be in an inner block because then it becomes a new declaration of a different structure. ✞ 1 struct x; /* Incomplete type */ 3 /* valid uses of the tag */ struct x *p, func (void ); 5 void f1(void ) { 7 struct x { int i; 9 }; /* redeclaration ! */ } 11 /* full declaration now */ 13 struct x { float f; 15 } s_x; 17 void f2(void ) { /* valid statements */ 19 p = &s_x; *p = func (); 21 s_x = func (); } 23 struct x func (void ) { 25 struct x tmp; tmp.f = 0; 27 return (tmp); } ✌ ✆ The other principal way to get incomplete types is to declare arrays without specifying their size and their type is incomplete until a later declaration provides the missing information: ✞ int ar []; /* incomplete type */ 2 int ar [5]; /* completes the type */ ✌ ✆ If you try that out, it will only work if the declarations are outside any blocks (external declarations), but that’s for other reasons. There were three elements linked into the list, which could have been built like this: ✞ struct list_Elem { 2 int data ; struct list_Elem *pointer ; 4 } ar [3]; 6 int main (int argc , char *argv []) {
  • 61. 3.3. DATA STRUCTURES 241 ar [0]. data = 5; 8 ar [0]. pointer = &ar [1]; ar [1]. data = 99; 10 ar [1]. pointer = &ar [2]; ar [2]. data = -7; 12 ar [2]. pointer = 0; /* mark end of list */ return (0); 14 } ✌ ✆ and the contents of the list can be printed in two ways. The array can be traversed in order of index, or the pointers can be used as in the following example. ✞ #include <iostream > 2 using namespace std; 4 struct list_Elem { int data ; 6 struct list_Elem *pointer ; } ar [3]; 8 int main (int argc , char *argv []) { 10 struct list_Elem *lp; 12 ar [0]. data = 5; 14 ar [0]. pointer = &ar [1]; ar [1]. data = 99; 16 ar [1]. pointer = &ar [2]; ar [2]. data = -7; 18 ar [2]. pointer = 0; /* mark end of list */ 20 /* follow pointers */ lp = ar; 22 while (lp) { cout << "contents " << lp ->data << endl ; 24 lp = lp ->pointer ; } 26 return 0; } ✌ ✆ ✞ contents 5 contents 99 contents -7 ✌ ✆ Structure As Arguments A structure can also passed to a function as shown in the example below: ✞ 1 #include <iostream > using namespace std;
  • 62. 242 Accessing System Files 3 #define TREE_NUM 50 5 /* Structure for garden tree length.*/ 7 struct g_len { char gardens[TREE_NUM ]; 9 double t_len_1; double t_len_2; 11 }; 13 /* Structure passed to the function .*/ double sum(struct g_len val) { 15 return (val.t_len_1 + val.t_len_2 ); } 17 int main (int argc , char *argv []) { 19 /* Initialized the structure .*/ struct g_len sbi = { 21 "G DELHI", 6524.12 , 23 9458.87 }; 25 double s=sum(sbi); cout << "Tree length is " << s << endl ; 27 return 0; } ✌ ✆ ✞ Tree length is 15982.99 m. ✌ ✆ 3.3.2 Enumerate In C++, enumerations are created by explicit definitions, which use the enum keyword and are reminiscent of struct and union definitions. Point of declaration of enum is that point of the program body, where, enum list is started. See example below. ✞ 1 #include <iostream > using namespace std; 3 enum { 5 /*0*/ /*1*/ /*2*/ TRUE , FALSE , NO 7 } b = NO; 9 int main (int argc , char ** argv ) { cout << "bool : " << b << endl ; 11 return 0; } ✌ ✆
  • 63. 3.3. DATA STRUCTURES 243 ✞ bool : 2 ✌ ✆ C also allows the programmer to choose the values of the enumeration constants explicitly, even without type. ✞ 1 #include <iostream > using namespace std; 3 enum { 5 TRUE = 0, FALSE = 1, NO = 10 } b = NO; 7 int main (int argc , char ** argv ) { 9 cout << "bool : " << b << endl ; return 0; 11 } ✌ ✆ ✞ bool : 10 ✌ ✆ In enumerate the values are assigned successively. If any enum key is set to a specific value then next enum key has value one larger than its preceding enum key if its value is not set. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 enum COLORS { 7 BLUE , /* Index value 0*/ GREEN = 3, /* Index value 3*/ 9 YELLOW , /* Index value 4*/ RED = 2, /* Index value 2*/ 11 BLACK /* Index value 3*/ }; 13 cout << "The colors are:n"; cout << BLUE << endl ; /*0*/ 15 cout << YELLOW << endl ; /*4*/ cout << BLACK << endl ; /*3*/ 17 return 0; 19 } ✌ ✆ ✞ The colors are: 0 4 3 ✌ ✆
  • 64. 244 Accessing System Files 3.3.3 Union The definition of a union is similar to that of a struct. The difference between the two is that in a struct, the members occupy different areas of memory, but in a union, the members occupy the same area of memory. Thus, in the following type, for example: ✞ union { 2 int i; double d; 4 } u; ✌ ✆ The programmer can access either ‘u.i’ or ‘u.d’, but not both at the same time. Since ‘u.i’ and ‘u.d’ occupy the same area of memory, modifying one modifies the value of the other, sometimes in unpredictable ways. The size of a union is the size of its largest member. A simple example is ✞ #include <iostream > 2 #include <string > using namespace std; 4 union Data { 6 int i; float f; 8 char str [50]; }; 10 int main (int argc , char ** argv ) { 12 union Data data ; data .i = 10; 14 data .f = 220.5; string str("C Programming "); 16 str.copy (data .str , str.length()); data .str[str.length ()]=’0’; 18 cout << "data .i : " << data .i << endl ; cout << "data .f : " << data .f << endl ; 20 cout << "data .str : " << data .str << endl ; return 0; 22 } ✌ ✆ ✞ data .i : 1917853763 data .f : 4.12236 e+30 data .str : C Programming ✌ ✆ A constructor and destructor member function can also be declared inside the union. union has few restrictions like 1. A union cannot have virtual functions, members of reference type and base classes. It cannot be used as a base class. 2. If a union has a member with a user-defined constructor, a copy operation, a move operation, or a destructor, then that special function is deleted for that union; that is, it cannot be used for an object of the union type.
  • 65. 3.4. MEMORY MANAGEMENT 245 3. At most one member of a union can have an in-class initializer. 3.4 Memory Management 3.4.1 Create Memory Space If there is requirement of a few bytes of memory to store data then we allocate memory space by using simple variables. But in case of array, string and stacks where addition of data is not static a dynamic memory allocation is required. Arrays, strings and stack stores non-counting data when a program is in run thus the memory size should be expanded when a new data is added. Allocation of memory while program is in run is called dynamic memory allocation. To create a dynamic memory space, we use new keyword for this purpose. Its syntax is ✞ 1 int *i = new int [10];/*A block of ten integers .*/ int *j = new int (10) ; /* Heap allocation for 10 integers .*/ ✌ ✆ The new returns the address of first element of the array to the pointer ‘i’. Each time a dynamic memory is created, must be freed before exit from the program by using delete keyword. ✞ delete i; ✌ ✆ ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int *i = new int [5]; int j; 7 for (j = 0; j < 5; j++) { i[j] = j; 9 } 11 for (j = 0; j < 5; j++) { cout << i[j] << endl ; 13 } delete i; 15 return 0; } ✌ ✆ ✞ 0 1 2 3 4 ✌ ✆
  • 66. 246 Accessing System Files 3.4.2 Delete Memory Space Each memory heap created dynamically by new operator must be freed by using delete keyword. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char ** argv ) { 5 int *i = new int [5]; // Create space for 5 integers delete i; // Clear the space 7 return 0; } ✌ ✆ 3.4.3 Placement Memory Space new() operator is used to place a memory space over the given buffer stack. For example, ‘b’ is declared as a buffer of two element. The new() operator ✞ int b[2]; 2 /* Create memory space and filled with 5*/ int *i = new(b) int (5); ✌ ✆ places a memory space over buffer and puts the integer value ‘5’. The address of this element is assigned to variable ‘i’. Similarly, ✞ 1 int *i = new(b + sizeof (int)) int (6); ✌ ✆ puts the integer value ‘6’ over the buffer at memory location 4 bytes (size of integer) ahead to the address of buffer ‘b’. See the example below: ✞ 1 #include <iostream > using namespace std; 3 int main () { 5 int b[2]; int *i = new(b) int (5); 7 int *j = new (b + sizeof (int)) int (6); cout << *i << endl ; 9 cout << *j << endl ; return 0; 11 } ✌ ✆ ✞ 5 6 ✌ ✆ Placements are not deallocated by using delete keyword.
  • 67. 3.5. STACK 247 3.5 Stack C++ has a ‘stack’ library which deals with all stack related activities. An stack is initiated as ✞ stack <int > myStack; /* For integer stack*/ 2 stack <float > myStack; /* For float stack*/ stack <string > myStack; /* For string stack*/ ✌ ✆ Stack is based on the Last In First Out (LIFO) principle. The last element inserted by push() function returns at first by pop() function. 3.5.1 Empty Stack empty() function tells whether a stack is empty or non empty. If stack is empty then it returns true otherwise returns false. ✞ 1 #include <iostream > #include <stack > 3 using namespace std; 5 int main (int argc , char ** argv ) { stack <int > myStack; 7 myStack .push (10) ; cout << myStack.empty() << endl ; /* Returns 0*/ 9 myStack .pop(); cout << myStack.empty() << endl ; /* Returns 1*/ 11 return 0; } ✌ ✆ ✞ 0 1 ✌ ✆ 3.5.2 Size of Stack size() function returns the size of the stack. ✞ #include <iostream > 2 #include <stack > using namespace std; 4 int main (int argc , char ** argv ) { 6 stack <int > myStack; myStack .push (10) ; 8 myStack .push (11) ; myStack .push (12) ; 10 cout << "Size of stack : "; cout << myStack.size () << endl ; /* Returns 3*/ 12 myStack .pop();
  • 68. 248 Accessing System Files cout << "Size of stack : "; 14 cout << myStack.size () << endl ; /* Returns 2*/ return 0; 16 } ✌ ✆ ✞ Size of stack : 3 Size of stack : 2 ✌ ✆ 3.5.3 Get Top Element top() returns the reference of topmost element of the stack. This function can replace the top most element or can do arithmetic on it if arithmetic operator is used. ✞ #include <iostream > 2 #include <stack > using namespace std; 4 int main (int argc , char ** argv ) { 6 stack <int > myStack; myStack .push (10) ; 8 myStack .push (11) ; myStack .push (12) ; 10 cout << "Size of stack before top () is : "; cout << myStack.size () << endl ; /* Returns 3*/ 12 myStack .top() = 10; cout << "Size of stack after top () is : "; 14 cout << myStack.size () << endl ;/* Returns 3*/ cout << "Top stack is : "; 16 cout << myStack.top () << endl ; /* Returns 10*/ myStack .top() -= 7; 18 cout << "Top stack is : "; cout << myStack.top () << endl ; /* Returns 3*/ 20 return 0; } ✌ ✆ ✞ Size of stack before top () is : 3 Size of stack after top () is : 3 Top stack is : 10 Top stack is : 3 ✌ ✆ 3.5.4 Add Element at Top push function is used to add an element into the stack. Its syntax is ✞ <stack name >. push (<value >); ✌ ✆
  • 69. 3.5. STACK 249 ✞ 1 #include <iostream > #include <stack > 3 using namespace std; 5 int main (int argc , char ** argv ) { stack <int > myStack; 7 myStack .push (10) ; myStack .push (11) ; 9 myStack .push (12) ; cout << "Top element is : "; 11 cout << myStack.top () << endl ; /* Returns 12*/ return 0; 13 } ✌ ✆ ✞ Top element is : 12 ✌ ✆ 3.5.5 Remove Top Element pop is used to remove the top of the element of a stack. It is used as ✞ 1 <stack name >. pop(); ✌ ✆ ✞ 1 #include <iostream > #include <stack > 3 using namespace std; 5 int main (int argc , char ** argv ) { stack <int > myStack; 7 myStack .push (10) ; myStack .push (11) ; 9 myStack .push (12) ; cout << "Top element is : "; 11 cout << myStack.top () << endl ; /* Returns 12*/ myStack .pop(); /* Remove top most element */ 13 cout << "Top element is : "; cout << myStack.top () << endl ; /* Returns 11*/ 15 return 0; } ✌ ✆ ✞ Top element is : 12 Top element is : 11 ✌ ✆
  • 70. 250 OOP in C++
  • 71. 4.1. STRUCTURES 251 4OOP in C++ 4.1 Structures In Object Oriented Programming, a structure is required. A struct is like a class except for the default access. C++ also support the C like structure. Structures are also allow Operator Overloading. A struct is defined as ✞ struct myStructType /*: inheritances */ { 2 public: <public memters > 4 protected : <protected members > 6 private : <private members > 8 } myStructName ; ✌ ✆ public members are accessed from anywhere by declaring structure object and calling public member. private members are accessed within the structure definition only, i.e. by member classes or member functions defined within the parent structure. protected members are accessible in the class or through derived classes. An object of type ‘myS- tructType’ is declared as ✞ myStructType <object name >; ✌ ✆ The simplest example of the struct is the structure for the coordinate point. A point structure is defined and initialized as ✞ 1 struct Point { double x, y; 3 }; ✌ ✆ In this definition of structure, there are two members named as x and y. We can set the values to the member of this structure as ✞ 1 struct Point blank; blank.x = 3.0; 3 blank.y = 4.0; ✌ ✆ We can read the values of an instance variable using the same syntax we used to write them: ✞ 1 int x = blank.x; ✌ ✆ See the example below:
  • 72. 252 OOP in C++ ✞ 1 #include <iostream > using namespace std; 3 struct Point { 5 double x, y; }; 7 int main (int argc , char *argv []) { 9 struct Point point; point.x = 1; 11 point.y = 1.5; cout << "x is " << point.x << " and y is " << point.y; 13 return 0; } ✌ ✆ ✞ x is 1 and y is 1.5 ✌ ✆ The detailed explanation is given in struct section. Size of struct is equal to the sum of sizes of its all variables. ✞ 1 #include <iostream > using namespace std; 3 struct A { 5 int i [30]; /*30 X 4= 120 bytes*/ int j [20]; /*20 X 4= 80 bytes*/ 7 };/* Total size is 200 bytes*/ 9 int main (int argc , char *argv []) { cout << "sizeof struct A = " << sizeof (A) 11 << " bytes" << endl ; return 0; 13 } ✌ ✆ ✞ sizeof struct A = 200 bytes ✌ ✆ struct can also holds the member function inside them. A member function inside the struct is modified by using operator ‘::’. The member function is accessed by calling struct and its member function. See the example below: ✞ 1 #include <iostream > using namespace std; 3 struct A { 5 void g();/* declaring member function */ }; 7 /* Accessing the member function g()* 9 *of structure A and modifing to it*/
  • 73. 4.1. STRUCTURES 253 void A::g() { 11 cout << "Sturcture A" << endl ; } 13 int main (int argc , char *argv []) { 15 /* Declare and initialized struct A*/ struct A a; 17 /* Call to memeber function g()*/ a.g(); 19 return 0; } ✌ ✆ ✞ Sturcture A ✌ ✆ Pointer can also be used in argument of a member function. A child structure alongwith its members can also be defined inside the parent structure. See the example below: ✞ 1 #include <iostream > using namespace std; 3 struct A { 5 /* declaring member function * *with pointer type argument */ 7 void g(int* x); 9 struct B { void h(); 11 }; }; 13 /* Accessing the member function g()* 15 *of structure A and modifing to it*/ void A::g(int* x) { 17 cout << "Sturcture A" << endl ; cout << "x is " << *x << endl ; 19 } 21 void A::B::h() { cout << "Nested struct !!"; 23 } 25 int main (int argc , char *argv []) { struct A a; 27 int i = 12; a.g(&i); 29 struct A::B b; b.h(); 31 return 0; } ✌ ✆
  • 74. 254 OOP in C++ ✞ Sturcture A x is 12 Sturcture A x is -12 ✌ ✆ Following example has a nested struct model. The nested model has member function h(). Function definition of this member function is defined outside the structure by using operator ‘::’. ✞ #include <iostream > 2 using namespace std; 4 /* Outer parent structure */ struct A { 6 void g(int* x); 8 /* Nested child structure */ struct B { 10 void h(); }; 12 }; 14 void A::g(int* x) { cout << "Sturcture A" << endl ; 16 cout << "x is " << *x << endl ; } 18 /* Accessing function of nested child B * 20 *structure and defining its definitions .*/ void A::B::h() { 22 cout << "Nested struct !!"; } 24 int main (int argc , char *argv []) { 26 struct A a; int i = 12; 28 a.g(&i); struct A::B b; 30 b.h(); return 0; 32 } ✌ ✆ ✞ Sturcture A x is 12 Nested struct !! ✌ ✆
  • 75. 4.2. CLASSES 255 4.2 Classes Classes are used to create user defined types which includes the set of functions. An instance of a class is called an object and programs can contain any number of classes. As with other types, object types are case-sensitive. A class can have both, the data members and the function members associated with it. A class is defined by: ✞ 1 class MyClass { /* public , protected and private * 3 * variables /constants /functions */ }; ✌ ✆ An object of MyClass class is declared as shown in the following syntax. ✞ MyClass object; ✌ ✆ By default, all class members are initially private unless they are declared as pro- tected or public. A class is like a container which contains is all members. ✞ 1 class MyClass { int x;// integer variable x 3 void f(){}// function with definition }; ✌ ✆ MyClass x void f() Figure 4.1: Fields/Members of a class. Remember that the memory arrangement of the class object is in different form. Non- virtual functions do not reflects in memory arrangement. (See Virtual Function Table (VFT) for details.) The object of a class can not access to private data members of own class but they can be accessed from within the class. ✞ #include <iostream > 2 using namespace std; 4 class A { int x = 1; 6 public: int y = 2; 8 void X(){
  • 76. 256 OOP in C++ cout << x << endl ; 10 } }; 12 int main () { 14 A *a = new A(); // cout << a->x;// Error!! accessing private member 16 cout << a->y << endl ; a->X(); // Return the value of private A::x 18 return 0; } ✌ ✆ ✞ 2 1 ✌ ✆ A x=1 y=2 X() a (object of A) x=1 y=2 X() In first part of above figure, all data members of the class ‘A’ are shown. In second part of above figure, object of class ‘A’ can not access private member ‘x’ directly but it can access to it via member function ‘X()’. If object of a class is declared twice then each object is created at different location of memory address. See in the example given below: ✞ #include <iostream > 2 using namespace std; 4 class Address { int HNo; 6 int BlockNo ; public: 8 void getLocality (); void getDistrict (); 10 void getState (); int pin; 12 }; 14 int main () { Address A, B; 16 cout << "Memory Address of object A is " << &A << endl ; cout << "Memory Address of object B is " << &B << endl ; 18 return 0;
  • 77. 4.2. CLASSES 257 } ✌ ✆ ✞ Memory Address of object A is 0x22ff 54 Memory Address of object B is 0x22ff 48 ✌ ✆ Object ‘B’ int A::HNo; 0x22ff48 int A::BlockNo; 0x22ff4C int A::pin; 0x22ff50 Object ‘A’ int B::HNo; 0x22ff54 int B::BlockNo; 0x22ff58 int B::pin; 0x22ff5C Figure 4.2: Memory representation of object “Address B” and “Address A”. 4.2.1 Abstract Class An abstract class, a type of C++ class, is designed for specific use as a base class. A abstract class is that class which contains at least one pure virtual function by inheriting or by defining. See the following syntax: ✞ class myClass { 2 public: virtual void func ();// virtual function 4 virtual void funcn() = 0;// pure virtual function }; ✌ ✆ Here, function myClass::func is a pure virtual function. A function is said to be declared with definition, it function is followed by curly braces as shown below: ✞ 1 int func ();// Declaration without definition int func () {} // Declaration with definition ✌ ✆ A function declaration can not have both, i.e. a pure specifier and functions’ definition as shown below: ✞ class myClass { 2 public: virtual void func () {}= 0; // Invalid , compile time error 4 // virtual void func1() =0 {}; // Valid }; ✌ ✆ In above example, compiler shall show the error. An abstract class can not be declared as a parameter type or a function return type or the type of an explicit conversion or an object of an abstract class. However, pointers and references to an abstract class
  • 78. 258 OOP in C++ are acceptable. A derived class is abstract class unless its each inherited or owned pure virtual function is not overriden. ✞ 1 class myClass { // abstract base class public: 3 virtual void func () = 0;// pure virtual function }; 5 class myDerivedClass : public myClass {// Not an abstract class 7 void func ();// Virtual function is overriden here }; ✌ ✆ Instances can not be created for the abstract base class. Therefore, a class derived from an abstract base class will also be abstract class unless and instance of such derived class can not be created. ✞ #include <iostream > 2 using namespace std; 4 class myClass { // abstract class public: 6 virtual void func () = 0; // pure virtual function }; 8 class myDerivedClass : public myClass {// abstract class 10 void newfunc (); }; 12 int main (int argc , char *argv []) { 14 myDerivedClass myObj;// Not allowed return 0; 16 } ✌ ✆ The compiler will not allow the declaration of object myObj because myDerivedClass is an abstract class. It inherited the pure virtual function func() from myClass. To create the instances of derived class, we need to override each pure virtual function of the derived class as well as of its inherited base class. Above codes are modified as given in the below example: ✞ #include <iostream > 2 using namespace std; 4 class myClass { // abstract class public: 6 virtual void func () = 0; }; 8 class myDerivedClass : public myClass {// Not an abstract class 10 void func ();//As virtual function is overriden }; 12
  • 79. 4.2. CLASSES 259 int main (int argc , char *argv []) { 14 myDerivedClass myObj; // allowed return 0; 16 } ✌ ✆ The compiler, here allows the declaration of object myObj as myDerivedClass::func() overrides the inherited pure virtual function myClass::func(). A compiler issues a warning for the calling of a pure virtual function directly, but not if it is called indirectly. An example of abstract class and derived class is given below: ✞ #include <iostream > 2 using namespace std; 4 class B{// abstract base class public: 6 virtual void show () = 0; }; 8 class D: public B{// Derived class not abstract class as 10 // show () is overrided here public: 12 void show () { cout << "In Derived n"; } }; 14 int main (void ){ 16 /* Create object of class D and cast it for class B. Same members * *of class D shall be overrided by non -virtual member of class B.*/ 18 B *bp = new D(); /* Here the virtual function show () in base class does * 20 *not override to the show () function of derived class.*/ bp ->show (); 22 return 0; } ✌ ✆ ✞ In Derived ✌ ✆ 4.2.2 Friend Class Friend classes or functions can be declared within a class template. When a template is instantiated, the names of its friends are treated as if the specialization had been explicitly declared at its point of initialization. Friendship is not mutual. If a class A is friend of B, then B doesnt become friend of A automatically. Friendship is not inherited. See the example below in which, class B is friend of class A. ✞ 1 #include <iostream > using namespace std; 3
  • 80. 260 OOP in C++ class A { 5 int a, b; public: 7 A(int i, int j) : a(i), b(j) { 9 } friend class B; // class B as Friend of class A 11 }; 13 class B { public: 15 int dispSum (A& x) { 17 /* Since class B is friend of class A, hence * *private members of A are accessible here . */ 19 return x.a + x.b; } 21 }; 23 int main () { A a(2, 3); 25 B b; cout << b.dispSum(a); 27 return 0; } ✌ ✆ ✞ 5 ✌ ✆ As with non-template classes, the names of name-space-scope friend functions of a class template specialization are not visible during an ordinary lookup unless explicitly declared at name-space scope. If a friend declaration in a non-local class first declares a class or function, the friend class or function is a member of the innermost enclosing name-space. ✞ 1 #include <iostream > using namespace std; 3 namespace myNameSpace { 5 class myClass { 7 // myNameSpace :: func is a friend friend void func (myClass); 9 }; // myNameSpace :: func is not visible here 11 myClass myClassObj ; 13 void func (myClass) { /* definition */ 15 } // func () is defined and known to be a friend } 17 using myNameSpace :: myClassObj ;
  • 81. 4.2. CLASSES 261 19 int main (int argc , char *argv []) { 21 myNameSpace :: func (myClassObj ); // OK myNameSpace :: myClass :: func (myClassObj );// error 23 /* func () is not a member of myNameSpace :: myClass */ 25 return 0; } ✌ ✆ In this example, function func() can only be called through namespace myNameSpace using the call ✞ myNameSpace :: func (myClassObj ) ✌ ✆ Attempting to call function func() through class myClass using the ✞ 1 myNameSpace :: myClass :: func (myClassObj ); ✌ ✆ call results in a compile-time error. Since the friend declaration first occurs in a non-local class, the friend function is a member of the innermost enclosing name-space and may only be accessed through that name-space. 4.2.3 Nested Class A nested class is a class which is declared in another enclosing class. A nested class is a member of outer class. It has same rights as other members of the outer class have. The members of an enclosing class have no special access to members of a nested class. General rules of a class are obeyed for accessing of member of the class. ✞ 1 #include <iostream > using namespace std; 3 /* Outer class */ 5 class myOuter { public: 7 /* start of inner Nested class declaration */ 9 class myInnerNested { private : 11 int s; public: 13 void myFunction (int a, int b) { 15 s = a + b; } 17 void show () { 19 cout << "Sum of two numbers is " << s; } 21 }; };
  • 82. 262 OOP in C++ 23 int main (int argc , char ** argv ) { 25 myOuter :: myInnerNested NC; NC.myFunction (2, 3); 27 NC.show (); return 0; 29 } ✌ ✆ ✞ Sum of two numbers is 5 ✌ ✆ In the above example, class members, variable ‘s’ and ‘myFunction()’ & ‘show()’ functions are declared as public. Therefore, these two functions can be assessed as object of the class. See another example: ✞ 1 #include <iostream > using namespace std; 3 /* Outer class */ 5 class myOuter { public: 7 int x; 9 /* start of inner Nested class declaration */ class myInnerNested { 11 public: 13 void myFunction () { myOuter e; 15 cout << e.x; } 17 }; }; 19 int main (int argc , char ** argv ) { 21 myOuter OC; OC.x = 2; 23 myOuter :: myInnerNested NC; NC.myFunction (); 25 return 0; } ✌ ✆ ✞ 2 ✌ ✆ Another example, similar to above one. ✞ 1 #include <iostream > using namespace std; 3 /* Outer class*/ 5 class OuterClass {
  • 83. 4.2. CLASSES 263 public: 7 int x; public: 9 /* Public inner class*/ class InnerClass { 11 public: /* Public function func inside inner class*/ 13 void func (OuterClass * p, int i) { /* Access public variable of outer class*/ 15 p->x = i; } 17 }; }; 19 int main (int argc , char ** argv ) { 21 /* Create object for outer class*/ OuterClass *oc = new OuterClass (); 23 /* Create object for inner class*/ OuterClass :: InnerClass ic; 25 /* Call function func of inner class*/ ic.func (oc , 10); 27 /* Get the value of variable x*/ cout << oc ->x; 29 return 0; } ✌ ✆ ✞ 10 ✌ ✆ A base class (say ‘Point’), can also be nested by creating its instances inside other base class (‘say Vector’). In this case, fields of the ‘Vector’ class are ‘Point’ class. See the syntax given below: ✞ 1 class Point{ public: 3 double x,y; }; 5 class Vector{ public: 7 Point init , final; }; ✌ ✆ The fields of ‘Point’ class and ‘Vector’ class are looked like
  • 84. 264 OOP in C++ Point x y Vector Point (init) x y Point (final) x y The creation of instances of the ‘Vector’ class also creates the instances of‘ Point’ class as ‘init’ and ‘final’. ✞ Vector vec; ✌ ✆ vec (Instance of Vector) init (Instance of Point) x y final (Instance of Point) x y
  • 85. 4.2. CLASSES 265 4.2.4 Derived Class Derived class is one which is created from the base class by inhering the data members of the base class. The derived class may contain additional data members or may access only to the data member of base class. A derived class is created like ✞ 1 class <BaseClassName >; class <DerivedClassName > : <access type > <BaseClassName >; ✌ ✆ Here, access type shall be one of the keywords private, protected and public that defines the scope of inherited class for the derived class. The function defined in base class can be overloaded in derived class. See the example below: ✞ #include <iostream > 2 using namespace std; 4 class BaseClass { protected : 6 int m; public: 8 BaseClass (int i) { 10 m = i; } 12 /* print() function in base class*/ 14 void print() { cout << m << " "; 16 } }; 18 /* Derived Class with protected inherited to base class*/ 20 class DerivedClass : protected BaseClass { double n; 22 public: 24 DerivedClass (int i, double d) : BaseClass (i), n(d) { } 26 /* Class initialization with default values of i and d*/ 28 // DerivedClass (int i=2, double j=3) : BaseClass (i), n(j) { } 30 /* print() function of base class is overloaded here .*/ void print() { 32 cout << m << " "; } 34 void print(DerivedClass &a) { 36 cout << a.m << " " << a.n << " "; } 38 };
  • 86. 266 OOP in C++ 40 int main () { DerivedClass dc(20, 30.5); 42 dc.print(); dc.print(dc); 44 return 0; } ✌ ✆ ✞ 20 20 30.5 ✌ ✆ The derived class has following properties: 1. Derived class inherits all data members of all base classes. Access to private data members of a class from the object of that class is not allowed. Derived class can add own data members. ✞ 1 class myClassB { public: 3 int x; // Base class member variable int myFuncB () { 5 } // Base class member function }; 7 class myClassD : public myClassB { 9 public: int y; // Derived class member variable 11 int myFuncD () { } // Derived class member function 13 }; ✌ ✆ In above classes, all members are public, therefore, all public members of class myClassB are inherited and accessed by object of class myClassD as shown in following figure. myClassB int x; int myFuncB(); myClassD; int x; int myFuncB(); int y; int myFuncD(); But private data members of base class are inherited by the derived class, but they can not be accessed by the object of derived class. This is why, in memory allocation to the object of derived class, private members of the base class share memory space. See the following example. ✞ 1 #include <iostream > using namespace std;
  • 87. 4.2. CLASSES 267 3 class myClassB { 5 int x; // Base class member variable public: 7 int myFuncB () { 9 } // Base class member function }; 11 class myClassD : public myClassB { 13 int y; // Derived class member variable public: 15 int myFuncD () { 17 } // Derived class member function }; 19 int main () { 21 cout << sizeof (myClassD ); return 0; 23 } ✌ ✆ ✞ 8 ✌ ✆ Memory allocation of a class is not based on its structure. Non-virtual functions do not get share in memory space of the object of a class. The memory allocation of base class and derived class are given in below figure. myClassB int x 4 bytes myClassD int x 4 bytes int y 4 bytes 2. Derived class inherits all member functions of all base classes. They may override a member function of any base class by redefining it with the same signature. Derived class may overload a member function of any base class by redefining it with the same name but different signature. Derived class does not inherit the friend member function of any base class. ✞ 1 #include <iostream > using namespace std; 3 class myClassB { 5 public: int x = 10; // Base class member variable
  • 88. 268 OOP in C++ 7 static void fB() { 9 cout << "fB" << endl ; }// Base class static member function 11 friend void gB() { 13 cout << "gB" << endl ; }// Base class friend member function 15 void hB() { 17 cout << "hB" << endl ; } // Base class member function 19 }; 21 class myClassD : public myClassB { int y = 20; // Derived class member variable 23 public: 25 void fD() { cout << "fD" << endl ; 27 } // Derived class member function }; 29 int main () { 31 myClassD D; cout << D.x << endl ; 33 D.fB(); //D.gB (); // Error!! accessing to friend myClassB ::gB() 35 D.hB(); D.fD(); 37 return 0; } ✌ ✆ ✞ 10 fB hB fD ✌ ✆ The member function of base class and derived class are shown in the following figure.
  • 89. 4.2. CLASSES 269 myClassB int x; static void fB(); friend void gB(); void hB(); myClassD int x; static void fB(); void hB(); int y; void fD(); In above figure, those members of base class, which are inherited by the derived class but have no access to them either by object method or from within the derived class, are not shown. Those members which are accessed from within the derived class are shown in above figure. 3. Derived class cannot access private members of any base class but they have access to the protected members of any base class. ✞ #include <iostream > 2 using namespace std; 4 class myClassB { int x = 10; // Base class private member variable 6 void privF() { 8 cout << "privF" << endl ; }// Base class private member function 10 public: 12 static void fB() { cout << "fB" << endl ; 14 }// Base class static member function 16 void gB() { cout << "gB" << endl ; 18 } // Base class member function }; 20 class myClassD : public myClassB { 22 int y = 20; // Derived class private member variable public: 24 void fD() { 26 cout << "fD" << endl ; } // Derived class member function 28 }; 30 int main () {
  • 90. 270 OOP in C++ myClassD D; 32 // cout << D.x << endl ; // Error!! accessing to private myClassB ::x D.fB(); 34 //D.privF()(); // Error!! accessing to private myClassB :: privF() //D.y(); // Error!! accessing to private myClassD ::y 36 D.fD(); return 0; 38 } ✌ ✆ ✞ fB fD ✌ ✆ The member function of base class and derived class are shown in the following figure. myClassB int x; void privF(); static void fB(); void gB(); myClassD static void fB(); void gB(); int y; void fD(); In above figure, those members of base class, which are inherited by the derived class but have no access to them either by object method or from within the derived class, are not shown. Those members which are accessed from within the derived class are shown in above figure. 4. First, a constructor of the derived class must call all constructors of the base classes to construct the base class instances of the derived class. Base class constructors are called in listing order. The destructor of the derived class must call the destructors of the base classes to destruct the base class instances of the Derived class. Derived class layout contains instances of each base class. ✞ class Point { 2 public: double x, y; 4 }; 6 class Vector { public: 8 Point init , final; }; ✌ ✆ The creation of instances of the ‘Vector’ class also creates the instances of‘ Point’ class as ‘init’ and ‘final’.
  • 91. 4.2. CLASSES 271 ✞ 1 Vector vec; ✌ ✆ vec (Instance of Vector) init (Instance of Point) x y final (Instance of Point) x y 5. Derived class layout contains instances of each base class. Derived class layout will have data members of its own. C++ does not guarantee the relative position of the base class instances and derived class members. See the previous ‘Point’ and ‘Vector’ classes: ✞ 1 class Point { public: 3 double x, y; }; 5 class Vector { 7 public: Point init , final; 9 int z; }; ✌ ✆ The creation of instances of the ‘Vector’ class also creates the instances of‘ Point’ class as ‘init’ and ‘final’. ✞ Vector vec; ✌ ✆
  • 92. 272 OOP in C++ vec (Instance of Vector) z init (Instance of Point) x y final (Instance of Point) x y 4.2.5 Polymorphic Class Any class containing a virtual member function (by definition or by inheritance, pure or non-pure) is called a Polymorphic Type. A hierarchy may be polymorphic or non- polymorphic. A non-polymorphic hierarchy has little value. ✞ 1 Class B{ public: 3 virtual void fB() =0; }; 5 class D : public B{ public: 7 void fD(){} } ✌ ✆ In above syntax, both, base class and derived class are polymorphic classes. 4.2.6 Data Abstraction A fundamental concept of Object Oriented (OO) programming is that an object should not expose any of its implementation details. The class, by design, allows to hide how the class is implemented. ✞ #include <iostream > 2 #include <iomanip > using namespace std; 4 class Add { 6 public: int a = 10; 8 int b = 20; 10 int add () const { return a + b;
  • 93. 4.2. CLASSES 273 12 } }; 14 int main (int argc , char *argv []) { 16 Add myAdd; cout << "Addition is " << myAdd.add() << endl ; 18 return 0; } ✌ ✆ ✞ Addition is 30 ✌ ✆ The keywords like private, public, and protected affect the permissions of the members, where members are either variables or functions or classes etc. Public Member Public members declared or defined within the public section can be accessed freely anywhere a declared object is in scope. ✞ 1 #include <iostream > #include <iomanip > 3 using namespace std; 5 class Add { public: 7 /* Public member. Accessible from any where.*/ int add(int a, int b) const { 9 return a + b; } 11 }; 13 int main (int argc , char *argv []) { Add myAdd; 15 cout << "Addition is " << myAdd.add(1, 2) << endl ; return 0; 17 } ✌ ✆ ✞ Addition is 3 ✌ ✆ Private Member Members defined declared and defined withing the scope of private are called private members. They are only accessible within the class which is defining them and from friend classes. Friend classes are usually the domain of member variables and helper functions. ✞ 1 #include <iostream > using namespace std; 3 class myClass { 5 public: int x; 7
  • 94. 274 OOP in C++ /* Public member. Accessible from any where.*/ 9 getSum(int a, int b) { /* Access to private member ’add’*/ 11 add(a, b); } 13 private: /* here ’add ’() is declared as private member.* 15 *Accessible within the declaring class only .*/ int add(int a, int b); 17 }; 19 /* Defining the ‘add’ private member function .*/ 21 myClass :: add(int a, int b) { return a + b; 23 } 25 int main (int argc , char ** argv ) { myClass *oc = new myClass (); 27 cout << oc ->getSum(2, 3); return 0; 29 } ✌ ✆ ✞ 5 ✌ ✆ Protected Member Members declared or defined within the scope of protected are protected member. It has a special meaning to inheritance, protected members are ac- cessible in the class that defines them and in classes that inherit from that base class or friends of it. 4.2.7 Data Hiding Encapsulation is a process of object oriented programming, in which sensitive information stored in object’s members are hidden by declaring members as private or protected. In encapsulation, variables and data flow is visible but not accessible to user from outside the class. See the example given below: ✞ 1 class MyClass { public: 3 // Public members of class private: 5 // Members are visible but are still private ( encapsulated ) int x; 7 int y; }; ✌ ✆ In data hiding we are unable to know, what is a user accessing via members. Data hiding is accomplished by using a void pointer or a forward declared struct pointer as the class data. See the example given below:
  • 95. 4.2. CLASSES 275 ✞ class MyClass { 2 public: // Public members of class 4 private: struct hiddenData ; 6 // User cannot see what ’h_data’ is in this class (hidden) hiddenData * h_data; 8 }; ✌ ✆ 4.2.8 Inheritance Inheritance is a property that describes a relationship between two (or more) types or classes or objects. It is possible to derive one class from another class or even several classes. A base class is a class that is created with the intention of deriving other classes from it. A child class is a class that is derived from another class, i.e. from parent class. In dynamic type of class, values for the class function are passed by user. ✞ #include <iostream > 2 #include <iomanip > using namespace std; 4 class MyClass { 6 protected : int age; 8 public: 10 void Age(int i) { this ->age = i; 12 cout << age; } 14 }; 16 int main (int argc , char *argv []) { 18 MyClass *a = new MyClass (); a->Age (10) ; 20 return 0; 22 } ✌ ✆ ✞ 10 ✌ ✆ By using the colon ‘:’ we can inherit the members of an existing class by new derived class. See the example below: ✞ 1 #include <iostream > #include <iomanip > 3 using namespace std;
  • 96. 276 OOP in C++ 5 class MyClass { protected : 7 int age; public: 9 void Age(int i) { 11 this ->age = i; cout << age; 13 } }; 15 /* Inheritance to MyClass by using colon (:)* *Inheritance is as <base > : <parent > type */ 17 class NewMyClass : public MyClass {}; 19 int main (int argc , char *argv []) { 21 NewMyClass *a = new NewMyClass (); a->Age (10) ; 23 return 0; 25 } ✌ ✆ ✞ 10 ✌ ✆ A class can also be inherited to other class with new variables and functions. See the example below: ✞ 1 #include <iostream > #include <iomanip > 3 using namespace std; 5 class MyClass { protected : 7 int age; public: 9 void Age(int i) { 11 this ->age = i; cout << age << endl ; 13 } }; 15 /*By inheritance , we can access MyClass * 17 *via NewMyClass class as shown below. */ class NewMyClass : public MyClass { 19 int gen; public: 21 void Gender() { 23 this ->gen = 1;
  • 97. 4.2. CLASSES 277 cout << gen << endl ; 25 } 27 }; 29 int main (int argc , char *argv []) { 31 NewMyClass *a = new NewMyClass (); a->Age (10) ; 33 a->Gender (); return 0; 35 } ✌ ✆ ✞ 10 1 ✌ ✆ In above example, the newly created class NewMyClass has been inherited from the MyClass class. Therefore, all the methods and properties (variables) from the MyClass class are available to the newly created class. Comma is used to use multiple classes to be inheritate. Calling of constructors directly is forbidden, but by the method shown below, we can call parent constructor. ✞ ChildClass :: ChildClass (int a, int b) : ParentClass (a, b){ 2 <statements for child construction > } ✌ ✆ See the example below: ✞ 1 #include <iostream > using namespace std; 3 class myClass { 5 const int i; public: 7 myClass (int j); void getOutPut (); 9 }; 11 myClass :: myClass(int j) : i(j) { } 13 void myClass :: getOutPut () { 15 cout << "Output is " << i << endl ; } 17 int main (int argc , char *argv []) { 19 myClass Func1(1) , Func2 (2), Func3 (3); Func1.getOutPut (); 21 Func2.getOutPut (); Func3.getOutPut ();
  • 98. 278 OOP in C++ 23 return 0; } ✌ ✆ ✞ Output is 1 Output is 2 Output is 3 ✌ ✆ In inheritance, derived class can access only public and protected members of the base class. Private members of the base class can not be accessed from derived class. Type of Inheritance There are three types of inheritance. (i) public inheritance, (ii) protected inheritance and (iii) private inheritance. Public Inheritance When we derive a class from a public type 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. The private members of base class can not be accessed by derived class directly, but they can be accessed from the members of the base class. ✞ 1 #include <iostream > using namespace std; 3 class A { 5 public: int a; 7 }; 9 /* Public type inheritance of class A */ class B : public A { 11 public: void display () { cout << a << endl ; }; 13 }; 15 int main () { B b; 17 b.a=10; b.display (); 19 return 0; } ✌ ✆ ✞ 10 ✌ ✆
  • 99. 4.2. CLASSES 279 Inheritance to Base Class by Derived Class Data Members of Base Class public protected private public public protected private protected protected protected private private private private private Access to Data Members of Base Class for Derived Class Table 4.1: Visibility of data members of base class when it is inherited by derived class as public, protected and private. Protected Inheritance When deriving a new class from a protected base class, public and protected members of the base class become protected members of the derived class. ✞ 1 #include <iostream > using namespace std; 3 class B { 5 protected : int b; 7 public: 9 void set_b(int y) { b = y; 11 }; }; 13 /* Public type inheritance of class B*/ 15 class D : public B { public: 17 void display () { 19 cout << b << endl ; }; 21 }; 23 int main () { D d; 25 d.set_b (4); d.display (); 27 return 0;
  • 100. 280 OOP in C++ } ✌ ✆ ✞ 4 ✌ ✆ Another example is : ✞ 1 #include <iostream > using namespace std; 3 class A { 5 protected : int a; 7 public: 9 void set_a(int x) { a = x; 11 }; }; 13 class B { 15 protected : int b; 17 public: 19 void set_b(int y) { b = y; 21 }; }; 23 /* Public type inheritance of class A & B*/ 25 class D : public A, public B { public: 27 void display () { 29 cout << a * b << endl ; }; 31 }; 33 int main () { D d; 35 d.set_a (3); d.set_b (4); 37 d.display (); return 0; 39 } ✌ ✆ ✞ 12 ✌ ✆ Private Inheritance When deriving a new class from a private base class, public and protected members of the base class become private members of the derived class. Private
  • 101. 4.2. CLASSES 281 inheritance is not used in standard programming practices. But it is required when we want to access protected or private members of base class from derived class. ✞ 1 #include <iostream > using namespace std; 3 class A { 5 int n; protected : 7 A(int i) : n(i) { } 9 virtual int get() = 0; virtual void print() = 0; 11 }; 13 int A:: get () { return n; 15 } 17 class B : private A { public: 19 // Constructor to initialize A::n B(int i) : A(i) { } 21 // Override get() function to return A::n 23 int get () { A:: get(); 25 }; 27 // Print the value of A::n void print() { 29 cout << get() << endl ; } 31 }; 33 int main () { B *p = new B(10) ; 35 p->print(); return 0; 37 } ✌ ✆ ✞ 10 ✌ ✆ Private members of a class can be accessed from unrelated class by making friend to unrelated class with the class. See the example below: ✞ 1 #include <iostream > using namespace std; 3 class A { 5 int a, b;
  • 102. 282 OOP in C++ public: 7 A(int i, int j) : a(i), b(j) { 9 } friend class B; // class B as Friend of class A 11 }; 13 class B { public: 15 void disp (A& x) { 17 /* Since class B is friend of class A, hence * *private members of A are accessible here . */ 19 cout << x.a << " " << x.b; } 21 }; 23 int main () { A a(2, 3); 25 B b; b.disp (a); 27 return 0; } ✌ ✆ ✞ 2 3 ✌ ✆ Multiple Inheritance Multiple inheritance allows the construction of classes that inherit from more than one type or class. This contrasts with single inheritance, where a class will only inherit from one type or class. Syntax of the multiple inheritance is given below: ✞ 1 class A{ <statements > 3 } class B{ 5 <statements > } 7 class MultiInherit : public A, public B{ <statements > 9 }; ✌ ✆ In above syntax, MultiInherit class inherited to two classes, i.e. class A and class B. See the example below, in which data members of base classes, i.e. class MyClassA and class MyClassB are inherited by derived class NewMyClass. Here inheritence is public type for both base classes. ✞ 1 #include <iostream > using namespace std;
  • 103. 4.2. CLASSES 283 3 class MyClassA { 5 protected : int age; 7 public: 9 void Age(int i) { this ->age = i; 11 cout << age << endl ; } 13 }; 15 class MyClassB { protected : 17 int income; public: 19 void Income(int i) { 21 this ->income = i; cout << income << endl ; 23 } }; 25 /*By inheritance , we can access MyClass * 27 *via NewMyClass class as shown below: */ class NewMyClass : public MyClassA , public MyClassB { 29 int gen; public: 31 void Gender() { 33 this ->gen = 1; cout << gen << endl ; 35 } 37 }; 39 int main (int argc , char *argv []) { 41 NewMyClass *a = new NewMyClass (); a->Age (10) ; 43 a->Income (15000); a->Gender (); 45 return 0; } ✌ ✆ ✞ 10 15000 1 ✌ ✆ If a derived class inherited to base class then it also inherited to all its members including public variables, functions and classes. If derived class redefines the members of base class
  • 104. 284 OOP in C++ then it overrides to that member of the base class and redefined member is associated to the object of derived class. See the examples given below, in which derived class inherited to the member function ‘sum()’ of base class and adds new function ‘mul()’ as its member function. ✞ 1 #include <iostream > using namespace std; 3 class mA { 5 public: 7 int sum(int i, int j) { return (i + j); 9 }//A:: sum() }; // class mA 11 class mB : public mA { 13 public: 15 int mul(int i, int j) { return (i * j); 17 }//mB :: mul() }; // class mB inherited to mA 19 int main () { 21 mA a; // Declared class object a 23 mB b; // Declared class object b cout << a.sum(2, 3) << endl ; // A:: sum() 25 cout << b.sum(2, 3) << endl ; // A:: sum(), inherited cout << b.mul(2, 3) << endl ; // B:: mul(), added 27 return 0; } ✌ ✆ ✞ 5 5 6 ✌ ✆ Second example is given below, in which derived class overrides to the member function ‘sum()’ of base class. ✞ 1 #include <iostream > using namespace std; 3 class mA { 5 public: 7 int sum(int i, int j) { return (i + j); 9 }//A:: sum() }; // class mA
  • 105. 4.2. CLASSES 285 11 class mB : public mA { 13 public: 15 int sum(int i, int j) { return (1 + i + j); 17 }// function is redefined , it override to mA:: sum () // now member of the class mB is as mB:: sum() 19 }; // class mB inherited to mA 21 int main () { 23 mA a; // Declared class object a mB b; // Declared class object b 25 cout << a.sum(2, 3) << endl ; // A:: sum() cout << b.sum(2, 3) << endl ; // B:: sum() 27 return 0; } ✌ ✆ ✞ 5 6 ✌ ✆ Class Constructors In class-based object-oriented programming, a constructor inside a class is a subroutine call to create an object of the class. Constructors that can take at least one argument are termed as parameterized constructors. A constructor is used to initialize the intial values of class members or used to update the intial values of the class members. For example: ✞ class myClass { 2 int x, y; public: 4 // Non -Parameterized constructor Or class declaration myClass (); 6 // Parameterized constructor Or class declaration 8 myClass (int a, int b); }; 10 // Body definition of Non -parameterized constructor 12 myClass :: myClass () {} 14 // Body definition of parameterized constructor myClass :: myClass(int a, int b){ 16 x = a; y = b; 18 } ✌ ✆
  • 106. 286 OOP in C++ When an object is declared in a parameterized constructor, the initial values have to be passed as arguments to the constructor function. A constructor has no return type and it’s name is name of the class. The constructors can be called explicitly or implicitly. ✞ myClass e = myClass (0, 50); // Explicit call 2 //Or myClass e(0, 50); // Implicit call ✌ ✆ If the programmer does not supply a constructor for an instantiable class, most languages will provide a default constructor with default parameter values. ✞ 1 class student { public: 3 int a, b; // default constructor with default values 5 student (a=0, b=0); }; ✌ ✆ See the example below: ✞ #include <iostream > 2 using namespace std; 4 class MyClass { private: 6 int i, j; public: 8 /* Class constructor with default values. It inherited * 10 /*to variables i and j. And assigning values to them . */ MyClass (int a = 2, int b = 3) : i(a), j(b) { //i=a and j=b 12 cout << "i : " << i << ", j : " << j << endl ; } 14 }; 16 int main (int argc , char *argv []) { MyClass f1; 18 MyClass f2 (0); MyClass f3(5, 6); 20 return 0; } ✌ ✆ ✞ i : 2, j : 3 i : 0, j : 3 i : 5, j : 6 ✌ ✆ Class Destructors A derived class object may be created by using pointer method. The object must be destroyed when object is not being used. In OOP, a destructor is automatically invoked
  • 107. 4.2. CLASSES 287 when the object is destroyed. During object construction, object acquires some resources, allocates reserved memory spaces etc during its lifetime. Class destructor frees these resources and/or deregister them from other entities which may keep referencing to it. To destroy the object explicitly, delete operator is used. See the example below: ✞ 1 #include <iostream > 3 using namespace std; 5 class B{ public: 7 B() { cout << "B Constructed n"; } ~B() { cout << "B Destructed n"; } 9 }; class D : public B { 11 int n; public: 13 D() { cout << "D Constructed n"; } ~D() { cout << "D Destructed n"; } 15 }; 17 int main () { // B *d= new D() ;// May use this method 19 // Or , begin of second method 21 D *d= new D(); B *b =d; 23 // End of second method 25 delete b; return 0; 27 } ✌ ✆ ✞ B Constructed D Constructed B Destructed ✌ ✆ In above example, base class destructor is not destructed. The reason is that, derived class object is created and cast into base class by using pointer, and base class destructor is not virtual. So, to delete base class constructor, destructor of the base class should be virtual. See the modified form of above example: ✞ 1 #include <iostream > 3 using namespace std; 5 class B{ public: 7 B() { cout << "B Constructed n"; } virtual ~B() { cout << "B Destructed n"; } 9 };
  • 108. 288 OOP in C++ class D : public B { 11 int n; public: 13 D() { cout << "D Constructed n"; } ~D() { cout << "D Destructed n"; } 15 }; 17 int main () { // B *d= new D() ;// May use this method 19 // Or , begin of second method 21 D *d= new D(); B *b =d; 23 // End of second method 25 delete b; return 0; 27 } ✌ ✆ ✞ B Constructed D Constructed D Destructed B Destructed ✌ ✆ Base class constructors are always constructed first, followed by derived class constructors. Destruction will be in reverse order, i.e. derived class destructor destructed first, followed by base class. See the example given below: ✞ #include <iostream > 2 using namespace std; 4 class B { int i; 6 public: 8 B(int d) : i(d) { cout << "B::B(int);" << endl ; 10 } 12 ~B() { /* No need it to be a virtual as derived * * class object , D d(1,2) is not a pointer */ 14 cout << "B::~B(): " << i << endl ; } 16 }; 18 class D : public B { int j; 20 public: 22 D(int d, int e) : j(d), B(e) { cout << "D::D(int);" << endl ;
  • 109. 4.2. CLASSES 289 24 } 26 ~D() { cout << "D::~D(): " << j << endl ; 28 } }; 30 int main () { 32 D d(1, 2);// with default call -by -values 1 and 2 return 0; 34 } ✌ ✆ ✞ B::B(int); D::D(int); D::~D(): 1 B::~B(): 2 ✌ ✆ In above example, when we create class object by calling ✞ D d(1, 2) ✌ ✆ The base class constructor is called first. So, “B::B(int);” is printed in output. After that, the derived class constructor is called and there is output “D::D(int)”. The destructors are called automatically, therefore, first derived class destructor is called and after that base class destructor is called. This is why, the result output is “D:: D(): 1” and “B:: B(): 2” in the ordered sequence. Named Constructors Named constructors require static member functions. Named constructors is the name given to functions used to create an object of a class without (directly) using its con- structors. Constructors are either private or protected and clients have access only to the public static functions. The static functions are called “named constructors” as each unique way of creating an object has a different intuitive name. See the example below: ✞ 1 #include <iostream > using namespace std; 3 class myClass { 5 public: 7 static myClass createMyClass1 () { return myClass (0); 9 } /* Named constructor */ 11 static myClass createMyClass2 () { return myClass (1); 13 }/* Named constructor */ protected : 15 myClass (int n);
  • 110. 290 OOP in C++ }; 17 int main (int argc , char *argv []) { 19 myClass g1 = myClass :: createMyClass1 (); /* Using named constructor */ myClass g2 = myClass (0); /* Without named constructor */ 21 return 0; } ✌ ✆ Without using the named constructor in the above class, it is difficult to convey the meaning of what myClass(0) and myClass(1) means. Copy Constructor The purpose of the copy constructor is to allow the programmer to perform the same instructions as the assignment operator with the special case of knowing that the caller is initializing/constructing rather than an copying. The most common form of copy constructor is shown below: ✞ <class name > (const <class name > &<obj >) { 2 <body of constructor > } ✌ ✆ Example is ✞ 1 #include <iostream > using namespace std; 3 class myClass { 5 int x; int y; 7 public: myClass (int i, int j) : x(i), y(j) { 9 } 11 myClass (const myClass &c) : x(c.x), y(c.y) { } 13 ~myClass () { 15 } 17 void print() { cout << "x : " << x << ", y : " << y << endl ; 19 } }; 21 int main (int argc , char *argv []) { 23 /* Object c is created for myClass class*/ myClass c(1, 2) , // Constructor - myClass(int , int) 25 // Now value of x is set 1 and y is set 2 c1(c), // Copy Constructor - myClass (const myClass &)
  • 111. 4.2. CLASSES 291 27 c2= c; // Copy Constructor - myClass (const myClass &) c.print(); 29 c1.print(); c2.print(); 31 return 0; } ✌ ✆ ✞ x : 1, y : 2 x : 1, y : 2 x : 1, y : 2 ✌ ✆ Copy Constructor is needed for initializing the data members of a UDT from an existing value. Function Constructors A constructor is a special member function that is called whenever a new instance of a class is created. The constructor is declared much like a normal member function but it will share the name of the class and it has no return value. Constructors are responsible for the run-time setup necessary for the class operation. Constructor has arguments and they can also be overloaded. ✞ 1 class MyClass { public: 3 /* Default function constructure */ MyClass (); 5 /* Function overload constructure */ MyClass (int a, int b); 7 private: 9 int x; int y; 11 }; ✌ ✆ Default Constructors A default constructor is one which can be called with no argu- ments. To create an array of objects of a class type, the class must have an accessible default constructor. Overloaded Constructors When an object of a class is instantiated, the class writer can provide various constructors each with a different purpose. A large class would have many data members, some of which may or may not be defined when an object is instantiated. Constructor Initialization Lists Constructor initialization lists are the only way to initialize data members and base classes with a non-default constructor.
  • 112. 292 OOP in C++ Constructor Type Declaration A default constructor X() A copy constructor X(const X&) A copy assignment X& operator=(const X&) A move constructor X(X&&) A move assignment X& operator=(X&&) A destructor ∼X() Table 4.2: Copy, move and delete constructors of a class ‘X’. Compiler provides default constructor and default free destructor if user does not provide constructor or destructor. Objects of a class are initialized by the constructors. Function Destructors Destructors are declared as any normal member functions but will share the same name as the Class. Destructor’s name is preceded with a “˜”. It does not have arguments and can’t be overloaded. Destructors are called whenever an Object of the Class is destroyed. A destructor function of a constructor function is declared as ✞ 1 class X{ void myFunc(int i);/* Constructor */ 3 ~myFunc (); /* Destructor */ } ✌ ✆ A destructor function does not require any arguments. A constructor and destructor member functions of a class ‘X’ are called as ✞ X:: myFunc(i);/* Calling of constructor function */ 2 X::~ myFunc ();/* Calling of destructor function */ ✌ ✆ If function destructor is not provided by the user, then compiler automatically provides default free destructor. Friend Function A function declared inside a class as friend when defined outside the scope of the class has full right to access all private and protected members of that class. Friend functions are prototypes inside the class but they are not member functions of that class. A friend can be a function, function template, or member function, or a class or class template. A friend function are defined as ✞ class myClass { 2 double width; public: 4 friend void getWidth (myClass mc);
  • 113. 4.2. CLASSES 293 }; ✌ ✆ See the example below: ✞ 1 #include <iostream > using namespace std; 3 class myClass { 5 double width; public: 7 /* Declaration function getWidth () as friend*/ friend void getWidth (myClass mc); 9 void setWidth (double wd); }; 11 /* Set ‘width’ from public function .*/ 13 void myClass :: setWidth ( double v) { width = v; 15 } 17 /* Access value of ‘width’ from friend function .*/ void getWidth (myClass mc) { 19 cout << mc.width; } 21 int main (int argc , char *argv []) { 23 myClass mc; cout << "Setting width to 10.2 " << endl ; 25 mc.setWidth (10.2); cout << "Printing width : "; 27 getWidth (mc); return 0; 29 } ✌ ✆ ✞ Setting width to 10.2 Printing width : 10.2 ✌ ✆ 4.2.9 Data Members Data members are declared in the same way as a global or function variable. It is a part of the class definition. They stores information for the class and usually are hidden. The this Pointer Member The this keyword acts as a pointer to the class being referenced. It acts like any other pointer. It can not be changed. It is only accessible within non-static member functions of a class, union or struct, and is not available in static member functions. ✞ #include <iostream > 2 using namespace std;
  • 114. 294 OOP in C++ 4 class MyClass { protected : 6 int age; public: 8 void setAge(int i) { 10 this ->age = i; } 12 void getAge() { 14 cout << age << endl ; } 16 }; 18 int main (int argc , char *argv []) { 20 MyClass *a = new MyClass (); a->setAge (10) ; 22 a->getAge (); return 0; 24 } ✌ ✆ ✞ 10 ✌ ✆ Static Data Member The static specifier in a data member, is shared by all instances of the owner class and derived classes. To use static data members, data member is declared as static and initialized outside the class declaration, at file scope. When data member is used in a class, all instances of that class share one copy of the variable. ✞ 1 #include <iostream > using namespace std; 3 class MyClass { 5 public: 7 MyClass () { ++i; 9 cout << "Created " << i << " instances of classn"; } 11 private: static int i; 13 }; 15 /* Allocate memory for i, and initialize it */ int MyClass ::i = 0; 17 int main (int argc , char *argv []) { 19 // MyClass f1 , f2 , f3; //Or 21 MyClass f1;
  • 115. 4.2. CLASSES 295 MyClass f2; 23 MyClass f3; return 0; 25 } ✌ ✆ ✞ Created 1 instances of class Created 2 instances of class Created 3 instances of class ✌ ✆ In the example above, the static class variable iNumMyClass is shared between all three instances of the MyClass class (f1, f2 and f3) and keeps count upward by one when the class MyClass has been instantiated. See another example: ✞ 1 #include <iostream > using namespace std; 3 class Address { 5 static int HNo; public: 7 void getHNo(); }; 9 int Address :: HNo = 10; 11 void Address :: getHNo() { cout << "House No is " << HNo << endl ; 13 } 15 int main () { Address A; 17 A.getHNo (); return 0; 19 } ✌ ✆ ✞ House No is 10 ✌ ✆ 4.2.10 Class Members Class members are those variable, functions and classes which are defined inside the class. The class members operate on any object of the class of which they are member. Class members have access to all other members of a class for that object. For example in the following syntax, three different types of members are defined here. ✞ 1 class myClass { int x; // Variable Member 3 double y; // Variable Member int sum (); // Function Member 5 class XYZ{}// Class Member } ✌ ✆
  • 116. 296 OOP in C++ Members of member functions can be defined inside the class or separately outside the class by using scope resolution operator, i.e. ‘::’. See the example given below: ✞ #include <iostream > 2 using namespace std; 4 /* Declaration of new class*/ class MyClass { 6 public: /* Public interger variable x*/ 8 int x; /* Prototype of member function doubleIt ().* 10 *Only declaration of the member function .*/ int doubleIt (); 12 }; 14 /* Defining the member function outside the class as * *its member function of the class using :: operator .*/ 16 int MyClass :: doubleIt () { cout << 2 * x; 18 } 20 int main (int argc , char *argv []) { /* Defining of class object.*/ 22 MyClass c; /* Accessing class member as object */ 24 c.x = 2; c.doubleIt (); 26 return 0; } ✌ ✆ Defining a member function within the class declares the function inline, even when inline specifier is not used. A member function is called by using a dot operator (.) on a object. See the example given below: ✞ 1 #include <iostream > using namespace std; 3 class MyClass { 5 public: int x; 7 int doubleIt () { 9 return 2 * x; } 11 }; 13 int main (int argc , char *argv []) { /* Object of MyClass is created.*/ 15 MyClass c; /* Accessing member function of the class by using object*/ 17 c.x = 2;
  • 117. 4.2. CLASSES 297 cout << c.doubleIt (); 19 return 0; } ✌ ✆ ✞ 4 ✌ ✆ Object inside the main() function can also be created by using pointer method as shown in the following example. ✞ 1 #include <iostream > using namespace std; 3 class MyClass { 5 public: int x; 7 int doubleIt () { 9 return 2 * x; } 11 }; 13 int main (int argc , char *argv []) { /* Object of MyClass is created.*/ 15 MyClass *c = new MyClass (); /* Accessing member function of the class by using object*/ 17 c->x = 2; cout << c->doubleIt (); 19 return 0; } ✌ ✆ Member functions can be used to interact with data contained within user defined types. Function prototypes are declared within the class definition. Function outside of the class definition uses the scope resolution operator “::”. This scope resolution operator allows to define the functions somewhere else. In case of the class and member function are defined separately, the header file which contains the class definition is named same as the class name. For example, assume a project, which is named as MyClass, then header file should be named like MyClass.h. It contains the class definition. ✞ #ifndef MyClass_H 2 #define MyClass_H 4 class MyClass { public: 6 /* Default function constructure . In other words * *declaring function prototype without definitions .*/ 8 void MyFunc(); /* Function overload constructure */ 10 int MyFunc(int a, int b); int Add(int g, int h); 12
  • 118. 298 OOP in C++ private: 14 int x; int y; 16 }; 18 #endif ✌ ✆ The member functions are defined outside the class definition in MyClass.cpp file. The scope operator is used to put the scope of function definitions inside the class. See the file script below: ✞ #include "MyClass.h" 2 /* Definition of member function MyFunc () of MyClass class*/ 4 void MyClass :: MyFunc() { x = 5; 6 y = 10; } 8 /* Definition of member function MyFunc () of MyClass class*/ 10 int MyClass :: MyFunc(int a, int b) { x = a; 12 y = b; } 14 /* Definition of member function Add() of MyClass class*/ 16 int MyClass :: Add(int g, int h) { x = h + g*x; 18 y = g + h*y; } ✌ ✆ Access to Protected Member Protected members of a class are accessible from the derived class, if they are accessed from withing the definition of derived class. A derived class is derived from a main class by using inherit operator ‘:’ (colon). ✞ 1 #include <iostream > using namespace std; 3 /* Main class*/ 5 class myClass { protected : 7 int num; }; 9 /* Derived class with access permission * 11 *to member function of the main class */ class myDerivedClass : public myClass { 13 public:
  • 119. 4.2. CLASSES 299 15 void printNum () { num = 10; 17 cout << num << endl ; } 19 }; 21 main (int argc , char *argv []) { myDerivedClass * c = new myDerivedClass (); 23 c->printNum (); } ✌ ✆ ✞ 10 ✌ ✆ Access to Virtual Function The access control applied to virtual functions is determined by the type used to make the function call. Overriding declarations of the function do not affect the access control for a given type (See the abstract classes section for details). Mutables A constant data member is not changeable even in a non-constant object. A mutable data member is changeable in a constant object. A data member is made mutable by using mutable keyword. mutable is applicable only to data members and not to variables. Reference data members, static data members and const data members cannot be declared as mutable. If a data member is declared mutable, then it is legal to assign a value to it from a const member function. ✞ 1 #include <iostream > using namespace std; 3 class MyClass { 5 int x; mutable int y; 7 public: 9 /* Set value of x and y by initialization */ MyClass (int m, int mm) : x(m), y(mm) { 11 } 13 int getX () const { return x; 15 } 17 void setX (int i) { // Not OK x = i; 19 }
  • 120. 300 OOP in C++ 21 int getY () const { return y; 23 } 25 void setY (int i) const { y = i; 27 } // Okay to change mutable }; 29 int main () { 31 const MyClass mC(1, 2);// Initialized MyClass object cout << mC.getX () << endl ; 33 // mC.setX (3); // Error to invoke cout << mC.getY () << endl ; 35 mC.setY (4); return 0; 37 } ✌ ✆ ✞ 1 2 ✌ ✆ Static Data Member A static data member is associated with class not with object. It is shared by all the objects of a class. It should need to be defined outside the class scope (in addition to the declaration within the class scope) to avoid linker error. ✞ class Y { 2 static int armLen; // Static data member public: 4 int i; } 6 /* static variable of class Y must be initialize here .*/ int X::Y:: armLen = 10; ✌ ✆ It must be initialized in a source file and should constructed before main() starts and destructed after main() ends. It may be private or public type. It can be accessed with the class-name followed by the scope resolution operator (::) or as a member of any object of the class. It virtually eliminates any need for global variables in OOPs environment. ✞ 1 #include <iostream > using namespace std; 3 namespace X { 5 class Y {/* class namespace */ public: 7 static int armLen; // Static data member }; 9 int i;
  • 121. 4.2. CLASSES 301 } 11 /* static variable of class Y must be initialize here .*/ int X::Y:: armLen = 10; 13 int main (int argc , char *argv []) { 15 /* Calling of class namespace .*/ cout << "Arm length is " << (X::Y:: armLen); 17 return 0; } ✌ ✆ ✞ Arm length is 10 ✌ ✆ The static data member does not have this pointer. It can not access or invoke non-static data members or member functions respectively. It can not be declared as constant and can not be exists with a non-static version of the same function. 4.2.11 This Pointer The address of the calling object is stored in a special pointer called the this pointer. The this pointer holds the memory address of the current object. The this is a constant pointer. It can not be modified by user. The this pointer is automatically supplied every time you call a non-static member function of a class. Within any member function, this pointer exists and that it holds the address of the current object. ✞ 1 #include <iostream > using namespace std; 3 class Address { 5 int HNo; public: 7 void setHNo(int); int getHNo (); 9 }; 11 void Address :: setHNo(int i) { (* this ).HNo = i; 13 } 15 int Address :: getHNo() { return (* this ).HNo; 17 } 19 int main () { Address A; 21 A.setHNo (10) ; cout << "House No is " << A.getHNo () << endl ; 23 return 0; } ✌ ✆
  • 122. 302 OOP in C++ ✞ House No is 10 ✌ ✆ In above example, the parentheses are required with ‘(*this).HNo’ as only this is a pointer. Otherwise, ‘this.HNo’ is considered as a pointer. The this pointer is also used as pointer- to-member operator as shown in the following example. ✞ 1 #include <iostream > using namespace std; 3 class Address { 5 int HNo; public: 7 void setHNo(int); int getHNo (); 9 }; 11 void Address :: setHNo(int i) { this ->HNo = i; 13 } 15 int Address :: getHNo() { return this ->HNo; 17 } 19 int main () { Address A; 21 A.setHNo (10) ; cout << "House No is " << A.getHNo () << endl ; 23 return 0; } ✌ ✆ ✞ House No is 10 ✌ ✆ The this pointer differentiate an object’s field and a local variable with the same identifier. ✞ 1 #include <iostream > using namespace std; 3 class Address { 5 int HNo; public: 7 void setHNo(int); int getHNo (); 9 }; 11 void Address :: setHNo(int HNo) { this ->HNo = HNo; // Object field left side 13 // and local variable at right side . } 15
  • 123. 4.2. CLASSES 303 int Address :: getHNo() { 17 return this ->HNo; } 19 int main () { 21 Address A; A.setHNo (10) ; 23 cout << "House No is " << A.getHNo () << endl ; return 0; 25 } ✌ ✆ ✞ House No is 10 ✌ ✆ The this pointer can access to static member variables of a class but it can not be used with static member functions. ✞ 1 #include <iostream > using namespace std; 3 class Address { 5 static int HNo; // static variable public: 7 void setHNo(int); int getHNo (); 9 }; int Address :: HNo = 0; 11 void Address :: setHNo(int HNo) { 13 this ->HNo = HNo;// can access to HNo member of class } 15 int Address :: getHNo() { 17 return this ->HNo; } 19 int main () { 21 Address A; A.setHNo (10) ; 23 cout << "House No is " << A.getHNo () << endl ; return 0; 25 } ✌ ✆ ✞ House No is 10 ✌ ✆ In above example, variable ‘HNo’ is static type and it can be accessed via this point. But following code failed to compile as a member function is declared as static. ✞ 1 #include <iostream > using namespace std; 3
  • 124. 304 OOP in C++ class Address { 5 int HNo; public: 7 void setHNo(int); static int getHNo(); // Static member function 9 }; 11 void Address :: setHNo(int HNo) { this ->HNo = HNo; 13 } 15 int Address :: getHNo() { return this ->HNo; // Error! ’this ’ is unavailable 17 // for static member functions } 19 int main () { 21 Address A; A.setHNo (10) ; 23 cout << "House No is " << A.getHNo () << endl ; return 0; 25 } ✌ ✆ 4.2.12 Operator Overloading Every operator is associated with an operator function that defines its behavior. For example, a + b is related to operator function as ✞ 1 operator +(a, b) //Or 3 a.operator +(b) ✌ ✆ Similarly, a = b is related to operator function as ✞ 1 operator =(a, b) ✌ ✆ c = a + b is related to operator function as ✞ 1 operator =(c, operator +(a, b)) ✌ ✆ + Overloading C++ provides way to overload built-in operators. Overloaded operators are functions with special names followed by the keyword operator and the symbol for the operator being defined. An overloaded operator has a return type and a parameter list. For example, the syntax ✞ 1 className operator +(<data -type > className ) ✌ ✆
  • 125. 4.2. CLASSES 305 declares the addition operator that can be used to add two className objects and returns final className object. Most overloaded operators may be defined as ordinary non- member functions or as class member functions. In case we define above function as non-member function of a class then we would have to pass two arguments for each operand as follows: ✞ 1 className operator +(<data -type > className , <data -type > className ) ✌ ✆ Following is the example to show the concept of operator over loading using a member function. Here an object is passed as an argument whose properties will be accessed using this object, the object which will call this operator can be accessed using this operator as explained below: ✞ 1 #include <iostream > using namespace std; 3 class myClass { // Declaration of a class 5 public: // The result member function 7 double getRes(void ) { return x; 9 } // Member function setting value of x 11 void setX (double v) { x = v; 13 } // operator class 15 myClass operator +( myClass X) { myClass Y; 17 Y.x = x + X.x; return Y; 19 } 21 private: double x; 23 }; 25 int main (int argc , char *argv []) { myClass X1; 27 X1.setX (1.0); myClass X2; 29 X2.setX (2.0); myClass X3; 31 X3 = X1 + X2; cout << X3.getRes(); 33 return 0; } ✌ ✆ ✞ 3 ✌ ✆ Unary operators like + + a and a + + can be overloaded as
  • 126. 306 OOP in C++ ✞ 1 operator ++(a); // ++a //Or 3 a.operator ++() ; // ++a ✌ ✆ and ✞ 1 operator ++(a, int); // a++ ✌ ✆ respectively. The operators, like ‘::’ (scope resolution), ‘.’ (member access), ‘.*’ (member access through pointer to member), sizeof, ‘**’, <>, &| and ‘?:’ (ternary conditional) cannot be overloaded. Operators other than above listed can be overloaded. The opera- tors ‘&’, ‘&&‘, ‘||’, and ‘,’ (comma) lose their special properties on operator overloading. Example of copy-assignment-operator is given below: ✞ 1 #include <iostream > using namespace std; 3 class Complex { 5 int real ; int imag ; 7 public: 9 Complex (int a = 0, int b = 0) : real (a), imag (b) { 11 } // Write function header and body for the copy -assignment operator 13 Complex & operator =( const Complex &t) { 15 real = t.real ; imag = t.imag ; 17 } 19 void print() { cout << real << "+i" << imag ; 21 } }; 23 int main () { 25 Complex t1(2, 3); Complex t3; 27 t3 = t1; // Using copy -assignment operator t3.print(); 29 return 0; 31 } ✌ ✆ ✞ 2+i3 ✌ ✆
  • 127. 4.2. CLASSES 307 << Overloading The operator << is also known as output operator, insertion operator and bitwise left shift operator. Output operator is a part of ostream object declared inside the header file ‘iostream’. This operator accepts two arguments, one the address where output is placed and second the data to be placed at output address. The output operator is overloaded as ✞ 1 ostream& operator <<(ostream &, <datatype >); ✌ ✆ The datatype may be an integer, a float or double value or a string or a class. ✞ 1 #include <iostream > using namespace std; 3 class AgeMrk { 5 private: int Age; 7 double Marks; public: 9 friend ostream& operator <<( ostream &, const AgeMrk &); AgeMrk(int , double); // constructor should be same 11 // name as of the class }; 13 AgeMrk:: AgeMrk(int age , double mk) { 15 Age = age; Marks = mk; 17 } 19 ostream& operator <<( ostream & out , const AgeMrk& amk) { out << "Age : " << amk.Age << 21 " Marks : " << amk.Marks << endl ; return out; 23 } 25 int main () { AgeMrk AgeMrk(10, 150.00) ; 27 cout << AgeMrk; return 0; 29 } ✌ ✆ ✞ Age : 10 Marks : 150 ✌ ✆ >> Overloading The operator >> is also known as input operator, extraction operator and bitwise right shift operator. Input operator is a part of istream object declared inside the header file ‘iostream’. This operator accepts two arguments, one the address from where input
  • 128. 308 OOP in C++ is extracted or receive and second the data to be accept from the address. The input operator is overloaded as ✞ 1 istream& operator >>(istream &, <data >); ✌ ✆ The datatype may be an integer, a float or double value or a string or a class. ✞ 1 #include <iostream > using namespace std; 3 class AgeMrk { 5 private: int Age; 7 double Marks; public: 9 friend ostream& operator <<( ostream &, const AgeMrk &); friend istream& operator >>( istream &, AgeMrk&); 11 AgeMrk(int , double); // constructor should be same // name as of the class 13 }; 15 AgeMrk:: AgeMrk(int age , double mk) { Age = age; 17 Marks = mk; } 19 ostream& operator <<( ostream & out , const AgeMrk& amk) { 21 out << "Age : " << amk.Age << " Marks : " << amk.Marks << endl ; 23 return out; } 25 istream& operator >>( istream & in , AgeMrk& amk) { 27 cout << endl ; // to clear the buffer cout << "Enter Age "; 29 in >> amk.Age; cout << "Marks "; 31 in >> amk.Marks; return in; 33 } 35 int main () { AgeMrk AgeMrk(0, 0); 37 cin >> AgeMrk; cout << AgeMrk; 39 return 0; } ✌ ✆ ✞ Enter Age 12 Marks 250 Age : 12 Marks : 250 ✌ ✆
  • 129. 4.2. CLASSES 309 ++, - - Overloading ++ and - - are incremental and decrement operators. ++ and - - may be used as prefix or postfix to a given variable. For example, ✞ 1 i++; // post fixed increment operator ++i; // pre fixed increment operator 3 i--; // post fixed decrement operator --i; // pre fixed decrement operator . ✌ ✆ The increment operator overloading is done by using operator keyword as shown below ✞ operator ++() ; ✌ ✆ In the following example, use of ++ operator overloading is explained. ✞ 1 #include <iostream > using namespace std; 3 class AgeMrk { 5 private: int Age; 7 double Marks; public: 9 friend ostream& operator <<( ostream &, const AgeMrk &); AgeMrk(int , double); // constructor should be same 11 // name as of the class AgeMrk& operator ++() ; 13 }; 15 ostream& operator <<( ostream & out , const AgeMrk& amk) { out << "Age : " << amk.Age << 17 " Marks : " << amk.Marks << endl ; return out; 19 } 21 AgeMrk:: AgeMrk(int ag , double mk) { Age = ag; 23 Marks = mk; } 25 AgeMrk& AgeMrk :: operator ++() { 27 ++ Age; ++ Marks; 29 return *this ; } 31 int main () { 33 AgeMrk AgeMrk(10, 20); cout << ++ AgeMrk; 35 return 0; } ✌ ✆
  • 130. 310 OOP in C++ ✞ Age : 11 Marks : 21 ✌ ✆ The decrement operator overloading is done by using operator keyword as shown below ✞ 1 operator --(); ✌ ✆ In the following example, use of - - operator overloading is explained. ✞ 1 #include <iostream > using namespace std; 3 class AgeMrk { 5 private: int Age; 7 double Marks; public: 9 friend ostream& operator <<( ostream &, const AgeMrk &); AgeMrk(int , double); // constructor should be same 11 // name as of the class AgeMrk& operator --() ; 13 }; 15 ostream& operator <<( ostream & out , const AgeMrk& amk) { out << "Age : " << amk.Age << 17 " Marks : " << amk.Marks << endl ; return out; 19 } 21 AgeMrk:: AgeMrk(int ag , double mk) { Age = ag; 23 Marks = mk; } 25 AgeMrk& AgeMrk :: operator --() { 27 --Age; --Marks; 29 return *this ; } 31 int main () { 33 AgeMrk AgeMark (11, 25); cout << --AgeMark; 35 return 0; } ✌ ✆ ✞ Age : 10 Marks : 24 ✌ ✆
  • 131. 4.2. CLASSES 311 [] Overloading The opereator [] is used for array. For example, ‘int myA[10]’ represents an array of 10 integer element size. The [] operator can be overloaded for adding additional capabilities, i.e. checking whether the array is overfloaded, or there is no element in the array etc. [] operator is overloaded by using operator keyword. ✞ 1 <data type > &operator [](< parameters >) ✌ ✆ See the following example. ✞ 1 #include <iostream > using namespace std; 3 const int SIZE = 10; 5 class myArr { private : 7 int mArr [SIZE ]; // mArr of size 10 9 public: myArr() { // constructor 11 register int i; for(i = 0; i < SIZE ; i++) { 13 mArr [i] = i; } 15 } 17 int &operator []( int i) { // overload [] operator if( i > SIZE ) { 19 cout << "Index out of bounds" <<endl ; return mArr [0]; 21 } return mArr [i]; 23 } }; 25 int main () { 27 myArr A; 29 cout << "Value of A[2] : " << A[2] <<endl ; cout << "Value of A[5] : " << A[5]<< endl ; 31 cout << "Value of A[12] : " << A[12]<< endl ; 33 return 0; } ✌ ✆ ✞ Value of A[2] : 2 Value of A[5] : 5 Index out of bounds Value of A[12] : 0 ✌ ✆
  • 132. 312 OOP in C++ 4.2.13 Function Overloading Member functions can be overloaded. Multiple member functions can exist with the same name on the same scope, but must have different signatures, i.e. input arguments, members etc. Constructors and other class member functions, except the destructor, can be overloaded. 4.3 Object Class is mere a blueprint or a template. They do not assign the value or create storage. Objects are instances of class, which holds the data variables declared in class. Member functions work on these class objects. Objects are initialised by using Constructors. If object is failed to be created, Destructors is automatically called to release the memory reserved by the object. ✞ #include <iostream > 2 using namespace std; 4 class MyClass { public: 6 int x; }; 8 int main (int argc , char *argv []){ /* Object c is created for MyClass class*/ 10 MyClass c; c.x=2; 12 return 0; } ✌ ✆ The class object can also be created by using default value as shown in the following example. Here, class is derived inside itself. ✞ 1 #include <iostream > using namespace std; 3 class MyClass { 5 int x; int y; 7 public: int z; 9 /* Initialize x and y data members * * data members of the other class * 11 * are initialized by class calling */ MyClass (int i, int j) : x(i), y(j) { 13 cout << "x : " << x << ", y : " << y << endl ; } 15 }; 17 int main (int argc , char *argv []) { /* Object c is created for MyClass class*/
  • 133. 4.3. OBJECT 313 19 MyClass c(1, 2); // Now value of x is set 1 and y is set 2 c.z = 2; 21 cout << "z : " << c.z << endl ; return 0; 23 } ✌ ✆ ✞ x : 1, y : 2 z : 2 ✌ ✆ In the following example, data members of derived MyClass and inherited YourClass are initialized by using derived class MyClass class and inherited YourClass privately by MyClass class. ✞ #include <iostream > 2 using namespace std; 4 class YourClass { public: 6 int k; /* Initialize k data member of own class. */ 8 YourClass (int f) : k(f) { } 10 }; 12 /* Inherit YourClass as private */ class MyClass : private YourClass { 14 int x; int y; 16 public: int z; 18 /* Initialize x and y data members of own class. * 20 * And k data member of inherited YourClass class.*/ MyClass (int i, int j, int k) : x(i), y(j), YourClass (k) { 22 cout << "x : " << x << ", y : " << y ; cout << ", k : " << YourClass ::k << endl ; 24 } }; 26 int main (int argc , char *argv []) { 28 /* Object c is created for MyClass class*/ MyClass c(1, 2, 3); // Now value of x is set 1 and y is set 2 30 c.z = 2; cout << "z : " << c.z << endl ; 32 return 0; } ✌ ✆ ✞ x : 1, y : 2, k : 3 z : 2 ✌ ✆
  • 134. 314 OOP in C++ 4.3.1 Casting Casting is performed when a value (variable) of one data type is used in place of other data type or to convert the type of an object, expression, function argument, or return value to another type. It does not need any argument and does not has return type. For example, to put the value of integer data type variable at double data type variable, casting is performed as ✞ int i=2; // integer data type variable declared & initialized 2 double j=2; // double data type variable declared & initialized double k=j/i; // integer i is casted as double and used ✌ ✆ In C++, there are two types of castings, (i) implicit casting and (ii) explicit casting. ✞ 1 int i=2; // integer data type variable declared & initialized double j=i; // implicit casting 3 double k=( double) i; // explicit casting or forced casting ✌ ✆ In casting, data of one data type is converted into data of other data type. Therefore, there is loss of data. For example, if double data type is casted as integer data type, then compiler shows warning. ✞ 1 double i = 2.0; // double data type variable declared & initialized int j = i; /* warning !! as double (8 bytes size ) is casted to * 3 *integer (4 bytes size ). Possible loss of data */ ✌ ✆ In case of referencing, implicit casting results in error, while explicit casting is acceptable. ✞ 1 int i = 2; // integer data type variable declared & initialized double j = 2.5; // double data type variable declared & initialized 3 double *k = &j; // explicit casting or forced casting i = k; // error!! invalid conversion from ’double*’ to ’int’ 5 i = (int) k;// explicit casting , acceptable ✌ ✆ Implicit casting in unrelated classes is not permitted, while forced casting is accepted. ✞ 1 class mA { public: 3 int i; }; // class mA 5 class mB { 7 public: double d; 9 }; // class mB not related to mA mA a; 11 mB b; a = b; // error 13 a = (mA)b; // error b = a; // error 15 b = (mB)a; // error p = q; // error
  • 135. 4.3. OBJECT 315 17 q = p; // error mA *p = &a; //OK , referencing instances of class mA 19 mB *q = &b; //OK , referencing instances of class mB p = (mA*)&b; // OK , Forced casting of class mB into class mA with reference 21 q = (mB*)&a; // OK , Forced casting of class mA into class mB with reference ✌ ✆ But force casting returns weird result. See the example below: ✞ 1 #include <iostream > using namespace std; 3 class mA { 5 public: int i = 2; 7 }; // class mA 9 class mB { public: 11 double d = 2.5; }; // class mB not related to mA 13 int main () { 15 mA a; mB b; 17 mA *p = &a; // class object mB *q = &b; // class object 19 cout << p->i << " " << q->d << endl ; p = (mA*) & b; // Forced casting 21 q = (mB*) & a; // Forced casting cout << p->i << " " << q->d << endl ; 23 return 0; } ✌ ✆ ✞ 2 2.5 0 5.28382e-308 ✌ ✆ In hierarchy, casting is permitted with limited sense. There are two ways of casting in hierarchical casting, (i) upward casting and (ii) downward casting. In upward casting, derived class is casted into base class and in downward casting, base class is casted into derived class. Downward casting is not permitted. ✞ #include <iostream > 2 using namespace std; 4 class mA { public: 6 int i; }; // class mA
  • 136. 316 OOP in C++ 8 class mB : public mA { 10 public: double d; 12 }; // class mB inherited to mA 14 int main () { 16 mA *a = 0; mB *b = 0; 18 a = b; // OK , upward casting b = a; // NOT OK , downward casting , error!! invalid conversion 20 return 0; } ✌ ✆ 4.3.2 Binding A class object is created by two ways, (i) static type and (ii) dynamic type. Static type of the object is declared for the object while codes are written. The compiler sees the static type objects. The dynamic type of the object is determined by the type of the object to which it currently refers. Compiler does not sees the dynamic objects. ✞ 1 #include <iostream > using namespace std; 3 class mA { 5 public: int i; 7 }; // class mA 9 class mB : public mA { public: 11 double d; }; // class mB inherited to mA 13 int main () { 15 mA *a; // Declared class object a as pointer 17 a = new mB; // Static type of a = mA // Dynamic type of a = mB 19 return 0; } ✌ ✆ Static binding (i.e. early binding) is done at compile-time. Normal function calls, over- loaded function calls, and overloaded operators are examples of static binding. Dynamic binding (i.e. late binding) is done at run-time. Function pointers, Virtual functions are examples of late binding. Binding is decided by the type of pointer if member functions of the classes are not virtual. See the examples given below: ✞ #include <iostream >
  • 137. 4.3. OBJECT 317 2 using namespace std; 4 class mA { public: 6 int sum(int i, int j) { 8 return (i + j); } 10 }; // class mA 12 class mB : public mA { public: 14 int sum(int i, int j) { 16 return (1 + i + j); } 18 }; // class mB inherited to mA 20 int main () { 22 mA a; // Declared class object a mB b; // Declared class object b 24 mA *p; // Declared class object b as pointer p = &a; 26 cout << p->sum(2, 3) << endl ; // A:: sum() p = &b; 28 cout << p->sum(2, 3) << endl ; // A:: sum() return 0; 30 } ✌ ✆ ✞ 5 5 ✌ ✆ Similarly, Binding is decided by the type of object if member functions of the base class are virtual. Example for dynamic binding is given below: ✞ #include <iostream > 2 using namespace std; 4 class mA { public: 6 virtual int sum(int i, int j) { 8 return (i + j); } 10 }; // class mA 12 class mB : public mA { public: 14 virtual int sum(int i, int j) {
  • 138. 318 OOP in C++ 16 return (i + j + 1); } 18 }; // class mB inherited to mA 20 int main () { 22 mA a; // Declared class object a mB b; // Declared class object b 24 mA *p; // Declared class object b as pointer p = &a; 26 cout << p->sum(2, 3) << endl ; // A:: sum() p = &b; 28 cout << p->sum(2, 3) << endl ; // B:: sum() return 0; 30 } ✌ ✆ ✞ 5 6 ✌ ✆ From the above example, it is clear that dynamic binding is possible only for pointer and reference data types and for member functions that are declared as virtual in the base class. If a member function is declared as virtual, it can be overridden in the derived class. If a member function is not virtual and it is re-defined in the derived class then the latter definition hides the former one. A derived class non-virtual member function overriding to a virtual member function of a base class is always virtual. A virtual member function of derived class overriding to the non-virtual member function of base class is always virtual. Virtual functions can be overrided by non-virtual function with same signature. ✞ #include <iostream > 2 using namespace std; 4 class mA { public: 6 int sum(int i, int j) { 8 return (i + j); } 10 }; // class mA 12 class mB : public mA { public: 14 virtual int sum(int i, int j) { 16 return (i + j + 1); } 18 }; // class mB inherited to mA 20 int main () { mA a; 22 cout << a.sum(2, 3) << endl ; // B:: sum()
  • 139. 4.3. OBJECT 319 mB b; 24 cout << b.sum(2, 3) << endl ; // B:: sum() return 0; 26 } ✌ ✆ ✞ 5 6 ✌ ✆ The VTF of the class B shall be looked like Object of mB VFT VFT mB::sum(int, int) 0 The definition of override and overload has a bit differences. A function that is rede- fined in derived class with or without same signature is known as overriding. Overloading word is used when a function is redefined with different number of parameters or with different signature. For example, ✞ class B { 2 protected : int var; 4 public: void print() { 6 cout << var << endl ; } 8 }; 10 class D : protected B { double dvar ; 12 public: 14 void print() {// overriding to base print() cout << var << " "; 16 } 18 void print(D& a) {// overriding and overloading to base print() cout << a.var << " " << a.dvar << " "; 20 } }; ✌ ✆ The ‘print()’ function is overriding and overloading in the derived class to the function ‘print()’ of base class. 4.3.3 Cast Operators In C++ there are four types of cast operators:
  • 140. 320 OOP in C++ const cast It is used like ✞ 1 const_cast <new type >(< expression >) ✌ ✆ It overrides const and/or volatile data-types. It does not allow to change the value. Only const cast may be used to cast away (remove) const-ness or volatility. ✞ 1 #include <iostream > using namespace std; 3 class B { 5 int j; public: 7 // Constructor of class B 9 B(int i) : j(i) { } 11 // Get the value of j 13 void get() const { cout << j << endl ; 15 } // Set the value of j 17 void set(int i) { 19 j = i; } 21 }; // print string 23 void print(char * str) { cout << str << endl ; 25 } 27 int main () { // Constant character string 29 const char * c = "sample text "; print(const_cast <char *> (c)); 31 // Create instance for class B by pas -by -value method const B b(1); 33 // Call the get() function b.get (); 35 // Cast class B to class B& const_cast <B&> (b).set (5); 37 // Call the get() function b.get (); 39 return 0; } ✌ ✆ ✞ sample text
  • 141. 4.3. OBJECT 321 1 5 ✌ ✆ static cast It is used like ✞ 1 static_cast <new type >(< expression >) ✌ ✆ It performs a non-polymorphic cast. It is used in computation of changed values either by implicitly or user defined. Following is an example in which, a variable of double data type is casted into integer data type. ✞ 1 #include <iostream > using namespace std; 3 int main () { 5 int i = 2; double d = 3.7; 7 i = (int) d; cout << i << endl ; 9 /* static_cast converts the variable d into int * *data type and assigns the result to variable i*/ 11 i = static_cast <int > (d); cout << i << endl ; 13 return 0; 15 } ✌ ✆ ✞ 3 3 ✌ ✆ Classes can also be cast from one class type to other class type. See the example given below: ✞ #include <iostream > 2 using namespace std; 4 class A {}; 6 class B : public A {}; 8 int main () { A a; 10 B b; // Up cast , derived class in casts as base class 12 A *p = &b; // implicit -- okay p = static_cast <A*> (&b); // static_cast -- okay 14 p = (A*) &b; //OK as it is explicit
  • 142. 322 OOP in C++ // Down cast , base class in casts as derived class 16 B *q = &a; // error as it is implicit q = static_cast <B*> (&a); // static_cast -- okay 18 q = (B*) & a; // OK as it is explicit return 0; 20 } ✌ ✆ In hierarchy, static cast, implicit cast and explicit cast are allowed in upward casting as shown in the code lines ✞ A a; 2 B b; // Up cast , derived class in casts as base class 4 A *p = &b; // implicit -- okay p = static_cast <A*> (&b); // static_cast -- okay 6 p = (A*) &b; //OK as it is explicit ✌ ✆ While implicit cast in downward casting is not allowed. ✞ A a; 2 B b; // Down cast , derived class in casts as base class 4 B *q = &a; // error as it is implicit q = static_cast <B*> (&a); // static_cast -- okay 6 q = (B*) & a; // OK as it is explicit ✌ ✆ Unrelated classes are those classes which do not inherited to each other. For example ✞ class A{}; 2 class B{}; ✌ ✆ both are unrelated as they do not inherited mutually. Consider the example as given below for unrelated classes in which class B is casted from class A by constructor method. ✞ #include <iostream > 2 using namespace std; 4 class A { int i; 6 public: // create constructor for class A 8 A(int ai) : i(ai) { } 10 // return value of i 12 int get () const { return i; 14 } }; 16 class B {
  • 143. 4.3. OBJECT 323 18 int i; public: 20 // create constructor for class B B(int ai) : i(ai) { 22 } 24 // return value of i int get () const { 26 return i; } 28 /* matching function conversion of * 30 *class A to class B, i.e. A ==> B*/ B(const A&) { }// conversion from A (constructor ) 32 }; 34 int main () { A a(1); 36 B b(2); /* static conversion of class * 38 *A to class B, i.e. A ==> B */ const B &r = static_cast <B> (a); 40 cout << a.get() << endl ; cout << b.get() << endl ; 42 cout << r.get() << endl ; return 0; 44 } ✌ ✆ ✞ 1 2 2293744 ✌ ✆ In static casting, a matching function for conversion of class A to class B, i.e. A ⇒ B shall be defined inside the class B. Similarly, integers is cast into class B as shown in the following example: ✞ 1 #include <iostream > using namespace std; 3 class A { }; 5 class B { 7 int i = 1; public: 9 // return value of i 11 int get () const { return i; 13 } 15 /* matching function conversion of *
  • 144. 324 OOP in C++ *int i to class B, i.e. i ==> B*/ 17 B(int ai = 1) { } 19 }; 21 int main () { int i; 23 B b; /* static conversion of integer* 25 *i to class B, i.e. i ==> B */ const B &r = static_cast <B> (i); 27 cout << b.get() << endl ; cout << r.get() << endl ; 29 return 0; } ✌ ✆ ✞ 1 1 ✌ ✆ To cast a class into an integer data type, the integer is overloaded by using keyword operator as shown in the following example. ✞ #include <iostream > 2 using namespace std; 4 class A { }; 6 class B { 8 int i; public: 10 // create constructor for class B B(int ai) : i(ai) { 12 } 14 // return value of i int get () const { 16 return i; } 18 /* matching function conversion of * 20 *class A to integer , i.e. i ==> B*/ operator int() { 22 } }; 24 int main () { 26 int i = 2; B b(2); 28 /* static conversion of class * *B to integer i, i.e. B ==> i */
  • 145. 4.3. OBJECT 325 30 const B &r = static_cast <int > (b); cout << b.get() << endl ; 32 cout << r.get() << endl ; return 0; 34 } ✌ ✆ ✞ 2 2293584 ✌ ✆ The keyword operator may also be used with classes as shown in the following example in which class B is casted to class A by type-cast method. ✞ #include <iostream > 2 using namespace std; 4 class A { int i; 6 public: 8 // create constructor for class A with default value 3 A(int ai = 3) : i(ai) { 10 cout << ai << endl ; } 12 }; 14 class B { public: 16 // conversion to A (type -cast operator ) operator A() { 18 return A(); } 20 }; 22 int main () { B b; 24 /* static conversion of class * *B to class A, i.e. B ==> A */ 26 const A &r = static_cast <A> (b); // B:: operator A() return 0; 28 } ✌ ✆ ✞ 3 ✌ ✆ In static casting, it can be explicitly call a single-argument constructor or a conversion operator to handle the casting between two unrelated classes. ✞ 1 #include <iostream > using namespace std; 3 class A {
  • 146. 326 OOP in C++ 5 int i; public: 7 A(int ai) : i(ai) { } int get () const { 9 return i; } 11 }; 13 class B { int i; 15 public: B(int ai) : i(ai) { } 17 int get () const { return i; 19 } /* conversion from A (assignment ) * 21 * to a single -argument constructor */ B(A& a) : i(a.get()) {} 23 // conversion to A (type -cast operator ) operator A(){return A(i);} 25 }; 27 int main () { int i=2; 29 A a(2); B b(3); 31 const B &r = static_cast <B> (a); cout << a.get() << ":"; 33 cout << r.get() << ":"; return 0; 35 } ✌ ✆ ✞ 2:2: ✌ ✆ reinterpret cast It is used like ✞ 1 reinterpret_cast <new type >(< expression >) ✌ ✆ It casts between unrelated pointer types or pointer and integer. It does not perform computation yet reinterprets value. It can convert any class object pointer to any other class object pointer. ✞ 1 #include <iostream > using namespace std; 3 int main (){ 5 float a = 12; int b = *reinterpret_cast <int*>(& a);
  • 147. 4.3. OBJECT 327 7 cout << b; return 0; 9 } ✌ ✆ ✞ 1094713344 ✌ ✆ In above example, reinterpret cast takes the address of ‘a’, reinterpret it into an int* and get back an int* that points to ‘a’. Deference value is returned to pointer as integer value. The float value of ‘a’ is recast as integer. This is why, the output in above example is not 12 as desired. dynamic cast It is used like ✞ 1 dynamic_cast <new type >(< expression >) ✌ ✆ It performs a run-time cast that verifies the validity of the cast. It also performs pre- defined computation, sets null or throws exception. Dynamic cast can only be used with pointers and references to the classes (or with void*). Its purpose is to ensure that the result of the type conversion points to a valid complete object of the destination pointer type. ✞ 1 #include <iostream > using namespace std; 3 class B { 5 public: 7 virtual void func () { } 9 }; 11 class D : public B { }; 13 int main () { 15 B b; D *d = dynamic_cast <D*> (b);// Error !! Source is not a pointer 17 //D *d = dynamic_cast <D*> (&b);// Allowed if (d != NULL ) 19 cout << 1; else 21 cout << "Error"; return 0; 23 } ✌ ✆ This naturally includes pointer upcast, implicit conversion and downcast of polymorphic classes iff the pointed object is a valid complete object of the target type. If the pointed object is not a valid complete object of the target type, dynamic cast returns a null
  • 148. 328 OOP in C++ pointer. If dynamic cast is used to convert to a reference type and the conversion is not possible, an exception of type bad cast is thrown. ✞ 1 #include <iostream > using namespace std; 3 class B { 5 }; 7 class D : public B { }; 9 int main () { 11 B *b = new D; /* Conversion of base class to* 13 *derived class , ie down cast */ D *d = dynamic_cast <D*> (b); 15 if (d != NULL ) cout << 1; 17 else cout << "Error!!"; 19 return 0; } ✌ ✆ In above example, there is error as we try to downcast and base class has no virtual function (ie downcast without polymorphism). In the following example, base class is added a virtual function and in this case downcast conversion by dynamic cast is possible. ✞ #include <iostream > 2 using namespace std; 4 class B { public: 6 virtual void func () { 8 } }; 10 class D : public B { 12 }; 14 int main () { B *b = new D; 16 D *d = dynamic_cast <D*> (b); if (d != NULL ) 18 cout << 1; else 20 cout << "Error"; return 0; 22 } ✌ ✆
  • 149. 4.4. TEMPLATES 329 ✞ 1 ✌ ✆ 4.4 Templates Assume functions with same name but of different signatures as given below: ✞ 1 int myFunc(int x){ return x; 3 } double myFunc(double x){ 5 return x; } ✌ ✆ These functions have a unique structure as given below: ✞ <return type > <function name >(< parameter type > <var >){ 2 <statements > } ✌ ✆ A template is a class or a function that serves the above purpose. A template for above functions has syntax like ✞ 1 template <class T> // T stands for any type T myFunc(T x){ 3 return x; } ✌ ✆ In above example, the less than and greater than symbol after the template keyword are internal part of program structure and they can not be replaced. The class type, i.e. datatype is represented by ‘T’ and it is automatically selected by the compiler according to the parameter datatype. The ‘class type’ are int, double, class, string, array etc. ✞ #include <iostream > 2 using namespace std; 4 template <class T> T myFunc(T x) { 6 return x; } 8 int main () { 10 double x = 10.12; cout << myFunc(x) << endl ; 12 int y = 10.12; cout << myFunc(y) << endl ; 14 return 0; } ✌ ✆
  • 150. 330 OOP in C++ ✞ 10.12 10 ✌ ✆ Templates can be overloaded. ✞ template <class T> 2 T myFunc(T x){ return x; 4 } template <class T> // Overloaded 6 T myFunc(T x, T y){ return x+y; 8 } ✌ ✆ ✞ #include <iostream > 2 using namespace std; 4 template <class T> T myFunc(T x) { 6 return x; } 8 template <class T> 10 T myFunc(T x, T y) { return x + y; 12 } 14 int main () { cout << myFunc (10.12) << endl ; 16 cout << myFunc(10, 20) << endl ; return 0; 18 } ✌ ✆ ✞ 10.12 30 ✌ ✆ The data qualifiers can be used accordingly as and when required. See the example below: ✞ #include <iostream > 2 using namespace std; 4 template <typename T> T const &Max(T const &a, T const &b) { 6 return a < b ? b : a; } 8 int main (int argc , char *argv []) { 10 cout << "Max(45, 74) : " << Max(45, 74) << endl ; return 0;
  • 151. 4.4. TEMPLATES 331 12 } ✌ ✆ ✞ Max(45, 74) : 74 ✌ ✆ This program shall run similar to the following one: ✞ 1 #include <iostream > using namespace std; 3 template <typename T> 5 T Max(T a, T b) { return a < b ? b : a; 7 } 9 int main (int argc , char *argv []) { cout << "Max(45, 74) : " << Max(45, 74) << endl ; 11 return 0; } ✌ ✆ ✞ Max(45, 74) : 74 ✌ ✆ For a template class, template keyword tells the compiler that the class definition that follows will manipulate one or more unspecified types. At the time the actual class code is generated from the template, those types must be specified so that the compiler can substitute them. A template class is declared as ✞ 1 template < class class_name >//< and > are part of program class <class name > { 3 T <variable >; public: 5 T <statements >; }; ✌ ✆ See the example below: ✞ #include <iostream > 2 using namespace std; 4 template < class T=int , class U=int > class Test { 6 T x; U y; public: 8 Test (T t, U u): x(t), y(u) { } void display () { cout << x << "," << y << endl ;} 10 }; int main () { 12 Test <char , char >b(’a’, ’b’); b.display (); 14 Test < >c(’a’, 12.9); c.display ();
  • 152. 332 Miscellaneous 16 return 0; } ✌ ✆ ✞ a,b 97,12 ✌ ✆ ✞ #include <iostream > 2 using namespace std; template <class T> void display(T x) { 4 cout << x << " "; } 6 template <class T, class U> void display (T x, U y) { 8 cout << x << " " << y << endl ; } 10 int main () { double d=1.5; 12 int i=2; char c=’a’; 14 display (c); display (i, d); 16 display (c, d); return 0; 18 } ✌ ✆ ✞ a 2 1.5 a 1.5 ✌ ✆
  • 153. 5.1. ERRORS 333 5Miscellaneous 5.1 Errors A program written by a programmer should be in order of the rules of the programming language. If any code line of code is outside of the set rules of the languages, compiler shows errors specifying the position of code line and type of error. 5.1.1 Exception Handling An exception is a problem that arises during the execution of a program. A C++ excep- tion arises when a non-acceptable event is created. For example, division of a number by zero is not acceptable. At this case, C++ throws an exception. C++ has an exception class in standard library. We can write a user defined exception by overriding exception class. To handle an exception, there are three keywords, throw, catch and try. throw A program throws an exception when a problem shows up using throw keyword. The throws value is catched by following catch keyword. catch A program catches an exception with an exception handler. It is done by catch keyword. try A try block identifies a block of code for which particular exceptions will be activated. Each try block should be followed by at least catch block. ✞ try{ 2 <statements > }catch(<exception name > <handle >){ 4 <statements > } ✌ ✆ Exceptions is throw from anywhere within a code block using throw statements. For example ✞ 1 void myFunc () { <condition > 3 throw <message / message id >; } ✌ ✆ Each exception is catched in catch block. Each catch block should be preceded by try block. ✞ try{ 2 <statements > }catch(<exception name > <handle >){
  • 154. 334 Miscellaneous 4 <statements > } ✌ ✆ ✞ 1 #include <iostream > using namespace std; 3 int main () { 5 char c = ’c’; try { 7 cout << "Try & throw c" << endl ; throw c; 9 } catch (char c) { cout << "Caught " << c << endl ; 11 } 13 return 0; } ✌ ✆ ✞ Try & throw c Caught c ✌ ✆ The catch block following the try block catches any exception. Codes which handle any exception should be inside the catch block. Each throw is catched by the following catch block. ✞ #include <iostream > 2 using namespace std; 4 int main () { try { 6 try { throw 78.9; // throw 1 8 } catch (int n) {// catch throw 1 cout << "Locally Handle " << ’n’; 10 throw; // throw 2 } 12 } catch (int n) {// catch throw 2 cout << "Handle in the outer loop " << ’n’; 14 } catch (...) { cout << "default "; 16 return 0; } 18 return 0; } ✌ ✆ ✞ Locally Handle Handle in the outer loop ✌ ✆
  • 155. 5.1. ERRORS 335 C++ has a list of standard exceptions defined in ‘exception’ class. The list of exceptions is given in following table: Exception Description std::exception An exception and parent class of all the standard C++ exceptions. std::bad alloc An exception thrown by new. std::bad cast An exception thrown by dynamic cast. std::bad exception It handles the unpredictable exceptions. std::bad typeid An exception thrown by type id. std::logic error An exception that is detected by reading the codes. std::domain error An exception thrown when a mathematically invalid domain is used. std::invalid argument An exception thrown due to invalid arguments. std::length error An exception thrown when a too big string is created. std::out of range It is thrown when a vector or list is used. std::runtime error An exception that can not be detected by reading the codes. std::overflow error This is thrown if a mathematical overflow occurs. std::range error Exception, occurs when out of range value is stored. std::underflow error This is thrown if a mathematical underflow occurs. We can also create our own exception by inheriting and overriding ‘exception’ class. User defined exception are declared as ✞ struct <exception name > : public exception { 2 const char * <excep member func > const throw () { return <thrown message >; 4 } }; ✌ ✆ The example of the user defined exception is given below: ✞ 1 #include <iostream > /* Standard exception header file .*/ 3 #include <exception > using namespace std; 5 struct DivByZero : public exception { 7 const char * noDiv() const throw () {
  • 156. 336 Miscellaneous 9 return "Division by zero is not acceptable !!"; } 11 }; 13 int main (int argc , char ** argv ) { try { 15 /* Throw the user defined exception */ throw DivByZero (); 17 } catch (DivByZero & ex) {/* Catch the exception */ /* Show what we caught.*/ 19 cout << "Division exception caught!!" << endl ; /* Show what system thrown*/ 21 cout << ex.noDiv() << endl ; } 23 } ✌ ✆ ✞ Division exception caught !! Division by zero is not acceptable !! ✌ ✆ We can raise the exceptions through the function call. The raised exception is caught by catch clause. ✞ #include <iostream > 2 #include <exception > using namespace std; 4 class myExc : public exception {// 6 virtual const char * what () const throw() { 8 return "Divide By Zero "; } 10 }; 12 class DivideByZero { public: 14 int num , den; DivideByZero (int a = 0, int b = 0) : num(a), den(b) {} 16 int divide(int num , int den){ if (den == 0) { 18 throw myExc(); } 20 return (num / den); } 22 }; 24 int main () { 26 DivideByZero d; 28 try { d.divide(1, 0);
  • 157. 5.1. ERRORS 337 30 }catch (exception & e) { cout << e.what () << endl ; 32 } 34 return 0; } ✌ ✆ Multiple catches for same try function can be used. See the example below: ✞ 1 #include <iostream > using namespace std; 3 void myFunction (int test ) { 5 try { if (test ) 7 throw test ; else 9 throw "Value is zero "; } 11 catch (int i) { 13 cout << "CaughtOne "; } 15 catch (const char *str) { 17 cout << "CaughtString "; } 19 } int main () { 21 myFunction (-3); myFunction (0); 23 return 0; } ✌ ✆ ✞ CaughtOne CaughtStrin ✌ ✆ 5.1.2 Error Type In a programming language, errors are classified as : Compile Time Error A compile time error is the error which arises when a compiler compiles the program. Compile time errors are mostly related to syntax, procedure and functions. Run Time Error Run time error is the error which arises when a program run. A program which stores the time stamp or time validity shown the run time error if the program is run after expiry of the time. Logical or Semantic Error This type of error arises in the program when it runs successfully but suffers mismanagement in memory and stack logic. For example, if an
  • 158. 338 Miscellaneous array is of size n and programmer tries to put the n + 1 elements then program shows errors. 5.1.3 Exception Specification C++ provides a syntax which helps users to diagnose errors and exceptions thrown by a function. This syntax is throw. A function can be defined with throw as given below: ✞ 1 <func type > <func name > throw(<exp func 1>, <exp func 2>, ...) ; ✌ ✆ Without throw, the above function is purely a traditional function without throwing any exception. See example below: ✞ 1 #include <iostream > using namespace std; 3 class Up { 5 }; 7 class Down { }; 9 void callFunc (int i) throw (Up , Down ) { 11 switch (i) { case 1: throw Up (); 13 break; case 2: throw Down (); 15 break; } 17 } 19 int main (int argc , char ** argv ) { for (int i = 1; i <= 3; i++) { 21 try { callFunc (i); 23 } catch (Up) { cout << i << ": Up caught" << endl ; 25 } catch (Down ) { cout << i << ": Down caught" << endl ; 27 } } 29 return 0; } ✌ ✆ ✞ 1: Up caught 2: Down caught ✌ ✆ The classes Up and Down are created solely to throw as exceptions. Often exception classes can hold additional information for depth querying.
  • 159. 5.2. WRAPPING C & C++ 339 ✞ #include <iostream > 2 using namespace std; 4 class Up { public: 6 virtual void what () { 8 cout << "UP" << endl ; } 10 }; 12 class Down { public: 14 virtual void what () { 16 cout << "DOWN " << endl ; } 18 }; 20 void callFunc (int i) throw (Up , Down ) { switch (i) { 22 case 1: throw Up (); break; 24 case 2: throw Down (); break; 26 } } 28 int main (int argc , char ** argv ) { 30 for (int i = 1; i <= 3; i++) { try { 32 callFunc (i); } catch (Up up) { 34 up.what (); } catch (Down down ) { 36 down .what (); } 38 } return 0; 40 } ✌ ✆ ✞ UP DOWN ✌ ✆ 5.2 Wrapping C & C++ extern keyword is used to link external files in C++ program. To link a .h header file in C++. we declared extern function as
  • 160. 340 Miscellaneous ✞ extern "C"{ 2 #include <math .h> } ✌ ✆ See the example below: ✞ 1 #include <iostream > using namespace std; 3 extern "C"{ 5 #include <math .h> } 7 int main (int argc , char ** argv ) { cout << sin (3.14) << endl ; 9 return 0; } ✌ ✆ ✞ 0.00159265 ✌ ✆ We can also link the multiple languages single by single or in nested form by using extern keyword. ✞ 1 extern "C" { void myF(); /* C linkage */ 3 extern "C++" { void myG(); /* C++ linkage */ 5 extern "C" void myH(); /* C linkage */ } 7 void m(); /* C linkage */ } ✌ ✆ IT is common requirement of calling C functions from C++. In thies case, C function should be defined as extern “C”. Otherwise, the linker won’t be able to locate the C function. To make a header suitable for both C and C++ compilers, all the declarations are put inside extern “C” brackets, but the C compiler does not recognize this syntax. Every C++ compiler predefined the macro cplusplus, so we can use that macro to guard the C++ syntax : ✞ #ifdef __cplusplus /* Begin definition */ 2 extern "C" { /* extern C begin */ #endif 4 <body of header statement > #ifdef __cplusplus 6 } /* extern C closed */ #endif /* End definition */ ✌ ✆ See the example ✞ 1 #include <iostream >
  • 161. 5.3. CODING STYLE 341 using namespace std; 3 #ifdef __cplusplus 5 extern "C" { #endif 7 #include <math .h> #ifdef __cplusplus 9 } #endif 11 int main (int argc , char ** argv ) { 13 cout << sin (3.14) << endl ; return 0; 15 } ✌ ✆ ✞ 0.00159265 ✌ ✆ We can access the C++ code from C. See the example below: ✞ 1 #include <iostream > using namespace std; 3 extern "C" int print(int i, double d) { 5 cout << "i = " << i << ", d = " << d << endl ; } 7 int main (int argc , char ** argv ) { 9 print(3, 14.2); return 0; 11 } ✌ ✆ ✞ i = 3, d = 14.2 ✌ ✆ 5.3 Coding Style 5.3.1 Reserved Keyword There are some keywords which are solely reserved for internal use by C++. They can not be redefined by programmer. These keywords also can not be overloaded. The list of reserved keywords is given in below table.
  • 162. 342 Miscellaneous and compl export namespace return try char16 t and eq const extern new short typedef char32 t asm const cast false not signed typeid constexpr auto continue float not eq sizeof typename decltype bitand default for operator static union noexcept bitor delete friend or static cast unsigned nullptr bool do goto or eq struct using static assert break double if private switch virtual thread local case dynamic cast inline protected template void wchar t catch else int public this volatile while char enum long register throw alignas xor class explicit mutable reinterpret cast true alignof xor eq Operator Type Id The typeid operator allows the type of an object to be determined at run time. The result of typeid is a ✞ 1 const type_info & ✌ ✆ The value is a reference to a type info object that represents either the type-id or the type of the expression, depending on which form of typeid is used. The typeid operator does not work with managed types (abstract declarators or instances). The typeid operator does a run-time check when applied to an l-value of a polymorphic class type, where the true type of the object cannot be determined by the static information provided. Such cases are: 1. A reference to a class 2. A pointer, dereferenced with * 3. A sub-scripted pointer (i.e. [ ]) ✞ 1 #include <iostream > #include <typeinfo > 3 using namespace std; 5 class A { public: 7 virtual ~A() { 9 } }; 11 class B : public A { 13 }; 15 int main () { A a;
  • 163. 5.3. CODING STYLE 343 17 A *b = new A(); cout << typeid (a).name () << ": " << typeid (&a).name () << endl ; 19 cout << typeid (b).name () << ": " << typeid (*b).name () << endl ; return 0; 21 } ✌ ✆ ✞ 1A: P1A P1A: 1A ✌ ✆ constexpr decltype nullptr thread local this typename 5.3.2 Case Sensitivity C++ identifiers are case sensitive i.e. myname, MYNAME, and MyName are the names of three different objects. Some linkers may map external identifiers to a single case, although this is uncommon in most modern linkers. See the following example, in which two variables ‘y’ and ‘Y’ are declared and initialized. They are treated as two different variables and can be accessed differently. ✞ #include <iostream > 2 using namespace std; 4 int main (int argc , char *argv []) { // Declare a variable y 6 int y = 1; // Declare a variable Y 8 int Y = 2; cout << "y is " << y << " and Y is " << Y; 10 return 0; } ✌ ✆ ✞ y is 1 and Y is 2 ✌ ✆ 5.3.3 Commenting Commenting inside the C++ code is a beautiful feature of C++ language. It provides the utility for writing managed codes. Commenting occurs within the C++ codes. It may be of a single line or can span in multiple lines. There are two way of commenting. First is
  • 164. 344 C++ Standards single line commenting which started with ‘//’. Anything written in the line started with ‘//’ are skipped by the C++ compilers. Presence of another ‘//’ in the same line does not end the single line comment. Second method is multiline commenting. Text starting with the token ‘/*’ are treated as a comments and ignored. The multiline comments are ended at next token ‘*/’. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 // Declare a variable // as y int y; 7 /* <-- given expression * *y = (5 + 3 - 4) % 2 * 9 *is computed in steps* *y = (8 - 4) % 2 * 11 *y = 4 % 2 = 0 -->*/ y = (5 + 3 - 4) % 2; 13 cout << "Result is : << y; return 0; 15 } ✌ ✆ ✞ Result is : 0 ✌ ✆
  • 165. 6.1. C++14 345 6C++ Standards 6.1 C++14 C++11 allowed lambda functions to deduce the return type based on the type of the expression given to the return statement. C++14 provides this ability to all functions. To induce return type deduction, the function must be declared with auto as the return type, but without the trailing return type specifier in C++11: ✞ 1 auto DeduceReturnType (); /* Return type to be determined */ ✌ ✆ If there are multiple return expressions then they all must be deduce the same type. Recursion can be used to a function of this type, but the recursive call must happen after at least one return statement in the definition of the function: ✞ 1 auto myF(int i) { if (i == 1){ 3 return i; /* return type deduced as int*/ }else { 5 /* Good & OK as there is prior return*/ return myF(i-1)+i; 7 } } ✌ ✆ ✞ #include <iostream > 2 using namespace std; 4 int myF(int i) { if (i == 1) { 6 return i; /* return type deduced as int*/ } else { 8 /* Good & OK as there is prior return*/ return myF(i - 1) + i; 10 } } 12 int main (int argc , char *argv []) { 14 cout << "myF (1) = " << myF (1) << endl ; cout << "myF (2) = " << myF (2) << endl ; 16 cout << "myF (3) = " << myF (3) << endl ; return 0; 18 } ✌ ✆
  • 166. 346 C++ Standards ✞ myF (1) = 1 myF (2) = 3 myF (3) = 6 ✌ ✆ ✞ 1 auto myF(int i) { if (i == 1){ 3 /* Bad & Not OK as there is no prior return */ return myF(i-1)+i; 5 }else { return i; /* return type deduced as int*/ 7 } } ✌ ✆ ✞ #include <iostream > 2 using namespace std; 4 int myF(int i) { if (i == 1) { 6 /* Bad & Not OK as there is no prior return */ return myF(i - 1) + i; 8 } else { return i; /* return type deduced as int*/ 10 } } 12 int main (int argc , char *argv []) { 14 cout << "myF (1) = " << myF (1) << endl ; cout << "myF (2) = " << myF (2) << endl ; 16 cout << "myF (3) = " << myF (3) << endl ; return 0; 18 } ✌ ✆ ✞ myF (1) = 1 myF (2) = 2 myF (3) = 3 ✌ ✆ Before C++14, only functions, classes or type aliases could be templates. In C++14, we can create the variables as templates. ✞ 1 template < typename T> constexpr T pi = T (3.141592653589793238462643383); ✌ ✆ Numeric literals in C++14 can be specified in binary form. The syntax uses the prefixes 0b or 0B. ✞ #include <iostream > 2 using namespace std;
  • 167. 6.1. C++14 347 4 int main (int argc , char *argv []) { int i = 0b1000; 6 cout << i << endl ; return 0; 8 } ✌ ✆ ✞ 8 ✌ ✆ Hexadecimal form of assignment of number to a variable is given in following example. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 int i = 0x1000; cout << i << endl ; 7 return 0; } ✌ ✆ ✞ 4096 ✌ ✆ Octal form of assignment of number to a variable is given in following example. ✞ 1 #include <iostream > using namespace std; 3 int main (int argc , char *argv []) { 5 int i = 01000; cout << i << endl ; 7 return 0; } ✌ ✆ ✞ 512 ✌ ✆ In C++14, the single-quote character may be used arbitrarily as a digit separator in numeric literals, both integer literals and floating point literals. In C++11, lambda function parameters need to be declared with concrete types. C++14 allows lambda function parameters to be declared with the auto type specifier. ✞ 1 auto lambda = []( auto x, auto y) {return x + y;}; ✌ ✆ As for auto type deduction, generic lambdas follow the rules of template argument de- duction. ✞ 1 struct unnamed_lambda { template <typename T, typename U> 3 auto operator ()(T x, U y) const { return x + y;} }; 5 auto lambda = unnamed_lambda {}; ✌ ✆
  • 168. 348 C++ Standards The deprecated attribute allows marking an entity deprecated, which shows warning at the time of code compilation. C++14 extends to allow fetching from a tuple by type instead of by index. If the tuple has more than one element of the type, a compile-time error results: ✞ 1 tuple <string , string , int > t("foo", "bar", 7); int i = get <int >(t); /* i == 7 */ 3 int j = get <2>(t); /* Same as before: j == 7 */ /* Compile -time error due to ambiguity */ 5 string s = get <string >(t); ✌ ✆