P. 1


|Views: 219|Likes:
Published by Teodor Rotaru

More info:

Published by: Teodor Rotaru on Apr 09, 2012
Copyright:Attribution Non-commercial


Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less






  • 1.9. VARIABLES
  • 1.13.1 Automatic Variables
  • 1.13.2. Static Variables
  • 1.13.3. External Variables
  • 1.13.4. Register Variable
  • 1.14.1. Assignment Operators
  • Unary Operators
  • Binary Operators
  • 1.14.3. Compound Assignment Operators
  • 1.14.4. Relational Operators
  • 1.14.5. Logical Operators
  • 1.14.6. Bit-wise Operators
  • 1.14.7. The Shift Operators
  • 1.14.8. Precedence and Order of evaluation
  • 1.14.9. The sizeof() operator
  • 1.16. TYPE CASTING
  • The if-else and else-if statements
  • The Conditional Expression Operator
  • The Switch Construct
  • The for Loop
  • The while Loop
  • The do..while Loop
  • 1.17.3. The break statement
  • 1.17.4. The continue statement
  • 1.17.5. The goto statement
  • 2.1. ARRAY TYPES
  • 2.11. UNIONS
  • 3.4.1. Encapsulation and Data Hiding
  • 3.4.2. Inheritance and Reuse
  • 3.4.3. Polymorphism
  • 3.5.1. Additional keywords in C++
  • 3.5.3. Variable Declaration
  • 3.5.4. The Scope Resolution Operator( :: )
  • 3.5.5. Default Arguments
  • 3.5.6. The new and delete operators
  • 6.6.1. Conversion from Basic to User-Defined variable
  • 6.6.2. Conversion from User-Defined to Basic data type
  • Conversion function in the Source Class
  • function in the Destination Class
  • 10.4. USING A FRIEND
  • 10.12.1. The #define Directive
  • 10.12.2. The #undef Directive
  • 10.12.3. The #ifdef, #elif, #else and #endif Directives
  • 10.12.4. The #error directive
  • 10.13. INPUT OUTPUT
  • 10.17.1. Changing Field width
  • 10.17.2. Padding the Extra Places
  • 10.17.3. Setting a precision
  • 10.17.4. The setf() Function


Object Oriented Programming (OOP) With C++


Table of Contents

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


• • •

• •

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

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

• • • •

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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


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

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

!(x == 0)

evaluates to true if condition is false.

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

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

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

23 { unsigned u = 0;

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

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

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

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

BIT2 0 1 0 1

BIT1 & BIT1 0 0 0 1

BIRT1 | BIT2 0 1 1 1

BIT1 ^ BIT2 0 1 1 0

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

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

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

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

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

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

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

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

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

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

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

g. } This is an infinite loop. ) { cout<<”hello”. The expressions in the for loop are optional but the semi-colons are necessary. i++. for( . with no expression.g. { cout << i.e. } . before entering the loop. 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. } This will print from 0 to 10. for( int i = 0. int j=10. e. y--) { cout << i. . ) { cout << i. i. which printed from 0 to 9.g. e.33 The initialize part is executed only once. i++) // In C++ you can declare a variable here. If the test evaluates to true then the updating takes place. } This is equivalent to our example.. i++. for( int i = 0. i< 10 && y>0 . e. i< 10. i< 10. int i = 0 for(.

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

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

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

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

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

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

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

2}.{3}}.2.exe .i< = 10. int arr[4][3] = {1. • Initialization using nested loops.9.11}}.g.6.{3. int arr[4][3] = {{0. This is a two-dimensional array with 4 as row dimension and 3 as a column dimension.7.2. e. e.5.{2}. // First element of rows are 0.41 int arr[4][3].4. • The nested brackets are optional. int arr[4][3] = { 0.g. POINTER TYPES i.3.i++) for(int j = 1.2] is considered as arr[2].7.2. int arr[4][3] = {{0}. j< = 10.10.{9.8.g.1. and remaining elements are considered Zero.{1}. } • Instead of arr[1][2] if you give arr[1.2.4. for(int i =}.1.8}.{6.4.j++) { arr[i][j] = i+j. • Multidimensional array can be initialized as follows e. 2. int arr[10][10].5}. // Initializes first three element of first row as 1.3 and remaining are considered zero.3.11}.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

122 }

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


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

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


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

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

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

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

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



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

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

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

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

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

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

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

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

Before call by address : n1 = 25 n2 = 50

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

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

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



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

n1 = fn( n2); }

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

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

7.7 .

The following example illustrates that the use of reference variable sometimes

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

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

//Constructor 2

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


String::~String() {

// Destructor

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

10. This can be done by making the base class a virtual class. class Aclass : virtual public base { : : }. class derived : public Aclass. . 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.175 9. class Bclass : virtual public base { : : }. This will resolve the ambiguity involved. It can be done as follows : class base { : : }. public Bclass { : : }.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

200 : void fn1() { : }

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

private : int Avar;

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


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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

cout << “ f3 = [ “<< f3 <<”]\n”. cout << “ f1 = [ “<< f1 <<”]\n”. float f3 = 10.g. cout << “ Default f1 = [ “<< f3 <<”]\n”.43.666667] f1 = [123. cout << “ f2 = [ “<< f2 <<”]\n”.0.220 e. cout. cout << “ Default f2 = [ “<< f2 <<”]\n”. cout << “ Default f1 = [ “<< f1 <<”]\n”. float f2 = 10.precision(2).333333] Default f3 = [1.67] . } Output : Default f1 = [123.0 / 3.43] Default f2 = [3.43] f2 = [3.33] f3 = [1. void main() { float f1 = 123.0 / 6.0.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

You're Reading a Free Preview

/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->