Programming in C++: Q. Give The Difference Between C and C++
Programming in C++: Q. Give The Difference Between C and C++
9. Abstract Data Type mechanism is implemented through class data in C++. 10. Overloading is not possible in C 10. Operator overloading and function overloading supports the implementation of new types in C++ 11. In C, array model is a pointer based and is one- 11. In C++, multi-dimensional, dynamic and bound dimensional checked arrays are implemented.
A derived class inheriting from a single base class is called single inheritance. A derived class inheriting from multiple base classes is called multiple inheritance. A derived class inheriting from a class that inherits from another class is called multilevel inheritance. Number of derived classes inheriting from a single base class is called hierarchical inheritance. A derived class inheriting from multiple base classes and multiple base classes inheriting from a single base class is called hybrid inheritance. With inheritance, user can plan a class hierarchy. It means OPP defines a hierarchy of different classes and subclasses within it. Class hierarchy also describes the relationship between classes and subclasses. It helps the programmer to scan minutely a small number of categories instead of a large number. Also coding can be shared by using the concept of inheritance and class hierarchy. 4. Polymorphism Polymorphism allows many different types of objects to perform the same operation by responding to the same message. It is the ability to take many shapes and forms. Polymorphism helps the programmer to call different functions with a single statement. It is very close inheritance. Polymorphism means the ability to take more than one form i.e. an operation may exhibit different behaviour in different forms. Polymorphism has overloading and virtual function classifications. When an existing operator, such as + or =, is given the capability to operate on a new data type, it is called overloading. A virtual function is used to handle some specific tasks related to class objects. Polymorphism plays an important role in allowing objects having different internal structure to share the same external interface. It is extensively used in implementing inheritance. 5. Encapsulation Encapsulation is also called data hiding. It consists of separating the external aspects of an object from the internal implementation details of the object which are hidden from other objects. In other words, collecting of data and functions into a single unit is called encapsulation. It prevents a program from becoming interdependent. Encapsulation gives a more clear result. Encapsulation in programs like C, BASIC, and FORTRAN are doe in small sub-programs. All external files and functions are encapsulated. Thus encapsulation means to hide the hide internal operations of a class to support abstraction. It permits accessing of data only through calling the functions. So these functions provide the interface between the object data and the program. Thus insulation of the data from the direct access by program is called data hiding. 6. Data Abstraction Abstraction is restricted examination of certain aspects of a problem. Here the most essential aspect of the problem is considered important and the other unimportant details are ignored. This concept is one of the major components of classes. User defined data type is called abstract data and the process of defining this type of data is called data abstraction. struct, typedef and class are three ways through which the user can define a data type. Classes use the concept of abstraction and are defined as a list of abstract attributes such as size, weight and cost and functions to operate on these attributes. They encapsulate all essential properties of the objects that are to be created. Since the classes use the concept of data abstraction, they are known as Abstract Data Types (ADT). 7. Dynamic Binding Binding in C++ is done in two ways: 1) Static binding and 2) Dynamic binding. Binding means linking. It is the linking of a procedure call to the code to be executed in response to the call. Dynamic binding is the address of the code in a member function and invocation is determined at the last possible moment. It is based on the dynamic run time of the object. Dynamic biding is the result of virtual function. In dynamic binding we use non constant pointer to postpone the allocation of memory until the program is running. Thus dynamic binding means the code associated with a given procedure call until the time of execution. 8. Message Passing Messaging passing is linked with inheritance and data binding. Although it is used only in virtual functions but it has a very important role in OOP. A message for an object is a request for execution of a procedure. It will call a function or procedure in the receiving object that generates the desired results. Message passing involves specifying the name of the object, the name of the function and the information sent. 9. Reusability Once a class has been written, created and debugged, it can be distributed to other programmers for use in their own programmers for use in their own programs. This is called reusability. It is similar to the way a library of functions in a procedural language can be incorporate into different programs. In OOP the concept of inheritance provides an important extension to the idea of reusability. A programmer can take an existing class without modifying and can use to develop any new application. This is done by
deriving a new class from the existing one. The new class will inherit the capabilities of the old one but is free to add new features of its own.
Q. What are Constants? Give types and rules for each one of them.
Ans. Constant is a quantity that doesnt change and can be stored at any location in the memory of the computer. These quantities may be combinations of alphabets, numbers or special symbols in C++. eg: 2y=30, where 2 and 30 are constants i.e., their value cannot be changed. C Constants can be divided into two categories: 1. Primary constants 2. Secondary constants Primary constants are as follows: i. Integer Constants An integer constant refers only to numbers. It may be a single digit or combination of digits. Generally, integer constants are written in decimal number system, which consist of combination of digits from 09. Rules for constructing Integer constants. a) An integer constant must contain of at least one digit. b) It should not contain decimal values. c) The numbers could either be positive or negative. d) It does not allow commas or blank space. e) The range of integer constant is 32768 to +32767 ii. Float Constants A float constant refers to numbers that contains a decimal point or an exponent or both. The float constants are often known as real constants that could be written in two forms: fractional or exponential. Rules for constructing Float constants a) A float constant must consist of at least one digit. b) It should have decimal values c) The numbers could either be positive or negative
d) It does not allow commas or blank spaces e) A letter e should separate the mantissa part and the exponent part. For example, 301224x10-17 would be represented as 301224 e 17 in float constants. f) The range of real constants is much greater than integer constants, which is expressed as 3.4e38 to 3.4e38. iii. Character Constants A character constant is defined as a single alphabet, a single digit or a special symbol enclosed within single quotes (r). Rules for constructing Character constants a) The maximum length of character constant can be 1 character. b) The quotes within the character is enclosed must point to the left as a. c) The characters constant have integer values determined by computers ASCII character set. d) The range of character constant is 128 to +127. Secondary Constants are as follows: Logical Constants A logical constant refers to either of two values zero or non-zero. Zero is treated as false whereas non-zero value is treated as true. eg: 12, -24, 1.7, are logical constants with true value whereas 0 is a logical constant with false value. These constants help solving logical expression and complex conditions easily. ii. String Constant A string constant is a combination of characters enclosed within double quotes (India). Some special characters like backslash are included as a part of string constant. Each of the string constant is ended with special character called null character represented as \0 that acts as a string terminator but it is not displayed on the screen. iii. Pointer Constants These include the name of an array without subscripts and the name of a function without parentheses. A string literal actually is an instance of a constant pointer, since its value is a pointer to the string. i.
5) No variable name may be a keyboard. This rule means we cannot give a variable a reserved name such as int. 6) No special characters, such as a blank space, period, semicolon, commas or slash are permitted in variable names.
6) Increment and Decrement Operators (a) + + (Increment operator) This operator increments the value of the operand by one. E.g.: if a = 23, the expression a+ + will increase the value of a by 1 that means now the value of a will become 24. (b) - - (Decrement operator) This operator decrements the value of the operand by one. For example, if a = 23, the expression a- - would return 22. These operators can be used either before i.e., prefix or after i.e., postfix to the operand. In both the cases the value of the operand is incremented by one. But if the increment or decrement operator is used in an expression that has to assign a value to some other variable, there is a difference between postfix and prefix notation. In the prefix form, the operand is incremented or decremented before the value is obtained expression. In the postfix, the original value is used in the expression and then the operand is modified. For example, consider the following expression int a = 10; int b; b = ++a; Here, there are two things to be done. One job is to assign the value of a and b and secondly, the value of a is to be incremented. This example is using the prefix notation that means the increment operator is written before the operand a. In prefix form the value of a will be incremented first and then the value of a will be assigned to b. This means b will get the value 11. a however, is incremented so after the expression the value of a will become 11 and that of b will also come out to be 11. Now let us consider the postfix notation. In this notation, the same example can be written as : int a = 10; int b; b=a++; Here also two jobs are to be done, assignment and increment. But since, it is a postfix notation the value of a will be assigned to b first and then the value of a will be incremented. Hence in this type of expression the value of b will be 10 and that of a will become 11. Note that it is the value of b that is affected due to prefix and postfix notations, the value of a will always be incremented. 7) Bitwise Operators The bitwise operators allow you to manipulate individual bits in a number. Bitwise operators perform Boolean algebra on the corresponding bits in the arguments to produce the result. These are special operators used for low level programming. These operators are used for the manipulation of binary data (bit). Bitwise operators should not be of float or double type. The six types of bitwise operator are: & Bitwise AND | Bitwise OR ^ Bitwise exclusive OR << Bitwise left >> Bitwise right ~ Bitwise NOT These operators are used for addition, multiplication, shifting and negating the binary data (bits). These operators are faster than any other operators as these operate in a part of the memory. These operators only operate on char or integer data types. It can be sign, unsigned, short or long. 8) Special Operators These are used for special purposes in C++ language. These operators are used in pointers, structures and unions etc. some special operators are: (i) Unary Operator The unary operator like plus(+) and minus (-) figures out the usage of an expression. The unary minus produces the negative of the value and the unary plus provides symmetry with unary minus. The unary increment (++) and unary decrement (--) increase or decrease the value by 1 respectively. The last unary operators are the address of (&), dereference (* and ->) and cast operators in C++ and new and delete in C++. These are used with pointers. e.g. x = ++a 7 * (-3) (+2) * (-7); (ii) Comma Operator When number of statements occur in C++ program having a relationship between expressions then we can write all the expressions or statements in a single expression using comma operator. e.g. a=12; b=10; c=a+b; can be written as c=(a+12,b=10,a+b);
(iii) Sizeof Operator The sizeof() operator stands alone because it gives you the information about the amount of memory allocated for data items. Thus it tells you the number of bytes used by any particular variable. It also gives the size of data type with no variable name. e.g. cout<<sizeof(double) = <<sizeof(double); (iv) Type Operator the type operator will automatically change one type of data into another if the circumstances allow it to. For instance if you assign an integer value to a floating-point variable, the compiler will secretly call a function to convert int to float. Type operator is used for conversion purpose. So it is called convert operator. This operator converts float data type in integer data type. The syntax of type operator is: (type) v or c; where v is variable (v) Pointer Operator There are two pointer operators used in C++. These are & (address) and * (indirection). (vi) Explicit Operators These are keywords for bitwise and logical operators. These keywords are: Keyword AND OR NOT NOT_EQ BITAND AND_EQ BITOR OR_EQ XOR XOR_EQ COMPL Meaning && (logical AND) || (logical OR) ! (logical NOT) != (logical not-equivalent) & (bitwise AND) &= (bitwise AND assignment) | (bitwise OR) |= (bitwise OR assignment) ^ (bitwise exclusive OR) ^= (bitwise exclusive OR assignment) ~ (ones complement)
if (condition) statement; If there is more than one statement to be executed in case the condition is true, than You would be required to include all such statement in a pair of curly braces as Shown below: If (condition) { Statement } Failure of doing so will result in the execution of just the immediate statement after the if condition. Rest of the statement will become ineffective form the if clause. The operation of if statement is
Test Expression
False
True Body of if
Exit
For example, to check the identity of a person named Mahesh and display an Appropriate message, we use the if condition as follow: If (identity = = 1024) { cout<<Found Mahesh; } The if-else statement The statement enclosed within the curly after the condition of the if clause would be executed only if the condition of is true. If you want to execute some statement if the condition is false, you can do this using else i.e., if condition is false the control moves to statement following else. The if-else statement helps reduce the complexity of a program to some extent and also improves its readability. The syntax of if-else statement is: if (condition) { statement; } else { statement; } For example, to find whether the number is odd or even if (number%2 = = 0)
{ cout<<the number is even; } else { cout<<the number is odd; } The if-else statements can also use the following syntax: (condition)? Statement1: Statement2
False
Body of if
Body of if
Exit
Nested if - When we combine several if statements, it is referred to as nested if statement. This improves the flexibility in programming. In these statements the control is moved to the next if statement only if the condition is true and after performing the first statement the next if condition is checked and if this is also true, then the second statement is performed. In case, the first condition is false, the control skips the following statements of both if conditions and moves to the else part, if specified. The syntax of Nested-if statement is: if (condition 1) { statement 1; if (condition 2) { statement 2; } } For example, to check if the identity of the person is 1024, display an appropriate message and then check if this age is greater than 25 and then display another message. If you make the program as shown below: if (identity = = 1024) { cout<<found match; } if (age> 25) { cout<<age matched; } here condition for age is checked separately from that of identity. In this case, if the age greater than 25 and the identity is not equal to 1024, then also the message is displayed. But actually it is required that the age verification should be checked only if the identity verification is true. The solution to this problem can be done through nested if as shown below: The syntax of the nested if-else statement is: If (condition 1) { statement 1; if (condition 2) { statement 2; else statement 3; } else
statement 4; }
Test Expressio n
Exit False
for example, to display the numbers from 1 to 10 main( ) { int a = 1; /* initialize the variable */ while (a <= 10) { cout<<\n<<a; a+ +;} /*increment the value of the variable*/ } In this program, first the condition is checked if it is true, then the value of a is displayed as 1, then the value of a is incremented and again the condition is checked. The process continues till the value of a is less than and equal to 10. Do-while loop If the condition in the while loop is initially false, then the body of the loop is not executed at all i.e. it first checks the condition and then performs the statement, but in the do-while loop the statement within the loop
10
is performed atleast once irrespective of the condition. In do-while loop the condition is given at the end i.e. after the body of the loop. The syntax of the do-while loop is: do { statements } Body of loop while (condition);
Test Expression
False Exit
True
For example, to display the nos. from 1 to 10, using do-while loop, the program will be as: main ( ) { int a = 1; do { cout<<\n<<a; a + +; while (a<=10); } } In this program, first the value of a is displayed as 1, then the value of a is incremented and the condition is checked for whether the value of a is less than or equal to 10. If it is true the body of the loop is performed otherwise the statements within the body of the loop are skipped and control is transferred to the statements written immediately following the condition. Thus, we see that a would have been displayed even if the condition were false for the first time. For loop In while and do-while loops the variable whose value is checked in the condition is initialized outside the body of the loop. Inside the body of the loop the variable is incremented or decremented as required. For loops with smaller body these are quite satisfactory but for bigger loops having larger number of statements it could become quite difficult to check for what is the initialization statement and to search the increment or decrement statement inside the body of the loop. for provides a better solution for this problem. In for loop the initialization, condition and increment or decrement can be done at one place, in the starting of the loop. The syntax of the for loop is: for (initialize variable; condition; increment or decrement variable) { statement }
11
Initialization Expression
Increment Expression
Here, the variable is initialized first, then the condition is checked. If the condition is true, only then the statements forming the body of the loop will be executed. After the execution of the statements the increment or decrement operation is performed and after that the condition is checked again. If it is still found to be true, the statements are executed once more, then the increment or decrement operation is performed and thus the process goes on till the condition does not become false. For example, to display the nos. from 1 to 10 the program can be written as: main () { int a; /* no need to initialize here */ for (a = 1; a<= ; a + +) { cout<<\n<<a; } } In this program, the first condition is checked, if it is true, then the value of a is displayed as 1, then the value of a is incremented and again the condition is checked for whether a is less than or equal to 10. If it is true, the body of the loop is performed otherwise the control comes out of the loop. the for loop is special for the following reasons: 1. You can declare variable inside the initialization stub 2. You can declare and initialize more than one variable in the initialization stub, all separated by comma. Similarly, more than one variables value can be modified in the increment or decrement stub. Explain the following: Switch statement Switch statement provides better alternative than a large series of if-else statements because any part of the code can be executed on the value of an expression. In this, a particular group of statement can be chosen from several available groups. This selection is based upon the current value of a expression, which is included within the switch statement. The syntax of the switch statement is : switch (n) { case 1: statement; First-case body statement; break; case 2: statement; Second-case body
12
statement; break; case 3: statement; statement; break; case n: statement; statement; n-case body statement; break; default: statement; Default body statement; statement; } Continue statement The break statement, when executed, causes the immediate termination of the loop containing it. C also provides a statement called Continue which terminates only the current iteration of the loop that immediate encloses it, thus causing execution to resume with the next iteration. For example the following function prints out all nos. in the range 1 through 100 which are not multiples of 7: non_7 ( ) Start of loop { int 1; for (i = 1 ; i <= 100; i + + ) { if (I % 7 = = 0) continue; Condition cout<<\n<<i; Continue within } loop Normal loop return Third-case body
The continue statement can easily be replaced by an if statement, but in a loop with a more complex body sometime sit is easier to use continue. Many proponents of structured programming criticize the use of continue because it can always be replaced by an if statement, other approve of is use for the same reason. Many programmers believe that both break and continue are acceptable in a structure programs since they permit control to be transferred only locally. Unlike the break statement, continue has no meaning in the context of a switch statement. If it is used inside one, it causes termination of the iteration of a loop enclosing the switch. If a continue statement is not enclosed within a loop a syntax error is indicated by the compiler. Break statement The Break statement is used to terminate a loop or a sequence of statement in a switch statement. A break statement enforces immediate termination. In a loop when a break statement is encountered, the loop is terminated and the program control moves to the next statement following the loop. It is simply written as break; For example, main ( ) { int i; for (i = 1; i <= 100; i + +) {
13
if (i = = 10) break; cout<<\n<<i; } cout<<\nOut of the loop; } Goto statement The goto statement is used to alter the normal sequence of program execution by transferring the control to some other part of the program. The control may be transferred to any part of the program. The goto statement is written as goto label; where label is the identifier used as the target where the control is to be transferred. For example, main ( ) { int i; cout<<enter the no. of times Pakistan has won against India:; cin>>I; if (i<10) goto change; cout<<India is the best team in Asia; goto end; change: cout<<change the Indian Team; end: } In this program change is the identifier that is used to target at the other statement where the control is transferred. After the first cout statement is written again a goto statement is used to make the control jump after the second cout function call. If this had not been done after executing first cout statement the control would come to next cout statement and the message, Change the Indian Team would also be printed.
Q. What are functions? How do you declare, define and call a function in C++?
Ans. A function groups a number of program statements into a unit and give it a name. The most important reason to use functions is to aid in the conceptual organization of a program. Dividing a program into functions is as one of the major principles of structured programming. Another reason to use functions is to reduce program size. Any sequence of instructions that appears in a program more than once is a candidate for being made into a function. The functions code is stored in only one place in memory, even though the function is executed many times in the course of the program. Thus functions serve as subprograms and procedures in C++. The components to execute functions in C++ are: Function declaration Calling the function Function definition Function declaration The most common approach is to declare the function at the beginning of the program. The syntax for declaring a function is Data-type function-name(argument list); Here data type can be int, float, char E.g. void starline(); The declaration tells the compiler that at some point we plan to present a function called starline. The keyword void specifies that the function has no return value, and the parenthesis indicate that it take no arguments. The function declarations are terminated with a semi-colon. It is a complete statement in itself. Function declarations are also called prototypes since they provide a model for the function. They tell the compiler a function that looks like this is coming up later in the program, so its all right if you see references to it before you the function itself. Calling the function The function is called when the function name is given. E.g.
14
starline(); This is all we need to call the function: the function name followed by parentheses. The syntax of the call is very similar to that of the declaration, except that the return type is not used. The call is terminated by a semicolon. Executing the call statement causes the function to execute; that is control is transferred to the function, the statements in the function definition are executed and then control returns to the statement following the function call. Function definition Finally we come to the function itself, which is referred to as the function definition. The definition contains the actual code fro the function. Eg void starline() // declarator { for (int =0;j<45;j++) // function body cout<< * ; cout<< endl; } The definition consists of a line called the declarator, followed by the function body. The function body is composed of the statements that make up the function, delimited by braces. The declarator must agree with the declaration. It must have the same function name, have the same argument types in the same order and have the same return type. Notice that the declarator is not terminated by a semicolon. As with loops the entire function definition including the declarator, opening brace, the function body, and the closing brace is considered to be one program statement. The following shows the syntax of the function declaration, function call and function definition void main() { void func1(); Return Semi-colon type FUNCTION DECLARATION func1(); Semi-colon .. FUNCTION CALL .. .. } void func1() No Semi-colon { Return FUNCTION FUNCTION DEFINITION type BODY } No Semi-colon Thus in short we can term the working of functions as following: Component Declaration (Prototype) Call Definition Purpose Specifies function name, argument types, and return values. Alerts compiler and programmer that function is coming up later Causes the function to be executed The function itself. Contains the lines of code that constitute the function Example void func();
Declarator
15
16
functions. By default, any variable defined in a function is interpreted as an automatic storage class unless it is specified. The features of automatic storage class variables are as under: i. It is stored in memory. ii. Any value can be assigned to a variable when declared and this value is called a garbage value. This is done only when the user does not initialize the variable with some specific value. iii. The scope of these variables is local to the block in which they are defined. iv. The life of a variable is till the control is in the block. As soon as the control is out of the block, the value of the variable is lost. (b) Static storage class The variables defined in static storage class have the same scope as that of automatic storage class i.e. they are local to the function in which it is defined. They cannot be accessed outside the function where they arte declared. These variables are defined in the same manner as automatic except that the variable declaration must begin within the key word static. The features of static storage class variables are as under: i. These variables are stored in memory. ii. The variable declared is initialized by a default value 0, if not initialized by the user. iii. The scope of the variable is local to the block in which it is defined. iv. Unlike automatic variables, static variables retain their value throughout the life of their program. Thus, if a function is existed and reentered later, static variable retain their value. (c) Register storage class The variables defined in register storage class are also local to the function in which they are declared i.e. they have local scope. These cannot be used in another function if declared in some specific function. These are also declared in the same way as automatic or static but are declared by using the keyword register. The feature of register storage class variables are as: i. These variables are stored in CPU registers. A value stored in CPU registers can be accesses faster than that stored in memory. ii. These variables are assigned any garbage value when declared. iii. These variables cannot be accessed out of the function in which they arte defined. This means that they have local scope. iv. These variables persist the value until the control remains in the block where they are defined. As soon as the control is out, life of the value is ended. Loop variables are the most frequently used as register storage class variables. When we declare a variable as register, this means that these are stored directly into the register, which performs operations. Unlike, memory there is no need to fetch the variables from register, as they are stored there it self. In spite of this advantage a limit of storing variables as register is that if the CPU register are busy performing some other operations, then the variable stored in the register would not get priority but will be treated as an automatic storage class variable. Another disadvantage is that it does not support all types of variables like float, double etc. As they require a large storing capacity. (d) External storage class The variables defined in external storage class do not have a local scope but a global scope. These variables persist the same value from functions to functions. They can be accessed in any of the function. These variables are declared outside of all functions, and can be made available to all functions that need to use them. The features of external storage class are as follows: i. These variables are stored in the memory of computer. ii. By default, the initial value of the variable is set to zero when declared, if the user does not initialize it. iii. The scope of the variable is global. These variables are also called External variables as they can be accessed in any of the function. a variable declared globally as an advantage as if a value is assigned to it in one function, this value can be used within another function that access it. iv. These are available, till the programs execution does not end.
Q. Why is the purpose of Return statement in C++? How does the return statement work with functions?
Ans. Return statement is the last statement of a function. The main reason for executing the return statement is that when it is executed the control moves to the calling statement. Whether a function send back any value to the calling function or not but there must be the use of the return statement with or without the return value. Thus the return statement communicates the result of the operation of the called function to the place where the call is
17
made. It transfers the execution control to the location where the function was accessed. The general syntax for return statement is: return; or return variable; or return(expression); or return(variable); The return statement gives either a single value or a number or a character. It can be empty also. E.g.: void main() { int x, y, z, mul(int, int); cout<<Enter the value of x and y:<<endl; cin>>x>>y; z=mul(x, y); cout<<Product is:<<z; getche(); } int mul(int p, int q) { int s; s=p*q; return(s); } Functions and Return Statement Sometimes a function program takes value from the main program and sometimes it does not. On the basis of this concept we categorize the function programs in three types: (a) Function with no argument and no return values In this category main program will not send any argument and also function subprogram will not send any return value. Function1() void function2() No argument { { statement; statement; statement; statement; No return function2(); return; statement; } statement; } (b) Function with argument and no return value Here main program will send actual argument value, but called program will not return any value to the main program or the calling program. Function1() void function2() With argument { { statement; statement; statement; statement; No return function2(); return; statement; } statement; } (c) Function with argument and with return value In this case main program or the calling program will send actual arguments and then on verifying the values the called program or the function will send back the return value. Function1() With argument { int p, r, t, si; int function2(arg, list); int function2(int a, int b, int c) { statement; statement;
18
With return
statement; return(z); }
19
20
As arrays are accessed by their index number, the dot operator accesses the members of the structures i.e. Structure-variable.member-varaible Thus, to access the three members of structure employee, we say: e1.name e1.address e1.salary To assign value we write as follows: Strcpy(e1.name,Tom); Strcpy(e1.address,12/2 New York); e1.salary = 500215;
21
{ cout<< e1.name<<e1.address<< e1.salary); } In other words, structure is declared global so that it becomes known to all functions in the program. Thus the relationship of structure with functions can be viewed as: (a) Passing structure to a function Here the structures can be passed to the functions as arguments. (b) Function returning structure All he values can be computed in the function programs and return a combined value of whole structure back (c) Passing array of structure to function A complicated passing of an array of structures to the function is a difficult job, but the passing of array becomes very easy by using the passing of array as an individual element.
The advantages or uses of pointers are as follows: i. The pointer enables the variables which is used outside the function or used in the another subprogram. ii. Pointer increases the execution speed of the C++ programming. iii. Pointer reduces the length and complexity of the program. iv. Pointers are more efficient in handling the data table i.e. two-dimensional arrays. v. Use of pointer to the character array or the string saves the storage space in the memory. vi. Pointer gives accurate result. vii. We can make C++ programming easier by the use of the pointer. viii. Pointers have a direct link with structure and union. ix. By using pointer, we can declare less number of variables in the memory.
22
this data item. This data item can be accessed if you know the address of the memory cell where the value of this data item is stored. Therefore, when you say &a this would return the address of the variable a and if we simply say a this would return the value of the variable a. Now, when we want to access the value of a particular variable by calling its address, we write the expression *(&a), this means the value of a variable a. For example, main( ) { int a = 10; cout<<Address of a = << &a; cout<<Value of a = <<*a; cout<<Value of a =<< a; The output of the above program would be: Address of a = 4002 Value of a = 10 Value of a = 10 Thus we can use the pointer in different ways as: &*(variable) address of the value stored *&(variable) value of the pointer *&*(variable) value of the variable through pointer
Thus, you can see that the address of a is stored in b which itself is stored at another location i.e. 6008. You need to declare the variable b before you use it. But, as this would not be an ordinary variable but a variable containing the address of some other variable so this would be declared as a pointer, which points to some others variable address. As, int *b; Thus, this expression means that if printed, it would display the value of the address of the variable it points i.e., 4002 because it points to location 4002 which consists of value 10.
23
cout<< p<< <<*p; p+ +; } } The output of the above program will be: 4000 10 4002 20 4004 30 4006 40 4008 50 Thus, the address of the first array element can be expressed as either &arr[0] or simply arr. Pointers are linked with arrays having two types: (a) One Dimensional Array Pointer - The address of an one dimensional array element through pointers can be computed as: Address of x(element no.) = base address + element no. * scale factor of data type (b) Two Dimensional Array Pointer Pointer with two dimensional array varies according their addresses. The syntax for this is: data-type(*array-name)[column-size];
24
cout<<\n<< i ; /* i will be 30 here */ } void fun(int *p) { *p = 30; } Here, we can see the address of variable i is passed to the function named fun using ampersand. While receiving the variable, p is declared as pointer to int in fun. In fun, the value of i is accessed using asterisk(*). Thus, after function call the value of i printed will be 30. Functions returning pointers The way functions return data type, similarly, a function can return a pointer. To make this possible we had to declare the function as a pointer, example, int display( ); /* function declaration as returning pointer */ For example, to find the greater of 2 nos. void main( ) { int a,b, *c; int *greater(int, int); cout<<enter two nos; cin>>a>>b; c = greater(a,b); cout<<greater number is << *c; } int *greater(int i, int j) { int *p,*q; p = &i; q = &j; if(*p >= *q) return (p); else return(q); } In the above program, when you pass the values of a and b to i and j, we assign their address to p and q and then check for the greater by using pointers. The function returns the pointer i.e., the address of the greater number and then display its value.
10
4002
6008
4002 6008 7024 What happens is that b stores the address of a. Thus, if we print *b it would give the value of a i.e. 10, whereas c contains the address of b which itself is a pointer to a. This is what is called pointer to pointer. Thus we say cout<< **c;
25
Output will again be 10. Pointer to pointer is also used to write multi-dimensional array pointers to objects. The pointer to a pointer is form of multiple of indirection or a class of pointer. It contains the address of the second pointer i.e. it points to the variable that contains the value desired. The general syntax used for the pointer to pointer is: Data-type **pointer-name ; Where data-type can be integer or float and pointer-name is the name of the pointer. The sign ** signifies the pointer to pointer. E.g. int **p; Where p=pointer which holds the address of another pointer.
26
{ private: data-type1 data-member1 ; ---------------------------------data-type n data-member n; member-function( ) ; operations ; list of functions ; public: data-types data-members ; member-function( ); operations ; protected: data-type n data-member n; operations ; list of functions ; }; class class-name v1, v2, v3,, vn where class keyword private, public, protected three levels of a class data-member arguments v1, v2, ..vn list of variables or objects So a class is an operation which is used to name a class, to declare its data variables and data functions or methods or interface operations of the class. In a class at least one of the following items is necessary: Data, function, classes (sub-classes), enumerations, bit fields, friends, data-type name
27
data-type n data-member n; operations ; list of functions ; The working of protected is similar to that of the private class. Global Class A class is said to be global class if its definition is outside the bodies of all function in a program. It means that an object of a global class can be declared from anywhere in the program. Local Class A class is said to be local class if its definition occur inside a function body. It means the object of this class type can be declared only within the function in which class is declared. Global Object An object is said to be a global object if it is declared outside all the functions bodies and it is available to all functions in the program. It means global object can be used anywhere. A global object can only be declared in a global class type. Local Object An object is said to be a local object if it is declared within a functions. It means local object is available only to the function in which it is declared so it cannot be used the function declaring it. A local object can be created from both global as well as local class type. Inline function The inline functions are designed to speed up the programs in C++. All the functions are defined in the class and are default. The inline functions tell the compiler to replace the function code where the function is called in the program. User can make a function inline by typing the keyword inline before the start of the function. (Why is inline function used in C++?) Mostly a function is used to reduce the size of the program. Whenever a function is called, control is transferred to the function. If a function is called from the calling function number of times, then the control has to be transferred to the function every time and so there be lot of overheads used. To call a function many times space has to be used to pass parameters to it by allocating storage for its local variables etc. So it is beneficial to declare a function inline. Inline function is a compact function calls. These functions are recommended only for functions having few statements. An inline function should be placed above all the function that call it. Inline functions run faster than the normal functions because its calling overhead consumes less memory space. If a function is called five times then five copies of the function are inserted into the code. The syntax for inline function is: Inline data-type function-name(argument list) { body of inline function ; } The other advantages of inline functions are: a) It reduces the size of the object code. b) It increases the execution speed of the program. c) It will compact the function calls. Friend function (Q. Why do we use friend functions?)A friend function is a non-member function that can access private and protected members of the class. A friend class can also access classs private and protected members. The prototype declaration of the friend function requires use of keyword friend before it. When two or more than two classes relate with each other in a program, very closely then a friend function interlinks these by sharing the private and protected data member and member function t make the full use of resources. The syntax of friend class is: Friend data-type function-name(argument list) ; The advantages of a friend function is as follows: a) Friend function can be declared anywhere in the class. b) A function may be declared as friend to more than one class. c) A friend class can access the members of another private and protected classes. d) By using the keyword friend member classes can be related to each other one-directionally e) Friend attribute depends only upon its original declaration and definition. f) It can be called like any other normal function.
28
g) Friend function cannot access the member of the class directly and these can be accessed through object name and dot operator ( . ) which is also called membership operator. h) A member function of the class operates on the members of the objects used to call it, while a friend function operates upon the objects passed to it as arguments. i) Friend functions can access both private and public members of the class while non-members can access only public members of the class. j) The keyword friend will appear with declaration of the function inside the class definition and not with the definition of function outside the class definition. Constant function A constant function is a member function that can modify the data. The keyword const is used to access this function. The syntax of the constant function is: Const data-type function-name(argument list) ; Nested function A nest member function is any member function which can call another member function in the same class. The syntax for nested function is as follows: Data-type classname : : function-name(argument list) { member function( ) ; } Static function A static function that type of function which can access only the static members of the class. A static member is always associated with the class rather than any instance of the class. The keyword static is used to precede the member function to make a member function static. It uses only the static data member of the class. The static member function acts as global for members of its class without affecting the remaining program. The main purpose of static member is to reduce the need for global variables by providing alternative that are local to a class. The syntax for static function is as: Static data-type function-name(argument list) ; Virtual function These are used to handle some specific tasks related to classes and objects. A virtual function is linked with concept of polymorphism. The keyword for virtual function is virtual. A virtual function is basically used when a pointer calls it and the class of the object pointed to determine which function definition is used.
29
data-type member1; data-type member2; data-type membern; }; struct tagname v1, v2, ., vn;
private: data members; member function; public: data members; member functions; protected: data members; member functions; }; class tagname obj1, obj2,, objn;
30
Here the return-type be either int or float or char or void etc. By using the scope resolution operator, several different classes can use the same function name. When a member function calls another function of the same class then there is no need of membership label. The membership label will resolve their identity and scope.
Q. What are Constructors? Why are Constructors used in C++? What are the properties of Constructors?
Ans. A constructor is a special member function used for automatic initialization of an object. They are used for initializing values to the member data element of a class. In C++ a constructor is a member of class and has the same name. C++ defines a constructor by default if it is not defined by the user. A member data can be initialized in a class using a constructor and modified outside the class provided the member data are declared in public. The syntax for defining a constructor is: Class class-name { private : data-type data members; public : class-name( ); // constructor defined } For example class Player { int health; int strength;
31
int agility; Player(); Player(int s, int a); void move(); void attackMonster(); void getTreasure(); }; // constructor - no return type // alternate constructor takes two parameters
Use of Constructors Constructors in C++ are used to initialize the value of object for the compiler. When an object is created for a program then it is only the programmer who knows what type of object is used and how it is initialized. IN case where the programmer fails to call assign( ) public member function during the program then the object will be full of garbage and it will provide compilations to the program. This will cause the program to halt or interrupt it. The solution to this problem is to let the compiler initialize the value the object as the compiler knows when the object was created. Every time an object is created, the compiler will automatically initialize it by involving the initializing function. Thus it becomes the compilers responsibility if and only if the initialization function bears the same name as that of the class and so it is a constructor. In other words, a constructor for a class is needed so that the compiler automatically initializes an object as soon it is created. A class constructor can be called of its defined whenever a program creates an object of that class. Properties of Constructors 1. A constructor has no return value. 2. The void type cannot be used. 3. Constructors can neither be virtual or static function 4. Constructors are called automatically when the objects are called. 5. Initialization of objects are performed under classes using constructors 6. If no constructor is defined, the compiler will provide default and copy constructor automatically 7. Member function can be accessed within a constructor function 8. A constructor can have default argument 9. Private and protected constructors are operated only with a friend function while a public constructor works with member functions only 10. Commonly constructors are public 11. It is not possible to copy the address of a constructor 12. Constructors cannot be a member of unions. 13. Constructors cannot be inherited 14. Memory is provided to the constructors by using call functions such as new( ) and delete( ) operators. 15. Member functions can be called from a constructor 16. The name of construct is the same of its class.
Q. What are Destructors? Why are Destructors used in C++? What are the properties of Destructors?
Ans. Destructors are used to destroy the objects created or initialized by constructor when they are no longer required. Destructors are used for redefining the objects which were created by the constructors. A destructor function also has the same name as that of its class but it is preceded by ~ symbol. The syntax for defining a destructor is as: ~ constructor-name ( ); or ~ class-name( ); For example Player::~Player() { strength = 0; agility = 0; health = 0; }
32
Like the constructors, the destructors also do not have any return type and arguments. Destructors are important in classes when dynamic memory allocation is used. In dynamic memory allocation technique, the memory space is created by new( ) and is removed by the delete( ), which is defined in destructor as: ~class-name(void) { delete variable-name; }; Use of Destructors The main purpose of destructor is to free the memory space when objects of the constructors are not used. These objects occupy unnecessary space and it is a good aim to free the memory for the allocation of other objects. Thus destructors are used. This can explained with an example. If a constructor is to open a file and a memory area is provide to it, the constructor will also allocate memory space to other objects that are linked with it. When the constructor is not required, there is a need to reallocate the memory space before the objects are destroyed. The destructor plays its role here by closing the file first and then releasing the memory area from the constructor. Thus destructor and constructor goes side by side. Properties of Destructors 1. Destructors are called automatically when objects are destroyed. 2. They may not be static 3. Destructors cannot be inherited 4. Destructors do not have any arguments and not also have any return type value 5. Destructors cannot be the members of unions. 6. Member function can be called or accessed within a class 7. Address of destructors cannot be copied. 8. No arguments can be provided to destructors. 9. Destructors can be accessed in public, private or protected. 10. If a class has a destructor, each object of that class will be initialized again before the object goes out of scope. Q. What are the types of Constructors? Explain them. Ans. Default Constructor A constructor that accepts no arguments is called the default constructor. Default constructors create objects like the variables of other data types. E.g. Class abc m1; Default constructors are further categorized in three ways: a) Default construct by the compiler When a user-defined class does not contain a properly defined constructor, the compiler automatically gives a default constructor that has no arguments. Class abc { int a; public: void read(); void write(); // member function }; main( ) { class abc m1; // uses default constructor m1.read(); // object m1 m1 write(); b) Default construct by the programmer without default argument When a default constructor is provide by the programmer without any argument or with or without any initial value. Any type of constructor can be defined inside the class definition as inline function or outside the class definition. Class abc :: abc( )
33
{ a = 0; b = 0.0; } c) Default constructor by the programmer with default argument Here default constructor is provided by the programmer with at least one argument and the value in the argument is initialized. Class abc { private: int rn; float fees; public: abc (int a=20, float b=1200.25); void write(void); }; abc :: abc(int a, float b) { rn = a; fees = b; } void main() { class abc m1(32); m1.write( ); abc m2 (54, 320.23) m2.write( ); } Parameterized Constructor The constructor which may take arguments is called parameterized constructor. This type of constructor allows the programmer to initialize the various data elements of different value when they are created. This is done by passing different values as arguments to the constructor function when the objects are created. The syntax used for this declaration is as: Class class-name { private: .. ; .. ; public: class-name(argument list) { ; .. ; ; } // parameterized constructor }; In a parameterized constructor, the compiler will display an error if initial values as arguments are not provided. Thus with a parameterized constructor, the initial values must be passed as the time of object creation. This can be done by two methods a) Implicit Call and b) Explicit Call Implicit Call is calling a constructor when the constructor name is not given in the statement. This is an easy way to use the initialization of values to parameter. e.g. abc m1(20, 534.56, A) // implicit call Explicit Call is done by calling a constructor with its name with the arguments and objects. It is a temporary call as it is removed immediately when it is not required.
34
//explicit call
Copy Constructor A copy constructor is a constructor which is used to initialize the value of an object by copying value of an object by copying values of another object of the same class. It is a constructor of the form (classname &). The syntax to use a copy construct is: Class-name (class-name or constructor-name &object-name); or Constructor-name (class-name or constructor-name &object-name); If a copy constructor is not defined, then compiler will automatically create it and place it in public. A copy constructor takes reference to an object of the same class an argument. The process of initializing through a copy constructor is known as copy initialization and it is done under the following two conditions: a) When an object is passed by value A pass-by value method requires a copy of passed argument to be created for the function to perform on it. So to create a copy of the passed object, copy constructor is called. e.g. void write(abc) // abc is a class then for the following function call write(m1) ; // m1 is an object of the abc type So the copy constructor would invoked to create a copy of the m1 object for use by the write( ) function. If no copy is created in case of pass-by reference, then copy constructor is called. b) When a function returns an object, then the copy constructor is called by using the following prototype as: abc write( ); // abc is a class called by the function m1 = write( ); The copy construct would be invoked to create a copy of the value returned by the write( ) and so ssign to the object m1. These are used when the compiler has to create a temporary object of a class object. So copy constructor can also be used only under the circumstances when objects are stated as value parameter of a function. The syntax of the copy constructor is as: Class-name :: class-name(class-name &ptr) or x :: x (x &ptr) where x is the user defined class name and ptr is the pointer to anoher class object. Dynamic Constructor Allocation of memory to objects at the time of their creation i.e. value provided at run time I called a dynamic constructor. The dynamic initialization is very useful to change the value without changing the program. The memory in the dynamic constructor can be allocated with the help of new operator and be destruct with the help of delete operator. The programmer can read new and delete operator in the dynamic allocation later on. By using these dynamic operators, the programmer can dynamically initialize the objects. This also helps in dynamic initialization of the copy constructor.
35
where return-type is the data type like int, float, char void etc. The keyword used for operator is op. Another format for declaration of operator overloading is: return-type or data-type class-name :: operator op (argument list) { body of function; } here operator op is called operator function. Operator function should be either member function or friend function. In operator overloading a friend function will have only one argument for the unary operators and two arguments for binary operators whereas a member function will have no arguments in the case of unary operator and one argument in the case of binary operators. Operator overloading can be done by creating a class that defines the data type that is to be used in the overloading operations then declare the operator function operator op in the public access level of the class. At the end we define the operator function for the implementation of the operations according to the users requirement. There are basically two types of pre-defined operator Unary Operator Overloading and Binary Operator Overloading. Advantages of operator overloading 1) Operator overloading gives new meaning to existing operators. 2) It works with objects 3) Major string operations can be done by operator overloading. 4) Coding becomes transparent 5) Makes codes more understandable. 6) Data conversion can be done by using operator overloading. 7) Operator overloading extends the meaning of various normal operators like +, * , = etc. 8) It can be applied to user-defined data 9) It can make statements very simple and easy to understand. 10) It decreases the size of a complex program 11) All the comparison and string operations like concatenation etc can be solved by using operator overloading.
36
count c1, c2; cout << \n c1 = << c1.get_count( ); cout << \n c2 = << c2.get_count( ); c1++; c2++; ++c2; cout << \n c1 = << c1.get_count( ); cout << \n c2 = << c2.get_count( ); }
// define and initialize // display // increment c1 // increment c2 (postfix) // increment c2 (prefix) // display again
Example for Overloading Binary Operator #include<iostream.h> class abc { private: int a; public: abc( ) // constructor { a = 0; } abc(int b) // overloading constructor { a = b; } abc operator + (abc obj1) { abc add; // binary operator overloading add.a = a + obj1.a; return (add); } void display( ); ~ abc ( ) { } }; void abc :: display( ) { cout<<Final values are<<a; } void main( ) { abc x(30); abc y(20); abc sum; sum = x + y; x.display( ); y. display( ); sum.display( ); getch( ); }
Q. What is Data Conversion in C++? What are different types of data conversion?
Ans. Data conversation Is another type of operation used in C++ which is closely related to operator overloading. C++ handles the conversion of simple data types like int and float automatically but conversions involving user-
37
defined types require some work on the programmers part so data conversion is used for this purpose. The assignment operator = is used to assign a value of one user-defined object to another object of the same type. When both the user-defined object are of the same type and we assign the value of one object to another object using assignment operator, then the values of all the member data items are simply copied into a new object. Such type of operation is called data conversion. During data conversion operation, compiler does not need any special instructions for assigning user-defined object having the same data type. There are three type of data conversion: 1) Conversion between basic types This type of conversion is used when two objects or two variables are of different types. For example if x and y are two variables of int and float type respectively then the expression to assign a value from y variable to x variable is: x=y; We can also convert one type of data type to another type by suing the cast operation. For this purpose cast operator is used. The syntax for cast operation is : v1 = (data type) v2; e.g. x = (float)y ; 2) Conversion between objects of same class and basic type Conversion from built in type like int, float, char, double, etc to object (class type) and vice versa can be done if variable and class are of different type. The conversion from basic type to class type is an easy task. This can be done by using a constructor. If we create a constructor to build an object from int type array, then such type of constructor perform a default type conversion from the arguments type to the constructors class type. e.g. date (float d) { day = (int) d/24; // d in hours month = (int) d/30; // d in days year = (int) d/12; // d in months } void main( ) { date today; flaot p=3600.00; today = p; } The above example will convert basic data type (float d) to the class type object today (integer) Another type of conversion is class to basic type for which the casting operator is used. The general form of an overloaded casting operator function is as: Operator type-name( ) { function statements; } 3) Conversion between objects of different classes In this type of conversion data types of one object class is converted into the data types of another class by using constructor functions. Suppose if we have two object classes x and y then the conversion is done in the following manner: destination class object x = object y of same class ; where object x is an object of class x and object y is an object of class y. When we do conversion from one class to another class, then one class is called the source class and the other class is destination class. Here y is the source class and x is the destination class.
Q. What are the disadvantages of Operator overloading and Conversion? (Operator overloading and Data Conversion dont go hand in hand. Give reasons.)
Ans. The disadvantages are as follows:
38
1) Both have same semantics the operator + is very much similar to the arithmetic + which is used to add a certain number variables. Similarly it is also used to concatenate strings, thus in certain cases this can create problems. 2) Both have same syntax Overloaded operators are used in same way as we use operators for some basic types. So an operator having the same symbol in a particular class can create a problem. If a and b are two different basic types then arithmetic assignment operator having addition operation can be used as: a + = b; the above statement can also be written as a = a + b; It means + operator is overloaded. So though syntax is different but the operation is same. Similarly we cannot overload a binary operator to unary operator and vice versa 3) Show restriction Sometimes operator overloading can create number of restrictions on using the same operator for different purposes. E.g. c = a + b ; will become meaningless if the number of overloaded operator grows too large and used in unstable manner. 4) Create Doubt Sometimes operations done by overloading becomes doubtful. E.g. If we us a overloading constructor and a overloading function having the same operator then for the compiler it becomes difficult to what to do. Thus operator should be in a well-defined way. 5) All operators cannot be overloaded Operators are either unary or binary or some are comparison, assignment and arithmetic operator. Thus it will create a problem if many operators are used for overloading. E.g. dot operator (.), scope resolution operator (::), pointer operator () etc are not used for operator overloading and data conversion.
Feature A
Feature D
Derived from
Feature B Feature A Defined in base class but accessible from derived class
39
2) Reusability is another powerful reason for the need of inheritance. User can add some additional features in sub-class and so can derive a new class from the existing class. 3)It has the transitive nature of inheritance. This means if A is the friend of B and B is the friend of C then C is the friend of A. In other words, if a class A inherits the properties of another class B, which further inherits the properties of B and the so on. Types of Inheritance There are five different types of inheritance: 1) Single Inheritance When a sub-class inherits only from one base class 2) Multiple Inheritances When a sub-class inherits from multiple base classes 3) Hierarchical Inheritance When many sub classes inherits from a single base class 4) Multi-level Inheritance When a sub class inherits from a class that itself inherits from another class. It has a transitive nature. 5) Hybrid Inheritance When a sub class inherits from multiple base classes and all of its base classes inherit from a single base class.
40
body of functions; }; Class C : public B // Class C is indirect derived class { body of functions; }; Here A and B classes work as base class. C is a derived class. Also class B work as direct derived class for the A base class. So a class which is a derived class at one time and work as base class other times is called as indirect base class.
41
c2- -; c2- -; c2- -; // decrement c2 cout << \n c2 = << c2.get_count(); // display c2 countdn c3 = c2- -; // create c3 from c2 cout << \n c3 = << c3.get_count(); // display c3 } This program uses two new constructors in the countdn class. Here is one argument constructor: Countdn( ) : counter( ) { } This constructor has an unfamiliar feature that is the colon (:) followed by a function name. This constructor causes the countdn( ) constructor to call the counter( ) constructor in the base class. In main( ), when we say Countdn c1 ; The compiler will create an object of type countdn and then call the countdn constructor to initialize it. This constructor will in turn call the counter( ) constructor which carries out the work. The countdn( ) constructor could add additional statements of its own but in this case it doesnt need to, so the function body between the braces is empty. The statement countdn c2(100) in main( ) uses the one argument constructor in countdn. This constructor also calls the corresponding constructor in the base class as in Countdn(int c) : counter(c) { } This construction causes the argument c to be passed from countdn( ) to counter( ), where it is used to initialize the object. In main( ) after initializing the c1 and c2 objects we increment one and decrement the other and then print the results. The one argument constructor is also used in the assignment statement as: Countdn c3 = c2- - ; Overriding member function If we apply a operation to insert more data items in an array or a list or a stack then the program will exceed because data is placed beyond the data range or the size of the array, list or a stack. Similarly if we try to delete or remove too many data item or elements from an array or stack or list beyond its lower limit then it will display the list as empty. So to avoid this problem, overriding member function is used. This involves the use of a new class which derived from the base class. Objects of derived class and the base class are same. The objects of the overriding member function warns the programmer when insertion of data elements is beyond its limit or deletion of data elements is beyond its lower limit. An example of overriding member function is: #include <iostream.h> #include <process.h> const int max=100; // maximum size of stack class stack { protected : int st[max] ; // stack : array of integers int top ; // index to top of stack public : stack( ) // constructor { top = 0; } void push(int var) // put number on satck { st[++top] = var; } int pop( ) // take number off stack { return st[top- -] ; } }; class stack2 : public stack { public : void push(int var) // put number on stack { if (top < max) // if stack is not full
42
stack : : push(var); // call push( ) in stack class else { cout<< \n Error! The Stack is Full ; exit (1) ; }} int pop( ) // take number off stack { if (top > 0) // if the stack is not empty return stack : : pop( ); // call pop( ) in stack class else { cout<< \n Error! The Stack is Empty ; exit (1) ; }} }; void main( ) { stack2 s1; s1. push(11) ; // push values onto stack s1. push(22) ; s1. push(33) ; cout<< endl << s1.pop( ); // pop values from stack cout<< endl << s1.pop( ); cout<< endl << s1.pop( ); cout<< endl << s1.pop( ); } Class Hierarchies (Hierarchical Inheritance) When we set one class as main class and other classes as subclasses and thus the procedure continues then a hierarchy or a tree having one node as parent (root) and other child node (branches) will be represented. Such type of representation of classes is called class hierarchy. Thus in hierarchical inheritance the objects of higher class share the data with the certain number of lower classes. Diagrammatically it can be represented as: MAIN CLASS
SUB-CLASS 1
SUB-CLASS 2
SUB-CLASS 3
SUB-CLASS N
Public and Private Inheritance C++ provides many ways to fine-tune access to class members. One such access control mechanism is the way derived classes are declared for example Class manager : public employee Here the keyword public specifies that objects of the derived class are able to access public member functions of the base class. The alternative keyword is private which is used when the objects of the derived class cannot access public member functions of the base class. Since objects can never access private or protected members of a class, the result is that no member of the base class is accessible to objects of the derived class. The syntax for public inheritance is
43
Class base-class-name { public : data-member ; } class derived-class-name : public base-class-name { statements ; statements ; } for example class A { public : int x ; private : int y ; }; class B : public A { private : int p ; } where A is the base class and B is the derived class. The class B is derived from the base class A and it will access the public. The syntax for private inheritance is as follows: Class base-class-name { private : statement1 ; statement2 ; statementn ; }; class derived-class-name : private base-class-name { x1 ; x2 ; xn ; }; An example for private inheritance is: Class A { private : int x ; public : int y ; }; Class B : private A { int p ; }; The class B is derived from the base class A and it will access all the public member. Multilevel Inheritance In multi-level inheritance, there are different types of level occurring according to the inherited classes. These levels are 1st level of inheritance, 2nd level of inheritance and so on until nth level of
44
inheritance reaches. So classes can be derived from classes that are derived themselves. The syntax to declare the levels is as following: Class A { body of statements; }; Class B : class A // 1st level of inheritance { body of statements ; }; Class C : class B // 2nd level of inheritance { body of statements; }; Here B is a derived class and A is the base class of B and similarly we also define class C which is the derived class of the base class B. Each relationship between the base class and the derived class make the level of inheritance. The procedure continues till the end of the nth derived class or the last derived class. Multiple Inheritances Multiple inheritances is used to remove the limitations that occur in single inheritance. Multiple inheritances has relation or links with number of classes. So a class can be derived from more than one base class, then such type of inheritance that occurs is called multiple inheritance. In other words if there are three classes A, B, C from which class A and class B are the base classes and C is the derived class, then we can say that C is multiple inherited from the class A and B. in other words, multiple inheritance is the process of creating a new class from more than one base class. The syntax for multiple inheritance is: Class A // base class A { statements ; }; Class B // base class B { statements ; }; Class C : public A, public B { statements ; // derived class C which is derived from base class A and B }; Diagrammatically we can explain multiple inheritance as:
BASE CLASS A
BASE CLASS B
DERIVED CLASS C
Function Overloading (Overloaded Function) Function Overloading is an extremely useful feature provided in C++. A function is said to be overloaded when a single function performs many times and thus saves number of comparisons and makes the program more efficient. When two or more functions can share the same name as long as their parameter declaration are different then such situation is overloaded function. This means that we
45
can use the same function name to create functions that perform a variety of different tasks. Function overloading performs one operation on one kind of data but another operation on a different kind. Actually function overloading is a logical method of calling several functions with different arguments and data types that perform basically identical things by the same name. So here each time a function is redefined it use different types of parameters or different sequence of parameters. The number, type or sequence of parameters is called function signature. Function overloading is important because it can help to manage complexity. Advantages of Function Overloading 1) it removes duplicate and repetitive use of function in a program 2) concept classes are easily understood with function overloading 3) errors can be easily debugged 4) source code can be easily manipulated 5) it can create a relationship between the program and the real world Polymorphism Polymorphism is the process of defining a number of objects of different classes into a group and then calling a method to carry out operation of the objects using different function calls. Thus polymorphism means to carry out different processing steps by function having same messages. Actually it treats objects of related classes in a generic manner. In other form when a base class member function can be overridden by defining a derived class member function with the same name as that of the base class member function, then such a concept is polymorphism. The compiler decides which class is to be executed. Polymorphism allows many different types of objects to perform the same operation by responding to the same message. It is the ability to take many shapes and forms. It also helps the programmer to call different functions with a single statement. It has the ability to take more than one form i.e. an operation may exhibit different behavior in different instances. It plays an important role in allowing objects having different internal structure to share the same external interface. Polymorphism is used in implementing inheritance. Polymorphism is sub-divided into two categories as:
POLYMORPHISM
OPERATOR
FUNCTION
FUNCTION
CLASS
Virtual Function and its characteristics A virtual function is used to handle some specific tasks related to class objects. When programmer uses the same function name in both the base and derived classes, then the function in base class is declared virtual by using the keyword virtual before the function name. In virtual function object oriented programming determines which function to use at run time based on the type of object pointed to by the base pointer, rather than the type of the pointer. When a virtual function are used in a C++ program, then that program which calls a function of one class actually can call the function of different class also. A virtual function is a function that is declared as virtual in a base class. We use pointer to base class to refer to all the derived objects. When we use the same function in both the base and the derived classes, the function in the base class is declared as virtual using the keyword virtual, along with its normal declaration. Thus after the declaration of virtual function it is the compilers job to find which function to use at the run time based on the type of object pointed by
46
the base pointer. The base pointer executes the different versions of the virtual function and it is accessed in public. The syntax for virtual function is: Class class-name { private : data member ; member function ; public : data member ; virtual return-type function-name(argument list) ; }; here the return-type can be a data type like int, float, void etc. Characteristics of Virtual Functions 1. Should be declared in the base class. 2. Should be the member of some class else an error is declared. 3. Cannot be a static function. 4. Can be a fiend of another class. 5. Can be accessed by using object pointer. 6. In virtual function process, derived class pointer cannot be used to access an object of the base class. 7. Virtual function can be applied on destructor. 8. The virtual function cannot be stand alone. 9. The prototypes of virtual base class and the derived class cannot be same. 10. When virtual function is called through a pointer to a base class, the derived class is activated. 11. Base pointer can point to any object of derived class. 12. Decrement and increment operation on pointers to derived class object is not allowed. 13. The keyword virtual should not be repeated in the definition outside the class declaration. 14. The declaration of virtual destructor function does not take any argument and no return type and no void also. Pure Virtual Function A pure virtual function is a virtual function with no body. So the body of the virtual function in the base class can be removed. It has only a function declaration. Here the base class becomes abstract class. A pure virtual function can be declared by equating it to zero thats why it is also called empty virtual function. The syntax fro declaring a pure virtual function is Virtual return-type function name ( ) = 0; The pure virtual function is declared in a base class where it has no definition relative to the base class. In such cases, the complier requires each derived class to either define the function or again declare it as a pure virtual function. Thus it cannot declare any objects of its own. In base class, a pure virtual function serves no purpose but it acts as a polymeric interface for the derived class. After declaring the pure virtual function, there is no need to create an object of base class because it is meaningless to call a function with no body. So if a pure virtual function is to be defined in the base class, then either it is declared in the derived class or that function becomes a virtual function. Abstract Classes An abstract class is often defined as one that will not be used to create any objects but exists only to act as a base class of other classes. A class that declares a pure virtual function is called an abstract class. Abstract class can declare pointers for manipulating the objects of the derived classes. An abstract class is used as a base class for deriving. It can contain one or more functions for which there is no definition and no objects can be created using an abstract class however only pointers to an abstract class can be created. A derived class should not become an abstract class because as an abstract class cannot create objects. Binding Binding is a concept that is linked with polymorphism and helps in creating virtual function. Binding in object oriented programming is of two types: Dynamic Binding and Static Binding Dynamic Binding It is implemented in C++ through the use of virtual array having pointers or virtual functions. It is compiled by compilers of each class. It helps to modify and extend the function of a program. Dynamic binding
47
can provide a library of classes which can be used by other programmer without source code. When a function is selected during execution time then such type of link is called dynamic linkage. In dynamic binding an object of a class must be declared either as pointer to a class or a reference to a class. Static Binding When a function is selected during compile time in the normal processing, then such type of linkage is called static binding. By default the compiler of C++ uses the static binding to get efficient results. Function calling also becomes faster in static binding. Virtual Classes The virtual class is used to achieve run-time polymorphism. When a derived class inherits two functions of the same name from two different base classes, a problem arises have to select the function as two copies of the same function are available. A virtual class is a class ensures that only one copy of the function is available. The main difference between the normal base class and the virtual base class is when an object inherits the base more than once. If virtual base classes are used then only one base class is present in the object otherwise multiple copies are found. Virtual Destructors Destructors are used to free the memory space covered by the constructors. The destructor member function of the derived class is not called to the free up the memory space that was allocated by the constructor of the derived class. It is due to the non-virtual relationship of destructor and the message will not reach the destructor under the execution time or static binding. Thus the use of destructor is necessary. An example of virtual destructor is below: #include<iostream.h> class abc { public : abc( ) ; // constructor without virtual class virtual ~ abc( ) ; }; class xyz : public abc { } class abc : : ~abc // virtual destructor { delete [ ]p ; } void main( ) { abc *p = new xyz ; delete p ; } Here a new operator is used to call a constructor automatically and delete operator is used to run the destructor automatically. Object I/O Since C++ is an object oriented language, its reasonable to wonder how objects can be written to and read from disk. The following are the examples that illustrate this: Writing an object to disk The following program shows thw listing of OPERS which asks the user fro information about an object to the disk file person.dat #include <fstream.h> // for file stream class person // class of person { protected : char name[40] ; // persons name int age ; // persons age public : void getdata(void) // get persons data { cout << Enter name: ;
48
cin >> name ; cout << Enter age: ; cin >>age ; }; void main(void) { person pers; // create a person pers.getdata( ); // get persons data ofstream outfile (person.dat) ; // create ofstream object outfile.write((char *)&pers, sizeof(pers)) ; // write to it } The getdata( ) member function of person is called to prompt the user for information which it places in the pers object. The contents of the pers object are then written to disk using write( ) function. The write( ) function takes two arguments: the address of the object to be written and the length of the object in bytes. We use sizeof( ) oprator to find the length of the pers object. The address of the object must be cast to type pointer to char. Reading from the disk Reading an object back from the person.dat file requires the read( ) member function. An example for this is: #include <fstream.h> // for file streams class person // class of person { protected : char name[40] ; // persons name int age; // persons age public : void showdata(void) // display persons data { cout<< \n Name: << name ; cout<< \n Age: << age ; } }; void main(void) { person pers ; // create person ifstream infile(person.dat) ; // create file infile.read ( (char *) &pers, sizeof(pers) ) ; // read file pers.showdata( ); // display person } Character I/O The put and get( ) functions which are member of ostream and istraem respectively, are used to output and input a single character at a time. The following program OCHAR that outputs a string and one character at a time: #include<fstream.h> // for file functions #include<string.h> // for strlen( ) void main( ) { char str[ ] = Time is a great teacher. ofstream outfile(Test.txt) ; // create file for output for(int j = 0; j < strlen(str); j++) // for each character outfile.put(str[ j ] ) ; // write it to file } In this program an ofstream object is created. The length f the string is found using strlen() function and the characters are output using put() in for loop. The string is written to the file test.txt. We can read this file back in and display it using the ICHAR program #include<fstream.h> // for file functions
49
void main( ) { char ch; // character to read ifstream infile(Test.txt) ; // create file for input while(infile) // read until EOF { infile.get(ch) ; // read character cout << ch ; // display it } } The program uses the get() function and continues reading until the EOF is reached. Each character read from the file is displayed using cout, so the entire text is displayed on the screen. String I/O Strings can be written and read in the following ways: Writing Strings The following program give the output of a string to a file #include<fstream.h> // for file functions void main( ) { ofstream outfile(test.txt) ; // create file for output and send text to file outfile << Twinkle Twinkle little star, \n ; outfile << How I wonder what you are! \n ; outfile << Up above the world so high, \n ; outfile << Like a diamond in the sky! \n ; } Here we define an object called outfile to be a member of the ofstream class. At the same time, we initialize it to the file name test.txt. This initialization sets aside the various resources for the file and accesses the file of that name on the disk. Since the insertion operator << is overloaded in ostream, we can use it to output text to the file. When the program terminates the outfile object goes out of scope. This calls the destructor which closes the file. When we run the program the lines of text are written to the file. Ther is no output to the screen. Reading Strings To read the same file we must create an object class ifstream. We do this in the ILINE example #include<fstream.h> // for file functions void main( ) { const int max = 80 ; // size of buffer char buffer[max]; // character buffer ifstream infile(test.txt) ; // create file for input while(infile) // until EOF { infile.getline(buffer, max); // read a line of text cout << buffer ; // display it } } Here the insertion operator doesnot work. Instead we read the text from the file one line at a time using the getline() function which is a member of istream. This function reads characters until it encounters the \n character and places the resulting string in the buffer supplied as an argument. The maximum size of the buffer is given as the second argument. The contents of the buffer are displayed after each line. The output of the ILINE will be the same data written to the TEST.TXT file by OLINE.
50