Object Oriented Programming
Object Oriented Programming
Module 1 Introduction to OOP - Evolution of object oriented languages - Need of Objects - Definition of Object-Oriented Language Classes and Objects Creating and Using Classes and objects Member functions and variables Constructors and Destructors. Module 2 Inheritance and Access Control - Member access control in classes Friend functions and classes Extending classes - Public Private and Protected Inheritance Classification of Inheritance Single Multiple Multilevel Hierarchical Hybrid. Module 3 Polymorphism Runtime and compile time polymorphism overloading functions and operators selecting friend member function for operator overloading - Virtual methods pure virtual methods Abstract classes - Defining and using of virtual methods, pure virtual methods and abstract classes applications of abstract classes. Module 4 Advanced Concepts- Virtual Destructors Virtual Base Classes Creating and using templates Namespaces - Template classes
Module 5 Dynamic Objects - Dynamic object allocation - Inline functions. Other Object oriented languages Java Object oriented features in Java Comparison with C++
References
1. Object Oriented Programming in C ++ - Robert Lafore, Galgotia Pub. 2. Object Oriented Programming in C++ - Nabajyoti Barkakati, PHI 3. Structured and Object Oriented Problem Solving using C++ - Andrew C Staugaard Jr., PHI 4. Object oriented Programming with C++ - E. Balaguruswamy, TMH 5. Java 2 Complete Reference - Herbert, Schildt, TMH 6. The Java Programming Language 3rd Edition - Arnold, Gosling, Holmes, Pearson Education Asia 7. Object-oriented programming using C++ - Ira Pohl, Pearson Education Asia 8. C++ How to program - Dietel & Dietel, Pearson Education Asia 9. An Introduction to Object-oriented programming Timothy Budd 10. Problem Solving with C++ - Walter Savitch, Pearson Education Asia 11. C++ Primer - Stanley B Lippman, Josee Zajoie, Pearson Education Asia
MODULE 1
INTRODUCTION TO OOP Object Oriented Programming Paradigm
Oops is a better way of solving problems in computers compared to the procedural language programming such as in C. oops is designed around the data being operated upon as opposed to the operations, these operations are designed to fit data. A type of programming in which programmers define not only the data type of a data structure, but also the types of operations that can be applied to the data structure. In this way, the data structure becomes an object that includes both data and functions. In addition, programmers can create relationships between one object and another. For example, objects can inherit characteristics from other objects. One of the principal advantages of object-oriented programming techniques over procedural programming techniques is that they enable programmers to create modules that do not need to be changed when a new type of object is added. A programmer can simply create a new object that inherits many of its features from existing objects. This makes object-oriented programs easier to modify. To perform object-oriented programming, one needs an object-oriented programming language such as Java C++ etc. The C++ programming language provides a model of memory and computation that closely matches that of most computers. In addition, it provides powerful and flexible mechanisms for abstraction; that is, language constructs that allow the programmer to introduce and use new types of objects that match the concepts of an application. Thus, C++ supports styles of programming that rely on fairly direct manipulation of hardware resources to deliver a high degree of efficiency plus higher-level styles of programming that rely on user-defined types to provide a model of data and computation that is closer to a humans view of the task being performed by a computer. These higher-level styles of programming are often called data abstraction, object-oriented programming, and generic programming. Features of OOPs are the following: Encapsulation Data abstraction Dept of CS , SJCET, Palai 4
An object is a variable of a user-defined type. Each time you define a new type of object, you are creating a new data type. Each specific instance of this data type is a compound variable.
Polymorphism: Polymorphism allows routines to use variables of different types at different times. An operator or function can be given different meanings or functions. Polymorphism refers to a single function or multi-functioning operator performing in different ways. Polymorphism is in short the ability to call different functions by just using one type of function call. It is a lot useful since it can group classes and their functions together. Polymorphism means that the same thing can exist in two forms. This is an important characteristic of true object oriented design which means that one could develop good OO design with data abstraction and inheritance, but the real power of object oriented design seems to surface when polymorphism is used. In C++, polymorphism means that if the same message is sent to different objects, the objects behavior depends on the nature of the object itself. This is sort of obvious for completely different objects, but the concept starts making sense when combined with inheritance. In C++ it is possible to use one function name for many different purposes. This type of polymorphism is called function overloading. Polymorphism can also be applied to operators. In that case it is called operator overloading. Dept of CS , SJCET, Palai 8
10
Additionally, to add a new-line, you may also use the endl manipulator. For example: cout << "First sentence." << endl; cout << "Second sentence." << endl; The endl manipulator produces a newline character, exactly as the insertion of '\n' does, but it also has an additional behavior when it is used with buffered streams: the buffer is flushed. Anyway, cout will be an unbuffered stream in most cases, so you can generally use both the \n escape character and the endl manipulator in order to specify a new line without any difference in its behavior.
11
The standard input device is usually the keyboard. Handling the standard input in C++ is done by applying the overloaded operator of extraction (>>) on the cin stream. The operator must be followed by the variable that will store the data that is going to be extracted from the stream. For example: int age; cin >> age;
The first statement declares a variable of type int called age, and the second one waits for an input from cin (the keyboard) in order to store it in this integer variable. can only process the input from the keyboard once the RETURN key has been pressed. Therefore, even if you request a single character, the extraction from cin will not process the input until the user presses RETURN after the character has been introduced.
cin
You must always consider the type of the variable that you are using as a container with cin extractions. If you request an integer you will get an integer, if you request a character you will get a character and if you request a string of characters you will get a string of characters. #include <iostream> using namespace std; int main () { int i; cout << "Please enter an integer value: "; cin >> i; cout << "The value you entered is " << i; cout << " and its double is " << i*2 << ".\n"; return 0; } Output : Please enter an integer value: 702 The value you entered is 702 and its double is 1404.
The user of a program may be one of the factors that generate errors even in the simplest programs that use cin (like the one we have just seen). Since if you request an integer value and the user introduces a name (which generally is a string of characters), the result may cause your program to misoperate since it is not what we were expecting from the user. So when you use the data input provided by cin extractions you will have to trust that the user of your program will be cooperative and that he/she will not introduce his/her name or something similar when an integer value is
12
C++ program
Our first C++ program will print the message "Hello World" on the screen. Open a text editor and start by typing the following line:
#include<iostream>
The above line includes the header file called iostream which will allow us to use the command to print words on the screen. Next you must type:
using namespace std;
This will let us use certain commands without having to type out their full name. Now we will type the main function.
int main() { }
The main function is where a program always starts. Every program must have a main function. The word int in front of main is to say what the return value is. The curly brackets belong to the main function and show where it begins and where it ends. Now we will type the command that prints "Hello World" on the screen between the curly brackets.
cout << "Hello World\n";
The cout command is used to print things on the screen. The << means that the text must be output. The words that you want printed must be surrounded by quotes. The \n means that the cursor must go the beginning of the next line. Lastly we must return 0 to the operating system to tell it that there were no errors while running the program.
return 0;
13
Save the file as hello.cpp. You now need to compile the program. You need to open a command prompt and type the command name of your C++ compiler and the name of the C++ file you have just created. Here is an example of how to do it with Borland C++:
bcc32 hello.cpp
If you are given error messages then you have made mistakes which means you should go through this lesson again and fix them. If you don't get any errors then you should end up with an executable file which in my case is called hello.exe. Enter hello to run the program and you should see "Hello World" printed on the screen. Congratulations! You have just made your first C++ program.
The second line of the program has a # symbol which represents the preprocessor directive followed by header file to be included placed between < >. The next structure present in the program is the class definition. This starts with the keyword class followed by class name employee. Within the class are data and functions. The data defined in the class are generally private and functions are public. These explanations we will be detailed in later sections. The class declaration ends with a semicolon. main() function is present in all C++ programs. An object e1 is created in employee class. Using this e1 the functions present in the employee class are accessed and there by data are accessed. The input namely ename and eno is got using the input statement namely cin and the values are outputted using the output statement namely cout.
14
15
16
Constants
Constants have fixed value. Constants, like variables, contain data type. Integer constants are represented as decimal notation, octal notation, and hexadecimal notation. Decimal notation is represented with a number. Octal notation is represented with the number preceded by a zero character. A hexadecimal number is preceded with the characters 0x.
Example 80 represent decimal 0115 represent octal 0x167 represent hexadecimal Dept of CS , SJCET, Palai 17
Strings are sequences of characters signifying string constants. These sequence of characters are represented between double quotes. Example: Exforsys Training is an example of string constant.
18
Most of the control structures that we will see in this section require a generic statement as part of its syntax. A statement can be either a simple statement (a simple instruction ending with a semicolon) or a compund statement (several instructions grouped in a block), like the one just described. In the case that we want the statement to be a simple statement, we do not need to enclose it in braces ( {}). But in the case that we want the statement to be a compund statement it must be enclosed between braces ({}), forming a block.
if and else
The if keyword is used to execute a statement or block only if a condition is fulfilled. Its form is: if (condition) statement Where condition is the expression that is being evaluated. If this condition is true, statement is executed. If it is false, statement is ignored (not executed) and the program continues right after this conditional structure. For example, the following code fragment prints x is 100 only if the value stored in the x variable is
indeed 100:
if (x == 100) If we want more than a single statement to be executed in case that the condition is true we can specify a block using braces { }: if (x == 100) { cout << "x is "; cout << x; }
19
prints on the screen x is 100 if indeed x has a value of 100, but if it has not -and only if not- it prints out x is not 100. The if + else structures can be concatenated with the intention of verifying a range of values. The following example shows its use telling if the value currently stored in x is positive, negative or none of them (i.e. zero): if (x > 0) cout << "x is positive"; else if (x < 0) cout << "x is negative"; else cout << "x is 0";
Remember that in case that we want more than a single statement to be executed, we must group them in a block by enclosing them in braces { }. Iteration structures / loops Loops have as purpose to repeat a statement a certain number of times or while a condition is fulfilled.
The while loop
Its format is:
and its functionality is simply to repeat statement while the condition set in expression is true.For example, we are going to make a program to countdown using a while-loop: #include <iostream> using namespace std; Dept of CS , SJCET, Palai 20
21
Its functionality is exactly the same as the while loop, except that condition in the do-while loop is evaluated after the execution of statement instead of before, granting at least one execution of statement even if condition is never fulfilled. For example, the following example program echoes any number you enter until you enter 0. include <iostream> using namespace std; int main () { unsigned long n; do { cout << "Enter number (0 to end): "; cin >> n; cout << "You entered: " << n << "\n"; } while (n != 0); return 0; } Output : Enter number (0 to end): 12345 You entered: 12345 Enter number (0 to end): 160277 You entered: 160277 Enter number (0 to end): 0 You entered: 0 The do-while loop is usually used when the condition that has to determine the end of the loop is determined within the loop statement itself, like in the previous case, where the user input within the block is what is used to determine if the loop has to end.
The for loop
Its format is: for (initialization; condition; increase) statement; and its main function is to repeat statement while condition remains true, like the while loop. But in addition, the for loop provides specific locations to contain an initialization statement and an increase statement. So this loop is specially designed to perform a repetitive action with a counter which is initialized and increased on each iteration. Dept of CS , SJCET, Palai 22
Using break we can leave a loop even if the condition for its end is not fulfilled. It can be used to end an infinite loop, or to force it to end before its natural end. For example, we are going to stop the count down before its natural end . #include <iostream> Dept of CS , SJCET, Palai 23
The continue statement causes the program to skip the rest of the loop in the current iteration as if the end of the statement block had been reached, causing it to jump to the start of the following iteration. For example, we are going to skip the number 5 in our countdown: // continue loop example #include <iostream> using namespace std; int main () { for (int n=10; n>0; n--) { if (n==5) continue; cout << n << ", "; } cout << "FIRE!\n"; return 0; }
allows to make an absolute jump to another point in the program. You should use this feature with caution since its execution causes an unconditional jump ignoring any type of nesting limitations.The destination point is identified by a label, which is then used as an argument for the goto statement. A label is made of a valid identifier followed by a colon (:).
Goto
24
void exit (int exitcode); The exitcode is used by some operating systems and may be used by calling programs. By convention, an exit code of 0 means that the program finished normally and any other value means that some error or unexpected results happened.
The selective structure: switch
The syntax of the switch statement is a bit peculiar. Its objective is to check several possible constant values for an expression. Something similar to what we did at the beginning of this section with the concatenation of several if and else if instructions. Its form is the following: switch (expression) { case constant1: group of statements 1; break; case constant2: group of statements 2; break; . Dept of CS , SJCET, Palai 25
switch (x) { if (x == 1) { case 1: cout << "x is 1"; cout << "x is 1"; } break; else if (x == 2) { case 2: cout << "x is 2"; cout << "x is 2"; } break; else { default: cout << "value of x unknown"; cout << "value of x unknown"; } }
The switch statement is a bit peculiar within the C++ language because it uses labels instead of blocks. This forces us to put break statements after the group of statements that we want to be executed for a specific condition. Otherwise the remainder statements -including those corresponding to other labels- will also be executed until the end of the switch selective block or a break statement is reached. For example, if we did not include a break statement after the first group for case one, the program will not automatically jump to the end of the switch selective block and it would continue executing the rest of statements until it reaches either a break instruction or the end of the switch selective block. This makes unnecessary to include braces { } surrounding the statements for each of the cases, and it can also be useful to execute the same block of instructions for different possible values for the expression being evaluated. For example: switch(x) { Dept of CS , SJCET, Palai 26
27
Type casting otherwise called as Explicit Conversion Explicit conversion can be done using type cast operator and the general syntax for doing this is datatype (expression); Here in the above datatype is the type which the programmer wants the expression to gets changed as In C++ the type casting can be done in either of the two ways mentioned below namely: C-style casting C++-style casting The C-style casting takes the synatx as (type) expression This can also be used in C++. Apart from the above the other form of type casting that can be used specifically in C++ programming language namely C++-style casting is as below namely: type (expression) This approach was adopted since it provided more clarity to the C++ programmers rather than the Cstyle casting.Say for instance the as per C-style casting (type) firstVariable * secondVariable is not clear but when a programmer uses the C++ style casting it is much more clearer as below type (firstVariable) * secondVariable Let us see the concept of type casting in C++ with a small example:
Function
A function is a structure that has a number of program statements grouped as a unit with a name given to the unit. Function can be invoked from any part of the C++ program. Features of Function: To understand why the program structure is written separately and given a name, the programmer must have a clear idea of the features and benefits of function. This will encourage better understanding of function usage:
Use of Functions gives a Structured Programming Approach Reduces Program Size: The piece of code that needs to be executed, or the piece of code that is repeated in different parts of the program, can be written separately as a function and stored in a place in memory. Whenever and Dept of CS , SJCET, Palai 29
30
Let us see a complete program in C++ to help the programmer to understand the function concepts described above: #include void main( ) { void exforsys( ); //Function Declaration exforsys( ); //Function Called cout<<\n End of Program; }
31
Argument
An argument is the value that is passed from the program to the function call. This can also be considered as input to the function from the program from which it is called. How to declare a function passed with argument Declaring a function: The general format for declaring the function remains the same as before except the data type passed as arguments in functions are in the same order in which it is defined in function. The format for declaring a function with arguments is: return_datatype functionname(datatype1,datatype2,..); In this example, the data types are the types of data passed in the function definition as arguments to the function. Care must be taken to mention the number of arguments and the order of arguments in the same way as in function definition. For example, suppose a function named exforsys takes two integer values as arguments in its functions definition and returns an integer value. The function declaration of exforsys would be written: int exforsys(int,int); Function Definition: The function definition has the same syntax as the function definition previously defined, but with added arguments. The general format for defining a function with arguments is written as: return_datatype functionname(datatype1 variable1,datatype2 variable2,..) { Dept of CS , SJCET, Palai 32
Reference Variable
C++ introduces a new kind of variable known as reference variable.A reference variable provides an alias (alternative name) for a previously defined variable.A reference variable is creaed as follows: Datatype & reference-name=variable-name Eg:float total=100; Float &sum=total; Then the sumand total can be used interchangeably to represent that variable. // passing parameters by reference Dept of CS , SJCET, Palai 34
To explain it in another way, we associate a, b and c with the arguments passed on the function call (x, y and z) and any change that we do on a within the function will affect the value of x outside it. Any change that we do on b will affect y, and the same with c and z. That is why our program's output, that shows the values stored in x, y and z after the call to duplicate, shows the values of all the three variables of main doubled. If when declaring the following function: void duplicate (int& a, int& b, int& c) we had declared it this way: duplicate (int a, int b, int c) without the ampersand signs (&), we would have not passed the variables by reference, but a copy of their values instead, and therefore, the output on screen of our program would have been the values of x, y and z without having been modified. Passing by reference is also an effective way to allow a Dept of CS , SJCET, Palai 35
#include <iostream>
using namespace std; void prevnext (int x, int& prev, int& next) { prev = x-1; next = x+1; } int main () { int x=100, y, z; prevnext (x, y, z); cout << "Previous=" << y << ", Next=" << z; return 0; } Output: Previous=99, Next=101 Call by value Call-by-value evaluation is the most common evaluation strategy, used in languages as far-ranging as C and Scheme. In call-by-value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function (usually by capture-avoiding substitution or by copying the value into a new memory region). If the function or procedure is able to assign values to its parameters, only the local copy is assigned -- that is, anything passed into a function call is unchanged in the caller's scope when the function returns. Call-by-value is not a single evaluation strategy, but rather the family of evaluation strategies in which a function's argument is evaluated before being passed to the function. While many programming languages that use call-by-value evaluate function arguments left-to-right, some (such as O'Caml) evaluate functions and their arguments right-to-left, and others (such as Scheme and C) leave the order unspecified (though they generally guarantee sequential consistency).
36
Call by reference In call-by-reference evaluation, a function is passed an implicit reference to its argument rather than the argument value itself. If the function is able to modify such a parameter, then any changes it makes will be visible to the caller as well. If the argument expression is an L-value, its address is used. Otherwise, a temporary object is constructed by the caller and a reference to this object is passed; the object is then discarded when the function returns. Some languages contain a notion of references as first-class values. ML, for example, has the "ref" constructor; references in C++ may also be created explicitly. In these languages, "call-by-reference" may be used to mean passing a reference value as an argument to a function. In languages (such as C) that contain unrestricted pointers instead of or in addition to references, call-by-address is a variant of call-by-reference where the reference is an unrestricted pointer Default Arguments When declaring a function we can specify a default value for each parameter. This value will be used if the corresponding argument is left blank when calling to the function. To do that, we simply have to use the assignment operator and a value for the arguments in the function declaration. If a value for that parameter is not passed when the function is called, the default value is used, but if a value is specified this default value is ignored and the passed value is used instead. For example: // default values in functions
#include <iostream>
using namespace std; int divide (int a, int b=2) { int r; r=a/b; return (r); } int main () { cout << divide (12); cout << endl; cout << divide (20,4); return 0; } Output: 6,5 As we can see in the body of the program there are two calls to function divide. In the first one: divide (12) Dept of CS , SJCET, Palai 37
Compound assignment operators function in a similar way the other operators +=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |= function. Increment and Decrement Operator The increment operator is denoted by ++ and the decrement operator by --. The function of the increment operator is to increase the value and the decrement operator is to decrease the value. These operators may be used as either prefix or postfix. A Prefix operator is written before the variable as ++a or a. A Postfix operator is written after the variable as a++ or a--. The Functionality of Prefix and Postfix Operators In the case that the increment or decrement operator is used as a prefix ( ++a or a), then the value is respectively increased or decreased before the result of the expression is evaluated. Therefore, the increased or decreased value, respectively, is considered in the outer expression. In the case that the increment or decrement operator is used as a postfix (a++ or a--), then the value stored in a is respectively increased or decreased after being evaluated. Therefore, the value stored before the increase or decrease operation is evaluated in the outer expression. For Example:
y=3; x=++y;
But for the postfix operator namely as below: y=3 x=y++; //Postfix : Here Value of x is 3 and Value of y is 4
39
The operator || corresponds with Boolean logical operation OR. The operator produces a true value if either one of its two operands are true and produces a false value only when both operands are false. The following table reflects the 40
|| Operator x y x || y
Conditional Operator The conditional operator evaluates an expression returning a value if that expression is true and a different value if the expression is evaluated as false. The syntax is:
7>5 ? x : y
Since 7 is greater than 5, true is returned and hence the value x is returned.
41
x = sizeof (char);
This returns the size of char in bytes. In this example, the size is 1 byte which is assigned to variable x.
42
produces the output: Exforsys Training setw Manipulator: This manipulator sets the minimum field width on output. The syntax is: setw(x) Here setw causes the number or string that follows it to be printed within a field of x characters wide and x is the argument set in setw manipulator. The header file that must be included while using setw manipulator is <iomanip.h>
43
void main( ) { int x1=12345,x2= 23456, x3=7892; cout << setw(8) << Exforsys << setw(20) << Values << endl << setw(8) << E1234567 << setw(20)<< x1 << end << setw(8) << S1234567 << setw(20)<< x2 << end << setw(8) << A1234567 << setw(20)<< x3 << end; } The output of the above example is: setw(8) setw(20) Exforsys Values E1234567 12345 S1234567 23456 A1234567 7892 setfill Manipulator: This is used after setw manipulator. If a value does not entirely fill a field, then the character specified in the setfill argument of the manipulator is used for filling the fields.
#include <iostream.h> #include <iomanip.h> void main( ) { cout << setw(10) << setfill('$') << 50 << 33 << endl; }
The output of the above program is $$$$$$$$5033 This is because the setw sets 10 width for the field and the number 50 has only 2 positions in it. So the remaining 8 positions are filled with $ symbol which is specified in the setfill argument.
44
#include <iostream.h> #include <iomanip.h> void main( ) { float x = 0.1; cout << fixed << setprecision(3) << x << endl; cout << sceintific << x << endl; }
The first cout statement contains fixed notation and the setprecision contains argument 3. This means that three digits after the decimal point and in fixed notation will output the first cout statement as 0.100. The second cout produces the output in scientific notation. The default value is used since no setprecision value is provided.
Pointers
A pointer is a variable that holds a memory address. It is called a pointer because it points to the value at the address that it stores. Using pointers If you want to declare a pointer variable you must first choose what data type it will point to such as an int or a char. You then declare it as if you were declaring a variable in the normal way and then Dept of CS , SJCET, Palai 45
You can store the address of another variable in a pointer using the & operator. Here is an example of how to store the address of variable called i in the pointer called pi.
int i; int *pi; pi = &i;
You must dereference a pointer to get the value at the memory location that the pointer points to. You use the * operator to dereference a pointer. Here is an example of how we first set the value of i to 5 and then set its value to 7 by dereferencing the pointer.
int i = 5; int *pi; pi = &i; *pi = 7; cout << i;
New And Delete The new operator is used to allocate memory that is the size of a certain data type. It returns a pointer to the address of the newly allocated memory. Here is an example of how to allocate memory for an integer and then set its value to 5.
int *pi; pi = new int; *pi = 5;
The delete operator deallocates memory. You need to deallocate the memory for all the memory that you have previously allocated before exiting the program or else you will have memory leaks.
int *pi; pi = new int; *pi = 5; delete pi;
Typed and untyped pointers We have been using typed pointers so far because they point to a specific data type. An untyped pointer can point to anything. You declare an untyped pointer as the data type void.
void *up;
46
Arrays
Concepts of Arrays in C++ In this C++ Tutorial you will learn about Concepts of Arrays in C++, What is an array?, How to access an array element, Declaration of Array and How to Access Array Elements. What is an array? An array is a group of elements of the same type that are placed in contiguous memory locations. How to access an array element? You can access an element of an array by adding an index to a unique identifier. For example Suppose Exforsys is an array that has 4 integer values in it that is of int data type, then Exforsys is internally represented as:
. Declaration of Array: Just like variables, We have to declare arrays before using them. The general syntax for declaring an array is
47
1 20
2 30
3 40
One interesting fact is that the size of the array element can also be left blank, in which case the array takes the size of the array as the number of elements initialized within { }. For example if the array takes the form as int Exforsys = {10,20,30,40,50};
Then the size of the array Exforsys is 5 which is the number of elements initialized within { }. Now the next step is to know how to access the array elements. Dept of CS , SJCET, Palai 48
#include <iostream.h> int Exforsys[ ] = { 10,20,30,40,50}; int i, outp=0; void main() { for(i=0;i<5;i++) { outp=outp+ Exfosys[i]; } cout<< outp; }
The output of the above program is: 150 What is a Multidimensional Array? A Multidimensional array is an array of arrays.
49
0 0 1 2
Highlighted cell represent Exforsys[1][2] Based on the above two-dimensional arrays, it is possible to handle multidimensional arrays of any number of rows and columns in C++ programming language. This is all occupied in memory. Better utilization of memory must also be made. Multidimensional Array Example:
#include <iostream.h> const int ROW=4; const int COLUMN =3; void main() { int i,j; int Exforsys[ROW][COLUMN]; for(i=0;i<ROWS;i++) Dept of CS , SJCET, Palai 50
The output of the above program is Enter value of Row 1, Column 1:10 Enter value of Row 1, Column 2:20 Enter value of Row 1, Column 3:30 Enter value of Row 2, Column 1:40 Enter value of Row 2, Column 2:50 Enter value of Row 2, Column 3:60 Enter value of Row 3, Column 1:70 Enter value of Row 3, Column 2:80 Enter value of Row 3, Column 3:90 Enter value of Row 4, Column 1:100 Enter value of Row 4, Column 2:110 Enter value of Row 4, Column 3:120
COLUMN 1 2 3 ROW 1 10 20 30 ROW 2 40 50 60 ROW 3 70 80 90 ROW 4 100 110 120 In the above example, the keyword const (specifying constant) precedes the data type that specifies the variable ROW and COLUMN to remain unchanged in value throughout the program. This is used for defining the array Exforsys ROW size and COLUMN size, respectively
51
In the above example, it is seen that variables of different types such as int and float are grouped in a single structure name Customer. Arrays behave in the same way, declaring structures does not mean that memory is allocated. Structure declaration gives a skeleton or template for the structure. After declaring the structure, the next step is to define a structure variable.
52
What happens when this is defined? When structure is defined, it allocates or reserves space in memory. The memory space allocated will be cumulative of all defined structure members. In the above example, there are 3 structure members: custnum, salary and commission. Of these, two are of type in and one is of type float. If integer space allocated by a system is 2 bytes and float four bytes the above would allo9acter 2bytes for custnum, 2 bytes for salary and 4 bytes for commission. How to access structure members in C++? To access structure members, the operator used is the dot operator denoted by (.). The dot operator for accessing structure members is used thusly: structure variable name.member name For example: A programmer wants to assign 2000 for the structure member salary in the above example of structure Customer with structure variable cust1 this is written as:
53
This means the character array has 30 storage location allocated where it can store up to a maximum of 30 characters. End String Notation The character array can store the specified maximum of array limit. This means it can store less than the allocated array limit up to the maximum. It is essential that a notation exist to mark the end of character array or string representation. This end of character array is denoted using backslash zero \0. The Differences Between Character Constants and String Literal: Initializing Char array Suppose the programmer wants to initialize the array char Exforsys[30] with value Training. This initialization of char array can be performed using two methods: Character representation String Literals The character representation is notated as follows: char Exforsys[30]= {T,r,a,i,n,i,n,g,\0}; The string literal representation is notated as follows: char Exforsys[30]= Training; Character representation uses single quotes to represent each character while string literal representation uses double quotes for the entire string literal. Another main difference with character representation is the end of character denoted by \0. String literal representation uses double quotes, there is no need for representing the end of character. The end of character task is automatically performed by C++ programming language. Dept of CS , SJCET, Palai 54
In the above case, the char array Exforsys is not mentioned with the size and is initialized with the string literal Company. The character array Exforsys takes the size of the initialized string literal. An Example: Input string defined as character array with the same output on the display screen:
#include <iostream.h> void main( ) { char Exforsys[80]; cout <<Input the String: ; cin >> Exforsys; cout <<The string entered is: << Exforsys }
The output of the above program is Input the String: Sample The string entered is: Sample Detailed example to understand the concept of character array and accessing of character array: The below example uses two input strings as two character arrays, accessing one character array character by character, then copies it into the other character array. #include <iostream.h> #include <string.h> void main( ) { char examp1[] = Exforsys; char examp2[80]; for(int i=0; i<strlen(exampl1);i++) examp2[i]=examp1[i]; examp2[i]=\0; cout<< The copied string is: << examp2; }
For example, if the programmer wants to represent a char array Exforsys with string literals as: Training Forums Program
56
57
There are mainly three implementations: Simula AS Lund Simula GNU Cim - Download available from the GNU ftp site In November 2001 Dahl and Nygaard were awarded the IEEE John von Neumann Medal by the Institute of Electrical and Electronic Engineers "For the introduction of the concepts underlying object-oriented programming through the design and implementation of SIMULA 67". In February 2002 they received the 2001 A. M. Turing Award by the Association for Computing Machinery (ACM), with the citation: "For ideas fundamental to the emergence of object oriented programming, through their design of the programming languages Simula I and Simula 67." Unfortunately neither Dept of CS , SJCET, Palai 58
Smalltalk
Smalltalk is an object-oriented, dynamically typed, reflective programming language. Smalltalk was created as the language to underpin the "new world" of computing exemplified by "human-computer symbiosis."[1] It was designed and created in part for educational use, more so for constructionist learning, at Xerox PARC by Alan Kay, Dan Ingalls, Adele Goldberg, Ted Kaehler, Scott Wallace, and others during the 1970s, influenced by Lisp, Logo, Sketchpad and Simula. The language was first generally released as Smalltalk-80 and has been widely used since. Smalltalk-like languages are in continuing active development, and have gathered loyal communities of users around them. ANSI Smalltalk was ratified in 1998 and represents the standard version of Smalltalk. Smalltalk has influenced the wider world of computer programming in four main areas. It inspired the syntax and semantics of other computer programming languages. Secondly, it was a prototype for a model of computation known as message passing. Thirdly, its WIMP GUI inspired the windowing environments of personal computers in the late twentieth and early twenty-first centuries, Dept of CS , SJCET, Palai 59
60
Need Of Objects:
Modeling the real world problem as close as possible to the users perspective. Interacting easily with computational environment using familiar metaphors Constructing reusable software components and easily extendable libraries. Easily modifying and extending implementations of components without having to recode every thing from scratch.
Definition of OOP:
OOP uses objects as its fundamental building blocks. Each object is an instance of some class. Classes allow the mechanism of data abstraction for creating new data types. Inheritance allows building of new classes from existing classes. Hence if any of these elements are missing in a program we cannot consider that program as objected oriented program. Object oriented programming is a programming methodology that associates data structures with a set of operators which act upon it. In OOPs terminology an instance of such an entity is known as an object. It gives importance to relationships between objects rather than implementation details. Hiding the implementation details within an object results in the user being more concerned with an objects relationship to the rest of the system, than the implementation of the objects behavior. Object oriented programming is an approach that provides a way f modularizing programs by creating partitioned memory area for both data and functions that can be used as template for creating copies of such modules on demand. Dept of CS , SJCET, Palai 61
62
There are different access specifiers for defining the data and functions present inside a class. Declaration and syntax In C++, a class is declared using the class keyword. The syntax of a classdeclaration is similar to that of a structure. Its general form is, class class-name { // private functions and variables public: // public functions and variables } object-list; In a class declaration the object-list is optional.The class-name is technically optional. From a practical point of view it is virtually always needed. The reason is that the class-name becomes a new type name that is used to declare objects of the class.Functions and variables declared inside the class declaration are said to bemembers of the class.By default, all member functions and variables are private to that class. This means that they are accessible by other members of that class. To declare public class members, the public keyword is used, followed by a colon. All functions and variables declared after the public specifier are accessible both by other members of the class and by any part of the program that contains the class.
Access specifiers: Access specifiers are used to identify access rights for the data and member functions of the class. There are three main types of access specifiers in C++ programming language: private public protected
63
A protected access specifier is a stage between private and public access. If member functions defined in a class are protected, they cannot be accessed from outside the class but can be accessed from the derived class. When defining access specifiers, the programmer must use the keywords: private, public or protected when needed, followed by a semicolon and then define the data and member functions under it.
class exforsys { private: int x,y; public: void sum() { } }; In the code above, the member x and y are defined as private access specifiers. The member function sum is defined as a public access specifier. General Template of a class: General structure for defining a class is: class classname { acess specifier: data member; member functions; acess specifier: data member; member functions; };
64
In this example, for members x and y of the class exforsys there are no access specifiers identified. exforsys would have the default access specifier as private.
The object can also be declared immediately after the class definition. In other words the object name can also be placed immediately before the closing flower brace symbol } of the class declaration. For example class exforsys { private: int x,y; public: void sum() { } }e1 ; The above code also declares an object e1 of class exforsys. It is important to understand that in object-oriented programming language, when a class is created no memory is allocated. It is only when an object is created is memory then allocated.
66
// member functions definition outside the class void myclass::set_a(int num) { a=num; } In general to declare a member function, you use this form: return-type class-name::func-name(parameter- list) { // body of function } Here the class-name is the name of the class to which the function belongs. The declaration of a class does not define any objects of the type myclass. It only defines the type of object that will be
67
class exforsys { int a, b; public: void sum(int,int); } e1; Then the member access is written as: e1.sum(5,6); Where e1 is the object of class exforsys and sum() is the member function of the class. The programmer now understands declaration of a class, creation of an object and accessibility of members of a class. It is also possible to declare more than one object within a class:
class exforsys { private: int a; public: void sum(int) { } }; main() Dept of CS , SJCET, Palai 69
class exforsys { int x; //Here access specifier is private by default }; whereas struct exforsys { int x; //Here access specifier is public by default }; It is not always the case that the member function declaration and definition takes place within the class itself. Sometimes, declaration of member function alone can occur within the class. The programmer may choose to place the definition outside the class. In a situation such as this, it is important to understand the identifying member function of a particular class. This is performed by using the operator :: this is called scope resolution operator. class exforsys { private: int a; public: void getvalues() };
void exforsys :: void getvalues() // Here Member Function is defined { Dept of CS , SJCET, Palai 70
// Program to illustrate Nested classes #include<iostream.h> class first { private: int a; int b; public: void assign(int p,int q) { a=p; b=q; } int multiply() { return a*b; } };
class second { private: int a ; int b; first fff; public: void assign1(int p,int q, int r,int s)
71
void main() { second obj; obj.assign1(3,2,5,6); int z=obj.multiply(); cout<<"\n The result is :"<<z; }
72
A constructor is a member function that is executed automatically whenever an object is created. There are two restrictions regarding it. First, the name of the constructor has to be name of the class. Second, it cannot have any return type, not even void. When such a constructor is present, it is automatically invoked when an object is declared. For example, class employee { public : employee ( ) ; employee ( long ) ; employee ( long, char * ) ; };
employee A ; // calls first constructor employee B ( 15362 ) ; // calls second constructor employee B ( 15362, "Naik" ) ; // calls third constructor
There are three constructors in the class employee. The first, which takes no arguments, is used to create objects which are not initialized. The second, which takes one argument, is used to create objects and initialize them. The third constructor, which takes two arguments, is also used to create objects and initialize them to specific values. C++ compiler has an implicit constructor ( default constructor ) which creates objects, even though it was not defined in the class. employee ( ) { } It contains the empty body and does not do anything. This works fine as long as we do not use any other constructors in the class. However, once we define a constructor, we must also define the default constructor. This constructor will not do anything and is defined just to satisfy the compiler. Dept of CS , SJCET, Palai 73
Constructors with Default Arguments It is possible to define constructors with default arguments. It means that if the constructor is defined with n parameters, we can invoke it with less than n parameters specified in the call. For example, Date ( int d, int m, y = 2007 ) ; This constructor has three parameters. Parameter number three is initialized with a value 2007. Now we can call the constructor in two possible ways. Date ( 15, 3, 2006 ) ; Date ( 15, 3 ) ; There are several forms in which a constructor can take its shape namely:
Default Constructor:
This constructor has no arguments in it. Default Constructor is also called as no argument constructor. For example:
class Exforsys { private: int a,b; public: Exforsys(); ... }; Exforsys :: Exforsys() { a=0; b=0; }
Parameterised constructors
74
Copy Constructor
A copy constructor is a constructor that executes when you initialize a new object of the class with an existing object of the same class. You don't need to create a constructor for this; one is already built into all classes. It's called default copy constructor. It's a one argument constructor whose argument is an object of the same class. For example, String s1 ( " hi " ) ; String s2 ( s1 ) ; String s3 = s1 ; The object s2 is initialized in the statement String s2 ( s1 ) ; This causes the default copy constructor for the String class to perform a member-bymember copy of s1 into s2. Surprisingly, a different format has exactly the same effect, causing s1 to be copied member-by-member into s3: Dept of CS , SJCET, Palai 75
76
Both the above formats can be sued to invoke a copy constructor. For Example:
#include <iostream.h> class Exforsys() { private: int a; public: Exforsys() {} Exforsys(int w) { a=w; } Exforsys(Exforsys& e) { a=e.a; cout<< Example of Copy Constructor; } void result() { cout<< a; } };
77
In the above the copy constructor takes one argument an object of type Exforsys which is passed by reference. The output of the above program is Example of Copy Constructor e3=50 Some important points about constructors: A constructor takes the same name as the class name. The programmer cannot declare a constructor as virtual or static, nor can the programmer declare a constructor as const, volatile, or const volatile. No return type is specified for a constructor. The constructor must be defined in the public. The constructor must be a public member. Overloading of constructors is possible. This will be explained in later sections of this tutorial.
Private Constructors
If a class constructor is private or protected, the object cannot be created in a scope where its constructor is not visible. In the following example, Distance :: Distance ( ) is declared private.
class Distance { friend class CC; // a friend class friend int Display ( ) ; // a friend function public : Distance ( float ) ; // . . . . private : Distance ( ) ; // . . . . }; class CC { public : void Compute ( ) { Distance d1 ; Dept of CS , SJCET, Palai
// ok 78
Within the program, only the Distance member functions, friend class CC and friend function Display ( ) may declare Distance objects that take no argument. There is no restriction on the declaration of Distance objects that take an argument of type float. Constructors in the Base and Derived Classes It is important to note that the constructors are not inherited in the inheritance process, unlike other methods that are inherited. This fact puts the burden on the programmer to provide a compulsorily special constructor in the derived class. When you declare an object of a derived class, the compiler executes the constructor function of the base class followed by the constructor function of the derived class.
The parameter list for the derived class's constructor function could be different from that of the base class's constructor function. Therefore, the constructor function for the derived class must tell the compiler what values to use as arguments to the constructor function for the base class.The derived class's constructor function specifies the arguments to the base class's constructor function.
D ( int a1, int a2, float b1, float b2, int d1 ) : A ( a1, a2 ), B ( b1, b2 ) { d = d1 ; }
The colon ( : ) operator after the derived constructor's parameter list specifies in this case that an argument list for a base class's constructor follows. The argument list is in parentheses and follows the name of the base class. Dept of CS , SJCET, Palai 79
Destructors
What is the use of Destructors Destructors are also special member functions used in C++ programming language. Destructors have the opposite function of a constructor. The main use of destructors is to release dynamic allocated memory. Destructors are used to free memory, release resources and to perform other clean up. Destructors are automatically named when an object is destroyed. Like constructors, destructors also take the same name as that of the class name. General Syntax of Destructors ~ classname(); The above is the general syntax of a destructor. In the above, the symbol tilda ~ represents a destructor which precedes the name of the class. Some important points about destructors: Destructors take the same name as the class name. Like the constructor, the destructor must also be defined in the public. The destructor must be a public member. The Destructor does not take any argument which means that destructors cannot be overloaded. No return type is specified for destructors. For example:
80
We can use arrays to hold the data of a class, but the size of these arrays will not be determined until run-time/object-instantiation-time. Below is an example of how to do it . class MyClass{ public: MyClass(int size){ myvararray = new double[size]; } private: double *myvararray;
}
Here the size of the array myvararray is determined when an object of MyClass is instantiated, using the argument of the constructer.
Arrays of objects
Array of objects is a linear sequence of objects in memoryie it is a collection of objects of the same class.The declaration syntax is as follows . Class *p = new Class[ sz ]; where *p is a pointer to the class and sz is the required size of the object array ie the maximum number of objects that should be included in the array.Here is an example. #include <iostream> class MyClass { int i; public: void setInt(int j) { i=j; Dept of CS , SJCET, Palai 81
82
MODULE 2
83
Inheritance
Inheritance is the process by which new classes called derived classes are created from existing classes called base classes. The derived classes have all the features of the base class and the programmer can choose to add new features specific to the newly created derived class. For example, a programmer can create a base class named fruit and define derived classes as mango, orange, banana, etc. Each of these derived classes, (mango, orange, banana, etc.) has all the features of the base class (fruit) with additional attributes or features specific to these newly created derived classes. Mango would have its own defined features, orange would have its own defined features, banana would have its own defined features, etc. This concept of Inheritance leads to the concept of polymorphism. Features or Advantages of Inheritance: Reusability: Inheritance helps the code to be reused in many situations. The base class is defined and once it is compiled, it need not be reworked. Using the concept of inheritance, the programmer can create as many derived classes from the base class as needed while adding specific features to each derived class as needed. Saves Time and Effort: The above concept of reusability achieved by inheritance saves the programmer time and effort. Since the main code written can be reused in various situations as needed. Increases Program Structure which results in greater reliability. Polymorphism General Format for implementing the concept of Inheritance: class derived_classname: access specifier baseclassname For example, if the base class is exforsys and the derived class is sample it is specified as:
84
If a member or variables defined in a class is private, then they are accessible by members of the same class only and cannot be accessed from outside the class. Public members and variables are accessible from outside the class.
Protected access specifier is a stage between private and public. If a member functions or variables defined in a class are protected, then they cannot be accessed from outside the class but can be accessed from the derived class. Inheritance Example: class exforsys { public: exforsys(void) { x=0; } void f(int n1) { x= n1*5; } void output(void) { cout<<x; } private: int x; }; class sample: public exforsys { public: sample(void) { s1=0; } void f1(int n1) { s1=n1*10; } void output(void) { exforsys::output(); cout << s1; Dept of CS , SJCET, Palai 85
The output of the above program is 50 200 In the above example, the derived class is sample and the base class is exforsys. The derived class defined above has access to all public and private variables. Derived classes cannot have access to base class constructors and destructors. The derived class would be able to add new member functions, or variables, or new constructors or new destructors. In the above example, the derived class sample has new member function f1( ) added in it. The line:
sample s; creates a derived class object named as s. When this is created, space is allocated for the data members inherited from the base class exforsys and space is additionally allocated for the data members defined in the derived class sample. The base class constructor exforsys is used to initialize the base class data members and the derived class constructor sample is used to initialize the data members defined in derived class. The access specifier specified in the line:
86
CRectangle
CTriangle
The class CPolygon would contain members that are common for both types of polygon. In our case: width and height. And CRectangle and CTriangle would be its derived classes, with specific features that are different from one type of polygon to the other. Classes that are derived from others inherit all the accessible members of the base class. That means that if a base class includes a member A and we derive it to another class with another member called B, the derived class will contain both members A and B. In order to derive a class from another, we use a colon (:) in the declaration of the derived class using the following format: class derived_class_name: public base_class_name { /*...*/ }; Where derived_class_name is the name of the derived class and base_class_name is the name of the class on which it is based. The public access specifier may be replaced by any one of the other access specifiers protected and private. This access specifier describes the minimum access level for the members that are inherited from the base class.
87
Member access control in classes We can use the following chart for seeing the accessibilities of the members in the Base class (first class) and derived class (second class).
Here X indicates that the members are not inherited, i.e. they are not accessible in the derived class.
Some important points to note while using friend functions in C++: The keyword friend is placed only in the function declaration of the friend function and not in the function definition. . It is possible to declare a function as friend in any number of classes. . When a class is declared as a friend, the friend class has access to the private data of the class that made this a friend. . A friend function, even though it is not a member function, would have the rights to access the private members of the class. . It is possible to declare the friend function as either private or public. . The function can be invoked without the use of an object. The friend function has its argument as objects, seen in example below. Example to understand the friend function:
#include<iostream.h> class exforsys { private: int a,b; public: void test() { a=100; b=200; } friend int compute(exforsys e1) //Friend Function Declaration with keyword friend and with the object of class exforsys to which it is friend passed to it };
int compute(exforsys e1) { //Friend Function Definition which has access to private data return int(e1.a+e2.b)-5; Dept of CS , SJCET, Palai 89
The output of the above program is The result is:295 The function compute() is a non-member function of the class exforsys. In order to make this function have access to the private data a and b of class exforsys , it is created as a friend function for the class exforsys. As a first step, the function compute() is declared as friend in the class exforsys as: friend int compute (exforsys e1)
Friend Class
A friend class is a class all of whose member functions are friend functions of a class, that is, whose member functions have access to the other class's private and protected members. Suppose the friend declaration in class B had been:
Copy Code friend class A; In that case, all member functions in class A would have been granted friend access to class B. The following code is an example of a friend class:
Copy Code // classes_as_friends2.cpp // compile with: /EHsc #include <iostream> using namespace std; class YourClass { friend class YourOtherClass; // Declare a friend class public: Dept of CS , SJCET, Palai 90
91
Extending Classes
Eg: #include <iostream> using namespace std; class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b;} }; class CRectangle: public CPolygon { public: int area () { return (width * height); } }; class CTriangle: public CPolygon { public: int area () { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; rect.set_values (4,5); trgl.set_values (4,5); cout << rect.area() << endl; cout << trgl.area() << endl; return 0; } Output : 20 10 The objects of the classes CRectangle and CTriangle each contain members inherited from CPolygon. These are: width, height and set_values().
92
members of the same class yes members of derived classes yes not members yes
Where "not members" represent any access from outside the class, such as from main(), from another class or from a function. In our example, the members inherited by CRectangle and CTriangle have the same access permissions as they had in their base class CPolygon: CPolygon::width CRectangle::width CPolygon::set_values() CRectangle::set_values() // protected access // protected access // public access // public access
This is because we have used the public keyword to define the inheritance relationship on each of the derived classes: Class CRectangle: public CPolygon { ... } This public keyword after the colon (:) denotes the minimum access level for all the members inherited from the class that follows it (in this case CPolygon). Since public is the most accessible level, by specifying this keyword the derived class will inherit all the members with the same levels they had in the base class. If we specify a more restrictive access level like protected, all public members of the base class are inherited as protected in the derived class. Whereas if we specify the most restricting of all access levels: private, all the base class members are inherited as private. For example, if daughter was a class derived from mother that we defined as: class daughter: protected mother;
93
#include<iostream.h> class base { public: base() { cout<<"\n Base class constructor"; } ~base() { cout<<"\n Base class destructor"; } };
class derived : public base { public: derived() { cout<<"\n Derived class constructor"; } ~derived() {
94
Test data Base class constructor Derived class constructor Derived class destructor Base class destructor
Public ,Private and Protected Inheritance Inheritance is probably the most powerful feature of object oriented programming. Inheritance is the technique that is used to build new classes from existing ones. In inheritance, you derive a new class from an existing class. The class from which you derive is called the base class, and the new class is called the derived class.
Public Derivation In a public derivation, the derived class inherits public members as public, and protected members as protected. They can be accessed by a new member function of the derived class. However, instances of the derived classes may access only the public members. Protected Derivation In a protected derivation, the derived class inherits public and protected members as protected. They can be accessed by a new member function of the derived class. However, instances of the derived classes may access only the public members. Private Derivation In a private derivation, the derived class inherits public and protected members as private. They can be accessed by a new member function of the derived class. However, instances of the derived classes may not access them. Also, public and protected members of the base class are not available for subsequent derivations. Regardless of the type of derivation, private members ( of base class ) are not accessible in Dept of CS , SJCET, Palai 95
Classification of Inheritance
1.Single inheritance : one base class one derived class 2.Multilevel inheritance : deriving from another derived class 3. Hierarchical inheritance : one base, many derived classes 4.Multiple inheritance : more than one base class 5.Hybrid inheritance : combination of all the types
96
Single Inheritance
For example: #include <iostream> class mother { public: mother () { cout << "mother: no parameters\n"; } mother (int a) { cout << "mother: int parameter\n"; } }; class daughter : public mother { public: daughter (int a) { cout << "daughter: int parameter\n\n"; } }; class son : public mother { public: son (int a) : mother (a) Dept of CS , SJCET, Palai 97
Multiple Inheritance
Multiple inheritance is achieved whenever more than one class acts as base classes for other classes. This makes the members of the base classes accessible in the derived class, resulting in better integration and broader reusability. For example: #include <iostream> using namespace std; class Cpolygon { protected: int width, height; public: void input_values (int one, int two) { width=one; height=two; } }; class Cprint { public: void printing (int output); }; void Cprint::printing (int output) Dept of CS , SJCET, Palai 98
99
100
************ RESULT ************** The Name Of Student : Lionel The Roll No. Is : 44 Marks In CP Is : 95 Marks In Drawing Is : 90 Total Of The Two : 185
102
Hierarchical Inheritance
When from one base class more than one classes are derived that is called hierarchical inheritance.With the help of hierarchical inheritance we can distribute the property of one class into many classes. Example: #include<iostream.h> #include<conio.h> Class B { Protected: int x,int y; public: void assign() { X=10;y=20; } Class D1:public B { int s; public: void add() { s=x+y; cout<<x+y=<<s<<endl; } }; Class D2:public B { int t; public: void sub() { t=x-y; cout<<x-y=<<t<<endl; } }; Class D3:public B { int m; public: void mul() { m=x*y; Dept of CS , SJCET, Palai 103
Hybrid Inheritance
If we apply more than one type of inheritance to design a problem then that is known as hybrid inheritance. Example: #include<iostream> using namespace std; class student { protected: int roll_number; public: void getnumber(int a) { roll_number=a; } void putnumber() { cout<<Roll No:<<roll_number<<\n; Dept of CS , SJCET, Palai 104
Constructors in the Base and Derived Classes It is important to note that the constructors are not inherited in the inheritance process, unlike other methods that are inherited. This fact puts the burden on the programmer to provide a compulsorily special constructor in the derived class. When you declare an object of a derived class, the compiler executes the constructor function of the base class followed by the constructor function of the derived class.
The parameter list for the derived class's constructor function could be different from that of the base class's constructor function. Therefore, the constructor function for the derived class must tell the compiler what values to use as arguments to the constructor function for the base class.The derived class's constructor function specifies the arguments to the base class's constructor function.
D ( int a1, int a2, float b1, float b2, int d1 ) : A ( a1, a2 ), B ( b1, b2 ) { d = d1 ; }
The colon ( : ) operator after the derived constructor's parameter list specifies in this case that an argument list for a base class's constructor follows. The argument list is in parentheses and follows the name of the base class. Dept of CS , SJCET, Palai 106
107
MODULE 3
108
Polymorphism
Introduction Polymorphism is the ability to use an operator or function in different ways. Polymorphism gives different meanings for operators or functions. Poly, referring to many, signifies the many uses of these operators and functions. A single function usage or an operator functioning in many ways can be called polymorphism. Polymorphism refers to codes, operations or objects that behave differently in different contexts. Below is a simple example of the above concept of polymorphism:
6 + 10 The above refers to integer addition. The same + operator can be used with different meanings with strings:
"Exforsys" + "Training" The same + operator can also be used for floating point addition:
7.15 + 3.78
Polymorphism is a powerful feature of the object oriented programming language C++. A single operator + behaves differently in different contexts such as integer, float or strings referring the concept of polymorphism. The above concept leads to operator overloading. The concept of overloading is also a branch of polymorphism. When the exiting operator or function operates on new data type it is overloaded. This feature of polymorphism leads to the concept of virtual methods. Polymorphism refers to the ability to call different functions by using only one type of function call. Suppose a programmer wants to code vehicles of different shapes such as circles, squares, rectangles, etc. One way to define each of these classes is to have a member function for each that makes vehicles of each shape. Another convenient approach the programmer can take is to define a base class named Shape and then create an instance of that class. The programmer can have array that hold pointers to all different objects of the vehicle followed by a simple loop structure to make the vehicle, as per the shape desired, by inserting pointers into the defined array. This approach leads to different functions executed by the same function call. Polymorphism is used to give different meanings to the same concept. This is the basis for Virtual function implementation. Dept of CS , SJCET, Palai 109
Types of Polymorphism:
C++ provides three different types of polymorphism. Virtual functions Function name overloading Operator overloading
110
Function overloading
Operator Overloading
Virtual Function
In addition to the above three types of polymorphism, there exist other kinds of polymorphism: run-time compile-time ad-hoc polymorphism parametric polymorphism Other types of polymorphism defined: Run-time: The run-time polymorphism is implemented with inheritance and virtual functions. It is also known as late binding or dynamic binding. Late binding refers function calls that are not resolved until run time. Virtual functions are used to achieve late binding. Objects and functions are not linked until run time. The main advantage to late binding is flexibility.
Compile-time: The compile-time polymorphism is implemented with templates. It is also known as early binding or static binding or static linking. Function overloading and operator overloading are compile time polymorphism. It occurs at compile time. All information needed to call a function is known at compile time. Efficiency and fastness is its main advantage. Ad-hoc polymorphism: If the range of actual types that can be used is finite and the combinations must be individually specified prior to use, this is called ad-hoc polymorphism.
111
Function Overloading
Function overloading means that we can use the same function name to create functions that perform a variety of different tasks by changing the number or type of parameters but not on the return type. This is known as function polymorphism. A function call first matches the prototype having the same number and type of arguments and then calls the appropriate function for execution. A best match must be unique. The function selection involves the following steps. 1.The compiler first tries to find an exact match in which the types of actual arguments are same, and use that function. 2.If an exact match is not found, the compiler uses the integral promotiopns to the act actul srgument, such as Dept of CS , SJCET, Palai 112
113
Test data Enter 1 to find maximum number among floats Enter 2 to find maximum number among integers 2 Enter 3 integer values 10 6 13
Operator Overloading
Operator overloading is a very important feature of Object Oriented Programming. It is because by using this facility programmer would be able to create new definitions to existing operators. In fact in other words a single operator can take up several functions as desired by programmers depending on the argument taken by the operator by using the operator overloading facility.
114
Broadly classifying operators are of two types namely: Unary Operators Binary Operators Unary Operators: As the name implies takes operate on only one operand. Some unary operators are namely ++ called as Increment operator, -- called as Decrement Operator, ! , ~, unary minus. Binary Operators: The arithmetic operators, comparison operators, and arithmetic assignment operators all this which we have seen in previous section of operators come under this category. Both the above classification of operators can be overloaded.
Inside the class Exforsys the data type that is returned by the overloaded operator is defined as class Exforsys { private: . public: Dept of CS , SJCET, Palai 116
//Constructor
void Exforsys :: display() { cout<<\nValue of x is: << x; } void Exforsys :: operator ++( ) //Operator Overloading for operator ++ defined { ++x; } void main( ) { Exforsys e1,e2; //Object e1 and e2 created cout<<Before Increment cout <<\nObject e1: <<e1.display(); cout <<\nObject e2: <<e2.display(); ++e1; //Operator overloading applied ++e2; Dept of CS , SJCET, Palai 117
The output of the above program is: Before Increment Object e1: Value of x is: 0 Object e1: Value of x is: 0 Before Increment Object e1: Value of x is: 1 Object e1: Value of x is: 1 In the above example we have created 2 objects e1 and e2 f class Exforsys. The operator ++ is overloaded and the function is defined outside the class Exforsys. When the program starts the constructor Exforsys of the class Exforsys initialize the values as zero and so when the values are displayed for the objects e1 and e2 it is displayed as zero. When the object ++e1 and ++e2 is called the operator overloading function gets applied and thus value of x gets incremented for each object separately. So now when the values are displayed for objects e1 and e2 it is incremented once each and gets printed as one for each object e1 and e2. This is how unary operators get overloaded Operator overloading is one of the most exciting features of object oriented programming. It is an important technique that has enhanced the power of extensibility of C++. For Example, a3 . add ( a1, a2 ) ; or a3 = a1 . add ( a2 ) ;
118
119
It should return a reference to a string object to allow the function cascading, such as
Operator functions must be either member functions ( non static ) or friend functions. A basic difference between them is that a friend function will have only one argument for unary operators and two for binary operators, while a member function has no arguments for unary operators and only one for binary operators. This is because the object used to invoke the member function is passed implicitly and therefore is available for the member function. This is not the case with friend functions.
Let us consider the unary minus operator. A minus operator, when used as a unary, takes just one operand. We will see here how to overload this operator so that it can be applied to an object in much the same way as is applied to an int or float variable. The unary minus when applied to an object should change the sign of each of its data items. For Example, class X { int a ; int b ; public : void get ( int m, int n ) ; void display ( void ) ; void operator - ( ) ; // overloaded unary minus }; void X : : get ( int m, int n ) { a=m; Dept of CS , SJCET, Palai 120
This program produces the output -10 -20. Note that the function operator - ( ) takes no argument. It changes the sign of data members of the object x. Since this function is a member function of the same class, it can directly access the members of the object which activated it.
121
#include <iostream.h> class Exforsys { private: int x; int y; public: Exforsys() { x=0; y=0; }
//Constructor
void getvalue( ) //Member Function for Inputting Values { cout << \n Enter value for x: ; cin >> x; cout << \n Enter value for y: ; cin>> y; } void displayvalue( ) //Member Function for Outputting Values { cout <<value of x is: << x <<; value of y is: <<y } Exforsys operator +(Exforsys); }; Exforsys Exforsys :: operator + (Exforsys e2) //Binary operator overloading for + operator defined { int x1 = x+ e2.x; int y1 = y+e2.y; return Exforsys(x1,y1); } void main( ) { Exforsys e1,e2,e3; //Objects e1, e2, e3 created cout<<\nEnter value for Object e1:; e1.getvalue( ); Dept of CS , SJCET, Palai 122
The output of the above program is: Enter value for Object e1: Enter value for x: 10 Enter value for y: 20 Enter value for Object e2: Enter value for x: 30 Enter value for y: 40 Value of e1 is: value of x is: 10; value of y is: 20 Value of e2 is: value of x is: 30; value of y is: 40 Value of e3 is: value of x is: 40; value of y is: 60
In the above example, the class Exforsys has created three objects e1, e2, e3. The values are entered for objects e1 and e2. The binary operator overloading for the operator + is declared as a member function inside the class Exforsys. The definition is performed outside the class Exforsys by using the scope resolution operator and the keyword operator. The important aspect is the statement: e3= e1 + e2; The binary overloaded operator + is used. In this statement, the argument on the left side of the operator +, e1, is the object of the class Exforsys in which the binary overloaded operator + is a member function. The right side of the operator + is e2. This is passed as an argument to the operator + . Since the object e2 is passed as argument to the operator+ inside the function defined for binary operator overloading, the values are accessed as e2.x and e2.y. This is added with e1.x and e1.y, which are accessed directly as x and y. The return value is of type class Exforsys as defined by the above example.
Let us implement binary operator overloading taking matrix operation as example. Here we are overloading an operator which has two operands, also known as binary operator. All operations are carried out just like arithmetic operations involving basic types. Dept of CS , SJCET, Palai 123
matrix::matrix(int r,int c) { rows=r; cols=c; } void matrix::input() { for(int i=0;i<rows;i++) for(int j=0;j<cols;j++) cin>>element[i][j]; } void matrix:: display() { for(int i=0;i<rows;i++) { for(int j=0;j<cols;j++) cout<<element[i][j]<<"\t"; cout<<endl; } } matrix matrix::operator + (matrix m) {
124
3 4 5 6 output 4 6 8 10
Selecting friend member function for operator overloading Overloading Unary Operators ( Friend functions )
It is possible to overload a unary minus operator using a friend function. friend void operator - ( X & obj ) ; void operator - ( X & obj ) { obj . a = - obj . a ; obj . b = - obj . b ; } // declaration
Note that the argument is passed by reference. It will not work if we pass argument by value because only a copy of the object that activated the call is passed to operator - ( ) . Therefore, the changes made inside the operator function will not reflect in the called Dept of CS , SJCET, Palai 125
#include<iostream.h> class sample { private: int value1,value2; public: sample(int x,int y); void operator ++ (); void display(); }; sample::sample(int x,int y) { value1=x; value2=y; } void sample::operator ++ () { ++value1; ++value2; } void sample:: display() { cout<<"\n Value1 = "<<value1; cout<<"\n Value2 = "<<value2; } void main() { sample obj(10,15); cout<<"\n Before overloading "; obj.display(); ++obj; cout<<"\n After overloading "; obj.display(); }
126
// declaration
matrix operator + ( matrix a, matrix b ) { matrix temp ( rows, cols ) ; for ( int i = 0 ; i < rows ; i++ ) for ( int j = 0 ; j < cols ; j++ ) temp . element [i] [j] = a . element [i] [j] + b . element [i] [j] ; return temp ; } We have three distinct ways ( styles ) of overloading. 1 ) Object + Object For Example, Complex operator + ( Complex b ) ; It will imply that you are adding two objects of class Complex and the result is also of class Complex. C = A + B ; // A object invokes operator + ( ) function 2 ) Object + basic data type ( say int ) For Example, class A operator + ( int m ) ; This poses no problem.
127
128
Overloading input ,output operators Overloading Output Operator/insertion operator(<<) It is quite simple to create an overload insertion operator(inserter)for a class.All inserter function have the general form : It must be a friend function. ostream& operator<<(ostream &stream,class_type obj) { //body of inserter return stream; } ostream means output stream Overloading Input Operator/extraction operator(>>)
129
The functionality of virtual functions can be over-ridden in its derived classes. The programmer must pay attention not to confuse this concept with function overloading. Function overloading is a different concept and will be explained in later sections of this tutorial. Virtual function is a mechanism to implement the concept of polymorphism (the ability to give different meanings to one function). Need for Virtual Function: The vital reason for having a virtual function is to implement a different functionality in the derived class. For example: a Make function in a class Vehicle may have to make a Vehicle with red colour. A class called FourWheeler, derived or inherited from Vehicle, may have to use a blue background and 4 tires as wheels. For this scenario, the Make function for FourWheeler should now have a different functionality from the one at the class called Vehicle. This concept is called Virtual Function. Properties of Virtual Functions: Dynamic Binding Property: Virtual Functions are resolved during run-time or dynamic binding. Virtual functions are also simple member functions. The main difference between a non-virtual C++ member function and a virtual member function is in the way they are both resolved. A non-virtual C++ member function is resolved during compile time or static binding. Virtual Functions are resolved during run-time or dynamic binding Virtual functions are member functions of a class. Virtual functions are declared with the keyword virtual, detailed in an example below. Virtual function takes a different functionality in the derived class. Declaration of Virtual Function: Virtual functions are member functions declared with the keyword virtual. For example, the general syntax to declare a Virtual Function uses: Dept of CS , SJCET, Palai 131
Referring back to the Vehicle example, the declaration of Virtual function would take the shape below:
class Vehicle //This denotes the base class of C++ virtual function { public: virtual void Make() //This denotes the C++ virtual function { cout <<"Member function of Base Class Vehicle Accessed"<<endl; } };
After the virtual function is declared, the derived class is defined. In this derived class, the new definition of the virtual function takes place. When the class FourWheeler is derived or inherited from Vehicle and defined by the virtual function in the class FourWheeler, it is written as:
class Vehicle //This denotes the base class of C++ virtual function { public: virtual void Make() //This denotes the C++ virtual function { cout <<"Member function of Base Class Vehicle Accessed"<<endl; Dept of CS , SJCET, Palai 132
class FourWheeler : public Vehicle { public: void Make() { cout<<"Virtual Member function of Derived class FourWheeler Accessed"<<endl; } };
void main() { Vehicle *a, *b; a = new Vehicle(); a->Make(); b = new FourWheeler(); b->Make(); } In the above example, it is evidenced that after declaring the member functions Make() as virtual inside the base class Vehicle, class FourWheeler is derived from the base class Vehicle. In this derived class, the new implementation for virtual function Make() is placed.
The programmer might be surprised to see the function call differs and the output is then printed as above. If the member function has not been declared as virtual, the base class member function is always called because linking takes place during compile time and is therefore static. In this example, the member function is declared virtual and the address is bounded only during run time, making it dynamic binding and thus the derived class member function is called. To achieve the concept of dynamic binding in C++, the compiler creates a v-table each time a virtual function is declared. This v-table contains classes and pointers to the functions from each of the objects of the derived class. This is used by the compiler whenever a virtual function is needed. The Literal Meaning of Virtual means to appear like something while in reality it is something else ie. when virtual functions are used, a program appears to call a function of one class but actually it may be calling a function from another class. In the previous example draw() is a virtual function since it Dept of CS , SJCET, Palai 133
class d2:public base // Derived Class 2 { public: void func() { cout<<"In d2::func()\n"; } }; int main() { d1 d; base *b=&d; Dept of CS , SJCET, Palai 134
Run this program and you would see that the output would be: In base::func() In base::func() Shouldn't this statement give an error? (b=&e;) No. Since the compiler allows a pointer of a base class to accept addresses of derived class objects. This is known as UPCASTING. Here the Compiler looks at the type of pointer b and since it belongs to the base class it calls the base class function. But now, let's make a slight modification in our program. Precede the declaration of func() in the base class with the keyword virtual so that it looks like this: virtual void func() { cout<<"In base::func()\n"; } Now Compile and Run the Program. Now the Output is: In d1::func() In d2::func() This time the Compiler looks at the contents of the pointer instead of it's type. Hence since addresses of objects of d1 and d2 classes are stored in *b the respective func() is called. But this way how does the compiler know which function to compile when it doesn't know which object's address 'b' might contain? Which version does the compiler call? Actually even the compiler does not know which function to call at compile-time. Hence it decides which function to call at run-time with the help of a table called VTABLE. Using this table the compiler finds what object is pointed by the pointer b and then calls the appropriate function. VTABLE is explained later. The method by which the compiler decides which function to call at run-time is known as late-binding or dynamic-binding. It slows down the program but makes it a lot more flexible.
// Program to illustrate virtual functions
136
class classname //This denotes the base class of C++ virtual function { public: virtual void virtualfunctioname() = 0 //This denotes the pure virtual function in C++ };
The other concept of pure virtual function remains the same as described in the previous section of virtual function. To understand the declaration and usage of Pure Virtual Function, refer to this example:
class Exforsys { public: virtual void example()=0; //Denotes pure virtual Function Definition }; class Exf1:public Exforsys { public: void example() { cout<<"Welcome"; } }; class Exf2:public Exforsys { public: void example() Dept of CS , SJCET, Palai 137
Since the above example has no body, the pure virtual function example() is declared with notation =0 in the base class Exforsys. The two derived class named Exf1 and Exf2 are derived from the base class Exforsys. The pure virtual function example() takes up new definition. In the main function, a list of pointers is defined to the base class. Two objects named e1 and e2 are defined for derived classes Exf1 and Exf2. The address of the objects e1 and e2 are stored in the array pointers which are then used for accessing the pure virtual function example() belonging to both the derived class EXf1 and EXf2 and thus, the output is as in the above example. The programmer must clearly understand the concept of pure virtual functions having no body in the base class and the notation =0 is independent of value assignment. The notation =0 simply indicates the Virtual function is a pure virtual function as it has no body.
Some programmers might want to remove this pure virtual function from the base class as it has no body but this would result in an error. Without the declaration of the pure virtual function in the base class, accessing statements of the pure virtual function such as, arra[0]->example() and arra[1]>example() would result in an error. The pointers should point to the base class Exforsys. Special care must be taken not to remove the statement of declaration of the pure virtual function in the base class.
The equal sign here has nothing to do with assignment; the value 0 is not assigned to anything. The =0 syntax is simply how we tell the compiler that a function will be pure virtual function.
A pure virtual function is a function declared in a base class that has no definition relative to the base class. In such cases, the compiler requires each derived class to either define the function or redeclare it as a pure virtual function. Remember that a class containing pure virtual functions cannot be used to declare any objects of its own. Such classes are called abstract base classes. The main objective of an abstract base class is to provide some traits to the derived classes and to create a base pointer required for achieving runtime polymorphism. .
class derived1:public base { public: void show() { cout<<"\nFrom derived1 class"; cout<<endl; } };
void main() { base *ptr; derived1 d1; derived2 d2; clrscr(); ptr=&d1; ptr->show(); ptr=&d2; ptr->show(); }
First the VPTR Pointer is initialised to it's proper VTABLE by the constructor which is automatically done by the compiler. When a Virtual Function is being called the VPTR looks up the VTABLE and calls the virtual function. If the function is not present in the VTABLE [like here display()] then the function of the base class is called. So everywhere where the display function is called item::display() is called everytime. No matter how many objects of a class are created they all point to the same VTABLE of the class.
//Fahrenheit to Celsius class f_to_c:public convert { public: f_to_c(double i):convert(i){} void compute() { val2=(val1-32)/1.8; } }; Int main() { Convert *p; L_to_g lgob(4); F_to_c fcob(70); //use virtual function mechanism P=&lgob; Cout<<p->getinit()<<liters is; p->compute(); cout<<p->getconv()<<gallons\n; p=&fcob; Cout<<p->getinit()<<Fahrenheit is; Dept of CS , SJCET, Palai 144
145
MODULE 4
146
Virtual destructor
If the destructors are not virtual, then just the destructor corresponding to the pointer type is called. If the destructors are virtual , the destructor corresponding to the object type is called. Using virtual destructors ensures that the correct sequence of destructors is called. If you destroy an object through a pointer or reference to a base class, and the base-class destructor is not virtual, the derived-class destructors are not executed, and the destruction might not be complete. Destructors are declared as virtual because if do not declare it as virtual the base class destructor will be called before the derived class destructor and that will lead to memory leak because derived class objects will not get freed. Destructors are declared virtual so as to bind objects to the methods at runtime so that appropriate destructor is called. #include <iostream.h> class Base { public: Base(){ cout<<"Constructor: Base"<<endl;} ~Base(){ cout<<"Destructor : Base"<<endl;} }; class Derived: public Base { public: Derived(){ cout<<"Constructor: Derived"<<endl;} ~Derived(){ cout<<"Destructor : Derived"<<endl;} > }; void main() { Base *Var = new Derived(); delete Var; } Try executing this code, the constructors are getting called in the proper order. But to the dread of a programmer of a large project, the destructor of the derived class was not called at all. This is where the virtual mechanism comes into our rescue. By making the Base class Destructor virtual, both the destructors will be called in order. The following is the corrected sample. #include <iostream.h> class Base Dept of CS , SJCET, Palai 147
//Interface.h file class Interface { public: virtual ~Interface() = 0; //pure virtual destructor declaration };
Somewhere outside the class declaration, the pure virtual destructor has to be defined like this:
//Interface.cpp file Interface::~Interface() {} //definition of a pure virtual destructor; should always be empty
148
Virtual constructor: Constructors cannot be virtual. Declaring a constructor as a virtual function is a syntax error Virtual destructors are used in situations like: 1) A virtual destructor is used when one class needs to delete object of a derived class that are addressed by the base pointers and invoke a base class destructor to release resources allocated to it. 2) Destructor of a base class should be declared as virtual functions. It ensures that the memory is released effectively.
In the above example, there are two derived classes Exf1 and Exf2 from the base class Exforsys. As shown in the above diagram, the Training class is derived from both of the derived classes Exf1 and Exf2. In this scenario, if a user has a member function in the class Training where the user wants to access the data or member functions of the class Exforsys it would result in error if it is performed like this:
class Exforsys { protected: int x; }; class Exf1:public Exforsys { }; class Exf2:public Exforsys { }; class Training:public Exf1,public Exf2 { Dept of CS , SJCET, Palai 149
The above program results in a compile time error as the member function example() of class Training tries to access member data x of class Exforsys. This results in an error because the derived classes Exf1 and Exf2 (derived from base class Exforsys) create copies of Exforsys called subobjects. This means that each of the subobjects have Exforsys member data and member functions and each have one copy of member data x. When the member function of the class Training tries to access member data x, confusion arises as to which of the two copies it must access since it derived from both derived classes, resulting in a compile time error. When this occurs, Virtual base class is used. Both of the derived classes Exf1 and Exf2 are created as virtual base classes, meaning they should share a common subobject in their base class. For Example:
class Exf1:virtual public Exforsys { }; class Exf2:virtual public Exforsys { }; class Training:public Exf1,public Exf2 { public: int example() { return x; } };
150
152
class Grandchild : public Child1, public Child2 { public : int readdata ( ) { return data ; } };
A compiler error occurs when the readdata ( ) member function in Grandchild attempts to access data in Parent. When the Child1 and Child2 classes are derived from Parent, each inherits a copy of Parent. Each of the two child-classes contains its own copy of Parent's data. Now, when Grandchild refers to data, which of the two copies will it access? This situation is ambiguous, and that's what the compiler reports. To eliminate the ambiguity, we make Child1 and Child2 into virtual base classes. class Parent { protected : int data ; };
};
};
class Grandchild : public Child1, public Child2 { public : Dept of CS , SJCET, Palai 153
Templates
Many C++ programs use common data structures like stacks, queues and lists. Re-inventing source code is not an intelligent approach in an object oriented environment which encourages re-usability. It seems to make more sense to implement a queue that can contain any arbitrary type rather than duplicating code. The solution is to use type parameterization, more commonly referred to as templates. C++ templates allow one to implement a generic Queue<T> template that has a type parameter T. T can be replaced with actual types, for example, Queue<Customers>, and C++ will generate the class Queue<Customers>. Changing the implementation of the Queue becomes relatively simple. Once the changes are implemented in the template Queue<T>, they are immediately reflected in the classes Queue<Customers>, Queue<Messages>, and Queue<Orders>. Templates are very useful when implementing generic constructs like vectors, stacks, lists, queues which can be used with any arbitrary type. C++ templates provide a way to re-use source code as opposed to inheritance and composition which provide a way to re-use object code. C++ provides two kinds of templates: class templates and function templates. Use function templates to write generic functions that can be used with arbitrary types. For example, one can write searching and sorting routines which can be used with any arbitrary type. The Standard Template Library generic algorithms have been implemented as function templates, and the containers have been implemented as class templates.
Function Templates To perform identical operations for each type of data compactly and conveniently, use function templates. You can write a single function template definition. Based on the argument types provided in calls to the function, the compiler automatically instantiates separate object code functions to handle each type of call appropriately. The STL algorithms are implemented as function templates.
154
Function templates are implemented like regular functions, except they are prefixed with the keyword template. Here is a sample with a function template. #include <iostream> using namespace std ; //max returns the maximum of the two elements template <class T> T max(T a, T b) { return a > b ? a : b ; }
Using Template Functions
Using function templates is very easy: just use them like regular functions. When the compiler sees an instantiation of the function template, for example: the call max(10, 15) in function main, the compiler generates a function max(int, int). Similarly the compiler generates definitions for max(char, char) and max(float, float) in this case. #include <iostream> using namespace std ; //max returns the maximum of the two elements template <class T> T max(T a, T b) { return a > b ? a : b ; } void main() { cout << "max(10, 15) = " << max(10, 15) << endl ; cout << "max('k', 's') = " << max('k', 's') << endl ; cout << "max(10.1, 15.2) = " << max(10.1, 15.2) << endl ; } Output max(10, 15) = 15 max('k', 's') = s max(10.1, 15.2) = 15.2
Template Instantiation
When the compiler generates a class, function or static data members from a template, it is referred to as template instantiation. A class generated from a class template is called a generated class. A function generated from a function template is called a generated function. Dept of CS , SJCET, Palai 155
A generic function defines a general set of operations that will be applied to various types of data. The type of data that the function will operate up on is passed to it as a parameter.Through generic function, a single general procedure (same algorithm) can be applied to a wide range of data. By using generic function , define the nature of the algorithm independent of data. Eg:Bubble sort for array of integers and floats.Here procedure is same , only data is different.So create a generic function which will work for all types of data. The generic function is created by using the keyword template General Form Template<class T> return-type function-name(arglist) { //body of function } T is a placeholder for a datatype used by the function. It will automatically replace with an actual data type when it creates a specific version of the function.When the compiler creates a specific version of the function, it is said to have created a specialization.This is called generated function and this act of generating a function is referred to as instatiating it. Placeholder T is used within the function definition where need a general data type. Eg1: Write a generic function for the following Int sum(int a, int b) { Return(a+b); } Generic Function is 1st Method : Template<class T> T sum (T a,T b) { Return(a+b); } This template function will work for any type of data ,int, float, double. Compiler creates specific version of the function according to the type of data. 2nd Merthod: Template Function as two lines: Template<class T> T sum(T a,T b) { Return(a+b); }
156
In some cases it is possible to override the template-generated code by providing special definitions for specific types. This is called template specialization. The following example demonstrates a situation where overriding the template generated code would be necessary: #include <iostream> using namespace std ; //max returns the maximum of the two elements of type T, where T is a //class or data type for which operator> is defined. template <class T> T max(T a, T b) { return a > b ? a : b ; } int main() { cout << "max(10, 15) = " << max(10, 15) << endl ; cout << "max('k', 's') = " << max('k', 's') << endl ; cout << "max(10.1, 15.2) = " << max(10.1, 15.2) << endl ; cout << "max(\"Aladdin\", \"Jasmine\") = " << max("Aladdin", "Jasmine") << endl ; return 0 ; Dept of CS , SJCET, Palai 157
158
T is a type parameter and it can be any type. For example, Stack<Token>, where Token is a user defined class. T does not have to be a class type as implied by the keyword class. For example, Stack<int> and Stack<float>are valid instantiations, even though int and float are not "classes".
Implementing template member functions is somewhat different compared to the regular class member functions. The declarations and definitions of the class template member functions should all be in the same header file. The declarations and definitions need to be in the same header file. Consider the following.
// B.CPP //B.H template <class t> class b { public: b() ; ~b() ; }; #include "B.H" template <class t> b<t>::b() { } template <class t> b<t>::~b() { } When compiling B.cpp, the compiler has both the declarations and the definitions available. At this point the compiler does not need to generate any definitions for template classes, since there are no instantiations. When the compiler compiles main.cpp, there are two instantiations: template class B<int> and B<float>. At this point the compiler has the declarations but no definitions! Dept of CS , SJCET, Palai 161 } //MAIN.CPP #include "B.H" void main() { b<int> bi ; b <float> bf ;
Using a class template is easy. Create the required classes by plugging in the actual type for the type parameters. This process is commonly known as "Instantiating a class". A good programming practice is using typedef while instantiating template classes. Then throughout the program, one can use the typedef name. There are two advantages: typedef's are very useful when "templates of templates" come into usage. For example, when instantiating an STL vector of int's, you could use: typedef vector<int, allocator<int> > INTVECTOR ; If the template definition changes, simply change the typedef definition. For example, currently the definition of template class vector requires a second parameter. typedef vector<int, allocator<int> > INTVECTOR ; INTVECTOR vi1 ; The compiler generates a class, function or static data members from a template when it sees an implicit instantiation or an explicit instantiation of the template. 1. Consider the following sample. This is an example of implicit instantiation of a class template . template <class T> class Z { public: Z() {} ; ~Z() {} ; void f(){} ; void g(){} ; }; int main() { Z<int> zi ; //implicit instantiation generates class Z<int> Z<float> zf ; //implicit instantiation generates class Z<float> return 0 ; } 2.Consider the following sample. This sample uses the template class members Z<T>::f() and Z<T>::g(). template <class T> class Z { public: Z() {} ; Dept of CS , SJCET, Palai 162
In some cases it is possible to override the template-generated code by providing special definitions for specific types. This is called template specialization. The following example defines a template class specialization for template class stream. #include <iostream> using namespace std ;
165
You may want to generate a specialization of the class for just one parameter, for example //base template class template<typename T1, typename T2> class X
{ };
//partial specialization template<typename T1> class X<T1, int> { } ; //C2989 here Dept of CS , SJCET, Palai 166
1.C++ templates allow one to implement a generic Queue<T> template that has a type parameter T. T can be replaced with actual types, for example, Queue<Customers>, and C++ will generate the class Queue<Customers>. For example, template <class T> class Stack { }; Here T is a template parameter, also referred to as type-parameter. 2.C++ allows you to specify a default template parameter, so the definition could now look like: template <class T = float, int elements = 100> Stack { ....} ; Then a declaration such as Stack<> mostRecentSalesFigures ; would instantiate (at compile time) a 100 element Stack template class named mostRecentSalesFigures of float values; this template class would be of type Stack<float, 100>. C++ also allows non-type template parameters. In this case, template class Stack has an int as a nontype parameter. If you specify a default template parameter for any formal parameter, the rules are the same as for functions and default parameters. Once a default parameter is declared all subsequent parameters must have defaults.
167
5.The value of a non-type-parameter cannot be assigned to or have its value changed. For example, template <class T, int size> class Stack { void f() Dept of CS , SJCET, Palai 168
int main() { Stack<double,10> si ; return 0 ; } 6.A template-parameter that could be interpreted as either a parameter-declaration or a typeparameter, is taken as a type-parameter. For example, class T {} ; int i ; template <class T, T i> void f(T t) { T t1 = i ; //template arguments T and i ::T t2 = ::i ; //globals T and i } int main() { f('s') ; //C2783 here return 0 ; } class T {} ; int i ; template <class T, T i> void f(T t) { T t1 = i ; //template arguments T and i ::T t2 = ::i ; //globals T and i } int main() { f<char, 's'>('s') ; //workaround return 0 ; Dept of CS , SJCET, Palai 169
The identifier in an original namespace definition is the name of the namespace. The identifier may not be previously defined in the declarative region in which the original namespace definition appears, except in the case of extending namespace. If an identifier is not used, the namespace is an unnamed namespace.
Declaring namespaces
The identifier used for a namespace name should be unique. It should not be used previously as a global identifier.
170
Extending namespaces
Namespaces are extensible. You can add subsequent declarations to a previously defined namespace. Extensions may appear in files separate from or attached to the original namespace definition. For example:
namespace X { // namespace definition int a; int b; } namespace X { // namespace extension int c; int d; } namespace Y { // equivalent to namespace X int a; int b; int c; int d; }
In this example, namespace X is defined with a and b and later extended with c and d. namespace X now contains all four members. You may also declare all of the required members within one namespace. This method is represented by namespace Y. This namespace contains a, b, c, and d.
171
Unnamed namespaces
A namespace with no identifier before an opening brace produces an unnamed namespace. Each translation unit may contain its own unique unnamed namespace. The following example demonstrates how unnamed namespaces are useful.
#include <iostream> using namespace std; namespace { const int i = 4; int variable; } int main() { cout << i << endl; variable = 100; return 0; }
In the previous example, the unnamed namespace permits access to i and variable without using a scope resolution operator. The following example illustrates an improper use of unnamed namespaces.
#include <iostream> using namespace std; namespace { const int i = 4; } int i = 2; int main() { cout << i << endl; // error return 0; }
Inside main, i causes an error because the compiler cannot distinguish between the global name and the unnamed namespace member with the same name. In order for the previous example to work, the namespace must be uniquely identified with an identifier and i must specify the namespace it is using. You can extend an unnamed namespace within the same translation unit. For example: #include <iostream> Dept of CS , SJCET, Palai 172
namespace A { int i; } namespace B { int i; using namespace A; } void f() { using namespace B; i = 7; // error }
In this example, attempting to initialize i within function f() causes a compiler error, because function f() cannot know which i to call; i from namespace A, or i from namespace B.
Explicit access
To explicitly qualify a member of a namespace, use the namespace identifier with a :: scope resolution operator.
175
176
MODULE 5
177
178
How to delete a single instance from the heap To delete a single instance from the heap, write the keyword delete followed by the name of the pointer that points to the heap space. For example, int * ptr = new int ; delete ptr ; How to delete an array of instances from the heap To delete an array of instances from the heap, write the keyword delete followed by empty brackets and the name of the pointer variable. For example, int * ptr = new int [ 10 ] ; Dept of CS , SJCET, Palai 179
Memory for a single instance of a user-defined class can be obtained from the heap in the same fashion as that of a built-in type. That is, you write the keyword new followed by the class type. For example, * ptr = new Item ; allocate one object of type Item. The pointer returned by new Item ; is of correct type ( pointer to Item ) without the need for explicit casting.
In this example, the first step is to allocate space for the instance of Item and the second step is to call the appropriate constructor of the class Item. Item * ptr = Item ( 17 ) ; The parentheses following the class name, if present, supply arguments to the class constructor. If the parentheses are not present, as in Item * ptr = new Item ; then the class must either define a constructor that does not require arguments or define no constructors at all.
Dynamic Memory Allocation for an array of Objects Programmer may also ask for more than one instance, that is, an array of objects of a particular type. The array is allocated from the free store by following the type specifier with a bracket-enclosed dimension. The dimension can be any expression. For example, Item * = new Item [ 5 ] ;
180
// rememb-o-matic #include <iostream> #include <new> using namespace std; int main () { int i,n; int * p; cout << "How many numbers would you like to type? "; cin >> i; p= new (nothrow) int[i]; if (p == 0) cout << "Error: memory could not be allocated"; else { for (n=0; n<i; n++) { cout << "Enter number: "; cin >> p[n]; } cout << "You have entered: "; for (n=0; n<i; n++) cout << p[n] << ", "; delete[] p; } return 0; }
How many numbers would you like to type? 5 Enter number : 75 Enter number : 436 Enter number : 1067 Enter number : 8 Enter number : 32 You have entered: 75, 436, 1067, 8, 32,
Notice how the value within brackets in the new statement is a variable value entered by the user (i), not a constant value: Dept of CS , SJCET, Palai 181
#include <iostream.h> void main() { //Allocates using new operator memory space in memory for storing a integer datatype int *a= new a; *a=100; cout << " The Output is:a="<<a; //Memory Released using delete operator Dept of CS , SJCET, Palai 182
window = new Frame("First", 10, 20, 50, 50); view = new Frame("Second",70, 20, 50, 50);
Frame *edit = new Frame ("Editor", 50, 75, 100, 100); // combine declaration of pointer // variable and object construction Frame *default = new Frame; delete window; delete view; delete edit; Dept of CS , SJCET, Palai // use default constructor values // destruct window Frame // destruct view Frame // destruct edit Frame 183
In this example, window and view are declared as variables that point to Frame objects. It is important to realize that this declaration does not create two frames; it merely creates to variables that will point to Frame objects that are created sometime in the future. The two Frame objects are then created and the variables "window" and "view" are set pointing to these objects. The declaration of the pointer variable and the construction of the object to which it points can be combined in a single statement as shown with the edit and default Finally, the three Frame objects are deleted. Notice the syntax of creating dynamic objects. The name of the class appears immediately after the keyword "new". The constructor arguments, if any, are given in parenthesis after the name of the class. When there are no constructor arguments, the parenthesis are omitted as shown in the creation of the default object. An operation is applied to a dynamic object using the "->" operator. This "arrow" operator is two adjacent characters, a minus sign and a greater than symbol. An exaple of operating on a dynamic object is the following: Frame* display = new Frame ("A Display", 10, 20, 100, 200); display->MoveTo(50, 50); display->Resize(200, 200); In this example the display object is moved and resized using the arrow operator to apply the corresponding methods.
Inline Functions
When a function is declared inline, the function is expanded at the calling block. The function is not treated as a separate unit like other normal functions. But a compiler is free to decide, if a function qualifies to be an inline function. If the inline function is found to have larger chunk of code, it will not be treated as an inline function, but as like other normal functions. Inline functions are treated like macro definitions by the C++ compiler. They are declared with the keyword inline as follows. int add(int x,int y); inline int add(int x,int y) { return x+y; } In fact, the keyword inline is not necessary. If the function is defined with its body directly and the function has a smaller block of code, it will be automatically treated as inline by the compiler.
184
The keyword inline specified in the above example, designates the function as inline function. For example, if a programmer wishes to have a function named exforsys with return value as integer and with no arguments as inline it is written as follows:
185
#include <iostream.h> int exforsys(int); void main( ) { int x; cout << \n Enter the Input Value: ; cin>>x; cout<<\n The Output is: << exforsys(x); } inline int exforsys(int x1) { return 5*x1; }
The output of the above program is: Enter the Input Value: 10 The Output is: 50
The output would be the same even when the inline function is written solely as a function. The concept, however, is different. When the program is compiled, the code present in the inline function exforsys( ) is replaced in the place of function call in the calling program. The concept of inline function is used in this example because the function is a small line of code.
The above example, when compiled, would have the structure as follows:
#include <iostream.h> int exforsys(int); void main( ) { int x; cout << \n Enter the Input Value: ; Dept of CS , SJCET, Palai 186
When the above program is written as normal function the compiled code would look like below:
#include <iostream.h> int exforsys(int); void main( ) { int x; cout << \n Enter the Input Value: ; cin>>x; //Call is made to the function exforsys cout<<\n The Output is: << exforsys(x); } int exforsys(int x1) { return 5*x1; } A programmer must make wise choices when to use inline functions. Inline functions will save time and are useful if the function is very small. If the function is large, use of inline functions must be avoided.
187
1.1
History of Java
Around 1990 James Gosling , Bill Joy and others at Sun Microsystems began developing a
language called Oak. The wanted it primarily to control microprocessors embedded in consumer items such as cable set-top boxes, VCR's, toasters, and also for personal data assistants (PDA).However, as of 1993, interactive TV and PDA markets had failed to take off. Then the Internet and Web explosion began, so Sun shifted the target market to Internet applications and changed the name of the project to Java.By 1994 Sun's HotJava browser appeared. Written in Java in only a few months, it illustrated the power of applets, programs that run within a browser, and also the capabilities of Java for speeding program development. Riding along with the explosion of interest and publicity in the Internet, Java quickly received widespread recognition and expectations grew for it to become the dominant software for browser and consumer applications.
JAVA
The basic features that make Java a powerful and popular programming language are: Platform Independence
o
The Write-Once-Run-Anywhere ideal has not been achieved (tuning for different platforms usually required), but closer than with other languages.
Object Oriented
o
Object oriented throughout - no coding outside of class definitions, including main(). 188
Compiler/Interpreter Combo
o o
Code is compiled to bytecodes that are interpreted by a Java virtual machines (JVM) . This provides portability to any machine for which a virtual machine has been written.
The two steps of compilation and interpretation allow for extensive code checking and improved security.
Robust
o
Exception handling built-in, strong type checking (that is, all data must be declared an explicit type), local variables must be initialized.
Security
o o o o
No memory pointers Programs runs inside the virtual machine sandbox. Array index limit checking Code pathologies reduced by
bytecode verifier - checks classes after loading class loader - confines objects to unique namespaces. Prevents loading a hacked "java.lang.SecurityManager" class, for example.
security manager - determines what resources a class can access such as reading and writing to the local disk.
Dynamic Binding
o
The linking of data and methods to where they are located, is done at run-time. 189
New classes can be loaded while a program is running. Linking is done on the fly. Even if libraries are recompiled, there is no need to recompile code that uses classes in those libraries. This differs from C++, which uses static binding. This can result in fragile classes for cases where linked code is changed and memory pointers then point to the wrong addresses.
Good Performance
o
Interpretation of bytecodes slowed performance in early versions, but advanced virtual machines with adaptive and just-in-time compilation and other techniques now typically provide performance up to 50% to 100% the speed of C++ programs.
Threading
o
Lightweight processes, called threads, can easily be spun off to perform multiprocessing.
o o
Can take advantage of multiprocessors where available Great for multimedia displays.
Built-in Networking
o
Java was designed with networking in mind and comes with many classes to develop sophisticated Internet communications.
SIMPLE EXAMPLES class welcome { public static void main(String a[]) { System.out.println("Welcome to Java"); }} * class welcome - declares a class called welcome . class is a keyword and declares that a new class definition follows. Dept of CS , SJCET, Palai 190
2)Add 2 Numbers class add { public static void main(String arg[]) {int a,b,c; a=5; b=10; c=a+b; System.out.println("a+b="+c); }} 3)Command line arguments class hello { public static void main(String arg[]) { System.out.println("Hello"); System.out.println(arg[0]); }
191
5)Compute Square root of a Number import java.lang.Math; class sqroot { public static void main(String arg[]) { double y,x=25; y=Math.sqrt(x); System.out.println("Sqroot of "+ x +"="+y); } } . sqrt is a method of Math class. import statement instruct the interpreter to load Math class from the package lang 6)Factorial class fact { public static void main(String args[]) { int i,fact=1; i=Integer.parseInt(args[0]); Dept of CS , SJCET, Palai
for(int f=i;f>0;f--) { fact=fact*f; } System.out.println("Fact="+fact); } } o/p javac fact.java java fact 5 Fact=120 7)Generate Series class series { public static void main(String args[]) { int a,b; for(a=1;a<=5;a++) { for(b=a;b<=5;b++) { System.out.print(b+" "); } 192
1.Class declaration
The class declaration declares the name of the class along with other attributes. One could make a class public, or private in the declaration. One could also extends another class (well leave this for another lab) or implements an interface (well leave this for later as well.) For our purposes, just a few keywords will suffice: public and private. Here is an example of a class declaration.
193
Class Body
The class body comes after the class declaration and is placed within curly braces. The class
body declares all instance variables and class variables (known collectively as member variables) for the class. In addition, the class body declares and implements all instance variables and class member functions for the class. Here is an example. class FishingPole { private string manufacturer; public void setManufacturer(String man) { manufacturer = man; } }The string named manufacturer is a variable, and setManufacturer() is a method. (Later we will see that manufacturer is actually called an instance variable and setManufacturer is called a class method. At this point, just know that they are variables and methods.) A real class would probably have many variables and methods defined. The variable named manufacturer will contain the name of the fishing pole manufacturer. This is the private data within the class that is protected from direct use. Dept of CS , SJCET, Palai 194
Instantiating an object
A possible main program that creates a FishingPole object could be as follows. public static void main(String args[]) { FishingPole myPole = new FishingPole(); myPole.setManufacturer(Spalding); } FishingPole myPole creates a variable that can hold a reference to a FishingPole object. new FishingPole creates an object of type FishingPole, allocating memory space to that object. The reference to this object is then assigned to the myPole variable by the assignment operator (=). Next we have a call to the method setManufacturer(). myPole.setManufacturer(Spalding); says to invoke (call) the setManufacturer() method on the myPole object. The actual parameter is the string "Spaulding". Now the program starts executing the setManufacturer() method defined in the FishingPole class. First the reference to the actual parameter ("Spaulding") is placed in the formal parameter, man. (Note that the types of the two parameters are the same. "Spaulding" is a string and man is of type String. The types of corresponding parameters are normally the same.) All that the setManufacturer() method does is store the name into the class variable manufacturer. Now the manufacturer associated with object myPole will have the value "Spaulding" until it is changed by another call to setManufacturer(). Creating classes- Simple Example //Main.java class rectangle Dept of CS , SJCET, Palai 195
4.
Constructors
Constructors are used when creating classes. They are used to initialize member variables
when a class is instantiated. Given the above FishingPole class, instead of creating an object of type FishingPole, then setting the manufacturer name via the setManufacturer() method, it may be easier to set that name when declaring and instantiating the FishingPole object in the first place.With a properly written constructor, we wouldnt need the call to method setManufacturer().Constructors are always named the same as the class they are in. class FishingPole { private String Manufacturer ; // Constructor public FishingPole(String man) Dept of CS , SJCET, Palai 196
STATIC CLASS/METHODS
There are two types of methods. Instance methods are associated with an object and use the instance variables of that object. This is the default. Static methods use no instance variables of any object of the class they are defined in. If you define a method to be static, you will be given a rude message by the compiler if you try to access any instance variables. You can access static variables, but except for constants, this is unusual. Static methods typically take all they data from parameters and compute something from those parameters, with no reference to variables. This is typical of methods which do some kind of generic calculation. A good example of this are the many utility methods in the predefined Math class.
which is then passed as an implicit parameter to the instance method, eg, inputTF.setText(""); Dept of CS , SJCET, Palai 198
called from within the same class. If called from outside the class and it wasn't declared static, it would have to be qualified (uselessly) with an object. Even when used within the class, there are good reasons to define a method as static when it could be.
199
There are two cases. Called from within the same class Just write the static method name. Eg,
Called from outside the class If a method (static or instance) is called from another class, something must be given before the method name to specify the class where the method is defined. For instance methods, this is the object that the method will access. For static methods, the class name should be specified. Eg,
If an object is specified before it, the object value will be ignored and the the class of the object will be used.
200
INHERITANCE IN JAVA
Inheritance is a major component of object-oriented programming. Inheritance will allow you to define a very general class, and then later define more specialized classes by simply adding some new details to the older more general class definition. This saves work, because the more specialized class inherits all the properties of the general class and you, the programmer, need only program the new features. For example, you might define a class for vehicles that has instance variables to record the vehicle's number of wheels and maximum number of occupants. You might then define a class for automobiles, and let the automobile class inherit all the instance variables and methods of the class for vehicles. The class for automobiles would have added instance variables for such things as the amount of fuel in the fuel tank and the license plate number, and would also have some added methods. (Some vehicles, such as a horse and wagon, have no fuel tank and normally no license plate, but an automobile is a vehicle that has these "added" items.) You would have to describe the added instance variables and added methods, but if you use Java's inheritance mechanism, you would get the instance variables and methods from the vehicle class automatically. Before we construct an example of inheritance within Java, we first need to set the stage with the following Programming Example. Programming Example: A Person Class Display 1 contains a simple class called Person. This class is so simple that the only property it gives a person is a name. We will not have much use for the class Person by itself, but we will use the class Person in defining other classes. So, it is important to understand this class.
201
public class Person { private String name; public Person() { name = "No name yet."; } public Person(String initialName) { name = initialName; } public void setName(String newName) { name = newName; } public String getName() { return name; } public void writeOutput() { System.out.println("Name: " + name); } public boolean sameName(Person otherPerson) { return (this.name.equalsIgnoreCase(otherPerson.name)); } } Most of the methods for the class Person are straightforward. Notice that the method setName and the constructor with one String parameter do the same thing. We need these two methods, even though they do the same thing, because only the constructor can be used after new when we create a new object of the class Person, but we need a different method, such as setName, to make changes to an object after the object is created. The method sameName is similar to the equals methods we've seen, but since it uses a few techniques that you may not have completely digested yet, let's go over that definition, which we reproduce in what follows: public boolean sameName(Person otherPerson) Dept of CS , SJCET, Palai 202
5.2
Derived Classes
203
205
1)Demonstrating Inheritance public class InheritanceDemo { public static void main(String[] args) { Student s = new Student(); s.setName("Warren Peace"); //setName is inherited from the class Person. s.setStudentNumber(2001); s.writeOutput(); }} Screen Output Name: Warren Peace Student Number: 2001 Dept of CS , SJCET, Palai 206
207
208
209
211
A final method cannot be overridden by subclasses. This is done for reasons of efficiency, since the method can then be placed inline wherever it is called. Example: public class MyClass { public final void myFinalMethod() {...} } A final variable is a constant. It can only be assigned a value once. Example: public class MyClass { public static final double PI = 3.141592653589793; }
INTERFACES
An interface in the Java programming language is an abstract type which is used to specify an interface (in the generic sense of the term) that classes must implement. Interfaces are declared using the interface keyword, and may only contain method signatures and constant declarations (variable declarations which are declared to be both static and final).
212
As interfaces are abstract, they cannot be directly instantiated. Object references in Java may be specified to be of an interface type; in which case they must either be null, or be bound to an object which implements the interface.The keyword implements is used to declare that a given class implements an interface. A class which implements an interface must either implement all methods in the interface, or be an abstract class.
One benefit of using interfaces is that they simulate multiple inheritance. All classes in Java (other than java.lang.Object, the root class of the Java type system) must have exactly one base class; multiple inheritance of classes is not allowed. However, a Java class may implement any number of interfaces.
Uses of Interfaces
Interfaces are used to collect like similarities which classes of various types share, but do not necessarily constitute a class relationship. For instance, a human and a parrot can both whistle, however it would not make sense to represent Humans and Parrots as subclasses of a Whistler class, rather they would most likely be subclasses of an Animal class (likely with intermediate classes), but would both implement the Whistler interface.
Another use of interfaces is being able to use an object without knowing its type of class, but rather only that it implements a certain interface. For instance, if one were annoyed by a whistling noise, one may not know whether it is a human or a parrot, all that could be determined is that a whistler is whistling. In a more practical example, a sorting algorithm may expect an object of type Comparable. Thus, it knows that the object's type can somehow be sorted, but it is irrelevant what the type of the object is.
Defining an Interface
Interfaces must be defined using the following formula (compare to Java's class definition). [visibility] interface InterfaceName [extends other interfaces] { constant declarations abstract method declarations } Dept of CS , SJCET, Palai 213
The body of the interface contains abstract methods, but since all methods in an interface are, by definition, abstract, the abstract keyword is not required. Since the interface specifies a set of exposed behaviours, all methods are implicitly public. Thus, a simple interface may be public interface Predator { boolean chasePrey(Prey p); void eatPrey(Prey p); }
Implementing an Interface
The syntax for implementing an interface uses this formula:
... implements InterfaceName[, another interface, another, ...] ... Classes may implement an interface. For example, public class Cat implements Predator { public boolean chasePrey(Prey p) { // programming to chase prey p } public void eatPrey (Prey p) { // programming to eat prey p }} If a class implements an interface and is not abstract, and does not implement all its methods, this will result in a compiler error. If a class is abstract, one of its subclasses is expected to implement its unimplemented methods. Classes can implement multiple interfaces public class Frog implements Predator, Prey { ... }
Interfaces are commonly used in the Java language for callbacks. Java does not allow the passing of methods (procedures) as arguments. Therefore, the practice is to define an interface and
214
use it as the argument and use the method signature knowing that the signature will be later implemented. First a simple link List for the example public class IntLinker { public int start; public IntLinker point; public IntLinker (int start, IntLinker point) { this.start = start; this.point = point; } }
Third, the final use of the IntMethod (not yet defined, but used) public class IntFinal { IntLinker build (IntMethod var, IntLinker builder){ return new IntLinker ( var.theMethod (builder.start), builder.point); }} Then, the only code written at some later point defining theMethod by implementing IntMethod Thus, a callback
public class ImplMethod implements IntMethod{ public int theMethod(int positive) { return Math.abs(positive);}
public static void main(String[] args) { IntFinal i = new IntFinal(); IntLinker t = i.build(new ImplMethod(), new IntLinker(-11, new IntLinker(2, null))); Dept of CS , SJCET, Palai 215
System.out.println(t.start); System.out.println(t.point.start); }} About Interface #Java does not support multiple inheritance #classes in java cannot have more than one super class. class A extends B extends C { }is not permitted in Java #Java provides an alternate approach known as interface to support the concept of multiple inheritanceAn interface is basically a kind of class.interface contains Abstract methods and final fields.interface does not provide any code to implement this methods and data fields contain constant values.It is the responsibility of the class that implements an interface to define the code for implantation of these methods #Syntax interface Interfacename {variable decln; method decln; } #variables are declared as final type variablename=value; all variables are declared as constants #method declaration contain only a list of methods without any body statements return-type methodname(parameter-list)
Example class test { int mark1,mark2; void getmark(int m1,int m2) { mark1=m1; mark2=m2; } Dept of CS , SJCET, Palai 216
void putmarks() { System.out.println("Marks"); System.out.println("Marks1="+mark1); System.out.println("Marks2="+mark2); }} interface sports { final int sportwt=6; void putwt(); } class result extends test implements sports {int total; public void putwt() {System.out.println("sportwt="+sportwt); } void display() {total=mark1+mark2+sportwt; putmarks(); putwt(); System.out.println("Total Score="+total); }} class inter4 { public static void main(String a[]) { result st=new result(); st.getmark(27,33); st.display(); }} O/P mark1=27 mark2=33 spwt=6 total=66
Example Interface1 interface Area { final static float pi=3.14F; float compute(float x,float y); }
217
class rectangle implements Area { public float compute(float x,float y) { return (x*y); } } class circle implements Area { public float compute(float x,float y) { return (pi*x*x); } } class inter { public static void main(String a[]) { rectangle rect=new rectangle(); circle cir=new circle(); Area area; area=rect; System.out.println("Area of Rectangle="+area.compute(10,20)); area=cir; System.out.println("Area of circle="+area.compute(10,0)); } } The interface approach enables you to inherit method descriptions not implementations Interface are used to to define a standard behaviour that can be implemented by any class anywhere in the class hierarchy. For example the shape rectangle and circle.both of them require common function area(). If we use an interface for Area,we can implement that interface in both rect and circle class
218
An inner class is a class defined inside another class. An inner class object is scoped not to the outer class, but to the instantiating object. Even if the inner class object is removed from the outer class object that instantiated it, it retains the scoping to its creator. If an object has a reference to another object's ("parent object"'s) inner class object, the inner class object is dealt with by that object as a separate, autonomous object, but in fact, it still has access to the private variables and methods of its parent object. An inner class instantiation always remembers who it's parent object is and if anything changes in the parent object (e.g. one of its property's value changes), that change is reflected in all its inner class instantiations. Inner classes are very useful in factory pattern situations. Syntax: [normal class declaration] { [scoping] class [inner class's name] [extends ....] [ implements ...] { // properties and methods of the inner class } } // rest of properties and methods of parent class
INNER CLASS Inner classes let you define one class within another. They provide a type of scoping
for your classes since you can make one class a member of another class. Just as classes
219
have member variables and methods, a class can also have member classes. You can define an inner class within the curly braces of the outer class, as follows: class MyOuter { class MyInner { } } And if you compile it,javac MyOuter.java youll end up with two class files:MyOuter.class and MyOuter$MyInner.class
The inner class is still, in the end, a separate class, so a class file is generated. But the inner class file isnt accessible to you in the usual way. You cant, for example, say %java MyOuter$MyInner in hopes of running the main method of the inner class, because a regular inner class cant have static declarations of any kind. The only way you can access the inner class is through a live instance of the outer class! In other words, only at runtime when theres already an instance of the outer class to tie the inner class instance to. Youll see all this in a moment. First, lets beef up the classes a little: class MyOuter { private int x = 7; // inner class definition class MyInner { public void seeOuter() { System.out.println("Outer x is " + x); } } // close inner class definition } // close outer class The preceding code is perfectly legal. Notice that the inner class is indeed accessing a private member of the outer class. Thats fine, because the inner class is also a member of the outer class. So just as any member of the outer class
To instantiate an instance of an inner class, you must have an instance of the outer Dept of CS , SJCET, Palai 220
class to tie to the inner class. Creating an Inner Class Object from Outside the Outer Class Instance Code If we want to create an instance of the inner class, we must have an instance of the outer class. it means you cant instantiate the inner class from a static method of the outer class (because, dont forget, in static code there is no this reference) or from any other code in any other class. Inner class instances are always handed an implicit reference to the outer class. The compiler takes care of it, so youll never see anything but the end resultthe ability of the inner class to access members of the outer class. The code to make an instance from anywhere outside nonstatic code of the outer class is simple, but you must memorize this for the exam! public static void main (String[] args) { MyOuter mo = new MyOuter(); MyOuter.MyInner inner = mo.new MyInner(); inner.seeOuter(); } Heres a quick summary of the differences between inner class instantiation code thats within the outer class (but not static), and inner class instantiation code thats outside the outer class: From inside the outer class instance code, use the inner class name in the normal way: MyInner mi = new MyInner(); From outside the outer class instance code (including static method code within the outer class), the inner class name must now include the outer class name, MyOuter.MyInner and to instantiate, you must use a reference to the outer class, new MyOuter().new MyInner(); or outerObjRef.new MyInner(); if you already have an instance of the outer class. # program MyOut.java Dept of CS , SJCET, Palai 221
class MyOut { private int x = 7; // inner class definition class MyInner { public void seeOuter() { System.out.println("Outer x is " + x); } } // close inner class definition public static void main (String[] args) { MyOut mo = new MyOut(); MyOut.MyInner inner = mo.new MyInner(); inner.seeOuter();}} .. import java.awt.*; import java.applet.*; import java.awt.event.*; public class event5 extends Applet { public void init() { addMouseListener(new myAdapter()); } class myAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { showStatus("Mouse Pressed"); } }} /* <applet code=event5.class width=250 height=200> </applet>*/
222
Anonymous inner class is an inner class with no name. Example: actionPerformed events utilize the Observer-Observable pattern -- An instance of the observer is added to the observable. button as its ActionListener. Anonymous inner classes are very similar to named inner classes: Anonymous inner classes can override methods of the superclass. Anonymous inner classes are scoped inside the private scoping of the outer class. They can access the internal (private) properties and methods of the outer class. References to an inner class can be passed to other objects. Note that it still retains its scope. But there are some important differences: Anonymous inner classes must use the no parameter constructor of the super class. Since an object made from the inner class has a "life" independent of its outer class object, there is a problem with accessing local variables, especially method input parameters. Two ways to pass initializing parameters to an inner class: Initialize a property that the inner class then uses -- properties have the cross-method-call persistence that local variables lack. Make the local variable "final" -- compiler will automatically transfer the value to a more persistent portion of the computer memory. Disadvantage: the value cannot be changed. Usages: Very useful for JBuilder creates an anonymous inner class to give to the
controlled access to the innards of another class. Very useful when you only want one instance of a special class. Syntax: [variable_type_superclass =] new superclass_name() { // properties and methods } [;]
223
Examples:
1 Timer object with anonymous ActionListener:
Timer timer = new Timer( 200, new ActionListener() { public void actionPerformed(ActionEvent e) {// do something } });
Initialization using a final input parameter (each Object made will have the name that
was used when makeObj() was called to make it.) public MyClass makeObj(final String name) { return new SubClassOfMyClass() { public String toString() { } } }; return "My name is "+name;
public Object makeObj(String name) { final String objName = "My name is " + name;
return new Object() { public String toString() { return objName; } };} 224
public Object makeObj(String name) { return new Object() { String objName; { objName = "My name is " + name; } public String toString() { return objName; } }; } An anonymous Inner class is one that is not assigned a name. Consider the applet shown below. Its goal is to display the string Mouse Pressed in the status Bar of the AppletViewer or browser when the mouse is pressed.The init() method calls the addMouseListener() method. Its argument is an expression that defines and instantiates an anonymous inner class.The syntax new MouseAdapter(){.} indicates to the compiler that the code between the braces defines an anonymous inner class. Furthermore the class extends the MouseAdapter.This new class is not named, but it is automatically instantiated when this expression is executed, because this anonymous inner class is defined within the scope of event6 class. Therefore it can call the showStatus() method directly. import java.awt.*; import java.applet.*; import java.awt.event.*; public class event6 extends Applet { public void init() { addMouseListener(new MouseAdapter(){ public void mousePressed(MouseEvent e) { showStatus("Mouse Pressed"); }}); }} /* Dept of CS , SJCET, Palai 225
Figure 1. Basic structure of JDK package Basically, files in one directory (or package) would have different functionality from those of another directory. For example, files in java.io package do something related to I/O, but files in java.net package give us the way to deal with the Network. In GUI applications, it's quite common for us to see a directory with a name "ui" (user interface), meaning that this directory keeps files related to the presentation part of the application. On the other hand, we would see a directory called "engine", which stores all files related to the core functionality of the application instead. Packaging also help us to avoid class name collision when we use the same class name as that of others. For example, if we have a class name called "Vector", its name would crash with the
Vector
class from JDK. However, this never happens because JDK use java.util as a package name for
the Vector class (java.util.Vector). So our Vector class can be named as "Vector" or we can put it into another package like com.mycompany.Vector without fighting with anyone. The benefits of using Dept of CS , SJCET, Palai 226
package reflect the ease of maintenance, organization, and increase collaboration among developers. Understanding the concept of package will also help us manage and use files stored in jar files in more efficient ways.
227
Figure 2. HelloWorld in world package (C:\world\HelloWorld.java) That's it!!! Right now we have HelloWorld class inside world package. Next, we have to introduce the
world
Note: If you used to play around with DOS or UNIX, you may be familiar with . (dot) and .. (dot dot). We use . as an alias for the current directory and .. for the parent directory. In our CLASSPATH we include this . for convenient reason. Java will find our class file not only from C: directory but from the current directory as well. Also, we use ; (semicolon) to separate the directory location in case we keep class files in many places. When compiling HelloWorld class, we just go to the world directory and type the command: C:\world\javac HelloWorld.java If you try to run this HelloWorld using java HelloWorld, you will get the following error: Dept of CS , SJCET, Palai 228
C:\world>java HelloWorld Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld (wrong name: world/HelloWorld) at java.lang.ClassLoader.defineClass0(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:442) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:101) at java.net.URLClassLoader.defineClass(URLClassLoader.java:248) at java.net.URLClassLoader.access$1(URLClassLoader.java:216) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:191) at java.lang.ClassLoader.loadClass(ClassLoader.java:290) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:286) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) The reason is right now the HelloWorld class belongs to the package world. If we want to run it, we have to tell JVM about its fully-qualified class name (world.HelloWorld) instead of its plain class name (HelloWorld). C:\world>java world.HelloWorld C:\world>Hello World Note: fully-qualified class name is the name of the java class that includes its package name To make this example more understandable, let's put the HelloWorld class along with its package (world) be under C:\myclasses directory instead. The new location of our HelloWorld should be as shown in Figure 3:
229
Figure 3. HelloWorld class (in world package) under myclasses directory We just changed the location of the package from C:\world\HelloWorld.java to
C:\myclasses\world\HelloWorld.java. Our CLASSPATH then needs to be changed to point to the new location of the package world accordingly. set CLASSPATH=.;C:\myclasses; Thus, Java will look for java classes from the current directory and C:\myclasses directory instead. Someone may ask "Do we have to run the HelloWorld at the directory that we store its class file everytime?". The answer is NO. We can run the HelloWorld from anywhere as long as we still include the package world in the CLASSPATH. For example, C:\>set CLASSPATH=.;C:\; C:\>set CLASSPATH // see what we have in CLSSPATH CLASSPATH=.;C:\; C:\>cd world C:\world>java world.HelloWorld Hello World C:\world>cd .. C:\>java world.HelloWorld Hello World Dept of CS , SJCET, Palai 230
public class HelloMoon { private String holeName = "rabbit hole"; public getHoleName() { return hole; } public setHole(String holeName) { this.holeName = holeName; } } If we store the package world under C: as before, the HelloMoon.java would be c:\world\moon\HelloMoon.java as shown in Figure 4 below:
231
Although we add a subpackage under package world, we still don't have to change anything in our CLASSPATH. However, when we want to reference to the HelloMoon class, we have to use
world.moon.HelloMoon
compile first.java Test is the package name .. package Test; public class first { public void view() { System.out.println("I am from Test package"); } } Step2: change to root directory create mainpack.java and import package Test in that file Create an object of class first and view the result from the package Test import Test.*; class mainpack { public static void main(String args[]) { first f=new first(); f.view(); } } Step 3: javac mainpack.java java mainpack o/p I am from the package Test
Importing classes from other packages Step1:create two directories pack1 &pack2 create first.java and save in package pack1 compile first.java from the folder pack1 Also create second.java and save in package pack2. compile second.java from the folder pack2 //first.java package pack1; public class first { public void view() { System.out.println("I am from package");
233
}} ----------------------------------//second.java package pack2; public class second { public void view2() { System.out.println("I am from package2"); }} -------------------------------------------Step2: change to root directory create mainpack1.java //mainpack1.java import pack1.*; import pack2.second; class mainpack1 { public static void main(String args[]) { first f=new first(); f.view(); second s=new second(); s.view2(); }} Step 3: javac mainpack1.java java mainpack1 o/p I am from the package1 I am from the package2
Subclasses an Imported class It is possible to subclass a class that has been imported from another package. For example Step1 create package pack2.create second.java and save in package pack2. compile second.java from the folder pack2 //second.java package pack2; public class second { public void view2() { Dept of CS , SJCET, Palai 234
System.out.println("I am from package2"); } } Step2: change to root directory create mainpack2.java. //mainpack2.java import pack2.second; class three extends second { void view3() { System.out.println("I am from pack2 extended in class three"); } } class mainpack2 { public static void main(String args[]) { three t=new three(); t.view2(); t.view3(); } } Step 3: javac mainpack2.java java mainpack2 o/p I am from the package2 I am from pack2 extended in class three
235