1

Object Oriented Programming (OOP) With C++

2

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.

(1

• • •

• •

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
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.

4
• • • • • 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.

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

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

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

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

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

e. VARIABLES Information stored in a variable can change in the course of the program. e. cout << 2*2*2*2*2*2*2*2*2*2 for 2^8. Can start with character or underscore.9. Variables are addressable. To find the value of power of some number we may write. RULES FOR NAMING THE VARIABLES: • • • • • e. 1. Are case sensitive i. 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. The type used in the definition describes the kind of information the symbol can store..g. therefore this qualifier is not of much use. fan is different from Fan and FAN. 1. digits and underscore. Can’t use keywords No limits on the length of the word. /* Can have characters.10. Some implementations have the qualifier signed. short int i. All the variables by default are signed. Variables help us to reuse the codes. To find the value of power of some number we may write.10 e.g. .

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

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

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

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

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

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

The scope of a global variable is not limited to any one function . However. int g = 0. extern int g = 0. 1. External Variables Different functions of the same program can be written in different source files and can be compiled together. 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. It is allocated memory and is initialized only for the first time. // FILE 1 – g is global and can be used only in main() and // // fn1(). but is extended to all the functions that are defined after it is declared.3.g. e. the scope of a global variable is limited to only those functions. . which are in the same file scope. we can use extern to declare them. If we want to use a variable defined in another file.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.13.

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

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

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.

1.14.2.2. 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.

21

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.

22

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;

The format is operand >> number or operand << number The first operand is the value. whereas the right shift operators shift ‘number’ bits to the right. after y = y>>3. char x. 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. Precedence and Order of evaluation . The result of x is 0x01. 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. y <<= 1. x = y <<2. The Shift Operators There are two shift operators : left shift ( <<) and right shift (>>).24 y |= z. The leftmost and the rightmost bits are shifted out and are lost. x >>=2. y = 0x80.7. The value of y which was 0x80(1000 0000) is changed to 0xFo(1111 0000) .g. which is to be shifted. y = y >> 3.14. The left shift operators shift ‘number’ bits to the left.14. 1.8. e. The second is the number of bits by which it is shifted. These are binary operators.

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

which returns the number of bytes taken up by a variable or data type. // returns 2 on a 16bit machine sizeof(float).9. to maintain compatibility of the data types.26 1. the operands are converted before evaluation.14. 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 value returned by this operator can be used to determine the size of a variable. char ch = ‘A’. float double . sizeof(int).g. // returns 4 on a 16bit machine 1. In this case. MIXED MODE EXPRESSIONS AND IMPLICIT TYPE CONVERSIONS A mixed mode expression is one in which the operands are not of the same type. The sizeof() operator This is a pseudo-operator given by the language.15.

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

else-if. } 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.17. if( ch < ‘0’ || ch > ‘9’) { cout << “ Not a Number). 1. The if-else and else-if statements. Branching Statements The control flow statements used for branching are if-else. switch. e. This control flow statement thus specify the order in which the computations are carried out.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.1. . The language offers for. } else { statements. goto as control statements. ifelse.g.17.1. We can classify them as branching and looping structures. cout<<” This is a number”. while. The syntax of if – else statement is : if(expression 1) { statements.1. } else // in case of a single statement the braces can be avoided. 1. else-if and switch. A single if(expression) without an else can also be used for checking a single condition. do-while.

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

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

1. : : break. case value2 : statements. : : break. The general format is as follows : switch(expression) { case value1 : statements. If the value does not match with any of the case statements then the statements under the default label are executed. and the body of the switch statement must be enclosed in braces.17. and branches accordingly. 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. The switch statement is another alternative to using nested if-else statements.3. : : break. : : } The expression must be declared in the parentheses. if it matches the statements under it are executed till it encounters a break statement. The values with case should be constants. .31 1. case value3 : statements. The expression is evaluated and compared with the values in cases. default : statements.

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

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

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

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

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

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

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

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

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

int arr[4][3] = {{0. for(int i = 1.7.3}. int arr[4][3] = {{0}.i< = 10.j++) { arr[i][j] = i+j. // First element of rows are 0.2.2.5}.g.i++) for(int j = 1.4.4.g.1.11}.9.11}}. • The nested brackets are optional. • Multidimensional array can be initialized as follows e.{6. This is a two-dimensional array with 4 as row dimension and 3 as a column dimension.6.1. int arr[4][3] = { 0.41 int arr[4][3]. } • Instead of arr[1][2] if you give arr[1.10. j< = 10.5.2}. e.2] is considered as arr[2]. • Initialization using nested loops.8}.3.2.{9.exe . 2.4. POINTER TYPES i.{2}.1.10. int arr[4][3] = {1.g. int arr[10][10]. and remaining elements are considered Zero.{3}}.3.2. e.{3.{1}.8. // Initializes first three element of first row as 1.3 and remaining are considered zero.7.

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

iptr1=ival. *iptr2 = &ival. e. e. sptr. . However.g. The pointer can hold the value of 0 . A pointer of one type cannot be assigned the address value of the object of another type.g. // invalid. vptr = dptr.g. double dval. // allowed iptr = &dval . e. iptr1 = iptr2 // both address ival iptr2 = 0. indicating that it points to no object or it can hold the address of same data type as mentioned earlier. string string * *sptr. int *iptr1 = 0. e. void *vptr = iptr. //not allowed However you can compare or interchange 2 types of address values using void pointer. ival is not address.43 You can declare a pointer variable in two ways. Pointers can never store a non-address value. int ival = 1024.g. // iptr2 now addresses to no object. 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. e. *dptr = &dval.g.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.1. A user. Some of them are highlighted below. SOME DIFFERENCES BETWEEN C AND C++ There are several differences between the C language and C++. Comments .2. This new subclass is said to derive from the existing type and is sometimes called a derived type.5.60 C++ supports the idea of reuse through inheritance.5. 3.4. 3. the user simply presses the accelerator and the car responds with the correct function. 3. however. for example. Poly means many.3. whereas morph means form. does not have to know about these differences.5. The CAR2 might engage fuel injection and a turbocharger. 3. which have nothing to do with OOP. polymorphism refers to the same name taking many forms. whereas the CAR1 simply get petrol into its carburetor. Through this concept. a new type can be declared that is an extension of the existing type. C++ supports this idea – that different objects do “the right thing “ – through function polymorphism and class polymorphism. Polymorphism The CAR2 in the above example may respond differently than the CAR1 when the car accelerates. Thus.

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

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

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

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

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

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

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

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

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

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

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

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

Sachin. 4. Once a class has been defined several objects of that type can be declared. age. thus reducing the complexities involved. [Or] class player Sachin . a class is a vehicle to implement the OOP features in the C++ language. Dravid. but function calcaverage() can be called only from the member functions of the class – getstats() and showstats(). and average – can be accessed only by member functions of the class calcaverage(). Mohan. e. Dravid. Mohan . Dravid.showstats().g. The interface(public) functions take care of this.73 The above example models a cricket player. Once a class is declared. tests.4. Mohan . The functions in the public section getstats() and showstats() can be called from the program directly . 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. highest.no_player = 10. Once the object is declared. runs. 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. an object of the class defined above can be declared with the following statement: player Sachin. CLASSES AND OBJECTS As seen earlier. For instance. where Sachin and Dravid are two objects of the class player. its public members can be accessed using the dot operator with the name of the object. an object of that type can be defined. The OOP methodology is to hide the implementation specific details. The variables in the private section – name. .getstats(). 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. getstats() and showstats(). The program need not know about the changes in the private data and functions.

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

75 } void player :: showstats (void) { : : } This notation indicates that the functions getstats () and showstats() belong to the class player. void get() { cin >> a. }.g. } private : int a. e. 4. Objects can also be passed by address. class check { public : check add(check). When an object is passed by content . PASSING AND RETURNING OBJECTS Objects can be passed to a function and returned back just like normal variables. 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.7. . which will be discussed later. } void put() { cout << a.

temp.get().i. c2. we may pass more than one object and also normal variable. c3. we can return an object or a normal variable from the function. c2 is referred as ‘c2. 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 . 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 ‘.add(c2). } The above example creates three objects of class check. return ( temp). This problem can be eliminated using .put(). We have made use of a temporary object in the function add() in order to facilitate return of the object.8. c3 = c1.c2.a’ . } check check :: add ( check c2) { check temp.76 void main() { check c1.a. 4.get().’. c1.a = a + c2. however. POINTERS TO OBJECTS Passing and returning of objects is. c2 and returns the result to another object c3. the invoking class c1 and the object that is passed to the function .c3. It adds the member variable of two classes. not very efficient since it involves passing and returning a copy of the data members.e.

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

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

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

Even though the this pointer is implicitly declared. only one copy of each member function per class is stored in memory. records[y]. Fortunately this pointer is supplied to each member function automatically when the function is called. but for different objects. The statement. . then for obvious reasons it would be impossible to create more than one instance of the class. Consequently. 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. In other words. If this were not the case. THE SPECIAL POINTER ‘THIS’ When several instances of a class come into existence. 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.printdetails(). an array of objects is declared just like any other array. using the array name qualified by a subscript. For different values of subscript. The solution to this dilemma is that. 4. it naturally follows that each instance has its own copy of member variables. even though the class member functions are encapsulated with the data members inside the class definition. This pointer variable has a special name ‘this’ (reserved word). On the other hand.80 As can be seen above. you always have access to it and may use the variable name anywhere you seem appropriate. each member function does have access to a pointer variable that points to the instance being manipulated.10. 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. it invokes the same member function. invokes the member funs printdetails() for the object given by the subscript y. all the compiler knows is the offset of each data member from the start of the class. in point of fact. Members of the class are accessed. and must be shared by all of the instances of the class. so that this burden is not placed upon the programmer.

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

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

it is important that initialization of these instantiations be performed so that the state of any object does not reflect “ garbage”.constructors Constructor with one argument.83 SESSION 5 CONSTRUCTOR AND DESTRUCTOR FUNCTIONS During this session you will learn about : • • • • • Automatic initialization of data members . 5. One of the principles of C++ is that objects know how to initialize and cleanup after themselves. The execution of such a function guarantees that the instance variables of the class will be initialized properly. 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.1 CONSTRUCTORS By definition. 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. . This automatic initialization and clean up is accomplished by two member functions – the constructor and the destructor.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

s6. } else if( s5 > s6 ) { s5. s6.putstr().putstr(). } else { s5. } else { s5. s6. cout << ” = ”.putstr(). } } 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().putstr(). cout << ” < ”. s6.putstr().103 String s6 = “ Apple “. cout << ” < ”.putstr(). if( s5 < s6 ) { s5.putstr(). cout << ” > ”.

s). where the data members contain pointers and have been allocated memory using the operator new. }. ~String() { delete cptr. // CONSTRUCTOR } void putstr() { cout << cptr . void main() // FUNCTION TO PRINT STRING . POINTER ODDITIES AND OPERATOR OVERLOADING Consider an example . strcpy(cptr. }. }. int size.4.104 6. class String { public : String (char *s = “”) { size = strlen(s). The following example explains this problem. cptr = new char [size + 1]. 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. private : char *cptr.

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

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

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

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

25 metres is : “ << d1.showdist().6. However. INCHES = 6. 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). cout << “ 2. INCHES = 1.719999 The above program converts distance in metres ( basic data type) into feet and inches ( members of an object of class Distance ).0.showdist() . The compiler first checks for an operator function for the assignment operator. then it uses the constructor to do the conversion. inches = 0.0.109 cout << “ 1.0 metres is :FEET = 6 . The declaration of first object d1 uses the second constructor and conversion takes place. } Output : 1. when the statement encountered is d2 = 2.25 metres is :FEET = 4 . }.0 metres is :“ << d2. 6. If the assignment operator is not overloaded.2.199999 2. class Distance { public : Distance(void) // Constructor with no { feet = 0. // argument Distance(float metres) { .

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

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

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

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

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

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

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

Overload >= or <= operators to compare the two strings. WAP to add. yet. 3. { make use of constructors and destructors whenever possible } .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 times using OOT and display the resultant time in watch format. It means one thing having many forms. This session covered operational polymorphism also called as operator overloading. It is very powerful. WAP to add 2 complex number using OOT(Operator Overloading techniques). We will see function overloading in future. simple concept which gives the C++ language a facility to redefine itself into a new language. EXERCISES 1. Sort an array of objects. 2. There are two types of Polymorphismoperational and functional. Each object has a string as a member variable. subtract and multiply 2 matrices using OOT.

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

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

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.

7.2.

PRECAUTIONS WITH FUNCTION OVERLOADING
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.

7.3.

CALL BY REFERENCE
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.

7.4.

USAGE OF REFERENCE VARIABLES.

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

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

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.

7.6.

RETURNING REFERENCES FROM FUNCTIONS

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 .

USE OF REFERENCE VARIABLE IS NOT A LUXURY BUT A NECESSITY
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; }

128

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

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

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

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

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

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

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

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

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

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

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

class derived2 : private derived { public : void g() { ++number. 8. therefore. e. // Access to number O. In this situation : The private members inherited from the base class are inaccessible to new members functions in the derived class. • • PUBLIC DERIVATION Public derivations are much more common than private derivations. 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.5. As you have just seen private derivations are very restrictive in terms of accessibility of the base class members .K // Access to number O. }.g. } }. class derived : public base { public : .139 { ++number. class base { private : int number. } }.

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

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 . 8. } }. }. . In this situation : • The private members inherited from the base class are inaccessible to new member functions in the derived class. ( this is exactly same as if a private or public derivation has occurred. you may also do a protected derivation. The public members inherited from the base class have protected have protected access. class base { protected : int number. class derived : public base { public : void f() { ++number. PROTECTED DERIVATION In addition to doing private and public derivations. // base member access O.K.7.) • • The protected members inherited from the base class have protected access privilege.

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

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.11. Because there is no ambiguity involved in this situation. assuming that the same name does not exist within the scope of the derived class . the members from the base class will automatically be used.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. USING THE DERIVED CLASS An instance of a derived class has complete access to the public members of the base class .

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

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

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

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

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

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

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

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

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

now from this derived class we can derive another class and so on. . from whom we derive another class .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++ .

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

constructors have to be defined for initializing the data members of all classes.8.. Bclass(. Like with normal inheritance . 9.. class Bclass .. The constructor in Cclass calls constructors for base 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.. }...).) { }. both publicly inherited. class Aclass { public : void put() { : } }. The constructor calls are separated by commas.) : Aclass (.171 private : : : public : Cclass(. PROBLEMS WITH MULTIPLE INHERITANCE The following example presents a problem with multiple inheritance.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2. However. since it does not belong to that object. the use of existing objects. an object is not required. class counter { public : counter (). That is. the number of objects (count) remains same at a given instance no matter which object is used to invoke the member function. to invoke such a function. like in the above example.190 number is a static variable and a constructor is used to write an equation to generate separate register numbers in some order. The example above demonstrates how to keep track of all the objects of a class which are4 in existence. it belongs to the entire class. 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. 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. private: static int count. static int getcount(). 10. is not an effective way to access the value of the static data member. In fact. for the same. this function uses existing objects to invoke a member function getcount(). C++ gives a facility to define static function members. STATIC MEMBER FUNCTIONS All the objects of the class share static data members of a class. The programme given below illustrates its use. A specific object should not be used to refer to this member. as can be seen from the previous output. It can be invoked with the name of the class.

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

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

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

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

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

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

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

} private : int Bvar. void main() { Aclass aobj. It means that all member functions of Bclass have been granted direct access to all member functions of Aclass. Bobj. Avar. }.8. 10. } The program declares class Bclass to be a friend of Aclass. 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. then you must code the classes and their member functions in this manner: . Bclass bobj. // Avar can be accessed.fn1(aobj).198 class Bclass { public : : : void fn1(Aclass ac) { Bvar = ac.

// Can’t define here Define the member functions of class B.199 • • • Forward declare class A. }. class Aclass class Bclass { public : : : void fn1(). you must qualify the names of these functions using the class name B and the scope resolution operator. • e. void fn3() { : : } private : int Bvar. Of course. class Aclass { public : : . 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.g.

200 : void fn1() { : }

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

private : int Avar;

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

10.9. OVERLOADING THE EXTRACTION AND INSERTION OPERATORS

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;

10.9 INLINE FUNCTIONS

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.

10.10. HOW TO WRITE A GLOBAL INLINE FUNCTION
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 :

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

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

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

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

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

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

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

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

put(‘A’). This function prints an entire string and has the prototype : ostream &write(char *. cout<< endl << “ Salary is “ << salary.212 cout << endl.15. cout.int). the ostream class provides some other functions for output.put(‘N’). There is another function write() in this class. cout << ”\n Age = “ <<age. e.put(‘I’). //Prints the character V It can also be used like : cout. One of them is put(). . 10.put(‘I’). } 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. This function prints only characters. It has the following prototype : ostream &put(char).g.put(‘D’).put(‘V’). OTHER OSTREAM FUNCTIONS Apart from the ‘cout’.

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

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

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

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

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

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

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

float f3 = 10.33] f3 = [1. } Output : Default f1 = [123.precision(2).0 / 3.43] f2 = [3.43.0. float f2 = 10.43] Default f2 = [3.666667] f1 = [123. cout << “ Default f1 = [ “<< f1 <<”]\n”.0 / 6. cout << “ f1 = [ “<< f1 <<”]\n”.220 e.0. cout << “ f2 = [ “<< f2 <<”]\n”. cout << “ f3 = [ “<< f3 <<”]\n”.333333] Default f3 = [1. cout << “ Default f2 = [ “<< f2 <<”]\n”. void main() { float f1 = 123. cout.g. cout << “ Default f1 = [ “<< f3 <<”]\n”.67] .

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

defined in the ios class definition and therefore have a class scope. The second prototype has two arguments. 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 above example shows the trailing zeros and decimal point.setf(ios::showpoint).222 These constants are enumerated constants. e.g. The first argument defines the bit settings that have to be changed. They have to be prefixed by the name of the class with the scope resolution operator(::). cout.

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

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

00e+01] 10. while(ch != ‘\n’) { cout << ch. cout << “Enter a String : “. cin >> ch.00] scientific : [+1. } } . OTHER ISTREAM FUNCTIONS. These functions accept a character. cin >> ch.g.18.ch2.225 output: Float : [+10] Showpoint : [+10. int get(void). void main() { char ch1.000000] 2decimals : [+10. e. Apart from the overloaded function for the extraction operator. 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). the istream class also has some other function. The second form returns back the character entered.

226 The program given above will not work. char ch =’\n’). cout <.get(ch). The solution is to use get() as below: e. Their function prototypes are : istream &getline(cahr *s. char ch =’\n’). “Enter a String : “. void main() { char ch1. while(ch != ‘\n’) { cout <<ch.ch2. since cin does not recognize white space characters and hence .get(ch). int size. int size. . cin.g. cin. istream &get(cahr *s. } } 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. . void main() { char *str = new char[100]. } The difference between get() and getline() is that get() leaves the new line character in the input system. 10. whereas getline() extracts it from the stream. The third argument is the terminating character. e. this function reads up to 49 characters or until new line character whichever is encountered first. cin. FUNCTION TEMPLATES Function templates provide you with the capability to write a single function that is a skeleton. for a family of similar functions.g.50).5. cout <<str. e. The second argument is the number of maximum characters to be read plus number. char string[100]. If omitted the function reads up to maximum characters specified or until new line character whichever is encountered first.227 The first argument is the address of the location where the input string is to be placed.19.’\n’)..get(string.g.get(str. or template. cout << “enter a string”.

long y) { return ( x > y) ? x : y . } long max( long x. overloaded functions are not the ultimate solution to the problem that is inherent when writing functions that are similar in their behavior. } char max(char x. . cout << max( 4L. Unfortunately. } float max(float x. Consider the following example: int max(int x.2) << endl. float y) { return ( x > y) ? x : y .3L) << endl. char y) { return ( x > y) ? x : y . } void main() { cout << max( 1.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 .

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

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

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. we can have more than one template parameter type in the same template . ++i) { if( array[i] < min_val) min_val = array[i].g. . The template needs to have parameters. either a template type representing a type or a template non-type parameter representing a constant expression. i<size. template < class Hello. it is used to declare min_val). } where Hello can be built in or user defined type and size is always constant and integer. casts etc.. A template type specifier can be used for variable declaration ( in the above example . first with an int.g. } return ( min_val). then with a double and then with a char. e. const int size > Hello min ( const Hello ( & array)[size]) { Hello min_val = array [0]. just like normal variable.231 Each of first three max () function class causes a template function to be instantiated. e. for(int i=1.

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

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

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

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

Sign up to vote on this title
UsefulNot useful