Object Oriented Programming (OOP) With C++


Table of Contents

1. Some features of C and Introduction to the language C++ - I. – 28) • Basic data types. - Literals (integer, float, Character) - Special character sets. Qualifiers. - unsigned - long - short Variables – declaration and definition and usage. Recursive function. Scope rules and Storage specifiers. - automatic - static - external - register. Operators - arithmetic - relational - logical Type casting. Control flow – Branching and looping statements. - if statement - switch statement - for statement - while statement - do..while statement The break and continue statements.


• • •

• •

2.Some features of C and Introduction to the language C++, II. (29 – 44) • • • • • • • • • • • Array types. Ways of initializing the arrays. Multidimensional arrays. Pointer types. Pointer Arithmetic. Relationship between Arrays and Pointers. Structures. Enumerated Constants. Reference Types. Difference between a Pointer and a Reference. Unions.

3. Object Oriented Programming – Introduction (45 – 55) • • • • Procedural, Structural and Object-Oriented Programming logic. Different implementation of OOP. Introduction to C++. C++ and OOP. - Data abstraction. - Data encapsulation and data hiding. - Reusability and inheritance. - Polymorphism. Differences between C and C++. - Additional keywords in C++. - Comments. - Variable declarations. The scope resolution operator. Default arguments. The new and delete operators. The cin and cout objects.

• • • •

4. Classes and Objects (56 – 68) • • • • • • • • • • • Structures Revisited. Introduction to class. How to define a user-defined variable – class. How to create variables (objects) of class. Access specifiers – Private, Public and Protected. Member functions of the class. Passing and returning objects. Pointers to objects. Array of objects. Initializing the array of objects. The special ‘this’ pointer.

5. Constructor and Destructor Functions (69 – 76) • • • • • Automatic initialization of data members - constructors Constructor with one argument, multi arguments Using the constructor Destructor Default constructor and destructor

6. Operator Overloading (77 – 97) • • Introduction to Operator Overloading. Operator Overloading Fundamentals.

• • • • • Implementing the operator functions. Rules for overloading the operators. Pointer oddities (assignment) and Operator Overloading. Copy Constructor (to solve the problem of initialization). Conversion functions. - Conversion from basic to user-defined variable. - Conversion from one user-defined to basic variable. - Conversion from one user-defined object to another. . Conversion function in source class. . Conversion function in the destination class.

7. Function Overloading and References (98 – 108) • • • • • • • Function overloading. Need to overload functions. Precautions to be taken while overloading functions. Call by reference- definition and usage. Passing and returning reference variables. Why using references is a must in some occasions. Reference oddities.

8. Inheritance I (109- 119) • • • • • • Reusability. Inheritance concept- single inheritance. Defining a derived class. Private, Public and Protected derivations. The access specifiers. Using the derived class.

9. Inheritance II (120-132) • • • • • • • • • • • • • Hiding overloaded functions. Constructor and destructor in derived class. Object initialization and conversion. Nested classes (Container classes). Multilevel inheritance. Multiple inheritance. Problems with multiple inheritance. Multiple inheritance with a common base class. Virtual base class. Abstract class. Pointers to objects. Virtual function. Pure virtual function.

#error directive. . Introduction to template functions.global inline functions . . . Input and Output. (133.class inline functions. Friend functions and Operator Overloading. Introduction to template classes.istream and ostream objects other than cout and cin. #elif. Overloading the extraction and insertion Operators. .the overloaded insertion and extraction operators.#define and #undefined directives . Friend functions.Manipulators. Granting friendship to few member functions of the class. #else and #endif directives. Friend classes.#ifdef. .166) • • • • • • • • • • • • Static member and Static functions. Necessity of friends. . Inline functions. Preprocess or Directives .5 10 Additional features of C++.

The C++ became still popular because it maintains the simplicity of the C Programming language and also makes it more powerful by supporting the Object Oriented Programming concepts. // 10 is a literal constant.automatic.g. . became one of the most popular programming language. can be attributed to the sheer power and simplicity of the languages. Recursive function. Their value is not changed during the course of the program. external. This chapter introduces several features of these languages. The C language has. Scope rules and Storage specifier . Control flow – Branching and Looping statements. sum = num1 + 10. LITERALS (CONSTANTS) Constants are data storage locations whose address is not accessible for the user. 1. Literal constant : represented by their value. register. this chapter prepares you to explore the language C++. Variables – declaration and definition and usage. // sum is a symbolic constant. If you already know C or even if you have not learnt the language earlier. static.1. Qualifiers. e. This rapid popularity. Symbolic constants : represented by their symbols / names. amongst other reasons. over the past few years.6 SOME FEATURES OF C AND INTRODUCTION TO THE LANGUAGE C++ (PART 1) During this session you will learn about: • • • • • • • Basic data types. The break and continue statements.

7 Constants as well as variables have types associated with them.1415F .4e38 2.3. e.535 -32. 1.768 to 32.648 to 2. F. int. 1L. suffixes such as L. 3.294. L are applied only to common decimal notation.295 -2. e. The following table summarizes the data types .483. FLOATING LITERAL They can be written in common decimal as well as scientific notation( floating point representation). 20 // Decimal 024 // Octal 0x14 // Hexadecimal To denote long.967.g.0L .g. INTEGER LITERAL Integer are numbers without fractional parts. l. . unsigned. Char Float Double Size in Bytes 2 2 4 4 2 2 1 4 8 Range 0 to 65.768 to 32767 0 to 4. 1028u.147. 12.8e308 1. 71l( 71 and small L) . By default it is of type double. U.647 -32.147. their sizes and their range.483. Short int.g.767 0 to 65. 8LU. 128U. u can be used. Long int.2e-308 to 1.2e-308 to 3. for a 16bit machine.0E-3. Unsigned int. e. Unsigned long int.535 256 character values 1. 1.2. 2. 3E1. Type Unsigned short int.345L. 1.

4.null string . These are terminated by a null character. 1. digits and some special symbols.5. e. They can also be represented using literal constants .6. e. BOOLEAN CONSTANTS It can hold 2 values – true(1) or false(0). \14 instead of \n for newline. e.g. STRING LITERAL An array of constant characters is represented as strings. ‘2’.g.8 1. Zero or more characters are represented within double quotation marks.7. e. 1. ’a’.’. These are called escape sequences. 1.g. ‘. they work in a different way. SPECIAL CHARACTER SET ( ESCAPE SEQUENCES): When normal characters are preceded with a \ (back slash) . The compiler does this. “ ” -. which are enclosed in single quotes and require a single byte of memory.g. \n – new line \t – horizontal tab \v – vertical tab \” – double quotes. CHARACTER LITERAL Character literals are characters . ‘ ’(blank) -uses a byte.

Note that in the second example the data type is omitted. in which case it defaults to being an integer. Note that the two qualifiers with one variable declaration can also be given. Also note that the letter ‘L’ or ‘l’ succeeds long constants. unsigned arr = 20. long int num = 1234354l. Similarly. if the variable is unsigned. unsigned long int ulinum = 0. If it is known beforehand that the value of a variable will not be signed. then the qualifier long can be used.g. an integer on a 16-bit processor is allocated 2 bytes. then the keyword unsigned can precede a variable. there is another qualifier short.8. . There are many occasions when values to be stored in the variable exceeds the storage space allocated to them. In this case the last two variables can have double the amount of storage and are unsigned.[cc]\n” “ a multiline \ string literal signals its \ continuation with a backslash” 1. This is called as a qualifier. e. or less than an integer. which can store at the most 65535.g. For instance. unsigned int num = 341. which gives storage equal to. thus declaring it an unsigned variable. QUALIFIERS All variables by default are signed ( the sign bit is also stored as a part of the number ). unsigned long ulnum. depending upon the implementation. e. If a bigger number is to be stored in a variable . long emp = 1234321L.9 “a” “\ncc\toptions\tfile.

short int i. RULES FOR NAMING THE VARIABLES: • • • • • e. /* Can have characters. e.g. int poodle int my_stud int _mystud int 4ever int double int Honk-Kong // Valid // Valid // Valid // Invalid starts with number // Invalid keyword // Invalid –(dash) not allowed as it // is a special character.g. cout << 2*2*2*2*2*2*2*2*2*2 for 2^8. therefore this qualifier is not of much use. digits and underscore. All the variables by default are signed.9.10 e. Variables are addressable. Can’t use keywords No limits on the length of the word.g.e. Can start with character or underscore. Are case sensitive i. 1. To find the value of power of some number we may write. Variables help us to reuse the codes. fan is different from Fan and FAN. To find the value of power of some number we may write.. Some implementations have the qualifier signed.10. . The type used in the definition describes the kind of information the symbol can store. 1. VARIABLES Information stored in a variable can change in the course of the program.

There are two terms associated with a variable : 1. } This is flexible compared to previous method but not reusable. l-value (location value) : Address in the memory location where data is stored. 2. This can be a literal or variable name. return res. It prints the literals or values of variables.g. r-value ( read value) : Data.11 cout is equivalent to printf() in C. We can generalize this operation by using 2 variables as follows. int exp ) { for ( res =1 . --exp ) { res = res * val. for ( cnt =1. cnt . } } You can call this function any number of times with different arguments. By using functions we can make them reusable too. pow =10. e. int pow( int val .g. int val = 4. e. exp>0 . Variables can alternatively be called as Objects. ++cnt ) { res = res*val. . cnt <= pow.*/ If we want to find the power of some number or if we want to change the number we have to type the whole sentence again.

e.cpp extern string filename.12 e. Objects or variables can have only a single location. 0 = 1.g. : : // file fileno2. So.‘0’ is r-value literal. THE DEFINITION OF AN OBJECT(VARIABLE ): We can define a variable(set memory to the variable) in the following ways. However.g. e. they can’t be defined twice.g. You can have the same symbol in both l-value and r-value.cpp string filename. they can be declared twice. e. : : The keyword extern informs the compiler that the filename is defined somewhere outside the existing file. Definition sets memory aside for a variable where as declaration just informs the compiler that this variable is defined somewhere in the program. In such cases we can define it in one file and declare it in all the files that use this variable. where ch is l-value. // file fileno1. . ch = ch . double salary. salary + extra = newsal // Error.‘0’.ch1 is r-value symbol.11.‘0’. Some variables may be needed in two or more files. 1. l value must be an // addressable variable and not an expression. // Error. cannot have a literal as l-value. ch = ch1 .g. If you need to declare many variables in different files you can declare once in a header file and include it in files where the declarations are needed.

e. int ival =100. If they are declared locally we have to initialize them as they may have some junk value stored in them. double pr =199. year =1975.99. double sal . special constructors are inbuilt that support initialization. they are initialized to zero by default constructors( functions that are used to initialize the variables) that are inbuilt . // Sets ival = 0 . initialized to zero. int ival(100). // Local . If the variables are declared globally. k. y .g. . // Can span multiline too. int x. double sal =10.0. wage. wage = sal + 10. int m . e. day = 19.g. int mon = 06. not initialized. d . An object can be initialized with an arbitrary complex expression.0. In C++.g.16. e.a.g. // Sets dval to 0. When more than one variable of same type are needed a comma can be used to declare multiple variables. e. double dval = double() . disc = 0. e.g. void main() { int i. int ival = int(). } You can initialize the variables in the following ways. // Global .13 int month.

n--. RECURSIVE FUNCTIONS Recursion is a process by which a function invokes itself with a condition for its safe exit. } long factorial(int num) // Non recursive { long f=1. void main() { long factorial ( int num). } long factorial(int num) // Recursive { if(n == 1) return (1).num. printf(“ Factorial of 5d is %ld”.factorial(num)).14 double sale( pr * disc ). while ( n) { f = f * n. A typical example is the factorial problem. // Forward declaration of //a function int num. scanf(“5d”. It is best suitable for a recursive problem. printf(“\n Enter a number:”).12. .&num). 1. } return(f). the programs without and with recursive functions are shown below.

All variables when declared within the function are .1 Automatic Variables Automatic variables are variable which are defined within the functions. There are four storage classes : automatic static external register 1. } void main() { print(). by default. cout << “ Value of i before incrementing is :<< i. They lose their value when the function terminates.13. It can be accessed only in that function.13. i = i + 10. SCOPE RULES AND STORAGE CLASSES The storage class determines the life of a variable in terms of its duration or its scope. e. we can explicitly declare them by using the keyword ‘automatic’. However. void print() { auto int i =0.15 else return( n* factorial(n-1)). . cout <<“\n”<< “ Value of i after incrementing is :<<i. are automatic.g. } 1.

} void main() { print().g. void print() { static int i =0. e.13. static variables retain their values over number of function calls. They are declared with the keyword static. The life of a static variable starts. i = i + 10. unlike automatic variables. till the program terminates. is executed and it remains in existence. Static Variables Static variables have the same scope s automatic variables.2. when the first time the function in which it is declared. } Output: . cout << “ Value of i before incrementing is :<< i.16 print(). cout <<”\n”<< “ Value of i after incrementing is :<<i. print(). } Output: Value of i before incrementing is : 0 Value of i after incrementing is : 10 Value of i before incrementing is : 0 Value of i after incrementing is : 10 Value of i before incrementing is : 0 Value of i after incrementing is : 10 1. print(). but . print().

void main() { : : } void fn1() { : : } // FILE 2 If the variable declared in file 1 is required to be used in file 2 then it is to be declared as an extern.13. e. It is allocated memory and is initialized only for the first time. int g = 0. extern int g = 0. but is extended to all the functions that are defined after it is declared. The scope of a global variable is not limited to any one function . we can use extern to declare them.3.17 Value of i before incrementing is : 0 Value of i after incrementing is : 10 Value of i before incrementing is : 10 Value of i after incrementing is : 20 Value of i before incrementing is : 20 Value of i after incrementing is : 30 It can be seen from the above example that the value of the variable is retained when the function is called again. // FILE 1 – g is global and can be used only in main() and // // fn1().g. which are in the same file scope. If we want to use a variable defined in another file. . 1. External Variables Different functions of the same program can be written in different source files and can be compiled together. However. the scope of a global variable is limited to only those functions.

