Object Oriented Programming
Object Oriented Programming
CEEN2231-L
4 Lab 4:Structures I 49
5 Lab 5:Structures II 59
8 Lab 8:Friend Function & Classes, This Pointer, and static Variables 99
iii
iv Contents
Chapter 1
A class is a data type that you define. It can contain data elements, which can
either be variables of the basic types in C++ or other user-defined types. The data
elements of a class may be single data elements, arrays, pointers, arrays of pointers
of almost any kind or objects of other classes, so you have a lot of flexibility in what
you can include in your data type. A class can also contain functions which operate
on objects of the class by accessing the data elements that they include. So, a class
combines both the definition of the elementary data that makes up an object and
the means of manipulating the data belonging to individual instances of the class.
The data and functions within a class are called members of the class. Funnily
enough, the members of a class that are data items are called data members and the
members that are functions are called function members or member functions. The
member functions of a class are also sometimes referred to as methods, although we
will not be using this term.
Figure 1.1:
Now let’s keep track of 4 ages instead of just one. We could create 4 separate
variables, but 4 separate variables have limited appeal. (If using 4 separate variables
1
2 Lab 1:Review of CS101 & Arrays (1D and
is appealing to you, then consider keeping track of 93843 ages instead of just 4).
Rather than using 4 separate variables, we’ll use an array.
Here’s how to create an array and one way to initialize an array:
Example 1.2:
On line (5), an array of 4 short’s is created. Values are assigned to each variable in
the array on line (6) through line (9).
Figure 1.2:
13 1 2 : cout <<" Age at index [ 2 ] = " <<age [2] < < endl
14 ; 1 3 : cout <<" Age at index [ 3 ] = " <<age [3] < <
15 endl ; 1 4 : return 0 ;
16
17 15: }
Lines (10) through line (13) produce the output we are expecting. There is no single
statement in the language that says "print an entire array to the screen". Each element
in the array must be printed to the screen individually.
Copying arrays
Suppose that after filling our 4 element array with values, we need to copy that array
to another array of 4 short’s? Try this:
Example 1.5:
Line (12) tries to copy the age array into the same_age array. What happened
when you tried to compile the program above?
The point here is that simply assigning one array to another will not copy the
elements of the array. The hard question to answer is why the code doesn’t compile.
Later in the tutorial this example will be re-examined to explain why line (12) doesn’t
work. This code should not compile on either C or C++ compilers. However, some
older C++ compilers may ignore the ISO C++ standard and allow line 12 to compile.
If it does compile on your C++ compiler, make a mental note that it is incorrect
behavior.
Let’s try copying arrays using a technique similar to the technique used to print
arrays (that is, one element at a time):
4 Lab 1:Review of CS101 & Arrays (1D and
Example 1.6:
This technique for copying arrays works fine. Two arrays are created: age and
same_age. Each element of the age array is assigned a value. Then, in order to
copy of the four elements in age into the same_age array, we must do it element by
element.
Like printing arrays, there is no single statement in the language that says "copy
an entire array into another array". The array elements must be copied individually.
The technique used to copy one array into another is exactly the same as the
technique used to copy 4 separate variables into 4 other variables. So what is the
advantage to using arrays over separate variables?
One significant advantage of an array over separate variables is the name. In
our examples, using four separate variables requires 4 unique names. The 4 short
variables in our array have the same name, age. The 4 short’s in the array are identical
except for an index number used to access them. This distinction allows us to shorten
our code in a way that would be impossible with 4 variables, each with unique names:
Example 1.7:
Since the only difference between each of the short’s in the arrays is their index, a
loop and a counter can be used to more easily copy all of the elements. The same
technique is used to shorten the code that prints the array to the screen. Even though
arrays give us some convenience when managing many variables of the same type,
there is little difference between an array and variables declared individually. There
is no single statement to copy an array, there is no single statement to print an array.
If we want to perform any action on an array, we must repeatedly perform that
action on each element in the array. section*2-Dimensional (2-D) Arrays So far we
have explored arrays with only one dimension. It is also possible for arrays to have
two or more dimensions. The two-dimensional array is also called a matrix.
Here is a sample program that stores roll number and marks obtained by a stu-
dent side by side in a matrix.
6 Lab 1:Review of CS101 & Arrays (1D and
Example 1.8:
There are two parts to the program,in the first part through a for loop we read in the
values of roll no. and marks, whereas, in second part through another for loop we
print out these values.
Look at the cin( ) statement used in the first for loop:
1 cin >>stud [ i ][ 0 ] > > stud [ i ] [ 1 ] ;
In stud[i][0] and stud[i][1] the first subscript of the variable stud, is row number
which changes for every student. The second subscript tells which of the two columns
are we talking about —he zeroth column which contains the roll no. or the first col-
umn which contains the marks. Remember the counting of rows and columns begin
with zero. The complete array arrangement is shown below.
Thus, 1234 is stored in stud[0][0], 56 is stored in stud[0][1] and so on. The above
arrangement highlights the fact that a two- dimensional array is nothing but a col-
lection of a number of one-dimensional arrays placed one below the other.
In our sample program the array elements have been stored rowwise and ac-
cessed rowwise. However, you can access the array elements columnwise as well.
Traditionally, the array elements are being stored and accessed rowwise; therefore
we would also stick to the same strategy.
};
Or we can write like this also..
The above format work also but it is more difficult to read as compared to the first
one. It is important to remember that while initializing a 2-D array it is necessary
to mention the second (column) dimension, whereas the first dimension (row) is op-
tional.
Let see the arrangement of the above student arrays in memory which contains roll
number and marks.
8 Lab 1:Review of CS101 & Arrays (1D and
Figure 1.5:
Example 1.9:
This example will simply define an array of 2x3 and take input from user and prints
scanned array.
1 # include <iostream . h>
2
3 void main ( )
4
5 {
6
7 int arr [2][3] , i , j ;
8
9 fo r ( i = 0 ; i < 2 ; i ++)
10
11 fo r ( j = 0 ; j < 3 ; j ++)
12
13 {
14
15 cout <<" Enter Value fo r " << i +1 << " row " << j +1 <<" column\n" ; cin >>ar r [ i ] [ j
];
16
17 }
18
19 cout <<"\n ! ! ! Scanning Array Complete ! ! ! \ n\n\n" ;
20
21 fo r ( i = 0 ; i < 2 ; i ++)
22
23 {
24
25 fo r ( j = 0 ; j < 3 ; j ++)
26 cout <<a r r [ i ] [ j ] <<"\ t " ;
27
28 cout <<"\n\n" ;
29
30 }
31
32 }
Example 1.10:
9
24
25 return 0;
26
27 }
Figure 1.6:
Note:
Exercise:
Q1. Write a program to find out number of even and odd out of array of size 10.
Figure 1.7:
Figure 1.8:
Q3. Write a program by declaring two functions maximum and minimum. Ini-
tialize two dimensional array of size 3*3 with integer numbers in main function of
the program. Pass array as parameter to function maximum to find out maximum
number and to function minimum to find out minimum number. Display minimum
and maximum numbers from main function of the program.
Figure 1.9:
1 Lab 1:Review of CS101 & Arrays (1D and
Chapter 2
In this lab we will be discussing pointers in detail. This is one of the most
important concepts in C++ language. Pointers are used everywhere in C++, so if you
want to use the C++ language fully you have to have a very good understanding of
pointers. They have to become comfortable for you.
C++ uses pointers in three different ways:
â A˘ c´ C++ uses pointers to create dynamic data structures – data structures
built up from blocks of memory allocated from the heap at run-time.
â A˘ c´ C++ uses pointers to handle variable parameters passed to functions.
â A˘ c´ Pointers in C++ provide an alternative way to access information
stored in arrays. Pointer techniques are especially valuable when you work with
strings. There is an intimate link between arrays and pointers in C++.
To fully grasp the concept of pointers all you need is the concept and practice of
pointers. Before talking about pointers letâ A˘ Z´ s talk a bit about computer
memory.
Computer Memory
Essentially, the computer’s memory is made up of bytes. Each byte has a number,
an address, associated with it. The picture below represents several bytes of a com-
puter’s memory. In the picture, addresses 924 thru 940 are shown.
Figure 2.1:
13
1 Lab 2 Pointers in
range over which the variable is allowed to vary. For example, on 32 bit PC’s the size
of an integer variable is 4 bytes. On older 16 bit PCs integers were 2 bytes.
Example 2.1:
Figure 2.2:
Figure 2.3:
1. The program finds and grabs the address reserved for fl–in this example 924.
2. The contents stored at that address are retrieved
The illustration that shows 3.14 in the computer’s memory can be misleading.
Looking at the diagram, it appears that "3" is stored in memory location 924, "." is
stored in memory location 925, "1" in 926, and "4" in 927. Keep in mind that the
computer actually converts the floating point number 3.14 into a set of ones and
zeros. Each byte holds 8 ones or zeros. So, our 4 byte float is stored as 32 ones and
zeros (8 per byte times 4 bytes). Regardless of whether the number is 3.14, or -273.15,
the number is always stored in 4 bytes as a series of 32 ones and zeros.
Pointer:
Pointer declaration:
A pointer is a variable that contains the memory location of another variable. The
syntax is as shown below. You start by specifying the type of data stored in the
loca- tion identified by the pointer. The asterisk tells the compiler that you are
creating a pointer variable. Finally you give the name of the variable.
Data_type *variable_name
Such a variable is called a pointer variable (for reasons which hopefully will become
clearer a little later). In C++ when we define a pointer variable we do so by preceding
its name with an asterisk. In C++ we also give our pointer a type which, in this case,
refers to the type of data stored at the address we will be storing in our pointer. For
example, consider the variable declaration:
int *ptr;
int k;
ptr is the name of our variable (just as k is the name of our integer variable). The
’*’ informs the compiler that we want a pointer variable, i.e. to set aside however
many bytes is required to store an address in memory. The int says that we intend to
use our pointer variable to store the address of an integer.
1 Lab 2 Pointers in
Referencing Operator
Suppose now that we want to store in ptr the address of our integer variable k. To
do this we use the unary & operator and write:
ptr = &k;
What the & operator does is retrieve the address of k, and copies that to the contents
of our pointer ptr. Now, ptr is said to "point to" k.
Dereferencing operator
The "dereferencing operator" is the asterisk and it is used as follows:
*ptr = 7;
will copy 7 to the address pointed to by ptr. Thus if ptr "points to" (contains the
address of) k,the above statement will set the value of k to 7. That is, when we use
the ’*’ this way we are referring to the value of that which ptr is pointing to, not the
value of the pointer itself.
Similarly, we could write:
cout«*ptr«endl;
to print to the screen the integer value stored at the address pointed to by ptr;.
Figure 2.4:
Example 2.2:
5 int f i r s t v a l u e = 5 , secondvalue = 1 5 ; i n t ∗ p1 , ∗ p2 ;
6 p1 = &f i r s t v a l u e ; // p1 = address of f i r s t v a l u e
7 p2 = &secondvalue ;// p2 = address of secondvalue
8 ∗p1 = 1 0 ; // value pointed by p1 = 10
9
10
11 ∗p2 = ∗p1 ;// value pointed by p2 = value pointed by p1
12 p1 = p2 ;// p1 = p2 ( value of po inte r i s copied )
13 ∗p1 = 2 0 ; // value pointed by p1 = 20
14 cout <<" F i r s t Value i s " << f i r s t v a l u e <<endl ;
15
16 cout <<" Second Value i s " <<secondvalue <<endl ; return 0 ;
17
18 }
19
Figure 2.5:
Here in this code we are trying to play with memory and address of our vari-
ables for the better understanding of Pointers. On line number 5 we have two integer
variables (i.e firstvalue and secondvalue). Both are assigned values of 5 and 15 re-
spectively. On line number 6 we have two integer pointer variables (i.e p1 and p2).
Both are assigned addresses of variables in line 5 firstvalue and secondvalue
respec- tively in line 7 and 8.
Figure 2.6:
In line 9 we see that *p1 is assigned value 10. This means that 10 should be copied
in the variable, which is lying on an address to which p1 is pointing. We know that
p1 is pointing to address of firstvalue. So line 9 results in assigning firstvalue the
value of 10.
1 Lab 2 Pointers in
Figure 2.7:
Figure 2.8:
Well the assignment in line 11 is a bit confusing but very simple, all this assign-
ment is doing is that now p1 is pointing to the same address as p2. So now we can
say p1 and p2 are pointing at same address.
Figure 2.9:
1
In line 12 we see that *p1 is assigned value 20. This means that 10 should be
copied in the variable, which is lying on an address to which p1 is pointing. We know
that p1 is now pointing to address of secondvalue because in last line we pointed
p1 to the address being pointed by p2. So line 12 results in assigning secondvalue
the value of 20.
Figure 2.10:
Now when we print the value of first value and second value it prints 10 for
firstvalue and 20 for secondvalue; which is right due to the reasons explained above.
Here is a cool aspect of C++: Any number of pointers can point to the same address.
For example, you could declare p, q, and r as integer pointers and set all of them to
point to i, as shown here:
1 int i ;
2
3 i n t ∗p , ∗q , ∗ r ;
4
5
6
7 p = &i ;
8
9 q = &i ;
10
11 r= p;
Note that in this code, r points to the same thing that p points to, which is i. You can
assign pointers to one another, and the address is copied from the right-hand side
to the left-hand side during the assignment. After executing the above code, this is
how things would look:
2 Lab 2 Pointers in
Figure 2.11:
The variable i now has four names: i, *p, *q and *r. There is no limit on the
number of pointers that can hold (and therefore point to) the same address.
Pointer Arithmetic’s
Like other variables pointer variables can be used in expressions. For example if p1
and p2 are properly declared and initialized pointers, then the following statements
are valid.
1 y=∗p1 ∗ ∗p2 ;
2 sum=sum+∗p1 ;
3 z= 5 − ∗p2$/$∗p1 ;
4 ∗p2= ∗p2 + 1 0 ;
object to which the pointer refers. The number of bytes depends on the object’s data
type.
Example 2.3:
28
29 1 8 : ptr 1 =ptr 1 + 1 ; // adds 4 in address of ptr 1 . ( 1 ∗ 4 = 4 )
30 1 9 : ptr 2 = ptr 2 ;
31 2 0 : cout <<" a : " <<a<<" b : " <<b<<endl ; of a and b
32 //Simply p r i n t s the value
33
34 2 1 : cout <<" Value in ptr 1 : " <<ptr 1 <<endl <<endl ; // 2293564 //The comment value i s the new memory l o
35 22:
36 cout <<"\nAddress−Value in ptr 1 : " <<∗ptr 1 <<endl <<endl ; // garbage value
//The comment value i s the new value of ptr 1 ( garbage value )
37
38 23: cout <<" Address of b : " <<ptr 2 <<endl <<endl ;
2 Lab 2 Pointers in
Here note that adding some thing in *ptr1 changes the value of the address stored
in ptr. However adding some thing in ptr will change the address it is pointing to.
Printing ptr1 after adding 1 in it gives different address as it has changed by 4 Bytes.
Figure 2.12:
How it Works:
This code explains all the rules related to arithematic of pointers. From line 1 to
line 11, it is simply adding, subtracting and like manipulating with the pointers and
variables. After all the manipulations and arithmetics it started printing values of
pointers and other simple variables till line 12.
Figure 2.13:
At line 18 it adds 1 to ptr1. Mostly people think that this will change the address
of the pointer, but they are totally wrong. Remember pointer is pointing to an ad-
dress. This addition does not change the address of the pointer, infact it changes the
value of the pointer (not the value of the address pointer is pointing at.). ptr1 has the
address of variable of variable a . So it adds 1 *4 Btytes = 4 bytes in the address of a
2
which is stored in ptr1. Where as ptr2 points at the same value as before due to the
assignment of line 19.
Figure 2.14:
Line 20 prints the same value as was printed by the Line 16, because values
of the variable was never changed, in fact ptr1âA˘ Z´ s value which was address
of a was changed. Now Line 21 will print the value stored in ptr1; which is address
of memory 4 bytes ahead of variable a. Line 22 is trying to print the value at
address, ptr1 is now pointing to, which was never assigned any value.
Example 2.4:
19 swap ( p , q ) ;
20
21 cout <<" a : " <<a<<" b : " <<b<<endl ;
22
23 cin >>a ;
24
25 }
26
27 void swap ( i n t ∗x , i n t ∗y )
28
29 {
30
31 int t = ∗x ;
32
33 ∗x = ∗y ;
34
35 ∗y = t ;
36
37 }
Figure 2.15:
a = 20 b = 10
Note that this program manages to exchange the values of a and b using their ad-
dresses stored in x and y.
Function Pointers
A function pointer is a variable that stores the address of a function that can later be
called through that function pointer. A useful technique is the ability to have pointers
to functions. Their declaration is easy: write the declaration as it would be for the
function, say
And simply put brackets around the name and a * in front of it: that declares the
pointer. Because of precedence, if you don’t parenthesize the name, you declare a
function returning a pointer:
/* function returning pointer to int */
int *func(int a, float b); //Wrong
2
Once you’ve got the pointer, you can assign the address of the right sort of func-
tion just by using its name: like an array, a function name is turned into an address
when it’s used in an expression. You can call the function as:
(*func)(1,2);
Example 2.5
valid:
myarray = mypointer;
Let’s see an example that mixes arrays and pointers:
Example 2.6:
Output would be
10, 20, 30, 40, 50, Pointers and arrays support the same set of operations, with the
same meaning for both. The main difference being that pointers can be assigned new
addresses, while arrays cannot.
In the chapter about arrays, brackets ([]) were explained as specifying the index
of an element of the array. Well, in fact these brackets are a dereferencing operator
known as offset operator. They dereference the variable they follow just as * does,
but they also add the number between brackets to the address being dereferenced.
For example:
1 a [ 5 ] = 0 ; // a [ o f f s e t of 5 ] = 0
2
3 ∗( a +5 ) = 0 ; // pointed by ( a +5 ) = 0
These two expressions are equivalent and valid, not only if a is a pointer, but also if
a is an array.
Remember that if an array, its name can be used just like a pointer to its first
element.
2
Note:
Before doing your lab exercises run the examples.
Exercise:
Q1: Write a program to take 10 values from user and store them in an array. Then
use pointers to display the squared values of the array in reverse order.
Q2: Write a program to ask 5 values from user and store them in an array, the
program should find the max value of the array by calling to a function, assign that
max value to variable Max and then display it in main using pointer.
Q3: Write a program that passes two values to a function "greater" through pointer
to function method. Display in main () which number is greater.
2 Lab 2 Pointers in
Chapter 3
Figure 3.1:
29
3 Lab 3:Strings in
Arrays of Characters
Re-Introduction to Characters
As it happens, strings are the most used items of computers. In fact, anything the
user types is a string. It is up to you to convert it to another, appropriate, type of
your choice. This is because calculations cannot be performed on strings. On the
other hand, strings can be a little complex,which is why we wanted to first know
how to use the other types and feel enough comfortable with them.
Example 2.3:
Figure 3.2:
When studying arrays, we were listing the numeric members of the array between
curly brackets. Here is an example:
int Number[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
Because a character is initialized by including it in single-quotes, when creating an
array of characters, to initialize it, you must also include each letter accordingly. A
name such as James can be initialized as follows:
As done with other arrays, each member of this array of characters can be accessed
using its index. Here is an example:
Example 3.1:
Figure 3.3:
The C/C++ provides another alternative. It allows you to declare and initialize the
array as a whole. To do this, include the name in double-quotes. With this technique,
the curly brackets that delimit an array are not necessary anymore. Here is an
exam- ple:
With this technique, the item between the double-quotes is called a string. It is
also referred to as the value of the string or the value of the variable.
When declaring and initializing an array of characters, the compiler does not need to
know the number of characters of the string. In fact, you can let the compiler figure
it out. Therefore, you can leave the square brackets empty:
char Name[] = "James";
After declaring such an array, the compiler would count the number of characters
of the variable, add one more variable to it and allocate enough space for the vari-
able. The character added is called the null-terminated character and it is represented
as \0. Therefore, a string such as James would be stored as follows:
To request the value of an array of characters, use the cin extractor just like you would
proceed with any other variable, without the square bracket. Here is an example:
1 char WeekDay [ 1 2 ] ;
2 cout << " Enter today ’ s name : " ;
3 c in >> WeekDay ;
To display the value of an array of characters, use the cout extractor as we have used
it with all other variables, without the square brackets. Here is an example:
Example 3.2:
This variable is in fact two arrays and each array contains 6 integers. For a string, if
you want to declare a two-dimension array of characters, the first dimension specifies
the number of string in the variable. The second dimension specifies the number of
characters that each string can hold. Here is an example:
In this case, the StudentName variable is an array of 4 strings and each string can
have a maximum of 9 characters (+1 for the null-terminated character). To locate a
string on this variable, type the name of the array followed by its index, which is
the index of the column. This means that the first string of the StudentName array
can be accessed with StudentName[0]. The second would be StudentName[1], etc.
This allows you to display each string on the cout extractor:
Example 3.3:
Student Names
Student 1: Hermine
Student 2: Paul
Student 3: Gertrude
Student 4: Leon
When declaring and initializing such an array, the compiler does not need to know
the number of strings in the array; it can figure it out on its own. Therefore, you
can leave the first pair square brackets empty. If you are only declaring the array but
cannot initialize, then you must specify both dimensions.
3
Figure 3.4:
Pointers can be quite challenging to learn. The diagram should provide a better in-
sight.
The variable name (a pointer to a char) was located at address 0x007fe78. A
pointer is 32 bits, ie. 4 bytes long and holds an address of the string which was
0x00408004. Addresses are always given in hexadecimal. The arrow shows what
the pointer is pointing to, ie what is at the address in the pointer variable.
At this address there were 13 bytes holding the string "David Bolton" with a ter-
minating NULL, the same value as ’\0’.
The name of the variable is a pointer to the beginning of the array. For this rea-
son, the name of the reason is sufficient to locate its value. Since in this case we do
not specify the number of characters in the array, we can also just use a pointer to
the array as the beginning of the array. The array can therefore be declared as follows:
Once again, to display the value of such an array, simply call its name on the cout
extractor:
To request the value of an array of characters from the user, you can declare a pointer
to char and initialize it with an estimate number of characters using the new operator.
Here is an example:
Example 3.4:
8 Value = 1 2 . 5 5 ;
9 cout << " Value = " << Value ;
10 return 0 ;
11
12 }
On the other hand, the following declaring of an array of characters and its later
initialization is perfectly legal:
Example 3.8:
Strings as Variables
oneString += "5";
â A˘ c´ For instance, what exactly does it mean if one string is "less than" another?
String I/O
â A˘ c´ A common problem with reading strings from user input is that it could
contain white spaces. Remember that white space (e.g. space, tab, newline) is treated
as termination for cin.
string fullname;
3
cin » fullname;
String Processing
â A˘ c´ In addition to giving us a new data type to hold strings, the string library
offers many useful string processing methods.
â A˘ c´ You can find most of them of them in the book, but here are a few useful
â A˘ c´ This method returns the integer length of the string. The length() and size()
are the same.
â A˘ c´
Example:
string s1 = "Super!";
at(index)
â A˘ This method returns the character at the specified index. Indices start from
c´
0.
â A˘ c´ Example:
string n = "Vikram";
erase(index)
â A˘ c´ This method removes all characters from the string starting from the
specified index to the end.
index! â A˘ c´ Example:
os.erase(9);
cout « os « endl;
find(str)
â A˘ This method returns the integer index of the first occurrence of the specified
c´
string
4
â A˘ c´ Example:
//0 is output
find(str, index)
â A˘ c´ This method returns the integer index of the first occurrence of the specified
string starting from the specified
//5 is output
insert(index, str)
â A˘ c´ Inserts the specified string at the specified index.
â A˘ c´ Example:
replace(index, n, str)
â A˘ c´ Removes n characters in the string starting from the specified index, and
inserts the specified
place. â A˘ c´
Example:
transport.replace(0, 5, "Sail");
substr(index, n)
â A˘ c´ Returns the string consisting of n characters starting from the specified
index. â A˘ c´ Example:
//outputs "Ship"
strlen() â A˘ c´
strcpy() â A˘ c
´ strncpy()
â A˘ c´
strcat() â A˘ c´
strncat()
4
â A˘ c´
strcmp() â A˘ c´
strncmp()
Strlen ()
Syntax:
len = strlen(ptr);
strlen() returns the length of a string, excluding the null. The following code will
result in len having the value 13.
int len;
char str[15];
len = strlen(str);
Example 3.9:
22 return 0;
23
24 }
Strcpy ()
strcpy(ptr1, ptr2);
where ptr1 and ptr2 are pointers to char
strcpy() is used to copy a null-terminated string into a variable. Given the following
declarations, several things are possible.
char S[25];
char D[25];
â A˘ c´ strcpy(D, &S[8]);
N.B. If you fail to ensure that the source string is null-terminated, very strange and
sometimes very ugly things may result.
Strncpy ()
strncpy(ptr1, ptr2, n);
where n is an integer and ptr1 and ptr2 are pointers to char
char S[25];
char D[25];
Assume that the following statement has been executed before each of the remaining
4
code fragments.
â A˘ c´ D[2] = ’\0’;
â A˘ c´ Copying the tail end of string S to D:
â A˘ c´ strncpy(D, &S[8], 15);
Strcat ()
strcat(ptr1, ptr2);
where ptr1 and ptr2 are pointers to char
â A˘ c´ strcat(D, S);
N.B. If you fail to ensure that the source string is null-terminated, very strange and
sometimes very ugly things may result.
4 Lab 3:Strings in
Strncat ()
Syntax: strncat(ptr1, ptr2, n);
where n is an integer and ptr1 and ptr2 are pointers to char
N.B. If you fail to ensure that the source string is null-terminated, very strange and
sometimes very ugly things may result.
Strcmp ()
Syntax: diff = strcmp(ptr1, ptr2);
where diff is an integer and
ptr1 and ptr2 are pointers to char
strcmp() is used to compare two strings. The strings are compared character by
character starting at the characters pointed at by the two pointers. If the strings are
identical, the integer value zero (0) is returned. As soon as a difference is found,
the comparison is halted and if the ASCII value at the point of difference in the first
string is less than that in the second (e.g. ’a’ 0x61 vs. ’e’ 0x65) a negative value is
returned; otherwise, a positive value is returned. Examine the following examples.
diff will have a negative value after the following statement is executed.
4
diff will have a value of zero (0) after the execution of the following statement, which
compares s1 with itself.
Strncmp ()
strncmp() is used to compare the first n characters of two strings. The strings are
compared character by character starting at the characters pointed at by the two
pointers. If the first n strings are identical, the integer value zero (0) is returned. As
soon as a difference is found, the comparison is halted and if the ASCII value at the
point of difference in the first string is less than that in the second (e.g. ’a’ 0x61 vs. ’e’
0x65) a negative value is returned; otherwise, a positive value is returned. Examine
the following examples.
diff will have a negative value after the following statement is executed.
diff will have a positive value after the following statement is executed.
diff will have a value of zero (0) after the following statement.
Note:
Before doing your lab exercises run the examples.
Exercise:
Q1: Write a program to count the number of words and number of spaces in a string.
Q2: Write a program to ask the user for a string and then checks where it is a
palindrome or not.
Chapter 4
Lab 4:Structures I
STRUCTURES
Arrays require that all elements be of the same data type. Many times it is neces-
sary to group information of different data types. An example is a materials list for a
product. The list typically includes a name for each item, a part number, dimensions,
weight, and cost.
C and C++ support data structures that can store combinations of character, inte-
ger floating point and enumerated type data. They are called a STRUCTS.
Often multiple variables must be passed from one function to another, and often
these variables have different data types. Thus it is useful to have a container to store
various types of variables in. Structs allow the programmer to do just that
A struct is a derived data type that consists of members that are each fundamen-
tal or derived data types.
struct is used to declare a new data-type. Basically this means grouping variables
together.
Structures Definition
Before a structure is created, it is necessary to define its overall composition. The
format of the a structure is provided in the shape of a template or pattern which is
49
5 Lab
then used to creatstructure variables of the same composition. The template is com-
posed of the names and attributes of the data items to be included in the structure.
The definition begins with the keyword structwhich is followed by a structure decla-
ration consist of a set of user-defined data names and data types. These entries are
separated by semicolons and enclosed within a pair of curly brackets. The definition
ends with a semicolon. Thus, in general, the structure definition has the form
1 s t r u c t tag−name {
2 type var −1;
3
. . . . . . . . . .−2;
type−var ...
4
5 typevar−n ;
6 };
Example 4.1:
1 s t r u c t employee
2
3 {
4 char name [ 3 0 ] ;
5 i n t age ;
6 float salary ;
7 }
Representation in Memory
1 s t r u c t student
2 {
3 char name [ 2 0 ] ;
4 introll_no ;
5 };
6 s t r u c t student s t ;
Structures Variables
This code fragment illustrates how structure variables of the type structemployee are
defined.
1 s t r u c t employee {
2 char name [ 3 0 ] ;
3
4 i n t age ;
5 float salary ;
5
Table 4.1:
...
0123 19
roll_no
6 };
7 structemployee emp1 , emp2 , emp3 ;
In the above example three structure variables emp1, emp2, and emp3 are created.
Each structure consists of three members identified by name, age, and salary.
OR
1 s t r u c t employee
2 { char name [ 3 0 ] ;
3
4 i n t age ;
5 float salary ;
6
7 } emp1 , emp2 , emp3 ;
Structure membership
Members themselves are not variables they should be linked to structure variables in
order to make them meaningful members.
The link between a member and a variable is established using the member operator
’.’ i.e. dot operator or period operator. We access individual members of a structure
with the .operator. For example to assign a value, we can enter:
1 structx
2 { int a;
3 int b;
4 int c;
5
6 };
7
8 main ( )
9 {
10 struct x z;
11
12 z . a = 1 0 ; // a s s i g n s member â A˘ Ÿ aâ A˘ Z´ o f s t r u c t u r e v a r i a b l e z
13 value 1 0 . z . b = 2 0 ;
14 z.c = 30;
15
16 }
1
2 struct x
3 {
4 int a;
5 int b;
6 int c;
7 };
8
9 main ( )
10 { struct x z;
11
12 z . a = 1 0 ; // Assigning a value to a member through a s t r u c t u r e va r i a b l e z .
a
++; // incrementing the member va r i a b l e . cout <<z . a ; // Retr ieving the
13 value .
}
Example 4.2:
1 s t r u c t l i b _b o o k s
2 {
3 char t i t l e [ 2 0 ] ;
4 char author [ 1 5 ] ;
5 i n t pages ;
6 f l o a t pr i c e ;
7
8 } book1 , book2 , book3 ;
Now
Book1.price
is the variable representing the price of book1 and can be treated like any other
ordinary variable. We can use scanf statement to assign values like
cin»book1.pages;
strcpy(book1.title,"basic");
strcpy(book1.author,"alagurusamy");
book1.pages=250;
book1.price=28.50;
5
Example 4.1:
1
2 i n t main ( )
3 {
4
5 s t r u c t Library
6 {
7 i n t ISBN , copies , PYear ;
8 char bookName [ 3 0 ] , AuthorName [ 3 0 ] , PublisherName [ 3 0 ] ;
9
10 };
11
12 Library l i b r a r y Va r i a b l e ;
13 L i br ar y V a r i a b l e . ISBN = 1 2 9 3 ;
14 s t rcpy ( l i b r a r y Va r i a b l e . bookName , " Network S e c ur i t y
15 " ) ; s t rcpy ( l i b r a r y Va r i a b l e . AuthorName , " Martin " ) ;
16
17 s t rcpy ( l i b r a r y Va r i a b l e . PublisherName , " Waley "
18 ) ; l i b r a r y Va r i a b l e . copies = 4 ;
19 l i b r a r y Va r i a b l e . PYear = 1 9 9 8 ;
20 cout <<" ISBN Number : " << l i b r a r y Va r i a b l e . ISBN<<endl ; cout <<" Library book
Name
: " << l i b r a r y Va r i a b l e . bookName<<endl ; cout <<" Author : " << l i b r a r y Va r i a b l
e . AuthorName<<endl ; cout <<" Publisher : " << l i b r a r y Va r i a b l e .
PublisherName ; cout <<"No. of Copies : " << l i b r a r y Va r i a b l e . copies ; cout <<"
21 Year : " <<
22 l i b r a r y Va r i a b l e . PYear ;
1
2 void main ( void )
3 {
4 s t r u c t Library
5 {
6 i n t ISBN , copies , PYear ;
7 char bookName [ 3 0 ] , AuthorName [ 3 0 ] , PublisherName [ 3 0 ] ;
8 };
9
10 Library l i b r a r y Va r i a b l e 1 , l i b r a r y Va r i a b l e 2 , l i b r a r y Va r i a b l e 3 ,
l i b r a r y Va r i a b l e 4 ; Library Library Array [ 4 ] ; // a l t e r n a t i v e and e a s i
e s t way
11
12 }
5 Lab
1
2
3 Library l i b r a r y Va r i a b l e 1 , l i b r a r y Va r i a b l e 2 ;
4 s t rcpy ( l i b r a r y Va r i a b l e 1 . bookName , "C Programming "
5 ) ; l i b r a r y Va r i a b l e 1 . ISBN = 1 2 9 3 ;
6 l i b r a r y Va r i a b l e 2 = l i b r a r y Va r i a b l e 1 ;
1
2 cout <<un i ve r s i t y Va r i a b l e . l i b r a r y Va r i a b l e .
3 bookName ; cout <<un i ve r s i t y Va r i a b l e . c i t y ;
4 cout <<un i ve r s i t y Va r i a b l e . l i b r a r y Va r i a b l e . bookName)
5 ; cout <<un i ve r s i t y Va r i a b l e . l i b r a r y Va r i a b l e . ISBN ) ;
1 struct x
2 {
3
4 int a;
5 int b;
6 int c;
7
8 };
9
10 main ( )
11
12 {
13 struct x
14 z;z.a = 10;
15
5
16 z . a ++;
17 cout <<" f i r s t member i s " << a ; // Error !
18
19 // a i s not a va r i a b l e . I t i s only the name of a member in a s t r u c t u r e
cout
20 << â A˘ I˙ f i r s t member i s "<<x . a ; // E r r o r !
21 // x i s not the name of a va r i a b l e . I t i s the name of a type
22
}
Arrays of structures
It is possible to define a array of structures for example if we are maintaining in-
formation of all the students in the college and if 100 students are studying in the
college. We need to use an array than single variables. We can define an array of
structures as shown in the following example:
1 s t r u c t u r e information
2 {
3 intid_no ;
4 char name [ 2 0 ] ;
5 char address [ 2 0 ] ;
6 char combination [ 3 ] ;
7 i n t age ;
8 }
9
10 student [ 1 0 0 ] ;
An array of structures can be assigned initial values just as any other array can. Re-
member that each element is a structure that must be assigned corresponding initial
values as illustrated below.
1
2 i n t main ( void )
3
4 { s t r u c t info
5
6 {
7
8 intid_no ;
9
10 char name [ 2 0 ] ;
11
12 char address [ 2 0 ] ;
13
14 i n t age ;
15
16 } std [ 1 0 0 ] ;
17
18
19 intI ,n;
20
21 cout <<" Enter the number of students " <<endl ;
22 cin >>n ;
5 Lab
23
24 cout <<endl <<" Enter Id_no , name address combination agem" <<endl ; fo r ( I = 0 ; I <n
; I ++)
25
26 {
27
28 cout <<endl <<"\ t Ent e r Record fo r student " <<I +1<<endl ;
29
30 cout <<" Student ID : " <<endl ;
31
32 cin >>std [ I ] . id_no ;
33
34 cout <<" Student Name: " <<endl ;
35
36 cin >>std [ I ] . name ;
37
38 cout <<" Student c i t y : " <<endl ;
39
40 cin >>std [ I ] . address ;
41
42 cout <<" Student Age : " <<endl ;
43
44 cin >>std [ I ] . age ;
45
46 }
47
48 cout <<endl <<" Student information " <<endl ;
49
50 fo r ( I = 0 ; I <n ; I ++)
51
52 { cout <<endl <<" Student ID:\ n\ t " <<std [ I ] . id_no <<endl ; cout <<" Student Name: "
<<std [ I ] . name<<endl ; cout <<" Student c i t y : " <<std [ I ] . address <<endl ; cout
<<" Student Age : " <<std [ I ] . age ;
53
54 }
55
56 }
Note:
Before doing your lab exercises run the examples.
Exercise:
Q1: Write a program using structure to display the area and parameters of Rectangle.
The parameters should be taken form user at run time. The length should be in int
5
Q2: Write a program using structure to display the record of 10 students where
member variable should be Name, roll.no, GPA, semester and age and each of these
members should be input by user at run time. Finally the GPA of all students is
summed up and average GPA should be displayed.
5 Lab
Chapter 5
Lab 5:Structures II
Example 5.1:
59
6 Lab 5:Structures
10 record . age = 2 1 ;
11 display ( record . name , record . age ) ; return 0 ;
12 }
13
14
15
16 void display ( char ∗name , i n t age )
17 {
18 cout <<"Name i s " <<name <<"\nAge i s " <<age ;
19 }
Example 5.2:
21
22
23 rec . age = 31 ;
24
25
26 /∗ change the value of a s t r u c t u r e
27 ∗ member .
28
29
30
31 ∗/
32
33
}
34
Pointers to Structure
As we have learnt a memory location can be accessed by a pointer variable. In
the similar way a structure is also accessed by its pointer. The syntax for structure
6
pointer is same as for the ordinary pointer variable. In general, the structure pointer
is defined by the statement struct-type *sptr; where struct-type refers to structure
type specifier, and sptr ia a variable that points to the structure. It must be ensured
that the pointer definition must preceed the structure declaration. For example, a
pointer to struct employee may be defined by the statement struct employee *sptr; In
other words the variable sptr can hold the address value for a structure of type struct
employee. We can create several pointers using a single declaration, as follows:
] Struct employee *sptr1, *sptr2, *sptr3;
1 We have a s t r u c t u r e :
2
3 s t r u c t employee {
4 char name [ 3 0 ] ;
5 i n t age ;
6 float salary ;
7
8 };
sptr1->name;
sptr1->age;
sptr1->salary;
Using the pointers the members of the structure variable emp1 can be initialized
asfollow:
Enumerations
An enumeration provides context to describe a range of values. The following exam-
ple shows an enumeration that contains the four suits in a deck of cards.
Spades };
The enumerator Diamonds is assigned the value 1. This affects the values that are
assigned to subsequent enumerators; Hearts is assigned the value 2, Clubs is 3, and
so on.
Example 5.3:
10 {
11
12 enum Days { Monday=13 , Tuesday =8 , Wednesday , Thursday } ;
13
14 Days d1=Wednesday ;
15
16 cout <<d1 ;
17
18 cout <<endl ;
19
20 int x;
21
22 x= i n t ( d1 +1 ) ;
23
24 cout <<x ;
25
26 getch ( ) ;
27
28 return 0;
29
30 }
Bitwise Operations
Bitwise Complement:
The bitwise complement operator, the tilde, , flips every bit. The tilde is
sometimes called a twiddle, and the bitwise complement twiddles every bit: This
turns out to be a great way of finding the largest possible value for an unsigned
number.
Bitwise AND:
The bitwise AND operator is a single ampersand: &:
01001000 &
10111000 =
—————-
00001000
Bitwise OR: The bitwise OR operator is a |:
01001000 |
10111000 =
6 Lab 5:Structures
ˆ Bitwise Exclusive Or Bit n of xyˆ is 1 if bit n of x or bit n of y is 1 but not if both are 1.
—————–
11111000
Bitwise Exclusive OR (XOR): The exclusive-or operation takes two inputs and re-
turns a 1 if either one or the other of the inputs is a 1, but not if both are. That
is, if both inputs are 1 or both inputs are 0, it returns 0. Bitwise exclusive-or, with
the operator of a carrot, ^, performs the exclusive-or operation on each pair of bits.
Exclusive-or is commonly abbreviated XOR.
01110010 ^
10101010
————–
11011000
Suppose, we have some bit, either 1 or 0, that we’ll call Z. When we take Z XOR
0, then we always get Z back: if Z is 1, we get 1, and if Z is 0, we get 0. On the other
hand, when we take Z XOR 1, we flip Z. If Z is 0, we get 1; if Z is 1, we get 0:
• myBits ^ 0 : No change
• myBits ^1 : Flip
Example 5.4:
Example 5.5:
1
2 # include <iostream >
3
4 # include <iomanip>
5
6 # include < b i t s e t >
7
8 using namespace std ;
9
10 void binary ( unsigned i n t u)
11
12 {
13
14 cout << setw ( 5 ) << u << " : " ;
15
16 cout << b i t s e t <16 >(( i n t ) u) ;
17
18 cout << "\n" ;
19
20 }
21
22 i n t main ( )
23
24 {
25
26 binary ( 5 ) ;
27
6
28 binary ( 5 5 ) ;
29
30 binary ( 2 5 5 ) ;
31
32 binary ( 4 5 5 5 ) ;
33
34 binary ( 1 4 5 5 5 ) ;
35
36 system ( "PAUSE" ) ;
37
38 return 0 ;
39
40 }
Note:
Before doing your lab exercises run the examples.
Exercise:
Q1: Write a program to create a structure of student and ask the user to enter student
name, roll no and marks of three subjects and find the average marks of these three
subjects using a function.
Q2: Write a program for structure of Employee and display the name of employee
and calculate the monthly salary of a specific month. Per day working hours and
salary of employee per hour is entered by the user. Display the name and monthly
salary of employee using pointer to structure.
6 Lab 5:Structures
Chapter 6
You could define variables, length, breadth and height to represent the dimensions
of the box and bind them together as members of a Box class, as follows:
1 class Box
2 {
3 public :
4 double length ;
5 double breadth ;
6 double height ;
7 };
This code actually creates a new type, called Box. The keyword class defines Box
as such, and the elements that make up this class are defined within the curly braces.
Note that each line defining an element of the class is terminated by a semicolon, and
that a semicolon also appears after the closing brace. The elements length, breadth
and height are referred to as data members. At the top of the class definition, you can
see we have put the keyword public - this just means that the data members are gen-
erally accessible from outside the class. You may, however, place restrictions on the
accessibility of class members, and we’ll see how this works a bit later in this chapter.
With this definition of a new data type called Box, you can go ahead and define
variables of this type just as you did with variables of the basic types:
69
7 Lab 6:Object Orientation in C+
Once we’ve defined the class Box, the declaration of variables of this type is quite
standard. The variable myBox here is also referred to as an object or an instance of
the class Box.
With this definition of a new data type called Box, you can go ahead and define
variables of this type just as you did with variables of the basic types. You can then
create, manipulate and destroy as many Box objects as you need to in your program.
This means that you can model objects using classes and write your programs around
them. So - that’s object-oriented programming all wrapped up then?
Well, not quite. You see, object-oriented programming (OOP) is based on a number
of foundations (famously encapsulation, polymorphism and inheritance) and what
we have seen so far doesn’t quite fit the bill. Don’t worry about what these terms
mean for the moment - we’ll be exploring these ideas in more detail as we learn more
about what you can do with classes.
First Class
The notion of class was invented by an Englishman to keep the general population
happy. It derives from the theory that people who knew their place and function
in society would be much more secure and comfortable in life than those who did
not. The famous Dane, Bjarne Stroustrup, who invented C++, undoubtedly acquired
a deep knowledge of class concepts while at Cambridge University in England, and
appropriated the idea very successfully for use in his new language.
The idea of a class in C++ is similar to the English concept, in that each class usually
has a very precise role and a permitted set of actions. However, it differs from the
English idea, because class in C++ has largely socialist overtones, concentrating on
the importance of working classes. Indeed, in some ways it is the reverse of the En-
glish ideal, because, as we shall see, working classes in C++ often live on the backs
of classes that do nothing at all.
Operations on Classes
In C++ you can create new data types as classes to represent whatever kinds of ob-
jects you like. As you’ll come to see, classes aren’t limited to just holding data; you
can also define member functions that act on your objects, or even operations that act
between objects of your classes using the standard C++ operators. You can define the
class Box, for example, so that the following statements work and have the meanings
7
1 Box Box1 ;
2 Box Box2 ;
3 i f ( Box1 > Box2 ) // F i l l the l a r ge r box
4 Box1 . F i l l ( ) ;
5 else
6 Box2 . F i l l ( ) ;
You could also implement operations as part of the Box class for adding, subtracting
or even multiplying boxes - in fact, almost any operation to which you could ascribe
a sensible meaning in the context of boxes.
We’re talking about incredibly powerful medicine here and it constitutes a major
change in the approach that we can take to programming. Instead of breaking down
a problem in terms of what are essentially computer-related data types (integer num-
bers, floating point numbers and so on) and then writing a program, we’re going
to be programming in terms of problem-related data types, in other words classes.
These classes might be named Employee, or Cowboy, or Cheese or Chutney, each
defined specifically for the kind of problem that you want to solve, complete with
the functions and operators that are necessary to manipulate instances of your new
types.
Program design now starts with deciding what new application-specific data types
you need to solve the problem in hand and writing the program in terms of opera-
tions on the specifics that the problem is concerned with, be it Coffins or Cowpokes.
Terminology
Let’s summarize some of the terminology that we will be using when discussing
classes in C++:
• A class is a user-defined data type
• Object-oriented programming is the programming style based on the idea of
defining your own data types as classes
• Declaring an object of a class is sometimes referred to as instantiation because
you are creating an instance of a class
• Instances of a class are referred to as objects
• The idea of an object containing the data implicit in its definition, together with
the functions that operate on that data, is referred to as encapsulation
When we get into the detail of object-oriented programming, it may seem a little
complicated in places, but getting back to the basics of what you’re doing can often
help to make things clearer, so always keep in mind what objects are really about.
7 Lab 6:Object Orientation in C+
They are about writing programs in terms of the objects that are specific to the do-
main of your problem. All the facilities around classes in C++ are there to make this
as comprehensive and flexible as possible. Let’s get down to the business of under-
standing classes.
Understanding Classes
A class is a data type that you define. It can contain data elements, which can either
be variables of the basic types in C++ or other user-defined types. The data
elements of a class may be single data elements, arrays, pointers, arrays of pointers
of almost any kind or objects of other classes, so you have a lot of flexibility in what
you can include in your data type. A class can also contain functions which operate
on objects of the class by accessing the data elements that they include. So, a class
combines both the definition of the elementary data that makes up an object and
the means of manipulating the data belonging to individual instances of the class.
The data and functions within a class are called members of the class. Funnily
enough, the members of a class that are data items are called data members and the
members that are functions are called function members or member functions. The
member functions of a class are also sometimes referred to as methods, although we
will not be using this term.
When you define a class, you define a blueprint for a data type. This doesn’t actu-
ally define any data, but it does define what the class name means, that is, what an
object of the class will consist of and what operations can be performed on such an
object. It’s much the same as if you wrote a description of the basic type double. This
wouldn’t be an actual variable of type double, but a definition of how it’s made up
and how it operates. To create a variable, you need to use a declaration statement.
It’s exactly the same with classes, as you will see.
Defining a Class
Let’s look again at the class we started talking about at the start of the chapter - a
class of boxes. We defined the Box data type using the keyword class as follows:
1 c l a s s Box
2 {
3 public :
4
5 double length ;
7
6
7 double breadth ;
8 double height ;
9 };
10
11
12
13
14
15 // Length of a box in inches
16
17 // Breadth of a box in inches
18 // Height of a box in inches
19
The name that we’ve given to our class appears following the keyword and the
three data members are defined between the curly braces. The data members are
defined for the class using the declaration statements that we already know and love,
and the whole class definition is terminated with a semicolon. The names of all the
members of a class are local to a class. You can therefore use the same names else-
where in a program without causing any problems.
Remember that all we have defined so far is a class, which is a data type. We haven’t
declared any objects of the class. When we talk about accessing a class member, say
height, we’re talking about accessing the data member of a particular object, and that
object needs to be declared somewhere.
Both of the objects Box1 and Box2 will, of course, have their own data members. This
is illustrated here:
Figure 6.1:
The object name Box1 embodies the whole object, including its three data mem-
bers. They are not initialized to anything, however - the data members of each object
will simply contain junk values, so we need to look at how we can access them for
the purpose of setting them to some specific values.
We can only access the data member in this way, in a function outside the class,
because the member height was specified as having public access. If it wasn’t de-
fined as public, this statement would not compile. We’ll see more about this
shortly.
Let’s have a go at creating a Box class and setting the values of it’s data members.
We’ll try it out in the following console application:
Example 6.1:
7
How It Works
Everything here works as we would have expected from our experience with struc-
tures. The definition of the class appears outside of the function main() and, there-
fore, has global scope. This enables objects to be declared in any function in the
program and causes the class to show up in the ClassView once the program has
been compiled.
We’ve declared two objects of type Box within the function main(), Box1 and Box2.
Of course, as with variables of the basic types, the objects Box1 and Box2 are local
to main(). Objects of a class obey the same rules with respect to scope as variables
declared as one of the basic types (such as the variable volume, which is used in this
7 Lab 6:Object Orientation in C+
example).
The first three assignment statements set the values of the data members of Box1.
We define the values of the data members of Box2 in terms of the data members of
Box1 in the next three assignment statements.
We then have a statement which calculates the volume of Box1 as the product of
its three data members. This value is then output to the screen. Next, we output
the sum of the data members of Box2 by writing the expression for the sum of the
data members directly in the output statement. The final action in the program is
to output the number of bytes occupied by Box1, which is produced by the operator
sizeof.
Figure 6.2:
Note that the Box object is still the same number of bytes. Adding a function
member to a class doesn’t affect the size of the objects. Obviously, a member func-
tion has to be stored in memory somewhere, but there’s only one copy regardless of
how many class objects have been declared, and it isn’t counted when the operator
sizeof produces the number of bytes that an object occupies.
The names of the class data members in the member function automatically refer
to the data members of the specific object used to call the function, and the function
can only be called for a particular object of the class. In this case, this is done by
using the direct member access operator (.) with the name of an object.
If you try to call a member function without specifying an object name, your pro-
gram will not compile.
function inside the class. If we rewrite the previous class with the function definition
outside, then the class definition looks like this:
Now we need to write the function definition, but there has to be some way of telling
the compiler that the function belongs to the class Box. This is done by prefixing
the function name with the name of the class and separating the two with the scope
resolution operator, ::, which is formed from two successive colons. The function
definition would now look like this:
It will produce the same output as the last example. However, it isn’t exactly the
same program. In the second case, all calls to the function are treated in the way
that we’re already familiar with. However, when we defined the function within the
definition of the class in Ex6_02.cpp, the compiler implicitly treated the function as
an inline function.
Inline Functions
With an inline function, the compiler tries to expand the code in the body of the func-
tion in place of a call to the function. This avoids much of the overhead of calling the
function and, therefore, speeds up your code. This is illustrated here:
7 Lab 6:Object Orientation in C+
Figure 6.3:
Of course, the compiler takes care of ensuring that expanding a function inline
doesn’t cause any problems with variable names or scope.
The compiler may not always be able to insert the code for a function inline (such
as with recursive functions or functions for which you have obtained an address),
but generally it will work. It’s best used for very short, simple functions, such as our
function Volume(), because they will execute faster and will not significantly increase
the size of the executable module.
With the function definition outside of the class definition, the compiler treats
the function as a normal function and a call of the function will work in the usual
way. However, it’s also possible to tell the compiler that, if possible, we would like
the function to be considered as inline. This is done by simply placing the keyword
inline at the beginning of the function header. So, for our function, the definition
would be as follows:
With this definition for the function, the program would be exactly the same as
the original. This allows you to put the member function definitions outside of the
class definition, if you so choose, and still retain the speed benefits of inlining.
You can apply the keyword inline to ordinary functions in your program that
have nothing to do with classes and get the same effect. However, remember that
it’s best used for short, simple functions.
7
We now need to understand a little more about what happens when we declare
an object of a class.
Note:
Before doing your lab exercises run the examples.
Exercise:
Q1: write a class for addition of complex numbers. The program should ask for real
and imaginary part of complex numbers and using function it should add the real
part to real part of the number and imaginary part to imaginary part of the
number.
Q2: Write program using class Geometry. The program should ask the user for
length and width if the length and width both are same then it should call square
function to calculate its area and parameter otherwise it should call rectangle func-
tion to calculate the area and parameter of the rectangle.
8 Lab 6:Object Orientation in C+
Chapter 7
Class Constructors
In the previous program, we declared our Box objects, Box1 and Box2, and then labo-
riously worked through each of the data members for each object, in order to assign
an initial value to it. This is unsatisfactory from several points of view. First of all,
it would be easy to overlook initializing a data member, particularly in the case of a
class which had many more data members than our Box class. Initializing the data
members of several objects of a complex class could involve pages of assignment
statements. The final constraint on this approach arises when we get to defining data
members of a class that don’t have the attribute public - we won’t be able to access
them from outside the class anyway. There has to be a better way, and of course there
is - it’s known as the class constructor.
What is a Constructor?
A class constructor is a special function in a class that is called when a new ob-
ject of the class is declared. It therefore provides the opportunity to initialize
objects as they are created and to ensure that data members only contain valid
values.
You have no leeway in naming a class constructor - it always has the same name
as the class in which it is defined. The function Box(), for example, is a constructor
for our Box class. It also has no return type. It’s wrong to specify a return type for
a constructor; you must not even write it as void. The primary function of a class
constructor is to assign initial values to the data elements of the class, and no return
type is necessary or, indeed, permitted.
Try It Out - Adding a Constructor to the Box class Let’s extend our Box class to
incorporate a constructor.
Example 7.1:
81
8 Lab 7:Object Orientation in C++
How It Works
The constructor, Box(), has been written with three parameters of type double, cor-
responding to the initial values for the length, breadth and height members of a Box
object. The first statement in the constructor outputs a message so that we can tell
when it’s been called. You wouldn’t do this in production programs, but, since it’s
very helpful in showing when a constructor is called, it’s often used when testing
a program. We’ll use it regularly for the purposes of illustration. The code in the
body of the constructor is very simple. It just assigns the arguments passed to the
corresponding data members. If necessary, we could also include checks that valid,
non-negative arguments are supplied and, in a real context, you probably would
want to do this, but our primary interest here is in seeing how the mechanism works.
Within main(), we declare the object Box1 with initializing values for the data
members length, breadth, and height, in sequence. These are in parentheses follow-
ing the object name. This uses the functional notation for initialization, which can
also be applied to initializing ordinary variables of basic types. We also declare a
second object of type Box, called CigarBox, which also has initializing values.
The volume of Box1 is calculated using the member function Volume() as in the
previous example and is then displayed on the screen. We also display the value of
the volume of CigarBox. The output from the example is:
Figure 7.1:
The first two lines are output from the two calls of the constructor, Box(), once for
each object declared. The constructor that we’ve supplied in the class definition is
8 Lab 7:Object Orientation in C++
automatically called when a Box object is declared, so both Box objects are
initialized with the initializing values appearing in the declaration. These are
passed to the constructor as arguments, in the sequence that they are written in
the declaration. As you can see, the volume of Box1 is the same as before and
CigarBox has a volume looking suspiciously like the product of its dimensions,
which is quite a relief.
Here, we’ve left Box2 without initializing values. When you rebuild this version
of the program, you’ll get the error message:
The answer is that the previous example used a default constructor that was sup-
plied by the compiler, because we didn’t supply one. Since in this example we did
supply a constructor, the compiler assumed that we were taking care of everything
and didn’t supply the default. So, if you still want to use declarations for Box objects
which aren’t initialized, you have to include the default constructor yourself. What
exactly does the default constructor look like? In the simplest case, it’s just a con-
structor that accepts no arguments, it doesn’t even need to do anything:
Box() { }
// Default constructor
How It Works
Now that we have included our own version of the default constructor, there are no
error messages from the compiler and everything works. The program produces this
output:
Figure 7.2:
All that our default constructor does is to display a message. Evidently, it was
8
called when we declared the object Box2. We also get the correct value for the vol-
umes of all three Box objects, so the rest of the program is working as it should.
One aspect of this example that you may have noticed is that we now know
we can overload constructors just as we overloaded functions. We’ve just run an
example with two constructors that differ only in their parameter list. One has three
parameters of type double and the other has no parameters at all.
If we decided that the default size for a Box object was a unit box with all sides
of length 1, we could alter the class definition in the last example to this:
1
2 c l a s s Box // Class d e f i n i t i o n at glob al scope
3
4 {
5 public :
6 double length ;// Length of a box in inches
7
8 double breadth ; // Breadth of a box in inches double height ;// Height of a box in inches
9
10 // Constructor d e f i n i t i o n
11
12 Box ( double lv = 1 . 0 , double bv = 1 . 0 , double hv = 1 . 0 )
13 {
14 cout << endl << " Constructor c a l l e d . " ;
15
16 length = lv ;// Set values of breadth = bv ; // data members height = hv ;
17 }
18 // Default c o n s t r uc t o r d e f i n i t i o n Box ( )
19 { cout << endl << " Default c o n s t r uc t o r c a l l e d . " ; }
20
21 // Function to c a l c u l a t e the volume of a box double Volume ( )
22 {
23 return length ∗ breadth ∗ height ;
24
25
26
27
28
29
30
8 Lab 7:Object Orientation in C++
31 }
32 };
If we make this change to the last example, what happens? We get another error
message from the compiler, of course. We get these useful comments:
Example 7.2:
19 height = hv ;
20 }
21 // Function to c a l c u l a t e the volume of a box double Volume ( )
22 {
23
24
25
26 return length ∗ breadth ∗ height ;
27 }
28 };
29
30 i n t main ( void )
31 {
32 Box Box2 ; // Declare Box2 − no i n i t i a l values
33 cout << endl
34 << " Volume of Box2 = "
35 << Box2 . Volume ( ) ; cout << endl ;
36 return 0 ;
37
38 }
39
40
How It Works
We only declare a single uninitialized Box variable, Box2, because that’s all we need
for demonstration purposes. This version of the program produces the following
output:
Figure 7.3:
This shows that the constructor with default parameter values is doing its job of
setting the values of objects that have no initializing values specified.
You shouldn’t assume from the above example that this is the only, or even the
recommended, way of implementing the default constructor. There will be many
occasions where you won’t want to assign default values in this way, in which case
you’ll need to write a separate default constructor. There will even be times when
you don’t want to have a default constructor operating at all, even though you have
defined another constructor. This would ensure that all declared objects of a class
must have initializing values explicitly specified in their declaration.
9 Lab 7:Object Orientation in C++
Now the values of the data members are not set in assignment statements in the
body of the constructor. As in a declaration, they are specified as initializing values
using functional notation and appear in the initializing list as part of the function
header. The member length is initialized by the value of lv, for example. This can
be rather more efficient than using assignments as we did in the previous version. If
you substitute this version of the constructor in the previous example, you will see
that it works just as well.
Note that the initializing list for the constructor is separated from the parameter
list by a colon and that each of the initializers is separated by a comma. This tech-
nique for initializing parameters in a constructor is important, because, as we shall
see later, it’s the only way of setting values for certain types of data members of an
object.
We can get it by using the keyword private when we define the class members. Class
members which are private can, in general, only be accessed by member functions
of a class. There’s one exception, but we’ll worry about that later. A normal
function has no direct means of accessing the private members of a class. This is
shown here:
9
Figure 7.4:
Having the possibility of specifying class members as private also enables you
to separate the interface to the class from its internal implementation. The
interface to a class is composed of the public members and the public member
functions in par- ticular, since they can provide indirect access to all the members
of a class, including the private members. By keeping the internals of a class
private, you can later mod- ify them to improve performance, for example, without
necessitating modifications to the code that uses the class through its public
interface. To keep them safe from unnecessary meddling, it’s good practice to
declare data and function members of a class that don’t need to be exposed as
private. Only make public what is essential to the use of your class.
16 public :
17 // Constructor d e f i n i t i o n
18 Box ( double lv = 1 . 0 , double bv = 1 . 0 , double hv = 1 . 0 )
19 {
20
21 cout << endl << " Constructor c a l l e d . " ; length = lv ;// Set values of
22
breadth = bv ; // data members height = hv ;
23
}
24
25
26
27
28 //Function to c a l c u l a t e the volume of a box double Volume ( )
29 {
30 return length ∗ breadth ∗ height ;
31 }
32
33
34 pr iva t e :
35 double length ;
36
37 double breadth ; double height ;
38
39
40
41
42 // Length of a box in inches // Breadth of a box in box inches
in inches
// Height of a
43
44 };
45 i n t main ( void )
46 {
47
48 Box Match ( 2 . 2 , 1 . 1 , 0 . 5 ) ; // Declare Match box Box Box2 ; // Declare Box2 − no i n i t i a l values
49
50 cout << endl
51
52 <<" Volume of Match = "
53 <<Match . Volume ( ) ;
54
55 //Uncomment the following l i n e to get an e r r o r
56
57 //Box2 . length = 4 . 0 ; cout << endl
58 <<" Volume of Box2 = "
59 <<Box2 . Volume ( ) ; cout << endl ;
60
61 return 0;
62 }
63
64
65
9
How It Works
The definition of the class Box now has two sections. The first is the public section
containing the constructor and the member function Volume(). The second section
is specified as private and contains the data members. Now the data members can
only be accessed by the member functions of the class. We don’t have to modify any
of the member functions - they can access all the data members of the class anyway.
However, if you uncomment the statement in the function main(), assigning a value
to the member length of the object Box2, you’ll get a compiler error message con-
firming that the data member is inaccessible.
Figure 7.5:
This demonstrates that the class is still working satisfactorily, with its data mem-
bers defined as having the access attribute private. The major difference is that they
are now completely protected from unauthorized access and modification.
If you don’t specify otherwise, the default access attribute which applies to mem-
bers of a class is private. You could, therefore, put all your private members at the
beginning of the class definition and let them default to private by omitting the key-
word. However, it’s better to take the trouble to explicitly state the access attribute
in every case, so there can be no doubt about what you intend.
9 Lab 7:Object Orientation in C++
Of course, you don’t have to make all your data members private. If the applica-
tion for your class requires it, you can have some data members defined as private
and some as public. It all depends on what you’re trying to do. If there’s no reason
to make members of a class public, it is better to make them private as it makes
the class more secure. Ordinary functions won’t be able to access any of the private
members of your class.
You don’t need to start writing to your state senator to get it - it’s already avail-
able to you. All you need to do is to write a member function to return the value of
a data member. Look at this member function for the class Box:
Just to show how it looks, this has been written as a member function definition
which is external to the class. We’ve specified it as inline, since we’ll benefit from
the speed increase, without increasing the size of our code too much. Assuming that
you have the declaration of the function in the public section of the class, you can
use it by writing this statement:
All you need to do is to write a similar function for each data member that you
want to make available to the outside world, and their values can be accessed
without prejudicing the security of the class. Of course, if you put the definitions for
these functions within the class definition, they will be inline by default.
We now want to create another Box object, identical to the first. We would like
to initialize the second Box object with Box1.
Example 7.3:
1
2 //I n i t i a l i z i n g an o b j e c t with an o b j e c t of the same c l a s s # include < iostream >
using namespace std ;
3
4
5
6 c l a s s Box {
7
8
9 // Class d e f i n i t i o n at gl ob al scope
10
11
12 public :
13 // Constructor d e f i n i t i o n
14 Box ( double lv = 1 . 0 , double bv = 1 . 0 , double hv = 1 . 0 )
15 {
16
cout << endl << " Constructor c a l l e d . " ; length = lv ;// Set values of
breadth = bv ; // data members
17
18
19
height = hv ;
}
20
21
22
23
24 //Function to c a l c u l a t e the volume of a box double Volume ( )
25
26 {
27 return length ∗ breadth ∗ height ;
28 }
29
30 pr iva t e :
31 double length ;// Length ofa box ininches double breadth ; //Breadth of a box in inches
32 double height ;//Heightofa box ininches
33
34
9 Lab 7:Object Orientation in C++
35 };
36
37 i n t main ( void )
38 {
39
40
41 Box Box1 ( 7 8 . 0 , 2 4 . 0 , 1 8 . 0 ) ; Box Box2 = Box1 ;
42
43
44 // I n i t i a l i z e Box2 with Box1
45
46
47 cout << endl
48 << " Box1 volume = " << Box1 . Volume ( )
49 << endl
50 << " Box2 volume = " << Box2 . Volume ( ) ;
51
52 cout << endl ;
53
54 return 0;
55 }
How It Works
This example will produce this:
Figure 7.6:
Clearly, the program is working as we would want, with both boxes having the
same volume. However, as you can see from the output, our constructor was called
only once for the creation of Box1. But how was Box2 created? The mechanism is
similar to the one that we experienced when we had no constructor defined and the
compiler supplied a default constructor to allow an object to be created. In this case,
the compiler generates a default version of what is referred to as a copy constructor.
A copy constructor does exactly what we’re doing here - it creates an object of a
class by initializing it with an existing object of the same class. The default version of
the copy constructor creates the new object by copying the existing object, member
by member.
This is fine for simple classes such as Box, but for many classes - classes that have
pointers or arrays as members for example - it won’t work properly. Indeed, with
9
such classes it can create serious errors in your program. In these cases, you need to
create your own class copy constructor.
Destructor:
Example 7.4:
Note:
Before doing your lab exercises run the examples.
Exercise:
Q1: Write a C++ program to make a car class with wheels, doors as private data
members and cur_speed as public data member while speed and break as public
member functions. Use constructor with default value of wheels=4,doors=2 and
cur_speed=0 for initialization. Make two objects in the name of ferrari and hino.
Ferrari is initialized through default values while hino has 10 wheels, 4 doors. Every
time when you call speed function cur_speed is increased by 5 while break function
decrease it by 5. Display current speed.
Q1: Make a class in the name of circle with data memberâ A˘ Z´ s radius,
perimeter, and area. Use overloaded constructor one with no argument which
initializes ra- dius=1. The other constructor accepts argument of radius and
initializes. Make two objects circle1 and circle2, circle with no values and circle2
with any input value en- tered in run time from your keyboard. Find area and
perimeter of both circles and display them. Also modify destructor code which
display which circle with area is deleted. Formulas: Area=ÏA˘ r2ˆ perimeter=2ÏA˘ r
Chapter 8
Friend Classes
C++ provides the friend keyword to do just this. Inside a class, you can indicate that
other classes (or simply functions) will have direct access to protected and private
members of the class. When granting access to a class, you must specify that the
access is granted for a class using the class keyword:
Note that friend declarations can go in either the public, private, or protected section
of a class–it doesn’t matter where they appear. In particular, specifying a friend in
the section marked protected doesn’t prevent the friend from also accessing private
fields.
1 c l a s s Node
2
3 {
4
5 pr iva t e :
6
7 i n t data ;
8
9 i n t key ;
10
11 // . . .
12
13 f r i e n d c l a s s Binary Tree ; // c l a s s Binary Tree can now ac c e s s data d i r e c t l y
14
15 };
99
1 Lab 8:Friend Function & Classes, This Pointer, and static
Now, Node does not need to provide any means of accessing the data stored in the
tree. The BinaryTree class that will use the data is the only class that will ever need
access to the data or key. (The BinaryTree class needs to use the key to order the tree,
and it will be the gateway through which other classes can access data stored in any
particular node.)
Now in the BinaryTree class, you can treat the key and data fields as though they
were public:
1 c l a s s Binary Tree
2
3 {
4
5 pr iva t e :
6
7 Node ∗ root ;
8
9 i n t f ind ( i n t key ) ;
10
11 };
12
13 i n t Binary Tree : : f ind ( i n t key )
14
15 {
16
17 // check root fo r NULL . . .
18
19 i f ( root −>key == key )
20
21 {
22
23 // no need to go through an ac c e s s or function return root −>data ;
24
25 }
26
27 // perform r e s t of f ind
Friend Functions
Similarly, a class can grant access to its internal variables on a more selective
basis– for instance, restricting access to only a single function. To do so, the entire
function signature must be replicated after the friend specifier, including the return
type of the function–and, of course, you’ll need to give the scope of the function if
it’s inside another class:
For instance, in our example Node class, we would use this syntax:
1 c l a s s Node
2
3 {
4
5 pr iva t e :
6
7 i n t data ;
8
9 i n t key ;
10
11 // . . .
12
13 f r i e n d i n t Binary Tree : : f ind ( ) ; // Only Binary Tree ’ s f ind function has ac c e
14 ss
15
};
Now the find function of BinaryTree could access the internals of the Node class,
but no other function in BinaryTree could. (Though we might want a few others to
be able to!)
Note that when friends are specified within a class, this does not give the class
itself access to the friend function. That function is not within the scope of the class;
it’s only an indication that the class will grant access to the function.
Functions which are friends of a class and are defined within the class definition
are also by default inline.
Friend functions are not members of the class, and therefore the access attributes
do not apply to them. They are just ordinary global functions with special privileges.
Let’s suppose that we wanted to implement a friend function in the Box class to
compute the surface area of a Box object.
Example 8.1
1 Lab 8:Friend Function & Classes, This Pointer, and static
1 // Creating a f r i e n d f unc t i on of a c l a s s
2
3 # include <iostream > using namespace std ;
4
5
6
7 c l a s s Box
8
9 {
10
11
12 // Class d e f i n i t i o n at gl ob a l scope
13
14 public :
15 // Constructor d e f i n i t i o n
16
17 Box ( double lv = 1 . 0 , double bv = 1 . 0 , double hv = 1 . 0 )
18 {
19 cout << endl << " Constructor c a l l e d . " ; length = lv ;// Set values of
20 breadth = bv ; // data members
21
22 height = hv ;
23
}
24
25
26
27 //Function to c a l c u l a t e the volume of a box double Volume ( )
28
29 {
30 return length ∗ breadth ∗ height ;
31 }
32
33 pr iva t e :
34 double length ;// Length ofa box ininches double breadth ; //Breadth of a box in inches
35 double height ;//Heightofa box ininches
36
37 //Friend f unc t i on
38
39 f r i e n d double Box Surface ( Box aBox ) ;
40 };
41
42 //f r i e n d f unc t i on to c a l c u l a t e the s ur fa c e area of a Box o b j e c t double Box Surface ( Box aBox )
43
{
44
45
46 return 2 . 0 ∗ ( aBox . length ∗aBox . breadth +
47 aBox . length ∗aBox . height +
48 aBox . height ∗aBox . breadth ) ;
49 }
50
51 i n t main ( void )
52 {
53 Box Match ( 2 . 2 , 1.1 , 0 . 5 ) ; // Declare Match box
1
How It Works
We declare the function BoxSurface() as a friend of the Box class by writing the func-
tion prototype with the keyword friend at the front. Since the BoxSurface() function
itself is a global function, it makes no difference where we put the friend declaration
within the definition of the class, but it’s a good idea to be consistent when you po-
sition this sort of declaration. You can see that we have chosen to position ours after
all the public and private members of the class. Remember that a friend function
isn’t a member of the class, so access attributes don’t apply.
The definition of the function follows that of the class. Note that we specify ac-
cess to the data members of the object within the definition of BoxSurface(), using
the Box object passed to the function as a parameter. Because a friend function isn’t
a class member, the data members can’t be referenced just by their names. They each
have to be qualified by the object name in exactly the same way as they might in
an ordinary function, except, of course, that an ordinary function can’t access the
private members of a class. A friend function is the same as an ordinary function
except that it can access all the members of a class without restriction.
Figure 8.1:
This is exactly what you would expect. The friend function is computing the sur-
face area of the Box objects from the values of the private members.
Friend functions do not have a this pointer, because friends are not members of a
class. Only member functions have a this pointer.
Let us try the following example to understand the concept of this pointer:
When the above code is compiled and executed, it produces following result:
Constructor called.
Constructor called.
Box2 is equal to or larger than Box1
1 i n t GenerateID ( )
1 Lab 8:Friend Function & Classes, This Pointer, and static
2 {
3 s t a t i c i n t s_nID = 0 ;
4 return s_nID ++;
5 }
6
7 i n t main ( )
8 {
9
10 std : : cout << GenerateID ( ) << std : : endl ;
11
12 std : : cout << GenerateID ( ) << std : : endl ;
13
14 std : : cout << GenerateID ( ) << std : : endl ;
15 return 0 ;
16 }
0
1
Note that s_nID has kept itâ A˘ Z´ s value across multiple function calls.
The static keyword has another meaning when applied to global variables â A˘ Tˇ it
changes them from global scope to file scope. Because global variables are typically
avoided by competent programmers, and file scope variables are just global variables
limited to a single file, the static keyword is typically not used in this capacity.
1 c l a s s Something
2
3 {
4 public :
5 s t a t i c i n t s_nValue ;
6 };
7
8 i n t Something : : s_nValue = 1 ;
1
9
10 i n t main ( )
11 {
12 Something c F i r s t ;
13 c F i r s t . s_nValue = 2 ;
14
15 Something cSecond ;
16
17 std : : cout << cSecond . s_nValue ;
18
19 return 0;
20 }
Because s_nValue is a static member variable, s_nValue is shared between all ob-
jects of the class. Consequently, cFirst.s_nValue is the same as cSecond.s_nValue.
The above program shows that the value we set using cFirst can be accessed using
cSecond!
Although you can access static members through objects of the class type, this is
somewhat misleading. cFirst.s_nValue implies that s_nValue belongs to cFirst, and
this is really not the case. s_nValue does not belong to any object. In fact, s_nValue
exists even if there are no objects of the class have been instantiated!
1 c l a s s Something
2 {
3 public :
4 s t a t i c i n t s_nValue ;
5 };
6
7 i n t Something : : s_nValue = 1
8
9 ; i n t main ( )
10 {
11 Something : : s_nValue = 2 ;
12
13 std : : cout << Something : : s_nValue ;
14
15 return 0 ;
16 }
In the above snippet, s_nValue is referenced by class name rather than through an
1 Lab 8:Friend Function & Classes, This Pointer, and static
object. Note that we have not even instantiated an object of type Something, but we
are still able to access and use Something::s_nValue. This is the preferred method
for accessing static members.
int Something::s_nValue = 1;
This initializer should be placed in the code file for the class (eg. Something.cpp). In
the absense of an initializing line, C++ will initialize the value to 0.
Why use static variables inside classes? One great example is to assign a unique
ID to every instance of the class. Hereâ A˘ Z´ s an example of that:
1 c l a s s Something
2 {
3 pr iva t e :
4 s t a t i c i n t s_nIDGenerator
5 ; i n t m_nID ;
6 public :
7 Something ( ) { m_nID = s_nIDGenerator ++; }
8
9 i n t GetID ( ) const { return m_nID ; }
10 };
11
12 i n t Something : : s_nIDGenerator = 1 ;
13
14 i n t main ( )
15 {
16 Something c F i r s t ;
17 Something cSecond ;
18
19 Something c Third ;
20
21 using namespace std ;
22 cout << c F i r s t . GetID ( ) << endl ;
23 cout << cSecond . GetID ( ) << endl ;
24 cout << c Third . GetID ( ) << endl ;
1
25 return 0;
26 }
1
2
Static member variables can also be useful when the class needs to utilize an in-
ternal lookup table (eg. to look up the name of something, or to find a precalculated
value). By making the lookup table static, only one copy exists for all objects, rather
than a copy for each object instantiated. This can save substantial amounts of mem-
ory.
Note:
Before doing your lab exercises run the examples.
Exercise:
Question 1: Write a C++ class BankAccount having private data members int Ac-
count_no and double balance. It must contain constructor for initializing(Account_no
and balance) objects and member functions for setBalance, setAccount_no, getBal-
ance, getAccount_no, display , withdraw and deposit function to decrement and
increment the amount to the balance. Call these functions for two account holders.
Question 2: Write a program to find maximum out of two numbers using friend
function and also note one number is a member of one class and other number is
member of some other class. By using set function set values of data members.
1 Lab 8:Friend Function & Classes, This Pointer, and static
Question 3: Write a C++ program to create three objects for a class named pntr_obj
with data members such as roll_no & name . Create a member function set_data()
for setting the data values and print() member function to print which object has
invoked it using â A˘ Ÿ thisâ A˘ Z´ pointer .
Chapter 9
In C++ the overloading principle applies not only to functions, but to operators too.
That is, of operators can be extended to work not just with built-in types but also
classes. A programmer can provide his or her own operator to a class by overload-
ing the built-in operator to perform some specific computation when the operator
is used on objects of that class. Is operator overloading really useful in real world
implementations? It certainlly can be, making it very easy to write code that feels
natural (we’ll see some examples soon). On the other hand, operator overloading,
like any advanced C++ feature, makes the language more complicated. In addition,
operators tend to have very specific meaning, and most programmers don’t expect
operators to do a lot of work, so overloading operators can be abused to make code
unreadable. But we won’t do that.
The addition without having overloaded operator + could look like this:
Complex c = a.Add(b);
This piece of code is not as readable as the first example though–we’re dealing with
numbers, so doing addition should be natural. (In contrast to cases when program-
mers abuse this technique, when the concept represented by the class is not
related to the operator–ike using + and - to add and remove elements from a data
structure. In this cases operator overloading is a bad idea, creating confusion.) In
order to al- low operations like Complex c = a+b, in above code we overload the "+"
operator. The overloading syntax is quite simple, similar to function overloading,
the keyword
111
1 Lab 9:Operator
1 c l a s s Complex
2
3 {
4 public :
5 Complex ( double re , double im )
6 : r e a l ( re ) , imag ( im )
7 {};
8 Complex operator +( const Complex& other ) ;
9 Complex operator =( const Complex& other ) ;
10 pr iva t e :
11 double r e a l ;
12 double imag ;
13 };
14 Complex Complex : : operator +( const Complex& other )
15
16 {
17 double r e s u l t _ r e a l = r e a l + other . r e a l ;
18
19 double r e s u l t _ i m a g i n a r y = imag + other . imag ;
20
21 return Complex ( r e s u l t _r e a l , result_imaginary ) ;}
The assignment operator can be overloaded similarly. Notice that we did not have
to call any accessor functions in order to get the real and imaginary parts from the
parameter other since the overloaded operator is a member of the class and has
full access to all private data. Alternatively, we could have defined the addition
operator globally and called a member to do the actual work. In that case, we’d also
have to make the method a friend of the class, or use an accessor method to get at
the private data:
Why would you do this? when the operator is a class member, the first object in the
expression must be of that particular type. It’s as if you were writing:
Complex a( 1, 2 );
Complex a( 2, 2 );
Complex c = a.operator=( b );
1
when it’s a global function, the implicit or user-defined conversion can allow the
operator to act even if the first operand is not exactly of the same type:
Complex c = 2+b; //if the integer 2 can be converted by the Complex class, this
expression is valid By the way, the number of operands to a function is fixed; that is,
a binary operator takes two operands, a unary only one, and you can’t change it. The
same is true for the precedence of operators too; for example the multiplication oper-
ator is called before addition. There are some operators that need the first operand to
be assignable, such as : operator=, operator(), operator[] and operator->, so their use
is restricted just as member functions(non-static), they can’t be overloaded globally.
The operator=, operator& and operator, (sequencing) have already defined meanings
by default for all objects, but their meanings can be changed by overloading or erased
by making them private. Another intuitive meaning of the "+" operator from the STL
string class which is overloaded to do concatenation:
1 s t r i n g p r e f i x ( " de " ) ;
2 s t r i n g word( " composed " ) ;
3 s t r i n g composed = p r e f i x +word ;
Using "+" to concatenate is also allowed in Java, but note that this is not extensible
to other classes, and it’s not a user defined behavior. Almost all operators can be
overloaded in C++:
The only operators that can’t be overloaded are the operators for scope resolution
(::), member selection (.), and member selection through a pointer to a function(.*).
Overloading assumes you specify a behavior for an operator that acts on a user de-
fined type and it can’t be used just with general pointers. The standard behavior of
operators for built-in (primitive) types cannot be changed by overloading, that is, you
can’t overload operator+(int,int). The logic(boolean) operators have by the default a
short-circuiting way of acting in expressions with multiple boolean operations. This
means that the expression:
if(a && b&& c) will not evaluate all three operations and will stop after a false one
is found. This behavior does not
1 Lab 9:Operator
apply to operators that are overloaded by the programmer. Even the simplest C+
+ application, like a "hello world" program, is using overloaded operators. This is
due to the use of this technique almost everywhere in the standard library (STL).
Actually the most basic operations in C++ are done with overloaded operators, the
IO(input/output) operators are overloaded versions of shift operators(«, »). Their
use comes naturally to many beginning programmers, but their implementation is
not straightforward. However a general format for overloading the input/output
operators must be known by any C++ developer. We will apply this general form to
manage the input/output for our Complex class:
Notice the use of the friend keyword in order to access the private members in the
above implementations. The main distinction between them is that the operator» may
encounter unexpected errors for incorrect input, which will make it fail sometimes
because we haven’t handled the errors correctly. A important trick that can be seen
in this general way of overloading IO is the returning reference for
istream/ostream which is needed in order to use them in a recursive manner:
1 Complex a ( 2 , 3 ) ;
2 Complex b ( 5 . 3 , 6 ) ;
3
4 cout <<a<<b ;
Note:
Exercise:
Q 1: Write a program to make a class of Rational numbers with data members numer-
ator and denominator and member functions getdata() "to get data", showdata()"to
display data", adddata() "add the data of two fractions" and operator+() "to add two
objects such that numerator is added with numerator and denominator with denom-
inator".
Q2: Write a program to make a class Distance with data members meters and kilo-
meters, and member function getdata() "get data for distances", showdata()"display
data for distances’, operator++()"increments meters=meters+100, if meter exceeds
than 1000meters then increment kilometers by 1 and decrement meters by 1000 ",
and operator - -()"work in the same manner like ++ but operation is totally oppo-
site".
Q3: Write a program to make a class of Complex numbers with data members as
real and imaginary numbers and getreal(), getimg() and Show() to get real numbers
, imaginary numbers and to show data respectively and operator+()"subtract two
objects", operator-()"add two objects", operator/()"multiply two objects", and opera-
tor*() "divide first object by second object".
1 Lab 9:Operator
Chapter 10
Lab 10:Inheritance
The idea of inheritance implements the is a relationship. For example, mammal IS-
A animal, dog IS-A mammal hence dog IS-A animal as well and so on.
Consider a base class Shape and its derived class Rectangle as follows:
117
1 Lab
5 //Base c l a s s c l a s s Shape
6
7 {
8 public :
9 void setWidth ( i n t w)
10 {
11
width = w;
12
13 }
14
void set Height ( i n t h )
{
15
height = h ;
16
}
17
18
pr ot e ct e d : i n t width ; i n t height ;
19
};
20
21
//Derived c l a s s
22
c l a s s Rectangle : public Shape
23
{
24 public :
25
26 i n t get Area ( )
27
28
{
29
30 return ( width ∗ height ) ;
31 }
32 };
33
34 i n t main ( void )
35 {
36 Rectangle Rect ;
37
38 Rect . setWidth ( 5 ) ; Rect . set Height ( 7 ) ;
39
40 // P r i n t the area of the o b j e c t .
41 cout << " Total area : " << Rect . getArea ( ) << endl ;
42
43 return 0;
44 }
45
We can summarize the different access types according to who can access them in
the following way:
A derived class inherits all base class methods with the following exceptions:
• Constructors, destructors and copy constructors of the base class.
• Overloaded operators of the base class.
• The friend functions of the base class.
Type of Inheritance:
When deriving a class from a base class, the base class may be inherited through
public, protected or private inheritance. The type of inheritance is specified by the
access-specifier as explained above.
• Public Inheritance: When deriving a class from a public base class, public mem-
bers of the base class become public members of the derived class and protected
members of the base class become protected members of the derived class. A base
class’s private members are never accessible directly from a derived class, but can be
accessed through calls to the public and protected members of the base class.
1 Lab
• Protected Inheritance: When deriving from a protected base class, public and pro-
tected members of the base class become protected members of the derived class.
• Private Inheritance: When deriving from a private base class, public and protected
members of the base class become private members of the derived class.
Multiple Inheritances:
A C++ class can inherit members from more than one class and here is the extended
syntax:
Where access is one of public, protected, or private and would be given for every
base class and they will be separated by comma as shown above. Let us try the fol-
lowing example:
30 };
31
32 // Derived c l a s s
33 c l a s s Rectangle : public Shape , public Paint Cost
34 {
35 public :
36
i n t get Area ( )
37
38 {
39 return ( width ∗ height ) ;
40 }
41 };
42
43 i n t main ( void )
44 {
45
46 Rectangle Rect ; i n t area ;
47
48 Rect . setWidth ( 5 ) ; Rect . set Height ( 7 ) ;
49
50 area = Rect . getArea ( ) ;
51
52 // P r i n t the area of the o b j e c t .
53 cout << " Total area : " << Rect . get Area ( ) << endl ;
54
55 // P r i n t the t o t a l c o s t of pain tin g
56 cout << " Total paint c o s t : $ " << Rect . get Cost ( area ) << endl ; return 0 ;
57 }
58
59
60
61
62
When the above code is compiled and executed, it produces following result:
Total area: 35
Exercise:
Question 1: Define a class Student as a base class with data members as admissionNo,
Name, age and address as protected type and getStudent function for setting values
for these data members. These members and functions are common to both
derived classes. Make two derived classes of Student class as undergraduate and
graduate student each containing data member degree_program "in which student is
enrolled" and member functions getdegree "set degree_program" and show
"display whole information". Degree in which student is enrolled and display the
whole information of graduate and undergraduate student like this
Figure 10.1:
Lab 11:Introduction to
Polymorphism and Abstract Base
Classes
Polymorphism
Polymorphism is a mechanism that allows you to implement a function in different
ways. Polymorphism is by far the most important and widely used concept in
object oriented programming.
One of the features of derived classes is that a pointer to a derived class is type-
compatible with a pointer to its base class. Polymorphism takes advantage of this
feature.
123
1 Lab 11:Introduction to Polymorphism and Abstract Base
12
13 {
14 width= f i r s t ;
15 height= second ;
16 }
17
};
18
19
c l a s s CRectangle : public CPolygon
20
21 {
22
public :
i n t area ( )
23
24
25
{
26 return ( width ∗ height ) ;
27 }
28 };
29
30 c l a s s CTriangle : public CPolygon
31 {
32 public :
33
i n t area ( )
34
{
35
36 return ( width ∗ height / 2 ) ;
37 }
38 };
39
40 i n t main ( )
41
42 {
43 CRectangle r e c t a n gl e ; CTriangle t r i a n g l e ;
44 CPolygon ∗ ptr_polygon1 = &r e c t a n gl e ; CPolygon ∗ ptr_polygon2 = &t r i a n g l e ;
45
46
47
48
49
50 ptr_polygon1 −>setup ( 2 , 2 ) ;
51 ptr_polygon2 −>setup ( 2 , 2 ) ;
52 cout << r e c t a n gl e . area ( ) << endl ; cout << t r i a n g l e . area ( ) << endl ;
53
54
55
56 return 0;
57 }
As you can see, we create two pointers (ptr_polygon1 and ptr_polygon2) that point
to the objects of class CPolygon. Then we assign to these pointers the address of
(us- ing the reference ampersand sign) the objects rectangle and triangle. Both
rectangle and triangle are objects of classes derived from CPolygon.
In the cout statement we use the objects rectangle and triangle instead of the pointers
1
If we want to use the pointers to class CPolygon then area() should be declared
in the class CPolygon and not only in the derived classes CRectangle and Ctriangle.
The problem is that we use different versions of area() in the derived classes
â A˘ S¸ CRectangle and Ctriangle â A˘ S¸ so we canâ A˘ Z´ t implement one version of
area() in the base class CPolygon. (If they were the same we had no problem.)
Virtual Members
A virtual member is a member of a base class that we can redefine in its derived
classes. To declare a member as virtual we must use the keyword virtual.
27 i n t area ( )
28 {
29 return ( width ∗ height ) ;
30 }
31 };
32
33 c l a s s CTriangle : public CPolygon
34 {
35 public :
36 i n t area ( )
37
{
38
39 return ( width ∗ height / 2 ) ;
40 }
41
42 };
43
44 i n t main ( )
45 {
46 CRectangle r e c t a n gl e ;
47
48 CTriangle t r i a n g l e ; CPolygon polygon ;
49
50
51 CPolygon ∗ ptr_polygon1 = &r e c t a n gl e ;
52 CPolygon ∗ ptr_polygon2 = &t r i a n g l e ;
53 CPolygon ∗ ptr_polygon3 = &polygon ;
54
55 ptr_polygon1 −>setup ( 2 , 2 ) ;
56 ptr_polygon2 −>setup ( 2 , 2 ) ;
57 ptr_polygon3 −>setup ( 2 , 2 ) ;
58
cout << ptr_polygon1 −>area
59 ( ) << endl ;
60
61 cout << ptr_polygon2 −>area ( ) << endl ;
62 cout << ptr_polygon3 −>area ( ) << endl ;
63 return 0 ;
64 }
65
The term "shape" is an abstract concept, it could be a circle, a square, etc, etc. You
could say in C++ that class CShape is an abstract base class (ABC) and class circle
(etc) could be a derived class.
As we look at the C++ language we could say that an abstract base class has one
or more pure virtual member functions.
In the example above we put an implementation (return (0);) in the virtual mem-
ber function area(). If we want to change it into a pure virtual member function we
use =0; instead of the return (0). So the class will look like this:
1 c l a s s CPolygon
2
3 {
4
5 pr o te c te d :
6 i n t width , height ;
7 public :
8
9 void setup ( i n t f i r s t , i n t second )
10 {
11 width= f i r s t ;
12 height= second ;
13 }
14
15 v i r t u a l i n t area ( ) = 0 ;
16 };
This pure virtual function area() makes CPolygon an abstract base class. But you
have to remember the following: by adding a pure virtual member to the base
class, you are forced to also add the member to any derived class.
16 }
17 v i r t u a l i n t area ( ) = 0 ;
18 };
19
20 c l a s s CRectangle : public CPolygon
21 {
22
public :
23
i n t area ( void )
{
24
25
26 return ( width ∗ height ) ;
27 }
28 };
29 c l a s s CTriangle : public CPolygon
30 {
31
public :
i n t area ( void )
32
{
33
34 return ( width ∗ height / 2 ) ;
35 }
36
37 };
38
39 i n t main ( )
40 {
41 CRectangle r e c t a n gl e ;
42
43 CTriangle triangle ;
44
45 CPolygon ∗ ptr_polygon1 = &r e c t a n gl e ;
46 CPolygon ∗ ptr_polygon2 = &t r i a n g l e ;
47
48 ptr_polygon1 −>setup ( 2 , 2 ) ;
49 ptr_polygon2 −>setup ( 2 , 2 ) ;
50
51 cout << ptr_polygon1 −>area ( ) << endl ;
52 cout << ptr_polygon2 −>area ( ) << endl ;
53 return 0 ;
54
55
56 }
Note:
there is also an extra void in the derived classes CRectangle and CTriangle.
Using a unique type of pointer (CPolygon*) we can point to objects of different but
related classes. We can make use of that. For instance: we could implement an extra
function member in the abstract base class CPolygon that can print the result of the
area() function. (Remember that CPolygon itself has no implementation for the func-
tion area() and still we can use it, isnâ A˘ Z´ t it cool.) After implementation of
such a
1
Note:
Before doing your lab exercises run the examples.
Exercise:
Question 1: By using the concept of virtual function, create a class shape with data
members length and breadth as protected and these data members are initialized
using class constructor. Shape class has two virtual member functions area() "calcu-
lates area"and display() "display calculated area". Now derive three classes rectangle,
circle and trapezoidal from shape class. Each class has its own area() and display()
member functions to calculate area and display. Only rectangle class use data mem-
bers of shape class while circle and trapezoidal has its own data members. Make
three pointers of base class and object of each remaining classes, pointers pointing to
each class object.
Hint:
Circle Area: A=ÏA˘ r2ˆ
Trapezoidal Area: A=(1â A˛Dˇ 2*(lengthside1+lengthside2))*height;
Question 2:
By implementing pure virtual function, make a class student with data members
name and department as protected type and two pure virtual member functions
get_data() "to input the student record"and show_data() "display student record".
Now derive three classes Medical, Engineering, and Science from student class with
its own member functions of get_data() "to input the student record" and show_data()
"display student record" while using data members of student class. Now in main
portion of your program create an array of pointers of base class having size three
and assign to each index remaining class objects addresses. By using for loop
iterate
1
array and take input then again display records using for loop. Hint: Donâ A˘ Z´ t
need to pass name and department as argument to functions.
1 Lab 11:Introduction to Polymorphism and Abstract Base
Chapter 12
C++ provides the following classes to perform output and input of characters to/from
files:
• ofstream: Stream class to write on files
• ifstream: Stream class to read from files
• fstream: Stream class to both read and write from/to files.
These classes are derived directly or indirectly from the classes istream, and ostream.
We have already used objects whose types were these classes: cin is an object of
class istream and cout is an object of class ostream. Therfore, we have already been
using classes that are related to our file streams. And in fact, we can use our file
streams the same way we are already used to use cin and cout, with the only differ-
ence that we have to associate these streams with physical files. Let’s see an example:
This code creates a file called example.txt and inserts a sentence into it in the same
way we are used to do with cout, but using the file stream myfile instead. But let’s
go step by step:
133
1 Lab 12:File Handling in
Open a file
The first operation generally performed on an object of one of these classes is to
associate it to a real file. This procedure is known as to open a file. An open file
is represented within a program by a stream object (an instantiation of one of these
classes, in the previous example this was myfile) and any input or output operation
performed on this stream object will be applied to the physical file associated to it.
In order to open a file with a stream object we use its member function open():
Where filename is a null-terminated character sequence of type const char (the same
type that string literals have) representing the name of the file to be opened, and
mode is an optional parameter with a combination of the following flags:
Figure 12.1:
All these flags can be combined using the bitwise operator OR (|). For example,
if we want to open the file example.bin in binary mode to add data we could do it
by the following call to member function open():
ofstream myfile;
myfile.open ("example.bin", ios::out | ios::app | ios::binary);
Each one of the open() member functions of the classes ofstream, ifstream and
fstream has a default mode that is used if the file is opened without a second ar-
gument
For ifstream and ofstream classes, ios::in and ios::out are automatically and respec-
tively assumed, even if a mode that does not include them is passed as second argu-
ment to the open() member function.
The default value is only applied if the function is called without specifying any
value for the mode parameter. If the function is called with any value in that
param- eter the default mode is overridden, not combined.
1
File streams opened in binary mode perform input and output operations indepen-
dently of any format considerations. Non-binary files are known as text files, and
some translations may occur due to formatting of some special characters (like new-
line and carriage return characters).
Since the first task that is performed on a file stream object is generally to open
a file, these three classes include a constructor that automatically calls the open()
member function and has the exact same parameters as this member. Therefore, we
could also have declared the previous myfile object and conducted the same opening
operation in our previous example by writing:
ofstream myfile ("example.bin", ios::out | ios::app | ios::binary);
Combining object construction and stream opening in a single statement. Both forms
to open a file are valid and equivalent.
To check if a file stream was successful opening a file, you can do it by calling to
member is_open() with no arguments. This member function returns a bool value of
true in the case that indeed the stream object is associated with an open file, or false
otherwise:
This will open the file without destroying the current contents and allow you to
append new data. When opening files, be very careful not to use them if the file
could not be opened. This can be tested for very easily:
Closing a file
When we are finished with our input and output operations on a file we shall close
it so that its resources become available again. In order to do that we have to call the
stream’s member function close(). This member function takes no parameters, and
what it does is to flush the associated buffers and close the file:
myfile.close();
1 Lab 12:File Handling in
Once this member function is called, the stream object can be used to open another
file, and the file is available again to be opened by other processes. In case that an
object is destructed while still associated with an open file, the destructor automati-
cally calls the member function close().
Text files
Text file streams are those where we do not include the ios::binary flag in their open-
ing mode. These files are designed to store text and thus all values that we input
or output from/to them can suffer some formatting transformations, which do not
necessarily correspond to their literal binary value.
Data output operations on text files are performed in the same way we operated
with cout:
1 // writing on a t e x t f i l e
2 # include <iostream > # include <fstream > using namespace std ; i n t main ( ) {
3
4 ofstream myfile ( " example . t x t " ) ; i f ( myfile . is_open ( ) )
5
6 {
7
8 myfile << " This i s a l i n e .\ n" ;
9 myfile << " This i s another l i n e .\ n" ;
10 myfile . c l o s e ( ) ;
11 }
12 e l s e cout << " Unable to open f i l e " ;
13 return 0 ;
14 }
[file example.txt]
This is a line.
This is another line.
Data input from a file can also be performed in the same way
that we did with cin:
1 // reading a t e x t f i l e
2 # include <iostream > # include <fstream >
1
This is a line.
This is another line.
This last example reads a text file and prints out its content on the screen. Notice
how we have used a new member function, called eof() that returns true in the case
that the end of the file has been reached. We have created a while loop that finishes
when indeed myfile.eof() becomes true (i.e., the end of the file has been reached).
bad()
Returns true if a reading or writing operation fails. For example in the case that we
try to write to a file that is not open for writing or if the device where we try to write
has no space left.
fail()
Returns true in the same cases as bad(), but also in the case that a format error hap-
pens, like when an alphabetical character is extracted when we are trying to read an
integer number.
1 Lab 12:File Handling in
eof()
Returns true if a file open for reading has reached the end.
good()
It is the most generic state flag: it returns false in the same cases in which calling any
of the previous functions would return true.
In order to reset the state flags checked by any of these member functions we have
just seen we can use the member function clear(), which takes no parameters.
All i/o streams objects have, at least, one internal stream pointer:
ifstream, like istream, has a pointer known as the get pointer that points to the
element to be read in the next input operation.
ofstream, like ostream, has a pointer known as the put pointer that points to the
location where the next element has to be written.
Finally, fstream, inherits both, the get and the put pointers, from iostream (which is
itself derived from both istream and ostream).
These internal stream pointers that point to the reading or writing locations within a
stream can be manipulated using the following member functions:
These two member functions have no parameters and return a value of the member
type pos_type, which is an integer data type representing the current position of the
get stream pointer (in the case of tellg) or the put stream pointer (in the case of tellp).
1
seekg ( position );
seekp ( position );
Using this prototype the stream pointer is changed to the absolute position position
(counting from the beginning of the file). The type for this parameter is the same as
the one returned by functions tellg and tellp: the member type pos_type, which is an
integer value. The other prototype for these functions is:
And direction is of type seekdir, which is an enumerated type (enum) that deter-
mines the point from where offset is counted from, and that can take any of the
following values:
Exercise:
Lab-12 Task: Question1: Write a program that creates two files file1.dat and file2.dat,
input same data to both files and show data of both files. Now compare data of
both files and display a message "both files have same content". Now modify data
in file2 just by appending some more content at the end of file, again show data and
compare them and display message "files have different content".
Question2:
1 Lab 12:File Handling in