13. Also.4. OPERATORS . which are used to store data temporarily. otherwise it is taken as automatic. e. Operations can be performed on the data stored in registers more quickly than on the data stored in memory.14. i< 100. This is done using the keyword register. i++) { cout << i.g. global variables cannot be register variables.18 void fn2() { : : } void fn3() { : } 1. However. can be assigned a register. for(i=0. This is because the registers are a part of the processor itself. If a particular variable is used often – for instance. a register is assigned by the compiler only if it is free. rather than a variable . Register Variable Computers have internal registers. before any operation can be performed. Intermediate results of the calculations are also stored in registers. the control variable in a loop. } } 1. void loopfn() { register int i.

1.1.14. int z = -10. However. These operators increase or decrease the value of a variable on which they are operated. y = x. The operator for increment is ‘++’ and decrement is ‘—‘. The left hand side has to be a variable (lvalue. The language offers a range of operators. The value of y now becomes –5 and 'a' becomes -10. and their meaning changes depending on their usage. int x = 5. When . y = -x.19 The variables.14. functions etc. x = 10. which are operated upon by the operators. compound assignment and shift operators. Operators specify what operations are to be performed on the operands. ranging from arithmetic. which excludes constants.2. e. the language does not offer any unary + operator. Arithmetic Operators We can classify the arithmetic operators as UNARY and BINARY operators. which are declared and defined. by one(1). It is also used to specify a negative number.2. Increment and Decrement Operators. are the operands. Unary Operators Unary operators are those. Assignment Operators The equal (=) sign is used for assigning a value to another.1. e.). They can be used as prefix or postfix to the variable. a = z.g. which operate on a single operand.g. 1. relational and logical operators to bit-wise logical .14. expressions. Unary Minus Operator( Negation) This operand can be used to negate the value of a variable. 1. here a minus(-) sign is prefixed to the number.

20 used as prefix, the value of the variable is incremented/ decremented before using the expression. But when used as postfix, its value is first used and then the value is incremented or decremented. e.g. --x; x--;

In the above example it does not matter whether the decrement operator is prefixed or suffixed. It will produce the same result. However, in the following example it does make a difference : int a =0, b=10; a = ++b; is different from a=b++; In the first case, the value of ‘a’ after the execution of this statement will be 11, since ‘b’ is incremented and then assigned. In the second case, the value of ‘a’ will be 10 , since it is assigned first and then incremented. The value of ‘b’ in both the cases will be 11. The unary operators have a higher precedence than the binary arithmetic operators. Binary Operators There are five binary operators. These operators, require two operands. ‘+’ ‘-‘ ‘*’ ‘/’ ‘%’ e.g. z = x + y; f = 10 / 3; f = 10 % s; x = a + b – c / d * e; x = ((a + (b – c) / d )* e; for addition. for subtraction. fro multiplication. for division . for modulus.

The second example will give the quotient of 10 divided by 3, where as the third example will give the remainder after division.


The expressions in the fourth example is evaluated according to the precedence of operators, which is as follows: %, /, * on the same level, evaluated from left to right. +, on the same level, evaluated from left to right.

Arithmetic expressions can also contain parenthesis to override the precedence, as shown in the last example.

1.14.3. Compound Assignment Operators Apart from the binary and the unary arithmetic operators, we also have compound assignment operators. These are +=, -=, *=, /=, %=. Using these operators, the expression x = x + 5; can also be written as x += 5; This helps in writing compact code.

1.14.4. Relational Operators A relational operator is used to make comparison between two values. All these operators are binary and require two operands. There are the following relational operators : == != > >= < <= e.g. number < 6 ch != ‘a’ total == 1000 equal to not equal to greater than greater than or equal to less than less than or equal to

Note that no space is given between the symbols. All these operators have equal precedence amongst themselves and a lower precedence than the arithmetic operators.


1.14.5. Logical Operators We say any expression that evaluates to zero is a FALSE logic condition and that evaluating to non-zero value is a TRUE condition. Logical operators are useful in combining one or more conditions. The following are the logical operators : && || ! AND OR NOT

The first two operators are binary, whereas the exclamation(!) is a unary operator. It is used to negate the condition. e.g. x<0 && y>10 evaluates to true if both conditions are true x < 0 || z = = 0 evaluates to true, if one of the conditions is true

!(x == 0)

evaluates to true if condition is false.

The unary negation operator(!) has a higher precedence amongst the these, followed by the and (&&) operator and then the or(||) operator, and are evaluated from left to right.

1.14.6. Bit-wise Operators Some applications require operations to be done on different bits of a byte separately. Bit-wise operators offer a facility to do just that. There are several bit-wise operators :

Unary Operator : One’s Complement Operator(`) This operator is a unary operator that causes the bits of its operand to be inverted, i.e. 1 becomes 0 and 0 becomes 1. for instance, to see the largest possible number, which can be stored in an unsigned integer, a zero can be assigned to it. All the bits in this word will be zeros. When the one’s complement operator is used on this word, all the bits will be inverted to ones, giving the largest possible number. The program to show this conversion is below : main()

23 { unsigned u = 0;

printf(“Value before conversion : %d\n”,u); u = ~u; printf(“Value After conversion : %d\n”,u); }

Binary logical bit-wise operators There are three logical bit-wise operators : & | ^ and or exclusive or

These are binary operators. The operations are carried out independently on each pair of the corresponding bits of the operands. i.e. the bit 1 of operand 1 is logically operated with the bit 1 of operand 2. the operations of these operators are summarized in the following table:

BIT 1 0 0 1 1 e.g. char x, y, z, a, b; a = 0x01; b = 0x05;

BIT2 0 1 0 1

BIT1 & BIT1 0 0 0 1

BIRT1 | BIT2 0 1 1 1

BIT1 ^ BIT2 0 1 1 0

/* 0000 0001 */ /* 0000 0101 */

x = a & b; y = a ^ b; z = a | b; x &= y;

These are binary operators. x >>=2.7. The char y( which is allocated a byte of space on a 16-bit machine) will have its bits shifted to the right three places. The result of x is 0x01. char x. x = y <<2. since a=0 0 0 0 0 0 0 1 & & & && & & & b=0 0 0 0 0 1 0 1 x=0 0 0 0 0 0 0 1 1. y <<= 1. The Shift Operators There are two shift operators : left shift ( <<) and right shift (>>).14. whereas the right shift operators shift ‘number’ bits to the right.24 y |= z. e. y = 0x80.14. Precedence and Order of evaluation . which is to be shifted.g. after y = y>>3. The second is the number of bits by which it is shifted. The format is operand >> number or operand << number The first operand is the value. y = y >> 3. 1. The leftmost and the rightmost bits are shifted out and are lost. The value of y which was 0x80(1000 0000) is changed to 0xFo(1111 0000) .8. The left shift operators shift ‘number’ bits to the left.

(type)* sizeof * / % + << >> == != & ^ | && || ? : = / += -= etc. Associativity left to right right to left left to right left to right left to right left to right left to right left to right left to right left to right left to right right to left right to left left to right Operators on the same line have the same precedence. so. *. Also important for this purpose is the associativity of the operators. Precedence rules help in removing ambiguity of the order of operations performed while evaluating an expressions. /. . The precedence and associativity of the operators is summarized below: Operator () [] -> ! ~ ++ -. rows are in order of decreasing precedence.25 The languages follow a standard precedence for basic operators. associativity defines the direction in which the expression is evaluated when the operator is involved. for example. % all have the same precedence which are higher than that of + and – on the next line.

9. The value returned by this operator can be used to determine the size of a variable. the operands are converted before evaluation. sizeof(int). // returns 2 on a 16bit machine sizeof(float). which returns the number of bytes taken up by a variable or data type.14. to maintain compatibility of the data types.g. float double . In this case. char ch = ‘A’.26 1.15. The following table shows the conversion : Operand1 operand 3 Result char int int int long long int double double int float float int unsigned unsigned long double double double e. The sizeof() operator This is a pseudo-operator given by the language. MIXED MODE EXPRESSIONS AND IMPLICIT TYPE CONVERSIONS A mixed mode expression is one in which the operands are not of the same type. // returns 4 on a 16bit machine 1.

or c = (int) (a / b). TYPE CASTING Implicit type conversions. e.0. This is done by type-casting a value of a particular type. i = f / 3. int i = 0. Here. 1. Therefore. but since the lvalue is an integer the value will be automatically truncated to 3 and the fraction part is lost.333333 being stored in ‘c’. e. If the application requires integer division of two floating point numbers. as allowed by the language.0. 1. c = a / b. can lead to errors creeping in the program if care is not taken.0. since there is an integer(32) in the expression.27 ch = ch + 32. This expression will result in 3. resulting in 3. ch will be converted to an integer. float a = 10. In this expression . CONTROL FLOW .g.16. ( implicit conversion from float to int ). This is done by using the (type) operator as follows: (type) expression expression is converted to the given type by the rules stated above. The result will be an integer.17. b = 3. float f = 10. into the desired type. then the following expression with the type cast can be used: c = (int)a / (int)b. c. explicit type conversions may be used in mixed mode expressions.33333. the constant 3 will be converted to a float and then floating point division will take place.g.

cout<<” This is a number”.1. } else { statements. This control flow statement thus specify the order in which the computations are carried out. e. 1.1.g. The language offers for. goto as control statements. ifelse. The if-else and else-if statements.17. A single if(expression) without an else can also be used for checking a single condition. } If the expression1 is evaluated to be true the statements under it are executed otherwise if it is wrong the statements written after the keyword else are executed. if( ch < ‘0’ || ch > ‘9’) { cout << “ Not a Number). 1. Branching Statements The control flow statements used for branching are if-else. else-if and switch. . The syntax of if – else statement is : if(expression 1) { statements. switch. We can classify them as branching and looping structures.1. else-if.28 The control flow statements are used when it is required that the flow of the program is to be changed after taking some decision.17. } else // in case of a single statement the braces can be avoided. do-while. while.

e. if( option == 1) cout<<” 11111”. They can be nested as well: e.g. else if( option == 3) cout<<” 33333”. else if( option == 2) cout<<” 22222”. else cout << “ invalid “.g.29 A multi-way decision making segment can be written by using if statements inside the else part. which gives the else-if construct. if(expression 1) { if ( expression 2) { : : } else { } } else { if ( expression 2) { : : .

The if else construct if(a>b) { z = a. The Conditional Expression Operator An alternate method to using a simple if-else construct is the conditional expressions operator.2.17.1.g. if it is true then the expression 2 is the value of the conditional operator. it has three operand. otherwise the expression 3 is the value. ?: A conditional expression operator is a ternary operator. } This can be written as z = (a>b) ? a: b. } else { z = b. . e.30 } else { } } 1. whose general format is: expression1 ? expression2 : expression3 Here the expression1 is evaluated first.

3. The expression is evaluated and compared with the values in cases. : : break. and the body of the switch statement must be enclosed in braces.1. : : } The expression must be declared in the parentheses. case value3 : statements. . case value2 : statements.31 1. If the value does not match with any of the case statements then the statements under the default label are executed. The general format is as follows : switch(expression) { case value1 : statements. The Switch Construct The switch statement is a multi-way decision-making construct that tests whether an expression matches one of a number of constant values. : : break. and branches accordingly. The switch statement is another alternative to using nested if-else statements. default : statements. The values with case should be constants.17. if it matches the statements under it are executed till it encounters a break statement. : : break.

1.o.u then they are printed as vowels . The general format is : for( initialize .i.g.17.32 Omission of break takes control through the next case statements regarded whether the value of case matches or not.2. default : cout << “ Consonant “. 1. : : } . but its use is generally avoided as it leads to haphazard code and also increases the chances of errors. switch(ch) { case ‘a’ : case ‘e’ : case ‘i’ : case ‘o’ : case ‘u’ : cout << “Vowel”. while.1.17.2 Looping Statements The statements generally used for looping are for. This can also be used constructively when same operation has to be performed on a number of cases.e. The for Loop This is a controlled form of loop. otherwise they are printed as consonants. The goto statement can be used for looping. } In the above example if the value of ch is any of a. test . e. do-while. update) { statements.

) { cout << i.. for( int i = 0. e.g. } . with no expression. for( . } This will print from 0 to 10. e. { cout << i. i++. y--) { cout << i. i< 10 && y>0 . int j=10. before entering the loop. } This is an infinite loop. i< 10.33 The initialize part is executed only once. i.g. i++. } This is equivalent to our example. ) { cout<<”hello”. i++) // In C++ you can declare a variable here. More than one expression can also be inside the for loop by separating them using commas. e. which printed from 0 to 9. If the test evaluates to true then the updating takes place. If test evaluates to false then the next statement after for loop is executed. The expressions in the for loop are optional but the semi-colons are necessary.e. . int i = 0 for(.g. for( int i = 0. i< 10.

} while( x < = 10).2. .2..17. The while Loop The for loop is a form of a controlled loop.while Loop The general format is as follows : do { statements.2. The general format is : while(condition) { statements.17.g. int x = 0. } This example prints from 0 to 10 .34 1. while(condition). 1. : : } e.3. e. while( x < = 10) { cout << x. The do.g. do { cout << x. When the number of iterations to be performed are not known beforehand the while loop can be used. : } The statements in the loop are executed as long as the condition is true .

. The break statement The break statement. When there are nested loops it breaks only from the current loop in which it was written. // equivalent to scanf() if(num == 0) break. with one difference. .17.17. which was already covered in the switch. We can say do loop is executed at least once. case . The continue statement The continue statement causes the next iteration of the enclosing loop to begin. cin >> num. void main() { int num.whereas in while only after the expression is checked we enter the loop.3. Here testing is done after executing the statements inside the loop and if the condition evaluates to true then we enter the loop again . total = 0.35 This works exactly like our previous example . e. the do. When a loop statement is encountered in the loops the control is transferred to the statement outside the loop. do { cout << “ enter 0 to quit “.g.. while loop is exactly like while loop. the rest of the statements in the loop are skipped and control passes to the condition. can also be used in the loops. 1. 1. When this is encountered in the loop . Let us see an example that accepts a variable amount of numbers from the keyboard and prints the sum of only positive numbers.4.

e. } } } } cleanup: statements.5. The general format is : goto label. . . The goto statement This statement can be used to branch to another statement of the program. . } 1. cout << total. for( . ) { for( . . ) { if( condition) goto cleanup. This is rarely used as it violates the principle of structured programming. . total+=num.17. where label is a name(tag) followed by a colon. . ) { for( .g. . ) { for( . }while(1). However we can use it when we want to exit from deeply nested loops. .36 if(num < 0) continue. .

37 : : A good programmer will use control statements effectively in order to avoid the usage of unconditional branching statement – goto. Enumerated Constants. Pointer Arithmetic. Ways of initializing the arrays. The control flow required for any language to be structured was also discussed in detail. the scope rules and storage methods were also discussed in this session. The language offers a variety of operators. This session introduced some features of the C and C++ languages. The next session introduces some of the advanced topics. Pointer types. Relationship between Arrays and Pointers. The data types offered. SESSION 2 SOME FEATURES OF C AND INTRODUCTION TO THE LANGUAGE C++ (PART 2) During this session you will learn about: • • • • • • • • Array types. qualifiers to the data types. . Reference Types. Structures.

int arr[10]. The individual objects are accessed by their position in the array.g. // Declares array of 10 integer objects // Assigns the value of third element in the array into ival arr[0] = ival. Evaluates to 17 during compilation. The dimension value must be a constant expression. ARRAY TYPES An array is a collection of objects of a single data type. b = 20. extern int getsize(). the value should be available at compile time. e.1. // Assigns the value of ival in to array element arr[0] An array definition consists of a type specifier. We will learn a few advanced topics of the language construct. .and a dimension. // valid // valid . i. int c = 30. an identifier .g. Dimension specifies the number of elements contained in the array. We will learn how to bundle related data members of may be different names under the same name. Unions.constant expression. int i_arr[b-3]. int ival = arr[2].38 • • Difference between a Pointer and a Reference. In this session we will learn about storing a set of like type data members. const int a = 10. An array must be given dimension size greater than or equal to 1. 2.e.. This way of accessing is called indexing or subscripting. e. char c_arr[a].

i < size .2. int arr[size]. // Initialized as {0. } } • An array can be explicitly initialized as follows.2}.0} . • An explicitly initialized array need not specify size but if specified the number of elements provided must not exceed the size. The for loop initializes 10 elements with the value of their index.1. 2. int i_arr[get_size()].g.1. int arr[3] = {0.1.g. int arr1[5] = {0.39 int i_arr[c].2}. i++ ) // You can declare a variable here in C++. { arr[i] = i. e. for(int i = 0.2}. For an array of 10 elements . int arr[] = {0. • VARIOUS WAYS OF INITIALIZING THE ARRAYS.2. // ERROR: non-constant variable.1. // ERROR: non-constant expression The elements of an array are numbered beginning with 0.0. access to its value can only be accomplished runtime. If the size is given and some elements are not explicitly initialized they are set to zero e. the index values are 0 through 9. void main() { const int size = 10. Though it is initialized.

int ix.3.g.g. • • To copy one array to another each element has to be copied using for structure.iy. e.’+’} //size = 3.&iz}.2. . Any expression that evaluates into an integral value can be used as an index into array.iz. e.&iy. const char a_arr3[6] = ”Daniel”. int arr2[] = {1.’+’. arr[get_value()] = somevalue.40 const char a_arr1[] = {‘c’. We cannot have array of references. // ERROR: can’t assign one array to another. //Can have array of pointers int &arr[] = {ix. // ERROR: can’t initialize one array to anther arr1 = arr2. const char a_arr2[] = {“c++”} //size = 4 because of null character at the end of the string.iz}. // valid int arr1[] = arr2.g. Daniel has 7 elements • An array cannot be initialized with or assigned to another array.3}. 2. // ERROR. • MULTIDIMENSIONAL ARRAYS Each dimension is specified in separate brackets e. // ERROR: cannot have array of references.iy. int *arr[] = {&ix.

3. This is a two-dimensional array with 4 as row dimension and 3 as a column dimension.4.5.g.2}. // First element of rows are 0. 2. for(int i = 1.3}.{2}.4.{9. j< = 10.2. int arr[10][10].1.i++) for(int j = 1.{6. and remaining elements are considered Zero. int arr[4][3] = {{0.10. POINTER TYPES i. e.{1}.41 int arr[4][3]. int arr[4][3] = { 0.j++) { arr[i][j] = i+j.1.11}.3 and remaining are considered zero.{3.6.2] is considered as arr[2]. • The nested brackets are optional.2.11}}.5}.i< = 10. int arr[4][3] = {{0}. int arr[4][3] = {1.8}.10.9.7. • Multidimensional array can be initialized as follows e.1. } • Instead of arr[1][2] if you give arr[1. // Initializes first three element of first row as 1.2.{3}}.8.exe .g.2. • Initialization using nested loops.4.g.3.7. e.

In the following example lptr1 is a pointer to long variable and lptr2 is a normal long variable. . • Pointers are declared using the (*) operator. allowing for the indirect manipulation of that object.g. iptr = &num.g. e. e. float *fptr. e. The general format is: type *ptrname. lptr2. long *lptr1. Once the pointer variable is declared it can be made to point to a variable with the help of a address(reference) operator(&). They are used in creating linked data structures like lists. // iptr points to the variable num. type can be of any data type and pointer name becomes the pointer of that data type. int *iptr. cptr to a character and fptr to a float value. trees and management of objects that are dynamically created during program execution. The pointer iptr stores the address of an integer.g. char *cptr.42 Pointer holds the address of an object. In other words it points to an integer. int *iptr. int num = 1024.

A pointer of one type cannot be assigned the address value of the object of another type. the second format is not recommended as it may lead to the confusion that when we declare variables like just shown above could be correct.g. e.g. e. int *iptr1 = 0. void *vptr = iptr.43 You can declare a pointer variable in two ways. .g. The pointer can hold the value of 0 . *iptr2 = &ival. // invalid. // iptr2 now addresses to no object. sptr. e. // allowed iptr = &dval . iptr1=ival. vptr = dptr. double dval. iptr1 = iptr2 // both address ival iptr2 = 0.g. e.g. However. string string * *sptr. *dptr = &dval. indicating that it points to no object or it can hold the address of same data type as mentioned earlier. e. ival is not address. //not allowed However you can compare or interchange 2 types of address values using void pointer. Pointers can never store a non-address value. int ival = 1024.

g. e. k . POINTER ARITHMETIC We can manipulate the pointers too.g.. increment and decrement etc. subtraction.5. j. you can have pointer to pointer to int. int i. We can perform operations like addition. int arr[10]. e. *iptr = *iptr + 2. int * iptr = &ival1.. * iptr = ival2. adding or subtracting a number results in another address. 2. You can also have second level of indirection i. These are useful when using arrays. . They are only for transport of the variables.44 We cannot operate on an object pointed by void.g. e. e.. ival2 = 2084. The variable it points to can be accessed by using the indirection operator (*) also called the dereferencing operator. Since the pointer variables contain address. int *iptr3 = *ptriptr. // ival1 = ival2 // ival1 = abs(ival1) // ival1 = ival1 + 1. int *iptr = &i. int ival1 = 1024.e. // I = I + 2. * iptr = abs(*iptr). // content is an address. This may be memory address occupied by another variable. which is at an offset from the original address.g. Once the pointer is defined. int **ptriptr = &iptr. * iptr = * iptr + 1. iptr = iptr + 2 // adds 2 to address. We dereference it as follows.

4. ++iptrb. Diff between *(arr+1 ) and *arr+1 *(arr+1) means the address of arr is increased by 1 and then the contents are fetched. e. int *arr_end) { while(arr_beg ! = arr_end) { cout << arr_beg. ++arr_beg. Hence.3.g.5. If we write arr . int *iptre = &arr[10]. arr[0] or *arr.9}. Consider the following. *arr+1 means the contents are fetched from address arr and one is added to the content.7. void print(int *arr_beg.2.6. arr is equivalent to &arr[0].6. While ( iptrb != iptre) { Do something with the value if (*iptrb). RELATIONSHIP BETWEEN AN ARRAY AND POINTERS.45 int *iptrb = &arr[0]. Similarly to access the value we can write . arr[1] or *(arr+1). } } . } 2. int arr[] = {0.1. • The traversal of an array can be made either through subscripting or by direct pointer manipulation.8. it is considered as the address of the first element of an array. arr[1] <==>arr+1.

2.arr+9).9} print(arr.46 void main() { int arr[] = {0. : : }variables.2. like information of an employee. STRUCTURES A structure is a derived data type. This however works only with pointers to array containing integers. Unlike arrays.6. The general format of structure declaration is: struct tag { type member1.5.1. which are a collection of like data types.7. In C++ we can omit struct and simply write : . type member2.7. We can omit the variable declaration in the structure declaration and define it separately as follows : struct tag variable.8. structures can be made of members of unlike data type.4. The data items in the structures generally belong to the same entity . players etc.3. type member3. It is a combination of logically related data items. } arr_end initializes element past the end of the array so that we can iterate through all the elements of the array.

We can also have nested structures as shown in the following example : struct date { int dd.g. char acctype. float balance.0 cout << oldcust. Structure definition.g. 6500. We cannot copy one structure variable into another. char name[25]. mm. }. e. char acctype. . We can refer to the member variables of the structures by using a dot operator (.).00}. struct account { int accnum. e. [or] account newcust. yy. struct account { int accnum. ‘w’. }. newcust. account customer = { 100. Structure declaration. If this has to be done then we have to do memberwise assignment. char name[25]. struct account oldcust.47 tag variable. ‘David’.balance = 100.name.g. We can initialize the members as follows : e.

}. }. account *aptr. 2. Every thing is same as that of a single element except that it requires subscript in order to know which structure we are referring to. We can pass and return structures into functions . e. c1. account c1. account a[10]. struct date d1.dd=21.j. info *next.48 float balance.8. cout << aptr->name.k. If we declare array to account structure it will look like.g.d1. We can also declare pointers to structures and to access member variables we have to use the pointer operator -> instead of a dot operator. Now if we have to access the members of date then we have to use the following method. struct info { int i. ENUMERATED CONSTANTS .also called selfreferential structures. The whole structure will get copies into formal variable . A structure can contain pointer itself as one of the variables . We can also have array of structures.

• Even though enum symbolic constants are internally considered to be of type unsigned int we cannot use them for iterations.g.49 Enumerated constants enable the creation of new types and then define variables of these types so that their values are restricted to a set of possible values. num Days{SUN. MON. however. Colour is the name of an enumerated data type. It makes RED a symbolic constant with the value 0. TUE. THU. In our case RED.g. THU. Day = 3. for(enum i = SUN. You can define variables of type Colour. // error int and day are of different types Day = hello. You can declare objects of enum types. MON. Days day.BLACK = 1000 • • e. . BLACK = 1000}. If the program doesn’t specify otherwise.GREEEN.g. BLUE a symbolic constant with the value 1 and so on.BLUE = 101.WHITE = 501. TUE. Day = SUN.GREEEN = 500. enum Colour{RED = 100.WHITE. SAT}. i<SAT. FRI. the remaining constants will count up by 1 as compared to their predecessors. BLUE. The values assigned will be RED = 100.g. GREEN = 500. GREEN. those that are not initialised will count upwards from the value of previous variables. • Every enumerated constant has an integer value. BLACK}. // hello is not a member of Days. enum Days{SUN. e. SAT}. WHITE. but they can hold only one of the enumerated values.BLUE. e. enum Colour{RED. WHITE. e. BLUE. • Any of the enumerated constant can be initialised to have a particular value. WED. the first constant will have the value 0. WED. FRI.BLACK . i++) //not allowed.

A reference is referred to an alias.50 There is no support for moving backward or forward from one enumerator to another. } int num = 2*MON. e. REFERENCE TYPES The symbol “&” is interpreted as an address operator as well as AND operator.g. int &rval = ival. • However whenever necessary. if( MON > 0) { cout << ”ghjf”. num2 = 200. int &iref. i. e. This operator is also used to declare a “reference variable”.exe . void main() { int num1 = 10. // rval is reference to ival • A reference variable should be initialized at time of declaration itself. These are allowed. e.g. int &ref = num1. it cannot be changed to refer to another variable. serves as an alternative name for the object. int &iref = ival • Once a reference has been made to a variable . int ival = 1024.g. e.200.k. // wrong //o. 2.10. an enumeration is automatically promoted to arithmetic type.g. //10. cout<< num1 << num2 << ref .9.

cout << num1 << num2 << ref . we cannot initialize the address of an object to it. • Although a reference to a variable serves as a kind of pointer. int &refval = &ival.g. The same initializations are not legal for non-constant references. which is not the desired action. we can define a pointer to a reference. such as literal constants . e. .0.// ival = ival + 2 .can not // convert int* to int. const int &ir = 1024.g. double dval = 3. int *&ptr_ref = pi. int *pi = &refval // ii = 1002.51 ref = num2. //pi = &ival. e.1415. } It changes the contents of the original variable. const int &ir2 = dval.1000 + 2 =1002 int ii = refval.g.g. int *pi = &ival. refval = refval + 2.200 However . • All the operations on the reference variables are actually applied to the object to which it refers.200. • A constant reference can be initialized to an object of a different type as well as to non-addressable values. //the error message by the //compiler would be. const double &dr = dval +1. //200. e. e. int ival = 1000.

In case of non-addressable values. const int &ri = dval. int *const &pi_ref = &ival //o. e.52 Internally.g. /* this is reference to a pointer to an object of type int defined to be a constant. The compiler transforms this as. the compiler generates a temporary object that reference actually addresses but user has no access to these addresses. e. const int &ri = 0 . 2. // we require constant reference.*/ The correct form is. double dval = 1024.g. const int &ri = temp. such as literal constant and objects of different types. const int *&pi_ref = &ival. const int ival = 1000. int temp = dval. DIFFERENCES BETWEEN A POINTER AND A REFERENCE 1. which addresses a constant object. Now if we try to change ri. If we write. A reference must always point to some object where as this restriction is not imposed on a pointer. int *pi = 0. // pointer can point to no object. a reference maintains the address of the object for which it is an alias.10. Our reference is not to a constant but rather to a non-constant. would be converted as . int *&pi_ref = &ival.k. it actually changes temp and not dval as it is a constant We can initialise a reference to the address of a constant object. If we write.

11. const int &ri = temp.53 int temp = 0.g. type memvar3. ival2 = 2000. &ri2 = ival2. type memvar2. It is a collection of mutually exclusive variables . e. Union tag variable_name. *pi2 = &ival2. int *pi1 = &ival1. The assignment of one reference with another changes the object being referenced and not the reference itself. union utag . ri1 = ri2. • ival1 remains unchanged but pi1 and pi2 now address the same object ival2. ri1 and ri2 still refer to ival1 and ival2 respectively. 2. e. The size of the union is equal to the largest member variables. A union variable of this data type can be declared as follows. int ival1 = 1000. int &ri1 = ival1. which means all of its member variables share the same physical storage and only one variable is defined at a time. except that only one variable in the union is stored in the allocated memory at a time. : : }. 2.g. UNIONS A union is also like a structure . • ival1 becomes 2000. pi1 = pi2. A union is defined as follows : union tag { type memvar1.

4.ch. Thus unions use memory efficiently by using the same memory to store all the variables. . WAP a program to print first N prime numbers where N is accepted from the user. references. union tag filed. The session also covered the concepts of structures and unions.16).54 { int num. As can be seen pointers and references can be used to return more than one value from the functions.e. where N is accepted from the user. complex database management can be realized. only one of these two variables. which may be of different types. The above union will have two bytes of storage allocated to it. This session covered advanced concepts of the language like pointers.sum and ch is accessed as field. arrays. Any change made to one variable affects another. can be referred to.8. WAP to print the sum of squares between 1 & N. The variable num can be accessed as field. WAP to accept an array of character strings and print them in descending order. The unions are used to store variables of different types that are required at mutually exclusive times. 12345 is printed as 54321 2. EXERCISES 1. to speed the processing and to use memory more efficiently. When they are used with pointers. char ch. WAP to convert a decimal number into its equivalent of any other base(2. At any time. arrays etc. and relation between them . Write a Program(WAP) to print a given integer in the reverse order. 5. i. }. The structures or records are the basic elements of a database. 3. which exist at mutually exclusive times and are to be used in the program only once.

• • • Additional keywords in C++. or function. The new and delete operators. Structural and Object-Oriented Programming logic. STRUCTURED. We can also see features of C++ that are not present in C. Default arguments. AND OBJECT-ORIENTED PROGRAMMING LOGIC Until recently.55 SESSION 3 OBJECT ORIENTED PROGRAMMING : AN INTRODUCTION During this session you will learn about : • • • • • Procedural. Different implementation of OOP. Comments . programs were envisioned as a series of procedures that acted on data. Differences between C and C++. Variable declarations. This session introduces the features of Object Oriented programming and also discusses other programming methods. In earlier sessions we learnt about language features which had nothing to do with Object Oriented Programming techniques. The cin and cout objects.1 PROCEDURAL. 3. C++ and OOP. Introduction to C++. was defined as a set of specific instructions executed in sequential . A procedure.

as the programmer needs them. when an engineer needs a new transistor. until the tasks were sufficiently small and self-contained to be easily understood. and so on) as related ideas. To make sense of this potentially confusing situation. which functions called which functions. however. edit. for example) and ways that data can be manipulated (sort. which uses procedural method of programming. The principal idea behind structured programming was as simple as the idea of “divide and conquer. This software concept is modeled after the hardware world. and then plugging those components into a program. By the late 1980’s. and coupling data with the tasks that manipulate the data. Reinventing in a way is opposite of reusability. It is natural to think of data (employee records. programmers found themselves constantly reinventing new solutions to old programs. Object-oriented programming (OOP) attempts to meet these needs. providing techniques for managing enormous complexity. Second. structured programming was created. some of its deficiencies had become all too clear. Pascal is a language. achieving reuse of software components. Reusability involves building components that have known properties. The data is kept separate from the procedures. and which data was changed.” A computer program could be regarded as consisting of a set of tasks. Structured programming remains an enormously successful approach for dealing with complex problems. and the trick in programming was to keep track of. The language C uses structured programming approach. . she doesn’t usually invent one but goes to big bin of transistors and finds one that fits her needs. No similar option existed for a software engineer until reusability was developed. First. Any task that was too complex to be simply described would be broken into a set of smaller component tasks.56 manner. the separation of data from the tasks that manipulate the data became increasingly difficult to comprehend and maintain. or perhaps modifies the found transistor.

C+ as an enhancement to the C language was developed primarily to facilitate managing. .3. which C++ attempts to resolve by restricting indiscriminate access. The most important aspect of the C language is. Originally. At the same time. 3. also attempts to keep the freedom and flexibility given by the language. Instead. it was called as “ C with class”. However. In addition we have some new one’s too. probably. The limits of the language are defined by the programmer’s imagination.57 The essence of object-oriented programming is to treat data and the procedures that act on the data as a single “object” – a self-contained entity with an identity and certain characteristics of its own. with very large projects in which many programmers use shared routines. it deals with the overall design of the program . C++ is one language that supports all the features of OOP. C++. Actor and the latest version of Turbo Pascal. Eiffel. this liberty can lead to what are called as ‘ side effects ‘. This is one problem. programming and maintaining large software projects. However. The OOP features can be implemented in many languages that support them. INTRODUCTION TO C++ C++ was developed by Bjarne Stroustrup at Bell Laboratories in 1983. Unfortunately. Smalltalk. Other languages include Common Lisp object system. 3. the flexibility to do whatever the programmer wants. C++ is not merely an extension of the C language. where some new symbols have been added. Java. The basic purpose of C++ language is to add features to the C language that supports the concepts of OOP.2 DIFFERENT IMPLEMENTATIONS OF OOP Object-oriented programming is not particularly concerned with the details of the program operation. C++ is the most widely used object-oriented programming language. All the keywords of C are keywords of C++ also.

This mechanism helps in implementing encapsulation and data abstraction.. Most of the things in the real world are intrinsically complex. inheritance. Abstraction means ignoring those aspects of a subject that are not relevant to the current purpose in order to concentrate more fully on those that are relevant. AT & T however is the most advanced one. the details are embedded inside and are dealt with at a later stage. To an analyst who is as good as a subject expert it means choosing certain things or aspects of the system over others at a time. Before discussing these pillars let us know about some other terms associated with OOP. AT&T C++.58 There are several C++ products available – Turbo C++. 3. Encapsulation and Data Hiding . Association is used to tie together certain things that happen at some point in time or under similar conditions. including the four pillars of object- oriented development : encapsulation. 3.4. Association is the principle by which ideas are connected together or united. Turbo C++ and Borland C++ are most widely used. Abstraction is used by OOP as a primary method of managing complexity. which is used when interfaces are involved to communicate between the entities. OOP uses classes and objects have attributes. which can be exclusively accessed by services of the objects. By using abstraction one selects only a part of the whole complex instead or working with the whole thing. Communicating with messages is the principle for managing complexity. It does not mean ignoring the details altogether but only temporarily. To change the attributes of the object (a data member of the object). data hiding. and polymorphism. Sun C++ etc. Zortech C++. far more complex than one can comprehend at a time.4. The most important term is ‘Abstraction’.1. a message has to be sent to the object to invoke the service. C++ AND OBJECT-ORIENTED PROGRAMMING C++ fully supports object-oriented programming.

Once created. She walks over to a bin of resistors. because its data is hidden inside the resistors casing. but they would like to add a turbocharger and a six-speed transmission. 3. Encapsulation is the principle by which related contents of a system are kept together. when an engineer needs to add resistor to the device she is creating. The chief engineers would prefer to use the earlier model and make some changes to it than creating a new one (CAR2). called classes. users of well-defined class do not need to know how the class works. When they want to build a new car. she doesn’t typically build a new one from the scratch.4.2. The important advantage of using encapsulation is that it helps minimize rework when developing a new system. The actual inner workings of the class should be hidden.59 The property of being a self-contained unit is called encapsulation. The resistor is a “black box” as far as the engineer is concerned – that is. which use those requirements. Perhaps their former model is nearly perfect (say CAR1). . examines the colored bands that indicate the properties. It minimizes traffic between different parts of the work and it separates certain specific requirements from other parts of specification. they have two choices. examines the bin of resistors. or they can modify an existing model. The part of the work. All the resistor’s properties are encapsulated in the resistor object – they are not spread out through the circuitry. The idea that the encapsulated unit can be used without knowing how it works is called data hiding. which is prone to change. only how to use it. can be encapsulated together. Thus any changes can be made without affecting the overall system and hence changes can be easily incorporated. As noted before. a well-defined class acts as a fully encapsulated entity and can be used as a whole unit. C++ supports the properties of encapsulation and data hiding through the creation of user-defined types. she doesn’t care how it does its work as long as it conforms to her specifications. They can start from the scratch. and picks the one she needs. It is not necessary to understand how the resistor works to use it effectively. Inheritance and Reuse Consider a car manufacturing company.

The CAR2 might engage fuel injection and a turbocharger. a new type can be declared that is an extension of the existing type. however. the user simply presses the accelerator and the car responds with the correct function. whereas the CAR1 simply get petrol into its carburetor. Additional keywords in C++ class friend virtual inline const delete operator private public protected this new The actual use and description of these additional keywords will be covered in their specific contexts.3. for example. Comments . Some of them are highlighted below. C++ supports this idea – that different objects do “the right thing “ – through function polymorphism and class polymorphism. whereas morph means form. Thus. 3.5. A user. does not have to know about these differences. which have nothing to do with OOP. Polymorphism The CAR2 in the above example may respond differently than the CAR1 when the car accelerates. SOME DIFFERENCES BETWEEN C AND C++ There are several differences between the C language and C++. This new subclass is said to derive from the existing type and is sometimes called a derived type.2.5. 3. 3.5. polymorphism refers to the same name taking many forms.60 C++ supports the idea of reuse through inheritance.1. 3. Through this concept. Poly means many.4.

61 Comments are integral part of any program . e. the two forward slashes should be given on every line. It can be continued to next line and has to be ended with */ clrscr(). // Clears the Screen // Initialize variables. The C style of giving a comment is also available in C++. This form of giving comments is particularly useful for the short line comments. The compiler ignores them.5. : : } 3.g. A comment can start at the beginning of the line or on a line following the program statement. They should be used liberally in the program . a comment starts with two forward slashes ( // ) and ends with the end of that line. In C++. If a comment continues on more than a line. In C++ declaration of variables can be interspersed with executable program statements. e. void main() { /* this is a good old style of giving a comment. Variable Declaration This declaration of variables in the C language is allowed only in the beginning of their block. debugging and maintaining a program .g. remains the same – the block in which they are declared.3. prior to executable program statements. void main() . init()_. however. Comments help in coding. This style ( /*…. The scope id variables.*/) is particularly useful when the comment spans more than a line.

a deviation from the old style of declaring all variables in the beginning of the block. . i. The following example shows its usage. z++) // variable declared here. { y ++. int global = 10. However. the local variable is the one in the scope when the program executes that function . z < 10.e. The Scope Resolution Operator( :: ) Global variables are defined outside any functions and thus can be used by all the functions defined thereafter. 3. This operator is prefixed to the name of the global variable .5. Also. int y = 0.62 { int x = 10. for( int z= 0. void main() . a variable is not given a memory until the declaration statement. if a global variable is declared with the same name as that of a local variable of a function . x ++. this does save some amount of memory.4. The C++ language provides the scope resolution operator ( :: ) to access the global variable thus overriding a local variable with the same name.. printf (“ the value of x= % d\n”. } } Although. since a variable can be declared just before using it is suppose to give a better control over variables.x).

// Prototype void main ( void ) { drawbox(10. // parameters passed drawbox(). int color) { // Body of the function } .80.1. int y1=1. } The output of this program will be: Just writing global prints : 20 Writing ::global prints : 10 3. global).5. int x2. ::global).63 { int global = 20.14). int x2=25. int y2. int y2=80.g.5. printf(“ Writing ::global prints : %d\n”. int y1.25. void drawbox( int x1=1. Default Arguments A default argument is a value that is automatically assigned to a formal variable. if the actual argument from the function call is omitted. printf(“ Just writing global prints : %d\n”. } // uses default arguments void drawbox( int x1. e. int color=7).

int x2=25. . since. int x2=25. int x2. If these parameters are omitted. // Not Valid Default arguments are useful when the arguments almost have the same value. int y2.5. int y2=80. whereas. When a function is declared. 3. a default value for a particular argument cannot be given unless all default values for the arguments to its right are given. int color = 7). In other words. if there are some arguments missing in the middle then the compiler would not know as to which arguments have been specified and which should be taken as default. e. int y1=1. The pointer returned by the new operator need not be typecasted. as given in the declaration are passed. to release the memory allocated by new. int y1. void drawbox( int x1=1. int color ). default values must be added from right to left. // Valid void drawbox( int x1. C++ provides yet another approach to allocate blocks of memory – the new operator. using default arguments mean that existing function calls need not be modified. This is quite logical. int y1=1. They are also useful to increase the number of arguments to a function in an already working program. then the default values. int color = 7).64 Function drawbox() draws a box around the edges of the coordinates passed as parameters. This operator allocates memory for a given size and returns a pointer to its starting point. C++ also provides delete.malloc() and free() for dynamic allocation and de-allocation of memory.g. The new and delete operators The C language has defined library functions. // Valid void drawbox( int x1=1. In this case. new function calls pass more number of arguments. int y2=80.6.

// A block of 5 doubles char *cp.65 e. declaring an array is an example of static binding – the array is built at the compile-time. Once the new operator allocates memory. In the above example. // A block of 10 integers double *d5 = new double[5]. Whereas . In this case. using the delete operator. . This is an example of dynamic binding. This array remains in existence right from the beginning of the program to its end. e. even if not in use. It is possible that the system may not have enough memory available to satisfy a request by the new operator. new returns a null pointer. delete d5.g. char arr[100]. the array declared by new operator can be allocated memory only when required and can be released when over with. //Run time allocation of an //array. // Release memory. which otherwise may lead to an adverent system crashes.g. It is synonymous with declaring a character array. Thus. it can be accessed using the indirection operator (*) or the array subscripts. // One character only. new returns a pointer to a block of size bytes. Size can be a //constant or a variable. cp = new char. the returned value from the new should always be checked before performing any operations on it. However. // Character pointer arr = new char[size]. int *some = new int [10]. // Compile_time allocation of an array char *arr. delete some.

mm. ptr = new char [strlen(str)+1]. here we do not need any type specifiers like %d . date *dp = new date. .66 char *ptr . : : } else { printf(“ not enough memory “). However. // Character array if( ptr != 0) { strcpy(ptr. in place of scanf() and printf() functions of C.&dp->dd). to denote the variables type. cin and cout can be used in context with any basic data types. scanf(“%d”. : } NOTE : The cin and cout objects In C++ the keyword cin with the extraction operator “ >> “ is used to accept the input and the keyword cout with the insertion operator “ << “ is used to display string literals and values. }. // This allocated a new structure // to the pointer variable dp printf(“ enter day “). } struct date { int dd.yy. *str = “the shy is blue “. %f etc..str).

OOP improves upon the deficiencies of the traditional structured programming. float fvar. It is based on the C language and is thus a complete superset of the original C language. We can also concatenate various variables. .g. cin >> ivar . Use default argument methods. We will study about these in detail in later sessions. It is clear in the above example.67 e. then always print the factorial of 4. char name[10]. cout<< “ ivar = “ << ivar << endl. WAP to write a program to find the factorial of a number using recursion. If we do not accept the number from the user to find the factorial. Another manipulator endl can be used to end the line and get the cursor back to next line. how we can accept and display variables. Data abstraction. cin >> fvar >> cvar >> name. This session introduced the concept of Object-Oriented Programming. can be implemented in many languages. WAP to sort an array of strings. char cvar. cout<< “ fvar = “ <<fvar << “ cvar= “ << cvar << name. C++ is the most widely amongst them. int ivar. if you write some text in the quotes they are displayed as it is. The actual implementation features are covered from next session onwards. encapsulation and data hiding are some of the buzzwords of OOP. OOP. While displaying. Use new and delete operators. as seen. 2. Some additional features of C++ language were covered in this session. using the insertion operator and extraction operator. EXERCISES : 1.

Member functions of the class. It . The special ‘this’ pointer. Initializing the array of objects. Passing and returning objects. All these features have one thing in common – the vehicle to implement them. How to define a user-defined variable – class. Access specifiers – Private. Object-oriented programming (OOP) is a conceptual approach to design programs. This session will continue our discussion on OOP and C++. and these possible because of data abstraction. How to create variables (objects) of class. Public and Protected. This vehicle is class. Introduction to class. Some of the features of OOP are Data encapsulation and data hiding. Pointers to objects. Array of objects.68 SESSION 4 CLASSES AND OBJECTS During this session you will learn about: • • • • • • • • • • • Structures Revisited.

The above example depicts structure called students with enclosed data variables. a structure template is defined. Creating a structure is a two-part process. 4. First. [or ] In C++ you can even omit the struct tag and declare the variables as. STRUCTURES A structure is a user-defined data type. How it is stored in the memory? How many member variables are there in this composite data element? What are the types of its member variables? For data types like int. The keyword struct is used to define a structure template. 35. Student is a name or tag. This template gives a lot of information to the compiler. . But for the user-defined data types like structures. }. which may contain different data types as its members. char Name[15]. The variables of this type can be declared as follows : struct Student s1. struct Student { int Rollno. double. the structure data type is a stepping-stone to this singularly important concept of C++.jack. 20. “Sanket” .0}. This template creates a new data type.50. float. Student *sptr = &s1.30. char this information is built into the compiler. it has to be provided to the compiler.60. Variables of this new data type can then be declared and used like basic data types. int Marks[6].69 is a new data type similar to structures. For instance. This is given in the definition of the structure template. e.s2.g.1. Student s1 = ( 100.40. Since. Student s2.10. float percent. let us take another look at it.

However.g. but by the data type class. C++ supports the object-oriented features directly. e. The data type class is just like structures. It also has some access specifier. int Marks[6]. The C language also can be used to implement many of the object-oriented principles.2. 4. There are three functions in the template given above. int ClacPercent(). In C++ . whether they directly support OOP concepts or not. INTRODUCTION TO CLASSES Object-oriented programming (OOP) is a conceptual approach to design programs. The building together of data and the functions that operate on that data is called as data encapsulation. float percent. All these features like Data . void Putdetails().70 Student s[100]. But the problem is that the member variables of this structure can be accessed by functions other than the ones declared in the structure template. It can be implemented in many languages. These functions are called as member functions. functions also can be declared in a structure template. These functions have been incorporated in the structure definition to make it a fundamental unit. void Getdetails(). This direct access of member variables of a structure by functions outside the structure is not what OOP has to offer. which controls the access to member variables of a class . char Name[15]. struct Student { int Rollno. but with a difference. }. The actual OOP methodology in this regard is implemented in C++ not by the structure data type.

g. The vehicle is “ class. Using these. : }.3. whether in the private or the public section. Data encapsulation. as writing public overrides the private scope of the class. : private: type member_variable_name. public and protected. are the members of the class.” Class is a user defined data type just like structures. access to member variables of a class can be strictly controlled. They determine the accessibility of the members. but with a difference. CLASS DEFINITION The following is the general format of defining a class template: class tag_name { public : type member_variable_name.71 abstraction. 4. It also has three sections namely private. Since the class scope is private by default. e. The private and public sections of a class are given by the keywords ‘private’ and ‘public’ respectively. : type member_function_name(). you can also omit the keyword private. In such cases you must declare the variables before public. All the variables declared in the class. class tag_name { . : type member_function_name(). Information hiding etc have one thing in common – the vehicle that is used to implement them. // Optional // Must The keyword class is used to define a class template.

private : char name[40]. : type member_function_name(). float calcaverage(void). However. e. // private : public : type member_variable_name. a program can access the private members of a class only by using the public member functions of the class. }. int no_player.72 type member_variable_name. . int runs. // Must // private The variables and functions from the public section are accessible to any function of the program. : }. void showstats(void). class player { public : void getstats(void). float average. : type member_function_name(). int tests.g. int age. This insulation of data members from direct access in a program is called information hiding.

Once a class is declared. an object of the class defined above can be declared with the following statement: player Sachin. We can also use the variable no_player in the public section with a dot operator in functions other than the functions declared in the public section of the class. tests. Once the object is declared. For instance. highest. thus reducing the complexities involved.getstats(). Dravid. a class is a vehicle to implement the OOP features in the C++ language. The variables in the private section – name. Sachin. age.4.73 The above example models a cricket player. The OOP methodology is to hide the implementation specific details.showstats(). e. The program need not know about the changes in the private data and functions.g. and average – can be accessed only by member functions of the class calcaverage(). Mohan. Dravid. With information hiding one need not know how actually the data is represented or functions implemented. Both the objects have their own set of member variables. CLASSES AND OBJECTS As seen earlier. runs. Mohan . Dravid.no_player = 10. The functions in the public section getstats() and showstats() can be called from the program directly . but function calcaverage() can be called only from the member functions of the class – getstats() and showstats(). Mohan . An object is said to be a specific instance of a class just like Maruti car is an instance of a vehicle or pigeon is the instance of a bird. an object of that type can be defined. its public members can be accessed using the dot operator with the name of the object. Once a class has been defined several objects of that type can be declared. 4. . getstats() and showstats(). The interface(public) functions take care of this. [Or] class player Sachin . where Sachin and Dravid are two objects of the class player.

Its declaration in a class template must define its return value as well as the list of its arguments. in which case it is just like a normal function. MEMBER FUNCTIONS OF A CLASS A member function of the class is same as an ordinary function. The member functions that form the interface between the object and the program are declared in public section (otherwise these functions can not be called from the program ). As far as non-member functions are concerned. iterative statements etc should not be written inside the class specifier. You can declare or define the function in the class specifier itself. The syntax is: return_type class_name :: function_name (parameter list) : } e. But since the functions within the class specifier is considered inline by the compiler we should not define large functions and functions with control structures.6. However. which do not form a part of the interface. 4.74 4. the definition of a member function differs from that of an ordinary function if written outside the class specifier. void player :: getstats (void) { : { .5.g. PUBLIC. The header of a member function uses the scope operator (::) to specify the class to which it belongs. private and protected are one and the same.’protected’ or in the ‘private’ sections of the class. the data members of the class are normally declared in the private section. PRIVATE AND PROTECTED MEMBERS: Class members can either be declared in public’. The member functions which may have been broken down further or those. are declared in the private section of the class. pertains to the member functions of some new class that will be inherited from the base class. The third access specifier ‘protected’ that is not used in the above example. But as one of the features of OOP is to prevent data from unrestricted access. By default all the members of the class are private.

}.75 } void player :: showstats (void) { : : } This notation indicates that the functions getstats () and showstats() belong to the class player. } void put() { cout << a. which will be discussed later. 4. . PASSING AND RETURNING OBJECTS Objects can be passed to a function and returned back just like normal variables. When an object is passed by content . Objects can also be passed by address. class check { public : check add(check). e.7. } private : int a. the compiler creates another object as a formal variable in the called function and copies all the data members from the actual variable to it.g. void get() { cin >> a.

temp. } The above example creates three objects of class check.c3.add(c2). We have made use of a temporary object in the function add() in order to facilitate return of the object.get(). c1. It adds the member variable of two classes.8. 4. } check check :: add ( check c2) { check temp.e. POINTERS TO OBJECTS Passing and returning of objects is. the invoking class c1 and the object that is passed to the function .i.a’ . not very efficient since it involves passing and returning a copy of the data members. c2 and returns the result to another object c3. c3.’. c3 = c1. return ( temp).a = a + c2. c2 is referred as ‘c2. This is because the member function will be pointed by the pointer named this in the compiler where as what we pass should be accessed by the extraction operator ‘.a. c2. however.put().c2. This problem can be eliminated using . we may pass more than one object and also normal variable. we can return an object or a normal variable from the function.76 void main() { check c1. You can also notice that in the class add() the variable of the object c1 is just referred as ‘a’ where as the member of the object passed .get().

string str. A pointer variable containing the address of an object is said to be pointing to that object.77 pointers. private : char name[40]. Like pointers to other data types. int runs.g. Like other variables. Pointers to objects can be used to make a call by address or for dynamic memory allocation. // Assigns address of an existing object // Allocates memory with new. It has to be made to point to an already existing object or allocated memory using the keyword ‘new’. void showstats(void). a pointer to an object also uses the arrow operator to access its members. string *sp. // Object // Pointer to an object sp = &str. class player { public : void getstats(void). }. Declaring a pointer to an object of a particular class is same as declaring a pointer to a variable of any other data type. float average. float calcaverage(void). Just like structure pointer. int tests. void main() { . int age. objects of class can also have pointers. sp = new string A simple example of using pointers to objects is given below. e. a pointer to an object also has only one word of memory.

Dravid = new player. e. void printdetails().g. a class is a template. Sachin. }. private : int rollno.total. player *Dravid. void student :: getdetails() { int ctr. which can contain data items as well as member functions to operate on the data items.getstats().showstats(). Dravid->getstats(). . } 4. int marks[6]. an array of objects can be declared and used just like an array of any other data type.78 player Sachin. Also. Dravid->showstats(). Several objects of the class can also be declared and used. Sachin. ARRAY OF OBJECTS As seen earlier.9. An example will demonstrate the use of array of objects. float percent. char name[25]. class student { public : void getdetails().

} percent = total / 6. cin >> x. cout << “ How many students “. i<= x. int x=0. i<= x. i++) { records[i].printdeatils(). for ( int i =1. i++) { records[i]. cout << ” enter 6 marks “ . } } . total = total + marks[ctr]. ctr++ ) { cin >> marks[ctr]. cin >> rollno .getdeatils(). for( ctr = 1 . } for ( int i =1.79 cout << ”enter rollno”. } void student :: printdetails () { cout << rollno << name << percent .ctr <= 6 . cin >> name. cout << ”enter name”. } void main() { student records[50].

each member function does have access to a pointer variable that points to the instance being manipulated. This pointer variable has a special name ‘this’ (reserved word). it invokes the same member function. you always have access to it and may use the variable name anywhere you seem appropriate. then for obvious reasons it would be impossible to create more than one instance of the class. and must be shared by all of the instances of the class. The statement. records[y]. even though the class member functions are encapsulated with the data members inside the class definition. only one copy of each member function per class is stored in memory. But this poses a big problem for the compiler: How can any given member function of a class knows which instance it is supposed to be working on ? In other words. an array of objects is declared just like any other array. THE SPECIAL POINTER ‘THIS’ When several instances of a class come into existence. In other words.10. The solution to this dilemma is that. it naturally follows that each instance has its own copy of member variables. Even though the this pointer is implicitly declared. If this were not the case. For different values of subscript. in point of fact.printdetails(). so that this burden is not placed upon the programmer. invokes the member funs printdetails() for the object given by the subscript y. Consequently. Members of the class are accessed. it would be very inefficient in terms of memory usage to replicate all these member functions and store the code for them within each instance. Fortunately this pointer is supplied to each member function automatically when the function is called. but for different objects. . using the array name qualified by a subscript. all the compiler knows is the offset of each data member from the start of the class.80 As can be seen above. up to now in a class member function you have simply been referring to the members directly without regard to the fact that when the instantiations occur each data member will have a different memory address. 4. On the other hand.

t2 = t1. For example. Also. an explicit reference is made using the this pointer. try_this add(int). void main() { try_this t1. class try_this { public : void print(). t2. cout << this -> ivar . }. which invoked the member function.81 e. private : int ivar. } try_this try_this :: add(int v) { ivar = ivar + v.add(3).print().t2. return ( *this). } The function print refers to the member variable ivar directly.g. . void print() { cout << ivar. This special pointer is generally used to return the object.

Once class has been defined. which can be done by returning the object t1 using *this to t2. then the function add() adds them and ivar for t1 becomes 12 . We want to store this in another object t2. This is possible because of the internal pointer ‘*this’ which keeps track of which function is invoked by which object.82 } In the above example if ivar for t1 is 10 and value in v is 2. many objects of that class can be declared. This can be done as follows : try_this temp(*this). Only the public members of the class can access the data members declared in private section. Write functions for accepting time and displaying time. Define a class to model a banking system. WAP to implement the same. Dereferencing the Pointer this Sometimes a member function needs to make a copy of the invoking instance so that it can modify the copy without affecting the original instance. The primary concepts of OOP is implemented using class and objects. a query to facilitate for account and a facility to deposit and withdraw from the account. try_this temp = *this . A class contains data members as well as function members. Create a class called Time that has separate int member data for hours. The function members should allow initializing the data members. minutes and seconds.print() now will be 12. In OOP emphasis is on how the program represents data. . It is a design concept with less emphasis on operational aspects of the program. The result of t2. 2. The access specifiers control the access of data members. EXERCISES: 1. Data members of different objects of the same class occupy different memory area but function members of different objects of the same class share the same set of functions.

1 CONSTRUCTORS By definition. 5.constructors Constructor with one argument. a constructor function of some class is a member function that automatically gets executed whenever an instance of the class to which the constructor belongs comes into existence. multi arguments Using the constructor Destructor Default constructor and destructor Since C++ supports the concept of user-defined classes and the subsequent initiations of these classes. The execution of such a function guarantees that the instance variables of the class will be initialized properly. .83 SESSION 5 CONSTRUCTOR AND DESTRUCTOR FUNCTIONS During this session you will learn about : • • • • • Automatic initialization of data members . it is important that initialization of these instantiations be performed so that the state of any object does not reflect “ garbage”. This automatic initialization and clean up is accomplished by two member functions – the constructor and the destructor. One of the principles of C++ is that objects know how to initialize and cleanup after themselves.

y2 . for a single class many constructors can be written with different argument lists . but is invoked whenever we create an object of that class. boxclass::boxclass(int ax1. int ax2. i.84 A constructor function is unique from all other functions in a class because it is not called using some instance of the class. void disp(void). Only in very rare circumstances the programmers declare it in private section.g. int ay2) { x1 = ax1 . y1. 5.2 • • • • SYNTAX RULES FOR WRITING CONSTRUCTOR FUNCTIONS Its name must be same as that of the class to which it belongs. y1 = ay1 . It should have public or protected access within the class. It cannot be declared static (a function which does not belong to a particular instance). }. A constructor may be overloaded to accommodate many different forms of initialization for instances of the class. it will implicitly return a temporary copy of the instance itself that is being created. const( in which you can not make changes). It is declared with no return type (not even void). However. e. y2 = ay2 . int y1.int ay1. private : int x1. int y2). int x2. class boxclass { public : boxclass ( int x1. x2 = ax2 . . int x2.e.

Yet. class counter { public : counter ( int c) // constructor. Both the statements given above are equivalent. we can now create an object as. private : int count.25. The first way to call the constructor is explicitly as : boxclass bigbox = boxclass ( 1. }. this approach works if there is only one data item in the class. }. Thus.79). { count = c. This is the third way to initialize an object’s data member. all the following statements to initialize the objects of the class counter are equivalent: counter c1(20).1.1 Using the Constructor There are basically three ways of creating and initializing the object.2.85 } 5. another way of creating and initializing an object is by direct assignment of the data item to the object name. The above object can also be created with an implicit call to the constructor : boxclass bigbox(1. e. This is obvious because we cannot assign more than one value at a time to a variable.g. This statement creates an object with the name bigbox and initializes the data members with the parameters passed to the constructor function.1. But. . object cnt is initialized by a value zero at the time of declaration. counter cnt = 0. In the above example .25.79). This value is actually assigned to its data member count.

In other words. counter c1= 10. C++ is not so rigid in its approach. In the example above. Uninitialized objects like : counter cx. The key to defining an uninitialized object is to have a constructor with default arguments. declaration of objects of this class can be uninitialized as well. e. For instance. However.g. objects cannot be declaring without initializing them. sometimes the data members of an object may not require initialization. then the value of the formal variable c in the constructor defaults to zero. private : int count.86 counter c1 = counter(30). are not allowed. counter c1(20). }.cy. an object of class counter has to be declared and initialized in one of the three ways given above. the program must use it. It has defined means of circumventing such a problem. counter c2 = counter(30). in the above example. Thus. class counter { public : counter ( int c = 0) // Constructor. Once the constructor for a class has been declared and defined. { count = c. . if the actual argument is not given. counter c3 = 10. }. May be they have to be accepted from the user later.

salary = s. } An array of objects can be initialized at the time of declaration. The example given below uses the class employee to illustrate this. } . double salary. }. A constructor has to be provided foe the same.c5.28. as given below : counter create( int cc) { return counter(c).25. double s). private: char name[40].12600). class employee { public : employee(char *n. int a. int age. A constructor can be used to generate temporary instances as well . employee :: employee (char *n . employee(“sanket”. int a. n ).35. employee(“priya”.87 counter c4. double s) { strcpy( name.9600). } void main() { employee E[3] = { employee(“sanat”. age = a.21600) }.

the destructor function may be called explicitly allowing you to release the memory not required and allocate this memory to new resources. Class destructor is normally used to clean up the mess from an object. and therefore cannot be overloaded. However.88 5. It takes no input arguments .4.3.1. 5. the compiler automatically supplies them for you. The primary usage of a destructor function is to release memory space that the instance currently has reserved. Syntax rules for writing a destructor function • • • • • Its name is the same as that of the class to which it belongs. It should have public access in class declaration. It is declared with no return type ( not even void ) since it cannot ever return a value. It cannot be static. otherwise it can be given as an empty function. Class destructors become extremely necessary when class constructor use the new operator. DESTRUCTORS A destructor function gets executed whenever an instance of the class to which it belongs goes out of existence. THE DEFAULT CONSTRUCTOR AND DESTRUCTOR If you fail to write a constructor and destructor function. The compiler generates a class to destructor when the object expires. except that the first character of the name is the symbol tilde ( ~ ). These functions have public access and essentially do nothing useful. const or volatile. in Borland C++ version 3. this would look like: class employee { public : employee() { } . Generally the destructor cannot be called explicitly (directly) from the program. If you were to write these functions yourselves.

int size. void putstr(). e.h> class string { public : string ( char *s). }. string s2 = “ Welcome to C++ \n”. { } }. # include <iostream. since it may impose a limit on the number of characters that can be stored.5. ~string(). private : char *cptr. to model a user-defined data type for strings.h > # include < string. void main(void) { string s1(“ Hello student \n”). which can be determined at its run-time. The object doesn’t use a character array . 5. . The object simulates a character array ( string ) using a character pointer and an integer variable for its actual size. A CONSTRUCTIVE EXAMPLE Consider an example .89 ~employee().g.

This programme demonstrates the use of class along with the constructor and destructor to create a user defined data type String. It contains code to initialize the . after determining the actual size required. we may write a function just like any other function. s2. But then. cptr = new char[size + 1]. } void string::putstr() { cout << cptr.90 string s3 = string ( “ its fun \n”). A class can contain data members as well as function members. For initializing the data members of the class. s1. s3. This function is called automatically when we create an object. } string::string(char *s) { size = strlen(s). } The class defined in the above example contains a character pointer.putstr(). which will be assigned to the variable cptr in the absence of an actual parameter. The destructor uses the delete operator to release the memory allocated by the constructor . C++ provides a special function called constructor. which allocates memory at run–time.putstr(). The constructor function contains a default argument of null character.putstr(). strcpy(cptr. } string::~string() { delete cptr. we have to invoke this function explicitly. A member function is the only way to access the private section members of a class.s).

Add these variables of two objects and store the result in the third. 2. If we write such a function then we must pass parameters each time. SESSION 6 OPERATOR OVERLOADING . C++ also provides a special member function called destructor.91 member variables using the formal parameters if they are passed via objects. The class contains x and y co-ordinates. A constructor should be used to initialize these members. To evade this problem we can write many constructors to give some flexibility to create objects with different parameter lists. WAP to add co-ordinates of the plane. Create a class called Time that has a separate data members for day. which is called automatically when an object expires as per the scope rules. The destructor cannot have any parameters as well. Use a constructor to pass one pair of co-ordinates and a function to accept the second pair. Then write a function to add these dates and store the result in a third object and display it. Create three objects. Both constructor and destructors do not have return types. month and year. We can also use default arguments in the constructor. EXERCISES 1. not even void.

e. if (compare (v1. All computer languages have built in types like integers. as its operands. characters and so on. Conversion functions. v2) = = 0) : : where v1 and v2 are variables of the new data type and compare () is a function that will contain actual comparison instructions for comparing their member variables. real numbers. Rules for overloading the operators. comparisons can be done only on basic data types and not on derived (user-defined) data types. . co-ordinates of a point. add (). complex numbers. However. Some languages allow us to create our own data types like dates. The ability to create new data types. Implementing the operator functions. in C++. the concept of Operator Overloading. Copy Constructor (to solve the problem of initialization). Pointer oddities (assignment) and Operator Overloading. If we want to operate on them we must write functions like compare (). allows a statement like if (v1 = = v2) : : where the operation of comparing them is defined in a member function and associated with comparison operator(==).92 During this session you will learn about: • • • • • • • Introduction to Operator Overloading. is called as Operator Overloading. Operations like addition. on which direct operations can be performed is called as extensibility and the ability to associate an existing operator with a member function and use it with the objects of its class. Operator Overloading Fundamentals.g.

if they are objects of some class. . then the compiler knows the operation to be performed. if defined will be carried out. 6.an important feature of objectoriented programming . here an operator can be overloaded to perform different operations on different data types on different contexts. The asterisk (*) is used as multiplication operator as well as indirection (pointer) operator. Another form of polymorphism is function overloading. C++ has made this facility public. 6. OPERATOR OVERLOADING FUNDAMENTALS The C language uses the concept of Operator Overloading discreetly. IMPLEMENTING OPERATOR FUNCTIONS The general format of the Operator function is: return_type operator op ( argument list ). C++ can overload existing operators with some other operations. Operator Overloading is also called operational polymorphism. then the compiler will carry out the instructions. Now. The compiler decides what operation is to be performed by the context in which the operator is used. y and z are integer variables. then the overloaded operation. the C language has been using Operator Overloading internally. Op has to be a valid C++ operator.Polymorphism means one thing having many forms.93 Operator Overloading is one form of Polymorphism .1.e. e. If the operator is not used in the context as defined by the language. in the statement x = y + z. For example. If x. Where op is the symbol for the operator being overloaded. The ampersand (&) is used as address operator and also as the bitwise logical ‘AND’ operator. a new symbol cannot be used.g. which will be written for that operator in the class.2. Thus. i. But.

The function itself does not take any arguments. Similarly. It increments the data member Count. class Counter { public : Counter(). private : int Count.94 Let us consider an example where we overload unary arithmetic operator ‘++’. c1++. } void main() { Counter c1. ++c1. } void Counter::operator++(void) { ++ Count . to decrement the Counter object can also be coded in the class definition as: . Counter::Counter() { Count = 0. }. } // increments Count to 1 // increments Count to 2 In main() the increment operator is applied to a specific object. void operator++(void).

In the above example . to the following: c1. it does not work exactly like it does for the basic data types.Count = ++ Count . the operator function in the above example has a potential glitch. Counter Counter :: operator++(void) { Counter temp. then the statement to increment gets converted. it can be seen that such a facility is not a very big overhead on the compiler. However. or c1--. } . This is just like a normal function call qualified by the object’s name.operator++(). It has some special characters ( ++) in it. Hence. return ( temp ). the compiler treats it just like any other member function from the class. regardless of whether the operator is postfix or prefix. by the compiler.Count . If we want to assign values to another object in main() we have to return values to the calling function. the compiler checks if the operator is overloaded and if an operator function is found in the class description of the object. the operator function is executed first. } and invoked with the statement --c1. temp. With the increment and decrement operators overloaded.95 void operator--(void) { -. On overloading . Once this conversion takes place.

then assigns. } Counter::Counter( int c) // CONSTRUCTOR WITH 1 ARGUMENT { . private : int Count. // CONSTRUCTOR WITHOUT ARGUMENTS Counter( int c). } //increments to 1. In this example . c1 = c2 ++. We can do this in another way by creating a nameless temporary object and return it.96 void main() { Counter c1. assigns the incremented value of Count to the data member of temp and returns the new object. }.c2. This object is returned to main(). class Counter { public : Counter(). the operator function creates a new object temp of the class Counter. Counter::Counter() // CONSTRUCTOR WITHOUT ARGUMENTS { Count = 0. // CONSTRUCTOR WITH 1 ARGUMENT Counter operator++(void).

. Here we can see binary operator overloaded and also how to return values from the functions. return ( * this). Yet another way of returning an object from the member function is by using the this pointer. This special pointer points to the object. } One change we can see is a constructor with one argument. The constructor with one argument is not required in this approach. return Counter(Count). Hence one argument constructor is required. No new temporary object is explicitly created. It will have a real and an imaginary member variable.97 Count = c. } Consider a class COMPLEX for Complex numbers. class COMPLEX { public: COMPLEX operator+(COMPLEX). However return statement creates an unnamed temporary object of the class Counter initializes it with the value in Count and returns the newly created object. } Counter Counter::operator++(void) { ++ Count . Counter Counter :: operator++(void) { ++ Count . which invokes the function.

Symbolically addition can be carried out as C3 = C1 + C2. • Start by declaring a function in the normal function fashion. Here we have overloaded a binary operator(+). temp. You cannot arbitrarily choose a new symbol (such as @) and attempt to “overload it. imaginary. 6. e. The actual instructions of the operator are written in a special member function. Suppose that C1. but for the function name use the expression: . COMPLEX COMPLEX :: operator+( COMPLEX C2) { COMPLEX temp. RULES FOR OVERLOADING AN OPERATOR This summarizes the most important points you need to know in order to do operator function overloading. } The above example shows how Operator Overloading is implemented.imaginary = imaginary + C2. return (temp).98 private: int real. C2 and C3 are objects of this class. • The only operators you may overload are the ones from the C++ list and not all of those are available.3. imaginary. temp. It overloads “+” operator to perform addition on objects of COMPLEX class.real.g.real = real + C2. }.

^=. >. '. + . As with the predefined operators. %=. [].* :: ?: • • direct member direct pointer to member scope resolution ternary No default arguments are allowed in overloaded operator functions. • -> ! & * + ++ ++ The unary operators that you may overload are: indirect member operator not address dereference plus minus prefix increment postfix increment (possible in AT & T version 2.1) --postfix decrement prefix decrement (possible in AT & T version 2. &. |. *=.! =. <.>>.. i. you cannot change the associativity of the operators. >>=. &=.99 Operator op Where op is the operator to be overloaded. . =. If it is normally unary.! =. • The pre-defined precedence rules cannot be changed.e. you cannot. ||. =. In addition. <<. then it cannot be defined to be binary and vice versa. delete. ==. / . new. ^. You may leave one or more spaces before op. . >=. /=. &&. %. -. +=. • The operators that can not be overloaded are: . for example.1) ~ • one’s complement The binary operators that you may overload are: (). <<=. an overloaded operator may be unary or binary. make binary ‘+’ have higher precedence than binary ‘*’. <=.'(Comma). *. .

+ (Concatenation) using String class. . then it can be overloaded either way or both. String ( char str [] ).!=. it needs to have all its arguments explicitly defined). • The operator function for a class may be either a non-static member or global friend function. >. Consider an example. == (Equality). String operator + (String). private : char s[100].100 However. Since a friend function has no this pointer. int operator < (String s2). String::String () { // CONSTRUCTOR WITH // NO ARGUMENTS s[0] = 0. namely the address of the invoking instance (as specified by the pointer variable this). int operator != (String s2). }. <. • At least one of the arguments to the overloaded function explicit or implicit must be an instance of the class to which the operator belongs. int operator > (String s2). void putstr(). A non-static member function automatically has one argument implicitly defined. if an operator can be both unary and binary. String operator += (String s2). class String { public : String (). which depicts overloading of += (Compound assignment). }. int operator == (String s2).

s. s2. return (temp).str) }. strcat(temp. / ONE ARGUMENT void String:: putstr()// FUNCTION TO PRINT STRING { cout << s .s). .s.s). } int String::operator < (String s2) { return (strcmp (s. s2.s ) > 0).s). return (*this).s2. } String String :: operator+=(String s2) { strcat(s. } int String::operator > (String s2) { return (strcmp (s. String String :: operator+(String s2) { String temp.s2. }.s ) < 0). strcpy(temp.101 String:: String( char str [] ) // CONSTRUCTOR WITH { strcpy(s.

cout <<endl<<” *********************”. s4 = s1 + = s2. s4.102 } int String::operator == (String s2) { return (strcmp (s. s2. String s4. } void main() { String s1 = “welcome “. String s2 = “ to the world of c++”.putstr(). . String s3.s ) != 0). s2. String s5 = “ Azzzz “.putstr(). } int String::operator != (String s2) { return (strcmp (s. s1. cout << endl << “ s4 = “. s3 = s1 + s2. cout << endl << “s1 = “.s ) == 0).putstr(). cout << endl << “s2 = “. cout << endl << “ s3 = “. s3. s2.putstr().

cout << ” > ”.putstr(). cout << ” < ”. s6. s6. cout << ” < ”. s6.putstr().putstr(). if( s5 < s6 ) { s5.putstr().putstr(). } else { s5. s6.103 String s6 = “ Apple “. } else if( s5 > s6 ) { s5. } } Output: S1 = welcome S2 = to the world of C++ S3 = welcome to the world of c++ ************************** S4 = welcome to the world of c++ if( s5 != s6 ) if( s5 == s6 ) .putstr(). cout << ” = ”.putstr().putstr(). } else { s5.

// CONSTRUCTOR } void putstr() { cout << cptr . ~String() { delete cptr.104 6. }. }.4. The following example explains this problem. In this case using an assignment operator to assign one object to another will result in the pointer variable being copied rather than the contents at the address. void main() // FUNCTION TO PRINT STRING . strcpy(cptr. private : char *cptr. where the data members contain pointers and have been allocated memory using the operator new. class String { public : String (char *s = “”) { size = strlen(s). int size. cptr = new char [size + 1]. }. POINTER ODDITIES AND OPERATOR OVERLOADING Consider an example .s).

the delete operator called for the first object releases the memory and for the second call attempts to release the same memory location again. gets assigned to s2. The solution to this problem is to define an operator function for the assignment operator . which releases the memory allocated by new to the data member cptr. size = strlen ( s2. s2.putstr(). the destructor function is called automatically. of object s1. // Assignment s1. the data members’ cptr and size . The assignment operator in main() assigns the object s1 to s2. cptr = new char [size + 1]. resulting in the error message.105 { String s1(“hello students “).cptr ).putstr(). . after the assignment. The output of the program is : hello students hello students Null pointer assignment Why does the program give a ‘null pointer assignment’ message ? After the program is over. But. Thus. String s2. the data member cptr of both the objects point to the same location in the memory. It can be done as follows: String operator = (String s2) { delete cptr. s2 = s1. } The constructor function allocates a string and copies the contents of its formal variable in it.

the problem of assignment arises here too. } On including this member function in the class definition of the above example .5. whereas assignment can occur whenever desired in the program. And since one of the members is a pointer. Therefore. //Initialization The first statement declares an object s1 and passes a string as an argument to its constructor. the program outputs the following : hello students hello students Hence. . the operator function for assignment of an object to another of the same class removes the quirks associated with pointers as data members. s2. Since there is no constructor having an object as its formal argument. The second statement declares another object s2 and contains an object as its argument. This constructor is also called “copy constructor “. Defining a constructor function that takes object as its argument solves the problem of initialization. String s2(s1). return (*this). String s1(“this is a string”). COPY CONSTRUCTOR Similar problems occur at the time of initialization of an object with another of the same class . When an object is passed by value as an argument to a function. initialization takes place only once when the object is created. 6. Overloading the assignment operator solves the problem of assignment. Although initialization and assignment both assign values. It is called in three contexts : • • When one object of a class is initialized to another of the same class. The data members of s1 are initialized using the String.106 strcpy(cptr. the compiler itself initializes the second object‘s data members with those of the formal object . they differ conceptually.cptr).

since the compiler does not know anything about user-defined types (classes). CONVERSION FUNCTIONS Conversion functions are member functions used for the following purposes: 1. obviously this existing instance should never be modified by the copy constructor function . cptr = new char[size + 1]. float f = 3. implicit conversion f = (float) j. Conversions of one basic data type to another are automatically done by the compiler using its own built-in routines (implicit) and it can be forced using built-in conversion routines (explicit). A copy constructor for the above example is given below : String (const String &s2) { size = s2. a copy constructor is very important if the class contains pointer as data member . strcpy(cptr. j =19.5. } It is just like a normal constructor but the argument here is an object of the class . // i gets the value 3 . so the keyword const should be used in the function signature. int i = 2. Conversion of object to basic data type. 2.s2. 3. 6. the program has to define conversion functions. Hence . Conversion of objects of different classes. Conversion of basic data type to object.6.00. However. e. // f gets 19.cptr).107 • When a function returns an object.g. i = f. All these situations result in a copy of one object to another. explicit conversion .size.

feet = int(f). }. }. void main (void) { Distance d1 = 1.0. f = 3. class Distance { public : Distance(void) // Constructor with no { feet = 0.”. inches = 0.108 6. cout << “ Inches = “ << inches << endl. // Uses 2nd constructor // Uses 1st constructor . float inches. // Constructor with // one argument // argument // also used for }. float m. d2 = 2. Conversion from Basic to User-Defined variable Consider the following example. // Uses 2nd constructor Distance d2.28 * metres.25.0 .// conversion void display(void) { cout << “ Feet = “ << feet <<”.6. }. Distance(float metres) { float f.1. private : int feet. inches = 12 * ( f – feet).

} Output : 1.0 metres is :“ << d2.showdist(). 6. The declaration of first object d1 uses the second constructor and conversion takes place. INCHES = 1. INCHES = 6. inches = 0. cout << “ 2.199999 2.25 metres is : “ << d1.0.25 metres is :FEET = 4 . The compiler first checks for an operator function for the assignment operator. }.6. then it uses the constructor to do the conversion.showdist() . when the statement encountered is d2 = 2.0 metres is :FEET = 6 . // argument Distance(float metres) { . Conversion from User-Defined to Basic data type The following program uses the program in the previous section to convert the Distance into metres(float).109 cout << “ 1. If the assignment operator is not overloaded. class Distance { public : Distance(void) // Constructor with no { feet = 0.719999 The above program converts distance in metres ( basic data type) into feet and inches ( members of an object of class Distance ). However.2.0.

25 metres is :“ << d1. d2 = 2. f = inches / 12. }.28 * metres. cout << “ 2.0 . float inches.110 float f. }. m = float ( d1 ). private : int feet. //conversion // Also used for }.showdist ().28 ). cout << “ Inches = “ << inches << endl.0 metres is :“ << d2. // Constructor with f = 3.showdist (). // Conversion function // from Distance to float void display(void) { cout << “ Feet = “ << feet <<”. // one argument feet = int(f).25. float m. f = f + float (feet). operator float(void) { float f. // Uses 2nd constructor Distance d2. return ( f/ 3. cout << “ CONVERTED BACK TO METRES “. . void main (void) { Distance d1 = 1.”. inches = 12 * ( f – feet). // Uses 2nd constructor // Uses 1st constructor cout << “ 1. }. // Calls function explicitly.

} Output: 1. The conversion is achieved explicitly and implicitly.199999 2. m = float (d1).111 cout << “ d1 = “ << m.1. The function can be a member function of the source class or a member function of the destination class.3. Conversion function in the Source Class .INCHES = 1.00 Actually. Conversion Between Objects of Different Classes Since the compiler does not know anything about the user-defined type. 6. 6. The conversion function must not define a return type nor should it have any arguments.0 metres is :FEET = 6 .719999 CONVERTED BACK TO METRES d1 = 1.6. The second class DistMetres store distance in metres and has a constructor to receive the member. in the second assignment statement m = d2.6. is forced where as .INCHES = 6. We will consider both the cases. this conversion function is nothing but overloading the typecast operator float(). cout << “ d2 = “ << m. Consider a class DistFeet which stores distance in terms of feet and inches and has a constructor to receive these.3. the conversion instructions are to be specified in a function.25 d2 = 2. // Calls function explicitly. first the compiler checks for an operator function for assignment ( = ) operator and if not found it uses the conversion function.25 metres is :FEET = 4 . m = d2.

”. // Constructor with no // argument void ShowFeet(void) { cout << “ Feet = “ << feet << “. cout << “ Inches = “ << inches << endl. }.112 class DistFeet { public : DistFeet(void) { feet = 0. class DistMetres { public: DistMetres(void) { metres = 0 . . }. private : int feet.0. DistFeet(int ft. float inches. } DistMetres(float m) // constructor 1. inches = in }. inches = 0. }.float in) { feet = ft.

} void ShowMetres(void) { cout << “ Metres = “ << metres << endl. ifeet = int (ffeet). inches.ifeet). ffeet = 3. // Uses conversion function dm1. operator DistFeet(void) // conversion { // function float ffeet.ShowMetres(). DistFeet df1. } . void main (void) { DistMetres dm1 = 1. // constructor 2.113 { metres = m .28 * metres. }. return(DistFeet(inches.ShowFeet(). inches = 12 * (ffeet – ifeet). df1. df1 = dm1 .0. // OR df1 = DistFeet(dm1). }. private: float metres. int ifeet. }.

It could also have been called explicitly as df1 = DistFeet(dm1).2.6. } // constructor 2.114 In the above example.3.Conversion function in the Destination Class class DistMetres { public: DistMetres(void) { metres = 0 . DistMetres contains a conversion function to convert the distance from DistMetres ( source class). float GetMetres(void) { return(metres). to DistFeet ( destination class). void ShowMetres(void) { cout << “ Metres = “ << metres << endl. 6. // Constructor 1. The statement to convert one object to another df1 = dm1. }. } . calls the conversion function implicitly. } DistMetres(float m) { metres = m .

void ShowFeet(void) { cout << “ Feet = “ << feet << endl. cout << “ Inches = “ << inches << endl. inches = 0. DistFeet( DistMetres dm) // Constructor 3 { float ffeet. }. . }.115 private: float metres. class DistFeet { public : DistFeet(void) // Constructor1 with no { feet = 0. }. ffeet = 3. }.GetMetres(). // argument DistFeet(int ft. inches = 12 * (ffeet – ifeet).0. inches = in.28 * dm. feet = int (ffeet). }.float in) { feet = ft.

Since you can use any of the above methods. }. df1. // Uses 1st constructor // class DistFeet df1 = dm1 . void main (void) { DistMetres dm1 = 1. The function is required because the constructor is defined in the DistFeet class and since metres is a private member of the DistMetres class. } This program works same as previous function. // Uses 2nd constructor // class DistMetres DistFeet df1. it is strictly a matter of choice which method you choose to implement. we can see a new function GetMetres() . it cannot be accessed directly in the constructor function in the DistFeet class. . Here constructor is written in the destination class. float inches. // OR df1 = DistFeet(dm1).ShowMetres(). // Uses 3rd conversion function dm1.116 private : int feet.ShowFeet().0. The function returns the data member metres of the invoking object. Also.

{ make use of constructors and destructors whenever possible } . simple concept which gives the C++ language a facility to redefine itself into a new language. WAP to add. WAP to add 2 times using OOT and display the resultant time in watch format. We will see function overloading in future. It is very powerful.117 Table for Type Conversions Operation Function in Destination Class Operation Function in Source Class Basic to class Constructor Not Allowed Class to Basic Not Allowed Conversion Function Class to Class Constructor Conversion Function This session covered yet another concept of OOP – Polymorphism. WAP to add 2 complex number using OOT(Operator Overloading techniques). It means one thing having many forms. 3. This session covered operational polymorphism also called as operator overloading. Overload >= or <= operators to compare the two strings. 2. Sort an array of objects. yet. Each object has a string as a member variable. subtract and multiply 2 matrices using OOT. EXERCISES 1. There are two types of Polymorphismoperational and functional.

d1 > = d2 . if(m1==m2) { m3=m1+m2. Modify the matrix program (program 3) slightly. a) no_of_dasy = d1 – d2.. Display the result after every operation. Accept 2 valid dates in the form of dd/mm/yyyy. } else display error. where d1 and d2 are DATE objects. 5.where d1 is a DATE object and no_of_days is an integer. WAP to concatenate 2 strings by using a copy constructor.118 4. Implement the following by overloading the operators – and + . whether the column of first and the row of second matrix are same or not. m4=m1-m2. and no_of_days is an integer. 6.e. WAP to create a class called DATE . Overload == operator to compare 2 matrices to be added or subtracted. b) d1 = d1 + no_of_days . i. SESSION 7 FUNCTION OVERLOADING AND REFERENCES During this session you will learn about : .

The argument list of the function is also called as the function’s signature. Function overloading facilitates defining one function having many forms. but use different argument lists. int add( int. thus overloading the function names. Operator overloading is nothing but defining a member function. Order of arguments. Why using references is a must in some occasions.119 • • • • • • • Function overloading. int ). Reference oddities. Passing and returning reference variables. This is also called operational polymorphism. for a particular operator. e. which will be invoked when the operator is used with objects of that class. int ). Data types of the arguments. Like in operator overloading.1. int add( int. even here. .g. The differences can be 1. 3. 2. Call by reference. Precautions to be taken while overloading functions. int. do the same thing. 7. if the number and data types of the arguments are same. The previous session covered operator overloading. In number of arguments. The second form of polymorphism in C++ is functional polymorphism also called function overloading. You can overload the function only if their signatures are different. Function overloading is used to define a set of functions that essentially. FUNCTION OVERLOADING Function overloading is a form of polymorphism. In other words it facilitates defining several functions with the same name. the compiler uses context to determine which definition of an overloaded function is to be invoked. Need to overload functions.

120 float add( float, float ); float add( int, float, int ); float add(int,int,float);

The compiler cannot distinguish if the signature is same and only return type is different. Hence, it is a must, that their signature is different. The following functions therefore raise a compilation error. e.g. float add( int, float, int ); int add( int, float, int );

Consider the following example, which raises a given number to a given power and returns the result. long long_raise_to(int num, int power) { long lp = 1;

for( int i = 1; i <= power ; i++ ) { lp = lp * num ; } return lp; } double double_raise_to( double num, int power) { double dp = 1;

for( int i = 1; i <= power ; i++ ) { dp = dp * num ; } return dp;

121 } void main(void) { cout<<”2 raise to 8 is <<long_raise_to(2,8); cout<<”2.5 raise to 4 is <<double_raise_to(2.5,4); } In C we would required to write 2 different function names as can be seen from the above example. These functions do identical tasks. However using function overloading techniques we can write the same program in C++ as shown: long raise_to(int num, int power) { long lp = 1; for( int i = 1; i <= power ; i++ ) { lp = lp * num ; } return lp; } double raise_to( double num, int power) { double dp = 1;

for( int i = 1; i <= power ; i++ ) { dp = dp * num ; } return dp; } void main(void) { cout<<”2 raise to 8 is <<raise_to(2,8); cout<<”2.5 raise to 4 is <<raise_to(2.5,4);

122 }

The main () function makes two calls to the function raise_to() –once with 2 integers as arguments and again with an integer and a double. The compiler uses the context to determine which of the functions to invoke. Thus, first time it invokes first function and then the second one.


Function overloading is a boon to designers, since different names for similar

functions need not be thought of, which often is a cumbersome process given that many times people run out of names. But, this facility should not be overused, lest it becomes an overhead in terms of readability and maintenance. Only those functions, which basically do the same task, on different sets of data, should be overloaded.


Passing variables(parameters) to a function in C can be done in two ways – pass by

value, also called as call by value and pass by address or also called as call by address. C++ however , gives one more way to call a function – call by reference. In call by value , a copy of the actual contents of the variables is passed to the function. In this case, changes made to the formal variable , as they are called, are not reflected back in the calling function. Passing an address allows changes to be made directly to the memory, which are occupied by the actual variable.

However, a call by address requires the formal variable to be considered as pointer and thus the indirection operator has to be used with them. A reference on the other hand, is another name, for a previously defined variable. In other words, after a reference is defined for a particular variable, using its original name as well as the reference can refer to the variable. Hence, a reference is nothing but an alias.

Thus not passing a copy (call by value) saves time and is efficient. It does not have to create a temporary variable /. And not passing the address(call by address), eliminates the use

123 of pointers in the called functions. But, at the same time, the changes made to a formal variable , using its reference or alias can be reflected back in the calling function.



C and C++ , both use the ampersand ( &) symbol as the address operator. It is also overloaded to perform binary AND operation on its operands. C++, once more overloads this operator and uses it to declare a reference variable . e.g. void main() { int num1 = 10, num2 = 200; int &ref = num1; cout << “num1 = “ << num1 << endl; cout << “num2 = “ << num2 << endl; cout << “ref = “ << ref << endl; // & used only to // declare. ref = num2; cout << “ After change “ <<endl; cout << “num1 = “ << num1 << endl; cout << “num2 = “ << num2 << endl; cout << “ref = “ << ref << endl; }

Output : num1 = 10 num2 = 200 ref = 10 After change num1 = 200 num2 = 200 ref = 200

Also. int y) { int t. Reference variables are particularly useful when passing to functions. } void add_swap(int *x. } void val_swap(int &x. *y = t. The program given above shows the result of assigning another variable to a reference variable. PASSING REFERENCE TO FUNCTIONS. *x = *y. // Call by Value t = x. int &y) { int t. t = *x.124 A reference variable declared in a function should be initialized at the time of its declaration itself.g. actually assigns its contents the original one. once a reference has been made to a variable. 7. the reference to a particular variable may not be changed later in the program. The changes made in the called functions are reflected back to the calling function . // Call by Reference . it cannot be changes to refer to another variable. y = t. void val_swap(int x. Hence .5. e. int *y) // Call by Address { int t. swapping the values of two variables. The program uses the classic problem in programming. the output of the program shows that assigning a variable to a reference variable. x = y.

125 t = x; x = y; y = t; }

void main() { int n1 = 25, n2 = 50;

cout << “Before call by value : “; cout << “ n1 = “ << n1 << “ n2 = “ << n2 << endl; val_swap( n1, n2 ); cout << “ After call by value : “; cout << “ n1 = “ << n1 << “ n2 = “ << n2 << endl;

cout << “Before call by address : “; cout << “ n1 = “ << n1 << “ n2 = “ << n2 << endl; val_swap( &n1, &n2 ); cout << “ After call by address : “; cout << “ n1 = “ << n1 << “ n2 = “ << n2 << endl;

cout << “Before call by reference: “; cout << “ n1 = “ << n1 << “ n2 = “ << n2 << endl; val_swap( n1, n2 ); cout << “ After call by value : “ ; cout << “ n1 = “ << n1 << “ n2 = “ << n2 << endl; } Output : Before call by value After call by value : n1 = 25 n2 = 50 : n1 = 25 n2 = 50 // x = 50, y = 25

Before call by address : n1 = 25 n2 = 50

126 After call by address : n1 = 50 n2 = 25 //x = 50, y = 25

Before call by reference: n1 = 50 n2 = 25 After call by reference : n1 = 25 n2 = 50 //x = 25, y = 50

You can see that the only difference in writing the functions in call by value and call by reference is while receiving the parameters where as in pass by address the function body has some changes, i.e. they use (*) indirection operator to manipulate the variables.



Just as in passing the parameters by reference, returning a reference also doesn’t return back a copy of the variable , instead an alias is returned. e.g. int &func(int &num) { : : return(num); } void main() { int n1,n2; : :

n1 = fn( n2); }

Notice that the function header contains an ampersand (&) before the function name. This is how a function is made to return reference variable. In this case, it takes a reference to

127 an integer as its argument and returns a reference to an integer. This facility can be very useful for returning objects and even structure variables.

7.7 .

The following example illustrates that the use of reference variable sometimes

becomes imperative. It uses the String class, which has already been covered earlier. class String { public : String (); String(char *s); ~String(); String operator=(String str); private : char *ptr; int size; }; String::String () { size = 0; cptr = 0; cout << “ Constructor = ” << cptr << endl; } //Constructor 1

String::String(char *s) { size = strlen(s); cptr = new char[size+1]; strcpy(cptr,s);

//Constructor 2

cout << “ Constructor = “ << cptr << endl; }


String::~String() {

// Destructor

cout << “ Destructor= “ << cptr << endl; delete cptr; }

String::String operator=(String str) { delete cptr; size = strlen(str.cptr); cptr = new char[size+1]; strcpy(cptr,str.cptr); return(*this);

} void main() { String s1 = “ You are learning references”; String s2;

S2 = s1; } Output: Constructor = You are learning references Constructor = null Destructor = You are learning references Destructor = You are learning references Destructor = You are learning references Destructor = You are learning references

whos argument being nothing prints null. The assignment statement . The destructor function is called automatically by the compiler after this statement. gets converted into s2. it can be seen from the output that the destructor function is called four times for two objects. There is just one assignment statement in the program.8.str. s2 = s1. Therefore the destructor function is invoked four times .operator=(s1). The declaration of the first object invokes the second constructor and the second object invokes the first constructor. However. size = strlen(str.129 The example given above declares two objects s1 and s2 of class Sting. REFERENCE ODDITIES . The operator function needs to be changed slightly as given below: String &operator=(String &str) { delete cptr. when the object is passed to the function it is stored in a temporary object and while returning with *this.cptr). } Now the output will be : Constructor = You are learning references Constructor = null Destructor = You are learning references Destructor = You are learning references 7. which assigns the contents in s1 to s2 using the operatoroverloaded function. cptr = new char[size+1]. the solution to this is to pass and return objects by reference. strcpy(cptr. the compiler creates an unnamed temporary object. return(*this).cptr).

be it in an array or a member variable from structure or class. func(sint). For instance. func(sint + 10). } // Integer Constant // Expression Output : Before incrementing Small Int = 10 Long Int = 20 . cout << “Small int = “ << sint << endl. func(25). func(lint). } void main() { long lint = 20. int sint = 10.130 A reference variable can refer to any integer variable. void func(int &intref) { ++intref. cout << “Long int = “ << lint << endl. Reference variables can refer to constants as well. cout << “Small int = “ << sint << endl. take a look at the program given below. cout << “Before incrementing “ << endl. cout << “Long int = “ << lint << endl. // Integer Variable // Long Variable cout << “After incrementing “ << endl.

which receives a reference to an integer. Besides having the pointer notation also makes it obvious that the function is intended to make changes to the arguments. yet. if a function has to change the value of an argument. four times.131 After incrementing Small Int = 11 Long Int = 20 The program calls func() . classes and objects extensively. since a mismatch between the data types of the actual argument and the formal argument is shielded by these temporary reference variables. This session also discussed yet another way of passing arguments to a function. The func() increments the temporary variable and therefore as can be seen from the output . the last two calls do not result in errors but temporary variables are created for them just like in the earlier case. a) ADD(s1. b) ADD(s1. lint still has the same value. . which gets duly incremented. The compiler does not give a type mismatch error but instead . EXERCISES 1. references are still used with structures . This session along with the previous session covered the most exciting feature of C++ polymorphism.where s1 and s2 are COMPLEX numbers. A call by reference does not make a copy of the contents of the arguments nor does it uses the addresses. However. It again calls the func() with long variable. programmers prefer to use pointers. it allows changes made in the called function to be reflected back in the calling function. it creates a temporary variable of the correct type and assigns the value of the variable lint to this variable. by making a call by reference. Similarly. as can be seen from the output. WAP to create a class called as COMPLEX and implement the following by overloading the function ADD which returns a complex number. However. s2 ). s2) – where s1 is an integer ( real ) and s2 is a COMPLEX number. First with an integer variable .

diffdays = date1 – date2.132 2. month and year as its members.g. Create a class DateClass with day. e. The first function returns the difference between two dates in terms of days.g. SESSION 8 . somedate. int days. int diffdays. DateClass date1. Write an overloaded function for the minus sign. The second overloaded function is written which returns a date occurring a given number of days ago. e. DateClass newdate. date2. newdate = somedate – days.

Object-oriented programming as seen in the preceding sessions emphasizes the data. 8.1. Reusing old code not only saves development time. How to define a derived class ? Private. has given a new dimension to this idea of reusability. It leaves the programmer more time to concentrate on the overall logistics of the program. information hiding. It is better to use existing code. but also saves the testing and debugging time. REUSABILITY Reusability means reusing code written earlier . The access specifiers. files and so on. like reusability. the vehicle. OOP. Public and Protected derivations. Details about the hardware. writing new code may introduce bugs in the program. however. which has been time-tested rather than reinvent it. The previous sessions covered OOP features like extensibility. functional polymorphism and operational polymorphism. This session covers reusability and inheritance. encapsulated in a . has more jargon associated to it. Inheritance concept. Code. WHAT IS INHERITANCE? Class. may relieve a programmer of the nitty-gritty. data encapsulation. Moreover.may be from some previous project or from the library. Using the derived class . A class library consists of data and methods to operate on that data. inheritance. Many vendors now offer libraries of classes. user-interface. which is used to implement object-oriented concepts in C++. rather than emphasizing algorithms.133 INHERITANCE During this session you will learn about : • • • • • • Reusability. written and tested earlier. 8.2.

HOW TO DEFINE A DERIVED CLASS ? A singly inherited derived class id defined by writing : • • • • • • The keyword class. The old class is called the base class or parent class or super class and the class which is derived from this base class is called as derived class or child class or sub class. The remainder of the class definition. the derived class “is a “ type of base class. In other words. The new dimension of OOP uses a method called inheritance to modify a class to suit one’s needs. and this is possible without having the source of the course definition also. The name of the derived class . but with more details added. In other words. The source code of these libraries need not be available to modify them. a derived class not only inherits all properties of the base class but also has some refinements of its own. Deriving a new class from an existing one . Inheritance means deriving new classes from the old ones. or public ). . 8. The base class remains unchanged in the process.3. The name of the base. the relationship between a derived class and its base class is called an “is-a” relationship. allows redefining a member function of the base class and also adding new members to the derived class . A single colon (:). protected. or parent class. The type of derivation ( private .134 class . Class A Class B Single Inheritance Here class A is a base class and the class B is the derived class. For this reason.

void protected_function_A(). void private_function_C(). }. class B : private A { public : int public_B. . private : int pri_A. private : int pri_C. }. class C : public A { public : int public_C.135 e. void private_function_B(). void public_function_A(). }. protected : int protected_A. private : int pri_B. void public_function_B(). void private_function_A(). void public_function_C().g. class A { public : int public_A.

A derived class always contains all of the member members from its base class . if another private derivation occurs from this derived class. this means that the creator of the base class has absolute control over the accessibility of these members . e. and there is no way that you can override this. If a new class is derived privately from its parent class . However. just because you happen to derive a class does not mean that you are automatically granted complete and unlimited access privileges to the members of the base class. you cannot “subtract” anything from a base class. then a private derivation is assumed. In other words. In other words. accessing the inherited variables is a different matter. • The public members inherited from the base class have private access privilege. }. private : int pri_D. then these members are inaccessible to new member functions. It is also important to understand the privileges that the derived class has insofar as access to members of its base class are concerned. they are treated as though they were declared as new private members of the derived class. to understand this you must look at the different types of derivation and the effect of each one.g. PRIVATE DERIVATION If no specific derivation is listed.4. void private_function_D(). 8. However. void public_function_D(). then : • The private members inherited from its base class are inaccessible to new member functions in the derived class . so that new member functions can access them.136 class D : protected A { public : int public_D. class base { private : .

The compiler error message is ‘ base :: number ‘ is not accessible in the function derived :: f(). // Access to number O. class derived : private base { public : void f() { ++number. } }.137 int number. }.g. e. class derived2 : private derived { . class base { public : int number. class derived : private base { public : void f() { ++number. // Private base member not accessible } }. }.K.

the function derived :: f() has no problem accessing it . Of course. } }. In derived2 we can write. i. if derived1::g() were to call upon derived::f().e. class derived : private base { public : base :: number . however. this new class inherits number but cannot access it. void g() { f(). }. class base { public : int number. there is no problem since derived::f() is public and inherited into derived2 as private. // Access to number is prohibited.138 public : void g() { ++number. Since public members of a base class are inherited as private in the derived class. } or there is another way. The compiler error message is ‘ base :: number ‘ is not accessible in the function derived2 :: g(). when another class is derived from the class derived . Writing access declaration does this. void f() .

}. As you have just seen private derivations are very restrictive in terms of accessibility of the base class members . } }. In this situation : The private members inherited from the base class are inaccessible to new members functions in the derived class.g.139 { ++number. therefore. class derived : public base { public : .5. class derived2 : private derived { public : void g() { ++number. e. } }. // Access to number O. 8. this type of derivation is rarely used. The public members inherited from the base class may be accessed by new members functions in the derived class and by instances of the derived class .K // Access to number O. class base { private : int number. • • PUBLIC DERIVATION Public derivations are much more common than private derivations.K.

here is how protected works : • In a private derivation the protected members inherited from the base class have private access privileges. In both situations the new members functions and friends of the derived class have unrestricted access to protected members . Thus. as the instances of the derived class are concerned. The compiller error message is ‘ base :: number ‘ is not accessible in the function derived::f(). however. declaring the data member number as private is much too restrictive because clearly new members function in the derived class need to gain access to it and in order to perform some useful work. new member functions and friend of the derived class may access them. Here. so that direct access id always denied. // Private base member not accessible } }. • In a public derivation the protected members inherited from the base class retain their protected status.140 void f() { ++number. you can see that the new category of protected provides a middle ground between . THE PROTECTED ACCESS RIGHTS In the preceding example.6. only if the number is public then you can access it. protected and private are one and the same. They may be accessed by new members function and friends of the derived class . To solve this dilemma. the C++ syntax provides another class access specification called protected . Therefore. Note : However example 2 and 3 in the above section works here if you derive them as “public”. 8.

.K. you may also do a protected derivation. ( this is exactly same as if a private or public derivation has occurred. PROTECTED DERIVATION In addition to doing private and public derivations. } }. 8.141 public and private by granting access to new function and friends of the derived class while still blocking out access to non-derived class members and friend functions . }. // base member access O. In this situation : • The private members inherited from the base class are inaccessible to new member functions in the derived class.) • • The protected members inherited from the base class have protected access privilege. class derived : public base { public : void f() { ++number. class base { protected : int number.7. The public members inherited from the base class have protected have protected access.

In a protected derivation.9. private members are inherited by the derived class . 4. and certainly not by the instances of the derived class . SUMMARY OF ACCESS PRIVILEGES 1. if the designer wants to let everyone . the only difference between a public and a protected derivation is how the public members of the parent class are inherited. including the instances. have access to that member . then that member should be made public . the derived class inherits public and protected members as protected . a new member function of the derived class may access the public and protected members of the base class .a new members function of the derived class may access the public and protected members of the base class. the derived class inherits public members as public . the derived class inherits public and protected members as private . Regardless of the type of derivation. then that member must be protected. not even a derived class to access a member . In a private derivation. 8.8. a new members function can access these members. and protected as protected . If the designer of the base class wants no one. 3. Also any members of subsequently derived classes may not gain access to these members because of the first rule. TABLE OF DERIVATION AND ACCESS SPECIFIERS . then that member should be made private . but instances of the derived class may not. 8. but cannot be accessed by the new member function of the derived class . 3. both instances of the derived class may access only the public members . 2. 8. In public derivation.10.142 Thus . SUMMARY OF DERIVATIONS 1. It is unlikely that you will ever have occasion to do this type of derivation. If the designer wants any derived class function to have access to it.but instances of the derived class may access only the public members. 2.

11. assuming that the same name does not exist within the scope of the derived class .143 Derivation Type Base Class Member Private Private Public Protected Access in Derived Class (inaccessible ) Private Private Private Public Public Protected (inaccessible ) Public Protected Private Protected Public Protected (inaccessible ) Protected Protected 8. } . class base { public : base(int n = 0) { number = n. you do not need to use scope resolution operator to refer to this base class member. USING THE DERIVED CLASS An instance of a derived class has complete access to the public members of the base class . the members from the base class will automatically be used. Because there is no ambiguity involved in this situation.

use it . } Output: 0 0. void main() { derived d.144 int get_number(). } class derived : public base { }. }. protected : int number.base ::get_number(). else Does the member have accessible cope higher up in the hierarchy? If so use it. // Goes directly to class base cout<< d. // First checks class derived . use it . the compiler resolves the address by checking : • • • • Does the member function have scope in the derived class ? if so.get_number(). int base :: get_number() { return number. then class base cout << d. else Does the member have scope higher up in the hierarchy ? if so use it. Using derived instances to access function members without the base class name and scope resolution operator. else Does the member have scope in the parent class ? if so. else .

else generate a compilation error. the most important concept of OOP. Constructor and destructor in derived class . Nested classes ( container classes). Object initialization and conversion. probably. Multiple inheritance. Pure virtual function. Multiple inheritance with common base classes. Abstract class. Inheritance is the most powerful use of class and is also. Virtual base class.145 • Does the member exist in the file scope ? if so use it . It is the mechanism using which reusability of code is achieved. Virtual function. The facility to use the existing tested code reduces the time and cost of writing it all over again. The next session covers more suitable aspects of inheritance. Pointers to objects. This session discusses the more subtle aspects associated with class inheritance. Multilevel inheritance. . Class inheritance has given a new dimension to the idea of reusability of code. SESSION 9 MORE ON CLASS INHERITANCE During this session you will learn about: • • • • • • • • • • • • Hiding overloaded functions. This session introduced the concept of inheritance. The previous session introduced the concept of inheritance.

000000 .g. class base { public : void f(int n ) { cout << “ n = “ << n. void main() { derived d. e. class derived : public base { public :a void f(float n ) { cout << “ n = “ << n. HIDING OVERLOADED FUNCTIONS We cannot overload a base class function by redefining it in a derived class with a different argument list. } Output : n = 1. d. Consider examples to see if same function name exists in base as well as derived classes.f(1). } }. } }.1.146 9.

} }. The following example shows this. } Output: ‘Can not convert ‘char*’ to ‘double’ . compiler knows about. d. } }. the inherited members from the class will not be examined.147 Even though we have passed an integer. class derived : public base { public : void f(float n ) { cout << “ n = “ << n. void main() { derived d. the compiler uses the function of the derived class because it is the one.f(“A”). If there is no convincible match within the scope of the derived class. class base { public : void f(char *ptr) { cout << “ ptr = “ << ptr.

protected: int base_number. The output will be : ptr = A 9.2. So in the main if we call d. we can still access the hidden members from the base class using the scope resolution operator. Syntax in the derived class base/members initialization list : • • The base class name ( name of base constructor ) A list of arguments between parentheses.base::f(“A”). leave the argument list empty. as in any normal function call. before the derived class initialization list is honored. CONSTRUCTOR AND DESTRUCTOR FUNCTION WITH DERIVED CLASSES If there are constructors involved in the base class and the derived class. }.. int get_base_number(). To explicitly invoke the base class default constructor . ~base(). Remember the base class constructor always is called first. . the base class constructor will be called immediately. class base { public : base(int n=0).e. the compiler automatically calls both of them. This happens because as soon as the derived class constructor gets control and establishes formal arguments. i.148 However.

int d =0): base(b). } int base::get_base_number() { return base_number. }. cout << “base constructor “. } . derived::derived(int b=0. private : int derived_number. int get_derived_number(). } base::~base() { cout << “base destructor “. int d =0): base(b). } class derived : public base { public : derived(int b=0.derived_number(d).149 base::base(int n=0) { base_number = n.derived_number(d) { cout << “ derived constructor “. ~ derived(). } derived::~ derived() { cout << “derived destructor “.

it is the other way round. so that they can clean up the mess done by the constructor of the derived class .get_base_number()<<”.2 Derived destructor Base destructor As can be seen from the above example. Destructors for the derived class are invoked first. If both the classes have same data members . It uses the constructor of the base class . then no specific constructor needs to be defined in the derived class . With destructors. It is like demolishing the top floor of a building before going for the lower one. } Output: Base constructor Derived constructor D = 1. This is like building the first storey of the building before proceeding for the second.150 int derived::get_derived_number() { return derived_number. cout << d. cout < “ d= “ << d. An object of a base class can be assigned to the object of the derived class .”. if the derived class doesn’t contain any additional . Otherwise it can be just an empty function . the constructor for the base class is invoked before invoking the constructor for the derived class . Then the destructor for the base class is called.3.get_derived_number(). 9. OBJECT INITIALIZATION An object of a derived class can be initialized to an object of a base class . A destructor for the derived class is to be defined only if its constructor allocates memory. } void main() { derived d(1.2).

int apv): Aobj(apv) { . class Aclass { public : Aclass(int pv) { private_variable_A = pv. This has nothing to do with inheritance.4. 9. OBJECT CONVERSIONS Just like initialization .g. Another way is multiple inheritance . it becomes necessary to have a class contain properties of two other classes.151 data members . } private : int private_variable_A. the compiler resorts to a member-wise assignment in the absence of an overloaded function for the assignment operator . class Bclass { public : Bclass(int bpv. One way is to define a class within another – that is a class with member classes also called nested classes. if it does . conversions are also done automatically when an object of a derived class is assigned to an object of the base class . 9. e. then the assignment operator will have to be overloaded for the same. NESTED CLASSES Many a times. However. }. which will be discussed later. However.5.

However. Initialization section initializes the base class members . However. This is the example of the nested class . It is exactly like declaring an object of Aclass with the statement : Aclass Aobj(apv). the class Bclass contains an object Aobj in its private section as one of its members. This base class constructor is called before the constructor in the derived class. The variable bpv is used to initialize the private variable of Bclass. it is written after the colon in the initialization section of the Bclass constructor. As seen earlier . in case of the derived classes. // Declaring an object here. }.private_variable_B = bpv. 9. it contains a constructor function with the same name . MULTILEVEL INHERITANCE . The part after the colon in the definition of a constructor is called as initialization section and the actual body of the constructor is called as assignment section . As can be seen . Its assignment section contains code to initialize its own members.6. Also. Aclass Aobj. In this case.152 private_variable_B = bpv. The only change is that. the constructor contains something after the colon. The same constructor function can also be written as : Bclass (int bovine apv):Aobj(apv). the name of the object of the member class ‘Aclass’ is written after the colon. It tells the compiler to initialize the Aobj data member of Bclass with the value in apv. the name of the base class constructor is written after colon in the initialization section. whereas assignment section contains statements to initialize the derived class members . } private : int private_variable_B. this example does not contain a derived class. to which the two variables passed are bpv and apv.

from whom we derive another class . . now from this derived class we can derive another class and so on.153 In multilevel inheritance there is a parent class .

169 Class A Class B Class C Multilevel Inheritance class Aclass { : :} class Bclass : public Aclass { : : } class Cclass : public Bclass { : : } BSIT 34 OBJECTED ORIENTED PROGRAMMING WITH C++ .

The derived class inherits all the properties of all its base classes. MULTIPLE INHERITANCE Multiple inheritance . is deriving a class from more than one class . class Bclass { : : }. Consider the following example : Class A Class B Class C Multiple Inheritance class Aclass { : : }. as the name suggests . class Cclass : public Aclass .170 9.7. public Bclass { .

) : Aclass (..8. }.. The constructor in Cclass calls constructors for base classes.). PROBLEMS WITH MULTIPLE INHERITANCE The following example presents a problem with multiple inheritance... class Aclass { public : void put() { : } }. both publicly inherited.) { }.171 private : : : public : Cclass(. class Bclass . Like with normal inheritance .. constructors have to be defined for initializing the data members of all classes. The class Cclass in the above example is derived from two classes – Aclass and Bclass – therefore the first line of its class definition contains the name of two classes.. 9. Bclass(. The constructor calls are separated by commas.

B objB. the compiler does not know which class it is referring to. public Bclass { public : : : }. the derived class does not have. objC. the scope resolution operator has to be used to specify the correct object .172 { public : void put() { : } }. Both these classes have a function with the same name – put(). objB.put(). In this case. void main() { A objA.put(). which assume. class Cclass : public Aclass . C objC. Its usage is // From Class A // From class B // AMBIGUOUS –RESULTS IN ERROR . objA. The class C inherits the put() function from both the classes. When a call to this function is made using the object of the derived class .put(). } The above example has a class C derived from two classes A and B.

base Class A Class B derived Hybrid Inheritance class base { : : . The statement giving an error from the above example has to be replaced with the following : objC.B::put(). Only the imagination of the person concerned is the limit. which in turn have been derived from the same base class . There are many combinations in which inheritance can be put to use.A::put(). inheriting a class from two different classes. For instance.173 very simple. // for class A objC.9.g. e. // for class B 9. MULTIPLE INHERITANCE WITH A COMMON BASE (HYBRID INHERITANCE) Inheritance is an important and powerful feature of OOP.

Aclass and Bclass. The solution to this problem is provided by virtual base classes. contains a copy of the data members base class. are derived from base and therefore both of them. That means it contains two copies of base class members – one from Aclass and the other from Bclass. One potential problem here is that both. However. this subtlety of class inheritance is not all that simple. This gives rise to ambiguity between the base data members. public Bclass { : : }. This is multiple inheritance with a common base class . Aclass and Bclass are two classes derived from the same base class . . class Bclass : public base { : : }. class Aclass : public base { : : }. class derived : public Aclass. Another problem is that declaring an object of class derived will invoke the base class constructor twice. The class derived has a common ancestor – class base. The class derived is derived from these two classes.174 }.

10.175 9. It can be done as follows : class base { : : }. This will resolve the ambiguity involved. This keyword makes the two classes share a single copy of their base class . This can be done by making the base class a virtual class. . class Bclass : virtual public base { : : }. VIRTUAL BASE CLASSES This ambiguity can be resolved if the class derived contains only one copy of the class base. class Aclass : virtual public base { : : }. class derived : public Aclass. public Bclass { : : }.

class base { : : }. . class Aclass : public base { : : }.11. which are written just to act as base classes. class Bclass : public base { : : }. ABSTRACT CLASSES Abstract classes are the classes.176 9. Consider the following classes. class Cclass : public base { : : }.

can be made to point to objects as well. 9. This class is a general class whose sole purpose is to serve as a base class for the other three. Cclass objC. POINTERS TO OBJECTS Pointers. The following example illustrates its usage. Classes used only for the purpose of deriving other classes from them are called as abstract classes.177 void main() { Aclass objA. Bclass. class Person { public : void getname() { . The main () function declares three objects of each of these three classes. However. as seen earlier. As with structures the structure pointer ( -> ) can be used to access members of the class . and no objects for such classes are created. They simply serve as base class . : : } There are three classes – Aclass.12. it does not declare any object of the class base. Bclass objB. The usage of pointer with classes is exactly like that of its usage with structures. Cclass – each of which is derived from the class base.

Bill. Bush->getname().178 cout << “enter name “<< endl. Bush->putname(). } . Delete Bush. Bill. } void putname() { cout << “ name = “ << name . } private : char name[50].putname(). Bush = new Person. void main() { Person Bill. cin >> name. Person *Bush.getname(). }.

with inheritance. class Circle : public Shape { public : void print() { cout << “ I am a Circle “ << endl. class Triangle : public Shape { public : void print() { cout << “ I am a Triangle “ << endl. The following example illustrates yet another problem with class inheritance . class Shape { public : void print() { cout << “ I am a Shape “ << endl. } }. However. pointers can sometimes become problematic.179 Pointers to objects are generally used to form complex data structures like linked lists and trees. } }. .

print(). C. Shape *ptr. ptr = &S. Two other classes – Triangle and Circle – are derived from the base class . ptr = &C. ptr -> print(). The program declares three objects of the three classes.print(). } The example contains a base class called Shape.180 } }. ptr -> print(). T. The . S. ptr = &T.print(). void main() { Shape S. ptr -> print(). Triangle T. Circle C.

the first part works fine. The keyword virtual again comes into rescue. As far as the first question is concerned. for each of the calls with different addresses. because objects of the derived classes are type-compatible with pointers of base classes. The output of the program is given below: I am a Shape I am a Triangle I am a Circle I am a Shape I am a Shape I am a Shape As can be seen. but in a different context. then the print() function from base class is invoked. how can the compiler allow such a thing ? Well. the answer is polymorphism. if the pointer is pointing to any of the derived class Triangle or Circle then the print()function from these respective classes is invoked. to determine which function should be invoked. This answers the second question. is that the compiler ignores the contents of the pointer. In the second part the program declares a pointer to the base class Shape and assigns address of each of the object declared earlier to this pointer. for the second part. That is. this is not polymorphism. That is what polymorphism is all about – giving different meanings to the same thing. . Instead. here . the function from the base class Shape is executed. But . What happens. But . the compiler does not give an error on assigning address of a derived class to a pointer of the base class. the compiler chooses the function from the same class as that of the pointer.181 first part of the program calls print() function related to each of these classes. if the pointer points to the base class Shape. What is the objective of assigning addresses of the derived classes to a pointer of the base class ? Further. Whereas.

class Triangle : public Shape { public : void print() { cout << “ I am a Triangle “ << endl. This time it helps in implementing the idea of polymorphism with class inheritance .13. class Shape { public : virtual void print() { cout << “ I am a Shape “ << endl. } }. class Circle : public Shape { . VIRTUAL FUNCTIONS The keyword virtual was earlier used to resolve ambiguity for a class derived from two classes. both having a common ancestor. These classes are called virtual base classes. } }. The function of the base class can be declared with the keyword virtual. The program with this change and its output is given below.182 9.

ptr -> print().print(). void main() { Shape S. C. ptr = &S. } }. Triangle T. } . ptr -> print(). Circle C.183 public : void print() { cout << “ I am a Circle “ << endl. ptr = &T.print(). ptr -> print(). ptr = &C. Shape *ptr.print(). T. S.

which is used just for deriving some other classes. Similarly. 9. class Triangle : public Shape .then. Consider the above example with some changes. This facility can be very effectively used when many such classes are derived from one base class . an abstract class is one. Member functions of each of these can be . When declared with the keyword virtual . the output of the derived classes are invoked correctly. // Pure virtual function }.14. the compiler selects the function to be invoked.184 The output of the program is given below: I am a Shape I am a Triangle I am a Circle I am a Shape I am a Triangle I am a Circle Now. invoked using a pointer to the base class . based upon the contents of the pointer and not the type of the pointer. PURE VIRTUAL FUNCTIONS As discussed earlier. class Shape { public : virtual void print() = 0. there are pure virtual functions which themselves won’t be used. No object of this class is declared and used in the program.

} }. ptr = &C. ptr = &T. ptr -> print().185 { public : void print() { cout << “ I am a Triangle “ << endl. Circle C. void main() { Shape S. } }. Triangle T. class Circle : public Shape { public : void print() { cout << “ I am a Circle “ << endl. Shape *ptr. ptr -> print(). } .

the print() function from the base class is not invoked at all . Exciting OOP concepts like polymorphism have given a big boost to all this. Create a class drugs containing encapsulated data for medicine name. EXERCISES: 1. The class Ayurvedic should additionally store data on the herbs used. The main() should test the derived classes. They should contain functions to accept data and display the data. association to be used (whether honey or water).186 The output of the program is given below: I am a Triangle I am a Circle It can be seen from the above example that . The classes should contain constructors and destructors. whether solid or liquid. the pointer of the class Shape must point to its members. Inheritance has further enhanced the language. Object oriented programming has altered the program design process. . From this class derive two classes. even though the function is not necessary. price and purpose of use. Ayurvedic and Allopathic. This session has covered some of the finer aspects of inheritance. The next session will resolve some finer aspects of the language. it cannot be avoided. because . The class Allopathic should additionally include data on the chemicals used and the weight in milligrams.

then only one such data item is created for the entire class. Necessity of friends. 10. which make this language more powerful. Friend functions and Operator Overloading.1.187 SESSION 10 ADDITIONAL FEATURES OF C++ During this session you will learn about: • • • • • • • • • • Static member and Static functions. . In this session we will continue exploring some other features. the visibility of this data item remains same. if all objects of a class must share a common data item. the duration of this variable is for entire lifetime of the program. Whereas. there is an exception to this rule. An introduction to template functions and template classes. no matter how many objects it has. Friend classes. Static data members are useful. Friend functions. STATIC CLASS MEMBERS As we already know all the objects of the class have different data members but invoke the same member functions. We have already seen the powerful features of OOP that make C++ such a strong language. Inline functions Preprocess or Directives Istream and ostream objects and manipulators. If the data member is declared with the keyword static. However. Overloading the extraction and insertion Operators.

}. class counter { public : counter (). void main() { counter c1. int getcount(). private: static int count. cout << “ Count = “ << c1.c2.// INITIALIZATION OF STATIC MEMBER. } int counter::getcount() { return ( count ). counter::counter () { count++. . } int counter :: count = 0.getcount() << endl. such a variable can be particularly useful if an object requires to know how many objects of its kind exist.188 For example.

cout << “ Count = “ << c3. It contains just one data member count. counter c4. Whenever an object is created. Notice the initialization of this static class member. there can be a destructor to decrement it. Even though the data member is in the private section it can be accessed in this case as a global variable directly.getcount() << endl. For some compilers it is mandatory.c5. Similarly. } Output: Count = 2 Count = 2 Count = 3 Count = 5 Count = 5 // not 1 because 2 objects are already created.getcount() << endl. the class counter demonstrates the use of static data members. he will be automatically assigned a register number if the register . counter c3. cout << “ Count = “ << c5. In the above example.getcount() << endl. You can use these to generate register numbers for student objects from a student class. but has to be preceded by the name of the class and the scope resolution operator.getcount() << endl. cout << “ Count = “ << c4.189 cout << “ Count = “ << c2. This example contains a constructor to increment this variable.

That is. . The example above demonstrates how to keep track of all the objects of a class which are4 in existence. is not an effective way to access the value of the static data member. C++ gives a facility to define static function members. to invoke such a function. STATIC MEMBER FUNCTIONS All the objects of the class share static data members of a class. It can be invoked with the name of the class. static int getcount(). this function uses existing objects to invoke a member function getcount().190 number is a static variable and a constructor is used to write an equation to generate separate register numbers in some order. A specific object should not be used to refer to this member. 10. the number of objects (count) remains same at a given instance no matter which object is used to invoke the member function. The programme given below illustrates its use. an object is not required. In fact. You could initialize the variable to give the first register number and then use this in the constructor for further operations. which returns the value of the static data member. since it does not belong to that object. like in the above example. class counter { public : counter (). private: static int count. However. as can be seen from the previous output. for the same. What if the programme does not want to use objects to invoke this function and still the programme would like to know how many objects have been created? If there is no object how the member function is invoked? Further.2. the use of existing objects. it belongs to the entire class.

c5. cout << “ Count = “ << counter :: getcount() << endl. counter c3.c2. cout << “ Count = “ << counter :: getcount() << endl. } int counter::getcount() { } int counter :: count = 0. void main() { counter c1. } Output: Count = 2 Count = 2 . counter::counter () { count++. cout << “ Count = “ << counter :: getcount() << endl. counter c4. cout << “ Count = “ << counter :: getcount() << endl.191 }. // INITIALIZATION OF STATIC MEMBER. cout << “ Count = “ << counter :: getcount() << endl.

There are situations where a rigid and controlled access leads to inconvenience and hardships. the concept of data encapsulation sometimes takes information hiding too far. Such a function is called as a friend function. The data from the class can be accessed only through member functions of the class. USING A FRIEND Using a friend function is quite simple. consider a case where a function is required to operate on object of two different classes. class Aclass { // Forward Declaration . What can be done is that a function can be defined outside both the classes and made to operate on both.192 Count = 3 Count = 5 Count = 5 10. a function not belonging to either. 10. it also saves the data from any possible misuse. The following example defines a friend function to access members of two classes.3. This function cannot be made a member of both the classes. a friend function is a nonmember function.4. In other words. FRIEND FUNCTIONS One of the main features of OOP is information hiding. That is. However. class Bclass. but able to access both. which has access to a class’s private members. It is like allowing access to one’s personal belongings to a friend. For instance. This restricted access not only hides the implementation details of the methods and the data structure. accidental or otherwise. A class encapsulates data and methods to operate on that data in a single unit .

} friend int addup(Aclass &ac. Bclass &bc). private : int Avar. }. int addup(Aclass &ac. } friend int addup(Aclass &ac. Bclass &bc). }. private : int Bvar. class Bclass { public : Bclass(int v) { Bvar = v. Bclass &bc) { .193 public : Aclass(int v) { Avar = v.

the name of the member has to be prefixed with the name of the object . Since it does not belong to both the classes . A friend function. although it does not belong to either. Sometimes friend functions can be avoided using inheritance and they are preferred. that this function can directly access the private members of the classes. } void main() { Aclass aobj. along with the dot operator. total = addup(aobj. Notice.bobj). To access the private members.Avar + bc. } The program defines two classes.Bvar). The first line in the program is called forward declaration.194 return( ac. the keyword friend is just written before the declaration and not used while defining. Bclass bobj. int total. This friend function returns the sum of the two private members of the classes. is declared in the definition of both the classes. But sometimes they are unavoidable. It also has constructors for these classes. . addup(). Excessive use of friend over many classes suggests a poorly designed program structure. This is required to inform the compiler that the definition for class Bclass comes after class Aclass and therefore it will not show any error on encountering the object of Bclass in the declaration of the friend function.Aclass and Bclass. while defining it outside we do not give any scope resolution and we do not invoke it with the help of any object. Also .

Consider the following class that contains data members to simulate a matrix. Matrix &m). For instance with the operator overloading. The two ways are : Matrix * num.operator*(num). There are two ways in which we can do this.6. class Matrix { public: : : Matrix &operator*(int num). Several operations can be performed on the matrices. .195 10. FRIEND FOR OVERLOADING OPERATORS Some times friend functions cannot be avoided. Let us see this program in detail. [or] num * Matrix. Where Mobj is an object of Matrix and num is a normal integer variable. What happens to the second one ? It gets converted by the compiler as : num. In the first case we can overload * to perform the operation and an object invokes this as the statement gets converted to : Mobj.operator*(Mobj). One of them is to multiply the given matrix by a number( constant literal). friend Matrix &operator*(int n.

Matrix &m) { Matrix temp.196 private: int mat[20][20].mat[i][j]=mat[i][j]*num. } Matrix operator*(int n. j++) temp. for(int i=1. temp= m*n. j<=cols. } Matrix Matrix::operator*(int num) { Matrix temp. temp. return (temp). return temp. } void main() { Matrix M1. i<=rows.cols=cols. M3. M2. : : // accept matrix one and num . int num. temp.rows=rows. i++) for(int j=1. int rows. cols.

e. // calls member operator function. Intelligent use of friend functions makes the code more readable.7. the compiler calls friend function . which causes the member function to be invoked . // calls friend function. When is encountered before multiplication symbol as in the second call in the program. private : int Avar. in friend function we have just reversed the arguments. 10. GRANTING FRIENDSHIP TO ANOTHER CLASS To grant friendship to another class. The keyword class is optional.197 M2=M1*num. write the keyword followed by the class name. M3=num*M1. The implication of this declaration is that all off the member functions of the friend class are friend functions of the class that bestows the friendship. } Here when the compiler comes across the multiplication of an object by a number it invokes the operator member function. // Friend declaration. Note that this declaration also implies a forward declaration of the class to which the friendship is being granted. class Aclass { public : : : : friend class Bclass.g. }. .

Avar. }.8. void main() { Aclass aobj.fn1(aobj). It means that all member functions of Bclass have been granted direct access to all member functions of Aclass. // Avar can be accessed. GRANTING FRIENDSHIP TO A MEMBER FUNCTION OF ANOTHER CLASS If you want class A to grant friendship to one or more individual member functions of class B.198 class Bclass { public : : : void fn1(Aclass ac) { Bvar = ac. Bclass bobj. } The program declares class Bclass to be a friend of Aclass. then you must code the classes and their member functions in this manner: . } private : int Bvar. 10. Bobj.

}. Of course.g. void fn3() { : : } private : int Bvar. class Aclass class Bclass { public : : : void fn1(). Define class B and declare (not define) the member functions: Define class A in which you declare the friendship for the member functions of class B. // Can’t define here Define the member functions of class B. • e. you must qualify the names of these functions using the class name B and the scope resolution operator.199 • • • Forward declare class A. class Aclass { public : : .

200 : void fn1() { : }

friend classB:: fn1(); friend classB:: fn2();

private : int Avar;

}; void classB:: fn1() { Bvar = Avar; } void classB:: fn2() { Bvar = variable +25; }


We’ll finish this session by showing how to overload the extraction and insertion operators. Here, you can accept the input and output the results of the user-defined variables or objects just like normal variables. Consider a class Complex that consists of two system defined

201 variables, both float to denote the real and complex part of a complex number. In general cases to accept these member variables, we need to write some function say getval() and invoke it using the object of the class say Comobj.getval() and similar method would be required to display them. Using operator overloading we can accept or display the user-defined object just like a normal variable . i.e. by overloading the extraction operator >> we can accept the complex object as, cin >> comobj; Similarly, by overloading the insertion operator we can display the member variables of the object as, cout << comobj; just as if it were a basic data type. Consider the example : class Complex { public: friend istream& operator >> (istream &is, Complex &c2) friend ostream& operator << (ostream &os, Complex &c2) private: float real, imaginary;

}; istream& operator >> (istream &is, Complex &c2) { cout << “ enter real and imaginary “ << endl; is >> c2.real >> c2.imaginary; return (is); }

istream& operator << (ostream &os, Complex &c2)

202 { os << “ the complex number is “ <<endl; os << c2.real << “+i”<< c2.imaginary; return (os); } void main() { Complex c1,c2; cin >> c1; cout << c1; cin >> c2; cout << c2; }

The operator functions have to be declared friends , since they have to access the user class and the objects of istream and ostream classes that are system defined. Since these operator functions are friend functions, the two objects – cin and cout are passed as arguments, along with the objects of the user-class. They return the istream and ostream objects so that the operator can be chained. That is the above two input statements can also be written as, cin >> c1 >> c2; cout << c1 << c2;


Imagine a c program, which reads disk records containing employee information. If this is a payroll application each employee record data is probably processed via a series of function calls. These function calls could be to print the entity data, to compute the salary, to compute the taxes to be withheld etc,. Each one of these calls inherently contains overhead that must be part

203 of your overall program. In other words it takes code space and time to push actual arguments onto the stack, call the function, push some return value onto the stack and finally pop all of those values.

C++ provides the inline functions, a mechanism by which these explicit function calls can be avoided.

“ An inline function by definition is a function whose code gets substituted in place of the actual call to that function.”

Whenever the compiler encounters a call to that function it merely replaces it with the code itself thereby saving you all of the overhead. Such a function can be either a member of a class or a global function. Inline functions work best when they are small, straightforward bodies of code that are not called from too many different places within your program. The time saved will increase with the increase in number of calls.

Even if you request that the compiler make a function into an inline function, the compiler may or may not honor that request. It depends on the code of the function. For example, the compiler will not inline any function that contains a loop, static data member, or aggregate initializer list. If such cases case, a warning message will be issued.

The disadvantage with inline functions is that if the code itself ever needs to be modified, then all programs that use the these functions would then have to be recompiled. Furthermore, an inline function is a violation of implementation hiding.

First, let’s get away from member functions for a moment and consider a global function. To make a request that this function be inline :

printf (“Absolute value of %+d = %+d\n”. } void main( ) { for (int i=-2 .i.204 • • Precede the return type of the function with the keyword inline. Here is a program that uses an inline function to compute and return the absolute value of its input argument. # include <stdio. not just the declaration) before any calls to that function. value). Write the function body (the definition. i<2 . ++i) { int value = abs(i) .h> inline int abs(int x) { return x <0? -x : x . } } The output is: Absolute value of –2 =+2 Absolute value of –1 =+1 Absolute value of +0 =+0 Absolute value of +1 =+1 .

they can refer to .205 When the call to the abs ( ) function is encountered. The normal method of doing this is to simply define the function within the scope of the class definition. so the keyword inline does not need to be written. That’s why. instead of making a function call. Here the member function integer :: store ( ) is an inline member function because it is completely defined within the context of the class definition. }.11.g. e. HOW TO WRITE AN INLINE CLASS MEMBER FUNCTION In addition to global functions. if they are defined first. you may request that non-static member functions of a class be inlined. 10. } private: int number . the compiler. Functions inlined within the class definition are not evaluated by the compiler until the entire class scope has been processed. class integer { public : // This is an inline function void store (int n ) { number =n . In this case the inline request is made automatically. generates this assembly code.

or even compute the size of the class. you must write the keyword inline in front of both the function declaration and its definition. the usage of the keyword inline in front of the declaration ( within the class definition ) is not always necessary. class integer { public: inline void store (int) . Now there is no problem because the inlining will still occur. } The above example shows the correct way to define an inline function. The only problem with this class is that now it has been “ cluttered up” with the actual definition of the integer::store() function.g.206 members defined later. This is the case when the definition ( still preceded by the keyword inline) is encountered by the compiler before it is ever called. }. A better approach is to move the function definition outside the class and use the scope resolution operator to give it class scope. private: int number . e. // This is an inline function inline void integer :: store (int n ) { number = n. In order to make the inline request to the compiler. .

10. #define PI 3.14285 void main() { cout << PI.is an instruction to the preprocessor. macro substitution and conditional compilation etc. Whenever the preprocessor finds this name in the program. . It performs file inclusions. The is an following example which defines a value and gives it a name PI.14285.1. it is replaced by the text string it represents. The #define Directive The #define directive defines a macro which is a text string represented by a name.12.12. The output from the preprocessor becomes the input to the compiler and is also called as extended source code. which acts on the source code before the compilation process. } The # define directive works strictly on the basis of substitution of a text string for the macro names. } // no semicolon given This program is equivalent to : void main() { cout << 3. THE PREPROCESSOR DIRECTIVES A preprocessor directive which begins with a hash ‘#’ .207 10.

The #undef Directive This directive undefines a previously defined macro. The #ifdef. #ifdef condition statements. #endif. They are used in the following ways. #elif.14285 void main() { cout<< PI. #else and #endif Directives These directives are used for conditional compilation. example the following will give an error since PI is undefined. #endif.12. #else statements. For. 10. // no error here cout << PI.3.208 10.12.2. #ifdef condition statements. } // error after undef. . # undef PI. #define PI 3.

g. These directives control which portions of the code will be passed to the compiler. the program can make use of certain MSDOS features. Otherwise. e.209 #ifdef condition1 statements. some other code depending on the machine is executed. Just like #ifdef there is also #ifndef which negates the condition. #ifdef condition1 statements. #else statements. void main() { #ifdef __MSDOS__ DOS-fn(). #elif condition2 statements. #elif condition2 statements. these directives can be used for compiling the program written for two different machines. #else UNIX_fn(). #endif. #endif. For example. #endif. On MSDOS machines. } .

h . working with conditional compilation. INPUT OUTPUT Most languages have “statements” to perform I/O . which by default is the keyboard.4. In this case the #error directive is very useful. However in C and C++ we use “functions” to perform I/O. The #error directive This directive facilitates putting diagnostic messages into the preprocessor statements. #ifndef__LARGE__ #error Compile this program in the large model only #endif The example shows a program. cout This object corresponds to the standard output stream .which by default is the screen. error messages need to be displayed. which has to be compiled only in the large model. . C++ also has its own I/O mechanism – the cin and cout objects.210 10. the preprocessor prints the given error message and stops compilation. Sometimes. the program gets the following 4 objects automatically: Cin This object corresponds to the standard input Stream.13. declared in the header file iostream. If the compiler switch for a large model is not on. The following example illustrates the usage of this directive. On including iostream.h. 10.12.

10. The prototype of this function would be : ostream &operator << (int n). char * ln = “Murthy”.211 cerr & clog This object corresponds to the standard error Stream. float salary = 100000. which by default is the screen. int age = 55. ince we have been using this througout. the operator function for insertion operator is already overloaded for each of data types. THE OVERLOADED INSERTION OPERATOR AND EXTRACTION OPERATOR Output on the standard screen is done by using the cout object of the ostream class. cout << “ Name =” << fn. Thus. The following example shows various formats : void main() { char fn[100] = “ Narayan”. if the variable is an integer. then the function with the corresponding signature is invoked. cout << variable .14. cout << “ Sirname =” << ln. In other words. no further discussion is needed on this topic.00. . variable can be any basic data type.

It has the following prototype : ostream &put(char).put(‘I’).put(‘D’).212 cout << endl. e.put(‘I’). OTHER OSTREAM FUNCTIONS Apart from the ‘cout’.g. This function prints only characters. . } Output : Name = Narayan Sirname= Murthy Age = 55 Salary =100000 Similarly even cin is a object that accepts data in any data form and can be cascaded as well. //Prints the character V It can also be used like : cout. This function prints an entire string and has the prototype : ostream &write(char *.put(‘N’).15. cout << ”\n Age = “ <<age. cout. There is another function write() in this class.put(‘V’).int). One of them is put(). the ostream class provides some other functions for output.put(‘A’). cout<< endl << “ Salary is “ << salary. 10.

sub < = len . This function does not recognize the null character. e. sometimes it is necessary.213 The first argument gives the address of the character string to be printed. for( int sub = 0.h > void main() { char *magic = “ABRACADABRA”.g. Yet another function endl() prints a new line character. int len = strlen(magic).sub)<<”\n”. .write(magic. #include < iostream.h> #include < string. ++sub) { cout. } Output : A AB ABR ABRA ABRAC ABRACA ABRACAD ABRACADA ABRACADAB ABRACADABR ABRACADABRA A function flush() can be used to flush the output buffer. Therefore if the second argument is more than the length of the string then the compiler raises an error.

The number is in fixed-point notation or normalized form. . 10. They can be used with the insertion operator. They can also be used as follows: flush(cout).16. uses one position. FORMATTING THE OUTPUT WITH COUT The overloaded function for insertion operator << of the ostream variables before displaying. The field is just wide enough for the number and a minus sign if number is negative. cout<< ”I/O of the C++ is to be flushed “ <<flush. float displayed with 6 decimal places. The default formats are as follows: class format the char int displayed as a character. except for the & double trailing zeroes. whichever takes less space. displayed as a decimal integer uses space just enough for the number and a minus sign if the number is negative.214 cout<< ”ttttt” << endl. endl(cout).

cout<< posnum << “ ]\n”. cout << “ Double : [“ << d << ”]\n“.0 /3. cout << “ integer division 10/3 = [“. # include < iostream.h > void main() { char name[100] = “IGLOOCAMALOO”. cout << “ This is character : [“ << ch << “]\n”. int negnum = -123.0/3. cout << “ Positive integer :[“. char h = ‘v’. float f = 123. cout << 10/3 << “ ]\n”. cout << “ Negative Integer :[“.123. cout<< “ Float :[“ << f << ”]\n“.0 << “ ]\n”.1234566. cout << “ This is string : [ “ << name << “]\n”. cout << 10. double d = 12345678.0= [“. } .g. cout<< negnum << “ ]\n”. cout << “floating Division 10. int posnum = 123. e.215 Character displayed in a field equal to the length of the Strings string.

This header file has functions called manipulators. MANIPULATORS As discussed earlier. These manipulators are called in two ways : hex(cout). For instance.123457] integer division 10/3 = [3] floating Division 10. hex() to set the base in which a given number will be printed. some bits define the base in which the numbers will be printed. e. One of them is ios class. using which the output format can be controlled.0= [3. oct(). // use the insertion operator . there are several classes in the iostream. There are 3 manipulators dec(). void main(void) { // Not allowed. But since these manipulators are not member functions of the class .h header file.hex(). . some bits define the field width.g. // Pass the object name cout<< hex. it cannot be used as follows: cout.0 /3.216 Output : This is string : [ IGLOOCAMALOO] This is character : [V] Positive integer :[123] Negative Integer :[-123] Float :[123. This class stores the format state.333333] 10.123000] Double : [12345678.17.

similarly. cout << oct. int width(int newsize). use width specifier for controlling the width of its output .17. . // Back to decimal cout << “ Decimal } : “ << i. This function has the following prototype. dec(cout). cout << “ Default Base Decimal :“ << i << endl. Output : Default Base Decimal : 110 Hexadecimal :6e Octal Decimal :156 :110 10. Changing Field width The printf() and scanf() functions from the standard library. int width(void). // Print in Octal cout << “ Octal :“ << i << endl. the ostream class also has a member function width() for the same. cout << hex. // Print in hexadecimal cout << “ Hexadecimal :“ << i << endl.217 int i =110.1.

C++ pads spaces to extra places. cout<<”[“. } Output: Default width = 0. ostream contains a function fill() to set a new fill character. The function prototypes are : char fill(void) char fill(char c) //Returns current fill character //Set a new fill character.width(10). That is because . if the width specified is more than the actual output . It also returns the previous width. The filed width reverts to default afterwards. The default is always zero. The width() function affects only the next item displayed. cout<<”]”. Padding the Extra Places By default. cout. the cout object always uses space just wide enough to output the values and a default size if zero matches all. . void main() { cout<<” default width=”<< cout.g.width()<<endl.2.17. 10. e. The second form can be used to change the current width setting. The argument passed to it is the new width to be set. [ A] This is very useful in preparing reports. Set width to 10 cout<<”A”.218 The first form returns the current field width.

width(5). cout << “ Amount1 : [“. cout << amt1 <<”]\n”. void main() { int amt1 = 100. cout << “Amount 2 : [“. Setting a precision By default. The function does not merely truncate the trailing digits. amt2= 12345. C++ prints six decimal places after the decimal point. cout. // Returns a Current Value int precision(int p). The function precision() can be used to change this default behavior.219 e. // set a new precision . cout. it rounds them up. except for trailing zeroes. cout. } Output : Amount 1 : [**100] Amount 2 : [12345] 10.width(5). This function has the following prototype : int precision(void).3.g.17.fill(‘*’). cout << amt2 << “]\n”.

43] f2 = [3.220 e. cout. cout << “ Default f1 = [ “<< f1 <<”]\n”. float f2 = 10.0. cout << “ Default f2 = [ “<< f2 <<”]\n”. float f3 = 10.0. } Output : Default f1 = [123.333333] Default f3 = [1.67] .33] f3 = [1.precision(2).0 / 3. void main() { float f1 = 123. cout << “ f3 = [ “<< f3 <<”]\n”. cout << “ f2 = [ “<< f2 <<”]\n”.43.0 / 6.666667] f1 = [123. cout << “ Default f1 = [ “<< f3 <<”]\n”.43] Default f2 = [3. cout << “ f1 = [ “<< f1 <<”]\n”.g.

0x) for output Showpoint Show decimal point and trailing zeros Uppercase Use uppercase letters for hex output (A-F) showpos Use + for positive numbers .221 10. long setf(long flagbit. The setf() Function The ios contains a function setf() for controlling several formatting features.17.4. It can be any one of the following : Enumerated Constant Meaning Showbase Use base prefixes( 0. This class defines a set of enumerated constants that can be used as arguments to the setf() function. The first prototype has only one argument. int field). This function has the following prototypes : long setf(long flagbit).

cout. The above example shows the trailing zeros and decimal point. These arguments can be any of the following : Enumerated Constants Meaning First Argument Second argument dec Base field oct hex Use Decimal base Use Octal base Use Hexadecimal base Float field Fixed Use fixed point notation Scientific use scientific notation . The first argument defines the bit settings that have to be changed.g. The second prototype has two arguments.setf(ios::showpoint).222 These constants are enumerated constants. They have to be prefixed by the name of the class with the scope resolution operator(::). e. defined in the ios class definition and therefore have a class scope.

//right // uppercase hex. cout. cout. cout << ”Uppercase hex :[“<< inum << “]\n”. ios:: adjustfield). // show base prefix. //left justified. cout. Left justify the sign and Internal base prefix.setf(ios::showpos). void main() { int inum = 110. but right justify the value e. cout. cout. cout << inum << “]\n”. // show plus sign . cout << ”Base prefix :[“<< inum << “]\n”.setf(ios::showbase).setf(ios::right.setf(ios::uppercase}. cout << “showpos : [ “ << inum << “ ]\n”. ios:: adjustfield).setf(ios::left.223 Adjustfield Left Left justified for output. cout << Hex : [“ << hex << inum << “]\n”. cout << dec << ”left justified :[“.g.width(6). Right justified for Right Output. cout.

cout << “2 decimals :[“<<f<<”]\n”. cout << ”Right justified :[“. cout. cout << inum << “]\n”.g. cout << “Float :[“ << f << “]\n”. ios :: floatfield).precision(2). } [+110] [+110] .0.224 justified. cout. void main() { float f = 10. cout. cout << “Scientific : [ “ << f << “]\n”.setf(ios::showpoint). cout.setf(ios::scientific.width(6). } Output: Showpos : [+110] Hex : [6e] Base prefix : [0x6e] Uppercase hex : [0x6e] Left justified: Right justified: e. // show trailing 0s and point cout << “show point : [ “ << f << “]\n”.

int get(void). the istream class also has some other function. cin >> ch.00e+01] 10. The first form stores the character entered in ch and returns a reference to the istream object. One of them is get() with the following prototype : istream &get( char &ch). cin >> ch.ch2.000000] 2decimals : [+10. Apart from the overloaded function for the extraction operator. while(ch != ‘\n’) { cout << ch. void main() { char ch1.225 output: Float : [+10] Showpoint : [+10.18.g. cout << “Enter a String : “. These functions accept a character.00] scientific : [+1. } } . The second form returns back the character entered. OTHER ISTREAM FUNCTIONS. e.

} } The istream class defines two other functions getline() and an overloaded get() function for accepting strings. will ignore the <return> character resulting in an infinite loop. cin. since cin does not recognize white space characters and hence . int size. istream &get(cahr *s.get(ch). . void main() { char ch1. cin.g. while(ch != ‘\n’) { cout <<ch. char ch =’\n’). char ch =’\n’). “Enter a String : “.get(ch). cout <. Their function prototypes are : istream &getline(cahr *s. int size.ch2. The solution is to use get() as below: e.226 The program given above will not work.

void main() { char *str = new char[100].get(str. whereas getline() extracts it from the stream. cout << “enter a string”. or template. FUNCTION TEMPLATES Function templates provide you with the capability to write a single function that is a skeleton. e. char string[100].19.50).. this function reads up to 49 characters or until new line character whichever is encountered first. If omitted the function reads up to maximum characters specified or until new line character whichever is encountered first. cin.get(string. for a family of similar functions.g. cout <<str.’\n’). .5. } The difference between get() and getline() is that get() leaves the new line character in the input system. e.227 The first argument is the address of the location where the input string is to be placed. 10. cin. The third argument is the terminating character. The second argument is the number of maximum characters to be read plus number.g.

} void main() { cout << max( 1. float y) { return ( x > y) ? x : y . Unfortunately. char y) { return ( x > y) ? x : y . cout << max( 4L. long y) { return ( x > y) ? x : y . } long max( long x.3L) << endl. } char max(char x. overloaded functions are not the ultimate solution to the problem that is inherent when writing functions that are similar in their behavior. .2) << endl. } float max(float x.228 In function overloading technique it relieves someone who is using your functions from having to know about different names for various functions that essentially do the same task. int y) { return ( x > y) ? x : y . Consider the following example: int max(int x.

3. instead of you having to write many functions. In other words. How a Function Template solves this problem A function template solves the problem by allowing you to write just one function that serves as a skeleton. each function is essentially doing the same task. the problem with this example is that there is still too much repetitious coding. This function template does not specify the actual types of the arguments that the function accepts. cout << max(‘A’. or parameterized type.229 cout << max( 5.62. How to write a function template A function template should be written at the start of the program in the global area.48) << endl. or you may place it into a header file. instead . until you determine the specific types. it uses a generic. for a family of functions whose tasks are all similar. The syntax is : • • The C++ keyword template A left angle bracket ( < ) . Now. The process of invocation of these functions with actual parameter types is called the template instantiation. template. All function templates start with a template declaration.’a’) << endl.62 a Even though function overloading is used. as a “ place holder”. or. it would be nice if were to write only one function and can accommodate almost any type of input argument. } The output is : 2 4 5.

cout << max( 4.3) << endl. e.3.’a’) << endl. the keyword class ( this usage of class has nothing to do with the key word class used to create user-defined type. } The output is : 2 5. } void main() { cout << max( 1. A generic type consists of two parts 1. • A right angle bracket ( > ). Typically the name T is used.62 a 6 . char y) { return ( x > y) ? x : y .48) << endl.) 2.230 • A comma separates a list of generic types.g. but any valid C++ name will do. a variable that represents some generic type. cout << max( 5. and will be used whenever this type needs to be written in the function definition.2) << endl. each one. template < class T> T max(char x. cout << max(‘A’.62.

} where Hello can be built in or user defined type and size is always constant and integer. A template type specifier can be used for variable declaration ( in the above example .231 Each of first three max () function class causes a template function to be instantiated. ++i) { if( array[i] < min_val) min_val = array[i]. e. we can have more than one template parameter type in the same template . The template needs to have parameters. just like normal variable. const int size > Hello min ( const Hello ( & array)[size]) { Hello min_val = array [0]. template < class Hello. e. it is used to declare min_val). } return ( min_val)..g. either a template type representing a type or a template non-type parameter representing a constant expression. for(int i=1. . first with an int. The last call using two integers does not cause another instantiation to occur because this call can use the instantiated function that was generated as a result of the first class that also uses two integers. then with a double and then with a char. i<size.g. casts etc.

g. or parameterized. By definition. CLASS TEMPLATES In addition to function templates. int).g. i.232 template < class T1. T2 b). C++ also supports the concept of class templates. template <class T> T min ( T *. template <class T> T min ( T .20. We can even overload function templates. int). class T3> T3 min (T1 a . T). the ability to create a class (or structure) that contains one or more types that are generic. 10. e. You start by writing a template declaration followed by the class definition: e. Template <class T> class test { .e. a class template is a class definition that describes a family of related classes. class T2. The philosophy is essentially the same as that of function templates.. template <class T> T min ( T . A class template is defined in a manner similar to that of a function template.

U > Template < class T. Template < class T1. class U> // Error // O.K. In the second case they are converted as double variables. class T3> class classname. In this session we have seen how a static variable and static function combination can be used for variables. which are shared by all the objects and hence can be given a single . Template < class T. We can declare variables of this class as follows: void main() { test<int> intobj. Of course. } In the first instantiation the entire template types i. test<double> doubleobj.233 private : T item. variables of type T will be converted as integers. Each parameter should be preceded with the keyword class. • The generation of a class from class definition is called template instantiation.e. you may have more than one parameterized type between the angle brackets. class T2. // data and functions }.

We also covered how to enhance the output of the program. This session covered the subtle aspects of C++. The concept of templates gives another dimension to overloading and reusability. age. should not be overused. We saw how friend functions along with operator overloading can make the objects look like normal variables and thus giving the language a more natural look.234 memory location and how objects are not required to invoke them. Template < class T. height and qualification. EXERCISES: 1. Include a constructor and a destructor for this class. 2. These are substituted in place of function calls and are faster compared to calling and returning as compared to normal functions. but becomes extremely necessary sometimes. Functions can be made as inline functions if they are small. We discussed about friend functions. weight. sex. The functions of the template classes obey the rules of the function templates. which though should not be overused. Using the manipulators and iostream objects we can enhance the way our output appears on the screen. Generate the register number for them using the static variable and static functions. We also learnt how the shortcomings of function overloading could be overcome using template functions. const int buffer > class classname. Write am program to accept details of N students. WAP to create a class named CANDIATE . We also learnt how to share our private details with friends. • A non-type parameter represents a constant value. The class should contain the candidate’s name. which though are very tempting. An airlines company recruits female candidates for the post of airhostess. Create a class named . Include a member function to accept the data and display the data. which could not be classified under any of the previous sessions.

the candidate is called for the first interview and display "called for the first interview. . then display the message . The following checks should be performed: --sex and qualification should be same as that of PERFECT. . * * * * * . Based on the return type of the above perform the following operations. height.weight and height should be less than or equal to the PERFECT.if the first condition is -ve.if the first condition is +ve but the second is -ve .if both the conditions are +ve . and qualification from the company. weight."rejected". --age . "will be called later". Overload the = operator for this check. Overload the operator <= for this check.235 PERFECT to accept the exact requirements in terms of age. . then display.

Sign up to vote on this title
UsefulNot useful