You are on page 1of 416

LESSON PLAN Unit Level Unit Value:1

Unit Title: Object Oriented Programming Unit Code [C++] 3B-503 aculty: Vandana Babrekar (Pune) Daily Lecture Schedule with dates Name of the topic as given in RU Syllabus

Lea rnin g Out com es

Assi gnm ent no., if any

Number of Hours L T P To * * * ta l 1 1 1 1 1 1 1 1 1 1 1 1 1 1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Lecture 1 Lecture 2 Lecture 3 Lecture 4 Lecture 5 Lecture 6 Lecture 7 Lectur e8 Lecture 9 Lecture 10 Lecture 11 Lecture 12 Lecture 13 Lecture 14 Lecture 15 Lecture 16 Lecture

Object oriented Programming Concepts Class & Object C++ Getting Started Functions in C++ Control Structures Representation of Abstract Data Types & scope of Attributes GROUP DISCUSSION Constructor Constructor [Contd.] Overloading Overloading [Contd.] Arrays Pointers in C++ Inheritance Inheritance [Contd.] Inheritance [Contd.] TUTORIAL 1

1 1 1

1 1 1

1 1 1 1 1

1 1 1 2 1

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

17 Lecture 18 Lecture 19 Lecture 20 Lecture 21 Lecture 22 Lecture 23 Lecture 24 Lecture 25 Lecture 26 Lecture 27 Lecture 28 Lecture 29 Lecture 30 Lecture 31 Lecture 32 Lecture 33 Lecture 34 Lecture 35 Lecture 36 Lecture 37 Lecture 38 Lecture 39 Lecture 40

Virtual Functions Polymorphism Virtual Base Classes, Nesting Of Class Streams Streams [Contd.] TUTORIAL Working with Files Working with Files [Contd.] Working with Files [Contd.] Templates Templates [Contd.] Templates [Contd.] Exception Handling Exception Handling [Contd.] GROUP DISCUSSION Implementation Implementation Data Driven Omt CRC Design Refinement Standard Template Library Standard Template Library[Contd.] 1 1 1

1 1 1 1 1 1 1

1 1 2 1 1 1

1 1 1 1 1 1 1

1 2 1 1 2 1 1

1 1 1 1 1 1 1 1

1 2 1 1 1 1 1 1

41

Lecture 41 42 Lecture 42 43 Lecture 43

UML UML [contd.] GROUP DISCUSSION

1 1 1

1 1 1

UNIT I Lesson 1 OBJECT ORIENTED PROGRAMMING Objectives Basic Concept Today in this introductory lecture , I will brief you some of the new concept of object oriented programming . we are aware of modular/structured programming, unstructured programming which are the traditional methods of writing a program. We also saw how the main program is linked to subprogram or subroutine through procedure calls [example of swapping between two telephone calls received]. And the trend of object oriented programming was discussed in brief. Now lets understand object oriented programming through its programming tool. C++ Fundamental change in (object oriented programming )OOP is that a program is designed around data being operated upon rather than upon the operations themselves. C++ is an example of Object Oriented Programming . It is expanded version of C .The limitations of C language are evident when a software project is too large to be handled. In some circumstances, error occur at some place and some patch up programs are added to rectify that error.These programs introduce an unexpected error at some other location and this process continues. Introduction to object oriented programming Features of OOPS Benefits of OOPS Applications of OOPS

In 1980 Bjarne Stroustrup addressed this problem by adding several extensions to C language. The most important addition was the concept of CLASS . The addition made were mainly aimed at extending the language in such a way that it supports object-oriented programming. OBJECT ORIENTED PROGRAMMING PATTERN Inspiring factor in the invention of object-oriented approach is to remove some of the flaws encountered in the procedural approach. OOP treats data as a critical element in the program development and does not allow it to flow freely around the system. It ties data more closely to the functions that operate on it, and protects it from accidental modification from outside functions. OOP

allows decomposition of a problem into a number of entities called objects and then builds data and functions around these objects. Following fig shows the organization of data and functions in object-oriented programs . The data of an object can be accessed only by the functions associated with that object. However, functions of one object can access the functions of other objects.

Object A DATA FUNCTION Communication

Object B DATA FUNCTION

Object C

FUNCTION DATA

Organization of data and functions in OOP

CHARACTERISTICS OF C++: Emphasis is on data rather than procedure. Programs are divided into what are known as objects. Data structures are designed such that they characterize the objects. Functions that operate on the data of an object are tied together in the data structure. Data is hidden and cannot be accessed by external functions.

Objects may communicate with each other through functions. New data and functions can be easily added whenever necessary. Follows bottom-up approach in program design.

Definition: Object-oriented programming as an approach that provides a way of modularizing programs by creating partitioned memory area for both data and functions that can be used as templates for creating copies of such modules on demand. Thus, an object is considered to be partitioned area of computer memory that stores data and set of operations that can access that data. Since the memory partitions are independent, the objects can be used in a variety of different programs without modifications. BASIC CONCEPTS OF OBJECT-ORIENTED PROGRAMMING. It is necessary to understand some of the concepts used extensively in object-oriented Programming. They are: Objects Classes Data abstraction and encapsulation Inheritance Polymorphism Dynamic binding Message passing Objects are the basic run-time entities in an object-oriented system. They may represent a person, a place, a bank account, a table of data or any item that the program has to handle. They may also represent user-defined data such as vectors, time and lists. Objects take up space in the memory and have an associated address like a record in Pascal, or a structure in C. When a program is executed, the objects interact by sending messages to one another. For example, if "customer" and "account" are two objects in a program, then the customer object may send

OBJECTS:

a message to the account object requesting for the bank balance. Each object contains data, and code to manipulate the data. Objects can interact without having to know details of each other's data or code. It is sufficient to know the type of message accepted, and the type of response returned by the objects. Although different authors represent them differently.

Fig. Shows two notations that are popularly used in object-oriented analysis and design. Object: STUDENT DATA Name Date-f-birth Marks FUNCTIONS Total Average Display STUDENT Total Average

Display

Two ways of representing an object

Classes: Objects contain data, and code to manipulate that data. The entire set of data and code of an object can be made a user-defined data type with the help of a class. In fact, objects are variables of the type class. Once a class has been defined, we can create any number of objects belonging to that class. Each object is associated with the data of type class with which they are created. Definition : A class is a collection of objects of similar type. For e.g., mango, apple and orange are members of the class fruit. Classes are user-defined data types and behave like the built-in types of a programming language. The syntax used to create an object is

no different than the syntax used to create an integer object in C. If fruit has been defined as a class, then the statement Fruit mango; will create an object mango belonging to the class fruit. Data Abstraction and Encapsulation: The wrapping up of data and functions into a single unit (called class) is known as encapsulation. Data encapsulation is the most striking feature of a class. The data is not accessible to the outside world, and only those functions, which are wrapped in the class, can access it. These functions provide the interface between the object's data and the program. This insulation of the data from direct access by the program is called data hiding or information hiding. Abstraction refers to the act of representing essential features without including the background details or explanations. Classes use the concept of abstraction and are defined as a list of abstract attributes such as size, weight and cost, and functions to operate on these attributes. They encapsulate all the essential properties of the objects that are to be created. The attributes are sometimes called data members because they hold information. The functions that operate on these data are sometimes called methods or member functions. Since the classes use the concept of data abstraction, they are known as Abstract Data Types (ADT) Inheritance: Inheritance is the process by which objects of one class acquire the properties of objects of another class. For example, the bird 'robin' is a part of the class flying bird' which is again a part of the class 'bird'. The principle behind this sort of division is that each derived class shares common characteristics with the class from which it is derived as illustrated in Fig. Concept of inheritance provides the idea of reusability. This means that we can add additional features to an existing class without modifying it. This is possible by deriving a new class from the existing one. The new class will have the combined features of both the classes. The real appeal and power of

the inheritance mechanism is that it allows the programmer to reuse a class that is almost, but not exactly, what he wants, and to tailor the class in such a way that it does not introduce any undesirable side-effects into the rest of the classes.

Note that each sub-class defines only those features that are unique to it. Without the use of classification, each class would have to explicitly include all of its features. Bird Attributes Feathers Lay eggs

Flying Bird Attributes ---------------

Non-Flying Bird Attributes ---------------

Robin Attributes ------------

Swallow Attributes ------------

Penguin Attributes ------------

Kiwi Attributes ------------

Fig. Property inheritance Polymorphism Polymorphism, means the ability to take more than one form. An operation may exhibit different behaviors in different instances. The behavior depends upon the types of data used in the operation. For e.g., consider the operation of addition of two numbers, the operation will generate a sum. If the operands are strings, then the operation would produce a third string by concatenation.

The process of making an operator to exhibit different behaviors in different instances is known as operator overloading. Figure below illustrates that a single function name can be used to handle different number and different types of arguments. This is something similar to a particular word having several different meanings depending on the context. Using a single function name to perform different types of tasks is known as function overloading. Polymorphism plays an important role in allowing objects having different internal structures to share the same external interface. This means that a general class of operations may be accessed in the same manner even though specific actions associated with each operation may differ. Polymorphism is extensively used in implementing inheritance.

Shape Draw ()

Circle object Draw (circle)

Box object Draw (box)

Triangle object Draw (triangle)

Fig. Polymorphism Dynamic Binding Binding refers to the linking of a procedure call to the code to be executed in response to the call. Dynamic binding (also known as late binding) means that the code associated with a given procedure call is not known until the time of the call at run-time. It is associated with polymorphism and inheritance. A function call associated with a polymorphism reference depends on the dynamic type of that reference. E.g. Consider the procedure "draw" in Fig. By inheritance, every object will have this procedure. Its algorithm is, however, unique to each object and so the draw procedure will be redefined in each class

that defines the object. At run-time, the code matching the object under current reference will be caned.

Message Passing An object-oriented program consists of a set of objects that communicate with each other. The process of programming in an object-oriented language, therefore, involves the following basic steps: 1. Creating classes that define objects and their behavior, 2. Creating objects from class definitions, and 3. Establishing communication among objects. Objects communicate with one another by sending and receiving information much the same way as people pass messages to one another. The concept of message passing makes it easier to talk about building systems that directly model or simulate their real-world counterparts. A message for an object is a request for execution of a procedure, and therefore will invoke a function (procedure) in the receiving object that generates the desired result. Message passing involves specifying the name of the object, the name of the function (message) and the information to be sent. Objects have a life cycle. They can be created and destroyed. Communication with an object is feasible as long as it is a'1ive. BENEFITS OF OOP OOP offers several benefits to both the program designer and the user. Object-orientation contributes to the solution of many problems associated with the development and quality of software products. The new technology promises greater programmer productivity, better quality of software and lesser maintenance cost. The principal advantages are: Through inheritance, we can eliminate redundant code and extend the use of existing classes. We can build programs from the standard working modules that communicate with one another, rather than having to start writing the code from scratch. This leads to saving of development time and higher productivity.

The principle of data hiding helps the programmer to build secure programs that cannot be invaded by code in other parts of the program. It is possible to have multiple instances of an object to co-exist without any interference. It is possible to map objects in the problem domain to those in the program. It is easy to partition the work in a, project based on objects. The data-centered design approach enables us to capture more details of a model in implementable form. Object-oriented systems can be easily upgraded from small to large systems. Message passing techniques for communication between objects makes the interface descriptions with external systems much simpler. Software complexity can be easily managed.

While it is possible to incorporate all these features in an object-oriented system, their importance depends on the type of the project and the preference of the programmer. There are a number of issues that need to be tackled to reap some of the benefits stated above. For instance, object libraries must be available for reuse. The technology is still developing and, current products may be superseded quickly. Strict controls and protocols. need to be developed if reuse is not to be compromised. Developing software that is easy to use makes it hard to build. It is hoped that the object. oriented programming tools would help manage this problem. OBJECT ORIENTED LANGUAGES Object-oriented programming is not the right of any particular language. Like structured. programming, OOP concepts can be implemented using languages such as C and Pascal. However, programming becomes clumsy and may generate confusion when the programs grow large. A language that is specially designed to support the OOP concepts makes it easier to implement them. The languages should support several of the OOP concepts to claim that they are object., oriented. Depending upon the features they support, they can be classified into the following two categories: 1. Object-based programming languages, and 2. Object-oriented programming languages.

Object-based programming is the style of programming that primarily supports encapsulation and object identity. Major features that are required for object-based programming are: Data encapsulation Data hiding and access mechanisms Automatic initialization and clear-up of objects Operator overloading

Languages that support programming with objects are said to be object-based programming languages. They do not support inheritance and dynamic binding. Ada is a typical object-based programming language. Object-oriented programming incorporates all of object-based programming features along with two additional features, namely, inheritance and dynamic binding. Object-oriented programming can therefore be characterized by the following statement: Object-based features + inheritance + dynamic binding Languages that support these features include C++, Smalltalk, Object Pascal and Java. There are a large number of object-based and object-oriented programming languages. APPLICATIONS OF OOP Applications of OOP are beginning to gain importance in many areas. The most popular application of object-oriented programming, up to now, has been in the area of user interface design such as windows. Hundreds of windowing systems have been developed, using the OOP techniques. Real-business systems are often much more complex and contain many more objects with complicated attributes and methods. OOP is useful in these types of applications because it can simplify a complex problem. The promising areas for application of OOP include: Real-time systems Simulation and modeling Object-oriented databases Hypertext, hypermedia and expertext

AI and expert systems Neural networks and Parallel programming Decision support and office automation systems CIM/CAM/CAD systems

Object-oriented technology is certainly going to change the way the software engineers think, analyze, design and implement future systems. WHAT IS C++? C++ is an object-oriented programming language. It was developed by Bjarne Stroustrup at AT&T Bell Laboratories in Murray Hill, New Jersey, USA, in the early 1980's. Therefore, C++ is an extension of C with a major addition of the class construct feature of Simula67. Since the class was a major addition to the original C language, During the early 1990's the language underwent a number of improvements and changes. In November 1997, the ANSI/ISO standards committee standardized these changes and added several new features to the language specifications. C++ is a superset of C. Most of what we already know about C applies to C++ also. Therefore, almost all C programs are also C++ programs. However, there are a few minor differences that will prevent a C program to run under C++ compiler. We shall see these differences later and when they are encountered. The most important facilities that C++ adds on to C are Classes, Inheritance, Function overloading, and Operator overloading.

APPLICATIONS OF C++

C++ is a versatile language for handling very large programs. It is suitable for virtually any programming task including development of editors, compilers, databases, communication systems and any complex real-life application systems. . Since C++ allows us to create hierarchy-related objects, we can build special object oriented libraries which can be used later by many programmers. While C++ is able to map the real-world problem properly, the C part of C++ give the language the ability to get close to the machine-level details. C++ programs are easily maintainable and expandable. When a new feature need to be implemented, it is very easy to add to the existing structure of an object. It is expected that C++ will replace C as a general-purpose language in the near future A SIMPLE C++ PROGRAM Let us begin with a simple example of a C++ program that prints a string on the screen. This simple program demonstrates several C++ features. # include<iostream> using namespace std; int main() { cout<< C++ is better than C \n // C++ statement return(); } // end of example Namespace Namespace is a new concept introduced by the ANSI C++ standards committee. This define a scope for the identifiers that are used in a program. For using the identifiers defined in the name space scope we must include the using directive, like using namespace std. Here, std is the name space where ANSI C++ standard class libraries are defined. All ANSI C++ programs must include this directive. // include header file

This will bring all the identifiers defined in std u the current global scope. using and namespace are the new keywords of C++. Return Type of main( ) In C++, main() returns an integer type value to the operating system. Therefore, every main in C++ should end with a return( 0) statement; otherwise a warning or an error might occur Since main() returns an integer type value, return type for main() is explicitly specified as int Note that the default return type for all functions in C++ is int. An Example With Class : One of the major features of C++ is classes. They provide a method of binding together data and functions which operate on them. Like structures in C, classes are user-defined data types shows the use of class in a C++ program. #include<iostream> using namespace std; class person() { char name[30]; int age; public: void getdata(void); void display(void); } void person:: getdata(void) { cout "\n Enter Name: "; cin>> name; cout "\n Enter Age; cin >> age; }

void person :: display(void) { cout<<\n Name :<<name; cout <<\n age :<<age; } int main() { person p; p.getdata(); p.display(); return 0; } The output of Program is: Enter Name: Ajay Enter Age: 30 Name: Ajay Age: 30 The above program defines person as a new data of type class. The class person includes two basic data type items and two functions to operate on that data. These functions are called I member functions. The main program uses person to declare variables of its type. Class variables are known as objects. Here, p is an object of type person. Class objects are used to invoke the functions defined in that class. STRUCTURE OF C++ PROGRAM As it can be seen from the above Program a typical C++ program would contain four sections as shown in following Fig. These sections may be placed in separate code files and then compiled independently or jointly. Include files Class Declaration Member Function Definition Main Function program

Structure of a C++ program It is a common practice to organize a program into three separate files. The class declarations are placed in a header file and the definitions of member functions go into another file. This approach enables the programmer to separate the abstract specification of the interface (class definition) from the implementation details (member functions definition). Finally, the main program that uses the class is placed in a third file which "includes" the previous two files as well as any other files required. Summary Object-oriented programming as an approach that provides a way of modularizing programs by creating partitioned memory area for both data and functions that can be used as tempalates for creating copies of such modules on demand. A class is a collection of objects of similar type Inheritance is the process by which objects of one class acquire the properties of objects of another class. Polymorphism, means the ability to take more than one form. Dynamic binding (also known as late binding) means that the code associated with a given procedure call is not known until the time of the call at run-time

Object-orientation contributes to the solution of many problems associated with the development and quality of software products

Object-oriented programming incorporates all of object-based programming features along with two additional features, namely, inheritance and dynamic binding The most popular application of object-oriented programming, up to now, has been in the area of user interface design such as windows

Questions: 1. Discuss features of OOPS 2. What do you mean by Dynamic Binding? How it is useful in OOPS 3. What are the Applications of OOPS 4. State characteristics of C++

UNIT I Lesson 2 CLASS & OBJECT Objective: Class Object

Now you have an idea what object oriented programming is. Here in this second lecture of OOP we will go through some of the important terminologies used in OOP like class and object. CLASS A class is a logical method to organize data and functions in the same structure. They are declared using keyword class, whose functionality is similar to that of the C keyword struct, but with the possibility of including functions as members, instead of only data. Its form is: class class_name { permission_label_1: member1; permission_label_2: member2; ... } object_name; where class_name is a name for the class (user defined type) and the optional field object_name is one, or several, valid object identifiers. The body of the declaration can contain members, that can be either data or function declarations, and optionally permission labels, that can be any of these three keywords: private:, public: or protected:. They make reference to the permission which the following members acquire: private members of a class are accessible only from other members of their same class or from their "friend" classes. protected members are accessible from members of their same class and friend classes, and also from members of their derived classes.

Finally, public members are accessible from anywhere the class is visible. If we declare members of a class before including any permission label, the members are considered private, since it is the default permission that the members of a class declared with the class keyword acquire. For example: class CRectangle { int x, y; public: void set_values (int,int); int area (void); } rect; Declares class CRectangle and an object called rect of this class (type). This class contains four members: two variables of type int (x and y) in the private section (because private is the default permission) and two functions in the public section: set_values() and area(), of which we have only included the prototype. Notice the difference between class name and object name: In the previous example, CRectangle was the class name (i.e., the user-defined type), whereas rect was an object of type CRectangle. Is the same difference that int and a have in the following declaration: int a; int is the class name (type) and a is the object name (variable). On successive instructions in the body of the program we can refer to any of the public members of the object rect as if they were normal functions or variables, just by putting the object's name followed by a point and then the class member (like we did with C structs). For example: rect.set_value (3,4); myarea = rect.area();

but we will not be able to refer to x or y since they are private members of the class and they could only be referred from other members of that same class. Confused? Here is the complete example of class CRectangle: // classes example #include <iostream.h> class CRectangle { int x, y; public: void set_values (int,int); int area (void) {return (x*y);} }; void CRectangle::set_values (int a, int b) { x = a; y = b; } int main () { CRectangle rect; rect.set_values (3,4); cout << "area: " << rect.area(); } Output : area: 12 The new thing in this code is the operator :: of scope included in the definition of set_values(). It is used to declare a member of a class outside it. Notice that we have defined the behavior of function area() within the definition of the CRectangle class - given its extreme simplicity. Whereas set_values() has only its prototype declared within the class but its definition is outside. In this outside declaration we must use the operator of scope ::.

The scope operator (::) specifies the class to which the member being declared belongs, granting exactly the same scope properties as if it was directly defined within the class. For example, in the function set_values() of the previous code, we have referred to the variables x and y, that are members of class CRectangle and that are only visible inside it and its members (since they are private). The only difference between defining a class member function completely within its class and to include only the prototype, is that in the first case the function will automatically be considered inline by the compiler, while in the second it will be a normal (not-inline) class member function. The reason why we have made x and y private members (remember that if nothing else is said all members of a class defined with keyword class have private access) it is because we have already defined a function to introduce those values in the object (set_values()) and therefore the rest of the program does not have a way to directly access them. Perhaps in a so simple example as this you do not see a great utility protecting those two variables, but in greater projects it may be very important that values cannot be modified in an unexpected way (unexpected from the point of view of the object). One of the greater advantages of a class is that we can declare several different objects from it. For example, following with the previous example of class CRectangle, we could have declared the object rectb in addition to the object rect : // class example #include <iostream.h> class CRectangle { int x, y; public: void set_values (int,int); int area (void) {return (x*y);} }; void CRectangle::set_values (int a, int b) { x = a; y = b; }

int main () { CRectangle rect, rectb; rect.set_values (3,4); rectb.set_values (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; } Output rect area: 12 rectb area: 30 Notice that the call to rect.area() does not give the same result as the call to rectb.area(). This is because each object of class CRectangle has its own variables x and y, and its own functions set_value() and area().

On that is based the concept of object and object-oriented programming. In that data and functions are properties of the object, instead of the usual view of objects as function parameters in structured programming. In this and the following sections we will discuss advantages of this methodology. In this concrete case, the class (type of object) to which we were talking about is CRectangle, of which there are two instances, or objects: rect and rectb, each one with its own member variables and member functions. Object Definition (Object) An object is an instance of a class. It can be uniquely identified by its name and it defines a state which is represented by the values of its attributes at a particular time. The state of the object changes according to the methods which are applied to it. We refer to these possible sequence of state changes as the behaviour of the object: Definition (Behaviour) The behaviour of an object is defined by the set of methods which can be applied on it.

We now have two main concepts of object-orientation introduced, class and object. Object-oriented programming is therefore the implementation of abstract data types or, in more simple words, the writing of classes. At runtime instances of these classes, the objects, achieve the goal of the program by changing their states. Consequently, you can think of your running program as a collection of objects. MEMORY ALLOCATION FOR OBJECTS We have stated that the memory space for objects is allocated when they are declared and not when the class is specified. This statement is only partly true. Actually, the member functions are created and placed in the memory space only once when they are defined as a part of a class specification. Since all the objects belonging to that class use the same member functions, no separate space is allocated for member functions when the objects are created. Only space for member variables is allocated separately for each object. Separate memory locations for objects are essential, because the member variables will hold different data values for different objects.

Common for all objects Member Function 1

Member Function 2 memory created when Function defined Member Function 1 Member Function 1 Member Function 1

Member Function 2 Object 1

Member Function 2 Object 2

Member Function 2 Object 3 Memory created when Objects defined.

OBJECTS AS FUNCTION ARGUMENTS Like any other data type, an object may be used as a function argument. This can be done in two ways: A copy of the entire object is passed to the function. Only the address of the object is transferred to the function.

The first method is called pass-by-value. Since a copy of the object is passed to the function, any changes made to the object inside the function do not affect the object used to call the function. The second method is called pass-by-reference. When an address of the object is passed the called function works directly on the actual object used in the call. This means that any changes made to the object inside the function will reflect in the actual object. The pass-by reference method is more efficient since it requires to pass only the address of the object and not the entire object. Program illustrates the use of objects as function arguments. It performs the addition of time in the hour and minutes format. Example: Object as argument

#include<iostream.h> class time { int hours; int minutes; public: void gettime(int h, int m) { hours = h; minutes = m; } void puttime(void) { cout<<hours<< hours and; cout<<minutes<<minutes<<\n; }

void sum(time , time ); }; void time:: sum(time t1, time t2); { minutes = t1.minutes + t2.minutes; hours = minutes/60 minutes = minutes%60; hours = hours + t1.hours + t2.hours; } int main() { time T1,T2,T3; T1.gettime(2,45); T2.gettime(3,30); T3.sum(T1,T2);

/declaration with objects as arguments //t1 & t2 are objects

//get T1 //get T2 //T3=T1+T2

Cout<< T1= ;T1.puttime(); //display T1 Cout<< T2= ;T2.puttime(); //display T2 Cout<< T3= ;T3.puttime(); //display T3 Return 0; } Output T1 = 2 hours and 45 minutes T2 = 3 hours and 30 minutes T3 = 6 hours and 15 minutes

Since the member function sum( ) is invoked by the object T3, with the objects Tl and T2 as arguments, it can directly access the hours and minutes variables ofT3. But, the members of Tl and T2 can be accessed only by using the dot operator (like Tl.hours and T1.minutes). Therefore, inside the function sum() the variables hours and minutes refer to T3, T1.hours and T1.minutes refer to Tl, and T2.hours and T2.minutes refer to T2.

An object can also be passed. as an argument to a non-member function. However, such functions can have access to the public member functions only through the objects passed as arguments to it. These functions cannot have access to the private data members Attribute Definition( Attribute) A property of object. It cannot exist independently of the object. Attribute may take other objects as values. It has a type. It describes the range of values that that property may hold. Method Definition (Method) A method is associated with a class. An object invokes a method as a reaction to receipt of a message. A Method is a service that can be requested from any object of the Class to affect behavior. A Method (Operation) can either be a command or a question. A question should never change the state of the object only a command can. The outcome of the Operation depends on the current state of the object. Summary A class is a logical method to organize data and functions in the same structure. They are declared using keyword class private members of a class are accessible only from other members of their same class or from their "friend" classes. protected members are accessible from members of their same class and friend classes, and also from members of their derived classes. public members are accessible from anywhere the class is visible. An object is an instance of a class. It can be uniquely identified by its name and it defines a state which is represented by the values of its attributes at a particular time. The behaviour of an object is defined by the set of methods which can be applied on it.

Attribute: A property of object. It cannot exist independently of the object. A method is associated with a class. An object invokes a method as a reaction to receipt of a message.

Questions 1. Distinguish between Class and Object 2. Define a) Method b) Attribute.

UNIT I Lesson 3 C++ GETTING STARTED Objective Token Datatype Header files Operators As you know that C++ is extension of C , most of its features, data types , operator set are very much similar to C in syntax and constructs. Here in this lecture we will discuss differences in them TOKENS The smallest unit in a program is known as a token. C++ has the following tokens . Keywords Identifiers Constants Strings Operators KEYWORDS Keywords are reserved words that cannot be useds as names for the program variables or other user defined program entities. Compared to C, C++ has more keywords as specified below asm auto break case catch char class const continue default delete do Double Else Enum Extern Float For Friend Goto If Inline Int Long new operator private protected public register return short signed sizeof static struct switch template this throw try typedef union unsigned virtual void volatile while

IDENTIFIERS

Identifier is the name given to variables, functions, arrays, classes, user defined types etc. The naming convention in C++ is similar to C language. The rules are described below . The name starts with an alphabetic character and not with a digit. . A name can contain alphabets, digits and underscore characters. . Names are case sensitive that is uppercase and lowercase letters are different. . A keyword cannot be used as a name for a variable. DATA TYPES The basic data type in C language is supported in C++. C++ has four basic built-in data types. They are char, int, float and double. Char is for storing a single character and is usually one byte in size. Int stores an integral value u two bytes long. Float and double store floating point numbers. Float is for single precision numbers and double is for double precision floating points. Signed and unsigned are modifiers that can be used with any integral type. Th type is signed by default. C++ recognizes the data type shown in the table below. Type Name char unsigned char Signed char int unsigned int signed int short int Unsigned short int Signed short int Long int signed long int Unsigned long i.nt float double long double Bytes 1 1 1 2 2 2 2 2 2 4 4 4 4 8 10 Range of Values -128 to 127 0 to 255 -128 to 127 -32768 to 32767 0 to 65535 -32768 to 32767 -32768 to 32767 0 to 65535 -32768 to 32767 -2147483648 to 2147483647 -2147483648 to 2147483647 0 to 4294967295 3.4E-38 to 1.7E+38 1.7E-308 to 1.7E+308 3.4E-4932 to 1.1 E+4932

SPECIFIERS Specifiers modify the meaning of the basic built-in types. They effectively provide a larger set of built in types. T specifiers, or qualifiers, are short, long, signed, and unsigned. The long and short specifiers set the range that tt type will hold. Short int, int, and long int are in ascending order of range size. The actual values vary from mac machine. Similarly, float; double, and long double are in order of

increasing capacity. There is no long float and n float or double. The signed and unsigned specifiers indicate whether the first bit of the data type is to be used a~ indicator or not. Except for charthe default is signed. Char mayor may not be signed by default. The following pi shows the bytes used by the different data types along with the specifiers: #include <iostream.h> void main() int i; unsigned int ui; short si; long i; // int is understood //ditto II Header required for cout.

unsigned short usi; //ditto unsigned long uli; //ditto char c; unsigned char uc; float f; double d; long double Id; //cout is Console out similar to printf cout<<\nSize of int = <<sizeof(i); cout<<\nSize of unsigned int = "<<sizeof(ui); cout"\nSize of short int = "<<sizeof(si); cout<<"\nSize of long int = "<<sizeof(li); cout<<\nSize of unsigned short int = "<<sizeof(usi); cout<<\nSize of unsigned long int = "<<sizeof(uli)<<"\n"; cout<<"\nSize of char = "<<sizeof(c); cout<<"\nSize of unsigned char = "<<sizeof(uc)<<"\n"; cout<<"\nSize of float = "<<sizeof(f); cout<<"\nSize of double = "<<sizeof(d); cout<<''\nSize of long double = "<<sizeof(ld)<<''\n''; ESCAPE SEQUENCES

The escape sequences allow you to use a sequence of characters to represent special characters. Escape sequences are listed below. These escape sequences are used in I/O statements like printf(), scanf(), cout etc. Sequence \a \f \r \v \' \\ \b \n \t \? Name Alert (bell) Formfeed Carriaqe return Vertical tab Sinqle quotation mark Backslash Backspace Newline Horizontal tab Literal quotation mark

HEADER FILES All the header files available in C are used in C++, alongwith other header files of C++. A few of them are in the table. FileName ASSERT.H BIOS.H CDERR.H COLORDLG.H COMMDLG.H CONIO.H CPL.H CTYPE.H CUSTCNTL.H DDE.H DDEML.H DIRECT.H DOS.H ERRNO.H FSTREAM.H Major Contents Assert debugging macro IOS service functions Common dialog error return codes Common dialog color dialog's control id numbers Common dialog functions, types, and definitions Console and port I/O routines Control panel extension DLL definitions Character classification Custom Control Library header file Dynamic Data Exchange structures and definitions DDEML API header file Directory control MS-DOS interface functions errno variable definitions Functions used by the filebuf and fstream classes

GRAPH.H IO.H IOMAINP.H IOS.H IOSTREAM.H ISTREAM,H MALLOC.H MATH.H MEMORY.H MMSYSTEM.H I NEW.H NEW.H OSTREAM.H PENWIN.H PENWOEM.H PGCHART.H PRINT.H PROCESS.H SCRNSAVE.H SSEARCH.H SETJMP.H SHARE.H SHELLAPI.H SIGNAL.H STDARG.H STDDEF.H STDIO.H STDIOSTR.H STDLlB.H STREAMB.H STRESS.H

Low-level graphics and font routines File-handling and low-level I/O definitions / declarations for iostream's parameterized manipulators Functions used by the ios class Functions used by the iostream classes Functions used by the istream class Memory-allocation functions Floating-point-math routines Buffer-manipulation routines Include file for Multimedia APls. Declarations and definitions for C++ memory allocation functions. Functions used by the ostream class Pen Windows functions, types, and definitions Pen Windows APls into recognizer layer Presentation graphics Printing helper functions, types, and definitions Process-control routines Win3.1 screensaver defines and definitions Searching & sorting functions Setjmp and longjmp functions Flags used in _sopen SHELL.DLL functions, types, and definitions Constants used by signal function Macros for variable-length argument-list functions Commonly used data types and values Standard I/O header file Functions used by the stdiostream and stdiobuf classes Commonly used library functions Functions used by the streambuf class Stress functions definitions

OLE.H OLE functions, types, and definitions

STRING.H STRSTREA.H TIME.H VER.H VMEMORY.H WFEXT.H PREPROCESSOR DIRECTIVES

string manipulation function Functions used by strstream classes General time functions Version mngt. functions, types and definitions Virtual memory functions Windows File Manager Extensions definitions

The table below lists the directives to the preprocessor. Their usage and the meaning in C++ is the same as in any details regarding usage, please refer to any C reference material.. #define #error #include #else #ifdef #elif #pragma #if #Iine #endif #ifndef #undef

FILE EXTENSIONS In C++. all the programs carry ".CPP" extensions as compared to ".C" extensions in C. Anyway, even if you al working with a C++ compiler and give" .C" extension, C compiler takes over to compile that program. C++ COMMENTS

1. /* *1 comment is used to apply mutiline comment, where' 1*' begins a comment and' *1 . ends it. 2. Double-slash (II) sequence is used to comment single line completely. OPERATORS: The table below lists C and C++ operators by category. C++ introduced many operators compared to C. This is described below Scope resolution operator: As C language does not allow the global variable value to be accessed from the inner block having the same variable name as the global variable in order to solve this conflict the scope resolution operator is used. The example presented below #include <iostream.h> int gl =10; // global variable gl main() int gl = 20; int k = gl; int gl = 30; // gl declared again in inner block cout << "\n we are in inner block: \n"; cout << "k = " << k << "\n"; cout << "gl = " << gl << ''\n''; cout << ":: gl = " << ::gl << ''\n''; cout<< "\n We are in outer block: \n"; cout << "gl = " << gl << ''\n''; cout<< "::gl = " << ::gl << ''\n''; The output is we are in inner block: k=20 g1=30 ::gl=10 we are in outer block gl=20 // gl redeclared again, local to main

::gl =10 In the program above gl variable is declared three times with different scope and uses the :: scope resolution operator to access the global version as shown in the output. MEMBER DEREFERENCING OPERATOR The types of member referencing operators are described below ::* ->* .* Pointer to member declerator Pointer to member operator Pointer to member operator

This operator is used in context with pointer to object member. MEMORY MANAGEMENT OPERATOR In c++ two important memory management operators are described below delete Memory release operator new Memory allocation operator The general format of usage is Pointer-variable = new data-type Where Pointer-variable is used to hold the address of variable of data-type; Data-type is used to specify any valid data. The new operator is used to allocate sufficient memory to hold a data object of type data-type and returns the address of the object to pointer variable. Few examples are given below int *ptr ;. ptr = new int; Other formats are Pointer-variable = new data-type(value) Where value is the initial value assigned to Pointer-variable. Few examples are given below int *ptr = new int(25); assign value 25 to ptr variable

You can create an array using the new operator as specified in the general format below Pointer-variable = new data-type[size]; Where size is the required size of the memory to be allocated. Examples are given below int * Arrptr = new int[3][4]; To release the memory allocated using the new operator, delete operator is used. To delete memory allocated us the pointer holding the address of the allocated memory. Examples are given below delete p; delete [4] q; delete [ ] p; // to delete the memory area pointed by p. // deletes 4 elements from the array // deletes the entire array

You can delete number of element from the array which is specified in the square bracket as specified in the second example above. MANIPULATORS It is an operator used to format the presentation of data. This means that you can arrange the data on the screen in a desired format. The most common manipulators are endl setw Line Feed operator equivalent to special character' \n ' Field Width operator used to specify the display width of data on the screen.

TYPE CAST OPERATOR The type cast operator has similar functionality to C language. The syntax has changed as explained in the example below

In C language
Average = sum /(float)i; In C++ language Average = sum / float (i);

Arithmetic + * / % Relation < <= > >= -!= Less than Less than or equal to Greater than Greater than or equal to Equal Not equal Addition Subtraction Multiplication Division Modulus

Assignment = += /= Assignment Addition Subtraction Division

<<= Left shift assignment &= Bitwise AND |= Bitwise OR Bitwise & && || /\ ! | << >> ~ & Logical Bitwise AND Logical AND Logical OR Bitwise-exclusive- OR Logical NOT Bitwise OR Left shift Right shift One's complement Pointer Address of ?: Conditional Ternary

Indirection

Miscellaneous: C++ Only () :: [] -> .* ->* Function call Scope resolution Array element & Reference Pointer to structure member Pointer to member Pointer to member sizeof() Size in bytes

. (type) Type cast

The mathematical operators +, -, *, /, = all work in the same way, in mathematics and in C. Some are evaluated I others in an expression, and are said to have higher precedence than the latter. The unary operators are the ++ a - operators. They can be used before or after a variable and are accordingly called pre or post increment or pre ( decrement operators. When used before a variable the operation is first performed on the variable and then it i: in the expression. Conversely, when used after a variable, the variable is first used in the expression and the incremented. For example look at run the following program. Program: #include <iostream.h> void main() int i=10; cout<<''\n post-increment i = "i++; cout<<''\n pre-increment i = "<<++i; cout<<''\npost-decrement i = "<<i--; cout<<''\npre-decrement i = "<<--i; Output: post-increment i = 10 pre-increment i = 12 post-decrement i = 12 pre-decrement i = 10

CONSTANTS The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it. Example: const int i = 5; i = 10; i++; // Error // Error

You can define constant using the #define, but the constant defined using const keyword is typed check where as #define constant has no type information. C++ uses const keyword to declare a constant pointer of two types Constant pointer char. const ptr1 = "GOOD"; II constant pointer which means you cannot modify the address that ptr1 is initialized to Pointer to a constant int const .ptr2 = &m; // pointer to a constant Which means that you cannot change the value at the address ptr2. You can also declare both the pointer and the variable as constants in the following way const char.const cp = "xyz"; ENUMERATED DATA TYPE An enumerated data type is a user defined data type which provides a way to attach names to a number which helps you to remember the number. The syntax is similar to struct in C. For examples enum shape{ circle,square,triangle}; Here shape is a user defined type which is used to declare a variable of type shape which can take only the value

specified in the curly braces. The names in the curly braces represent the number 0 as circle, 1 as square, 2 as triangle automatically. ThedefauJt numbering starts from 0. To declare variable conics of type shape shape conics; You can assign values in conics in following ways conics = circle;// to assign 0 to conics conics = 0; conics= (shape) 0; int a = circle; //it is not allowed and Error in C++ // correct way to assign using cast operator. ' // it is allowed.

STRUCT AND UNION You can use struct and union to define user-defined type similar to C language along with function prototype in the structure. DECLARATION OF VARIABLES Unlike C language you can declare variable at any position inside the function but before using the variable. n program below demonstrates this feature. #include <iostream.h> void main() float x; float sum; for(int count = 1; count < 10;count++) cin>> x; sum = sum + x; float average; cout average; } The above program declares the variables and total at the beginning of the program and the variable average i: declared in ttie middle of the program. Such a creation helps to declare a variable with //declaration average = sum / count;//declaration //declaration

dynamic initialization; shown in the program above. The average variable is initialized with' sum/count '. Summary The smallest unit in a program is known as a token. C++ has the following tokens .

Keywords
Identifiers Constants Strings Operators Keywords are reserved words that cannot be useds as names for the program variables or other user defined program entities Identifier is the name given to variables, functions, arrays, classes, user defined types etc. The basic data type in C language is supported in C++. C++ has four basic built-in data types. They are char, int, float and double Float and double store floating point numbers Specifiers modify the meaning of the basic built-in types. They effectively provide a larger set of built in types. The escape sequences allow you to use a sequence of characters to represent special characters. In C++. all the programs carry ".CPP" extensions as compared to ".C" extensions in C As C language does not allow the global variable value to be accessed from the inner block having the same variable name as the global variable in order to solve this conflict the scope resolution operator is used To release the memory allocated using the new operator, delete operator is used. The mathematical operators +, -, *, /, = all work in the same way, in mathematics and in C. The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it. An enumerated data type is a user defined data type which provides a way to attach names to a number which helps you to remember the number. Question What is token? Explain. Explain the term Datatype, scope Resolution Operator, Enumerated Data Type

Give various types of operator set in C++

UNIT I LESSON 4 FUNCTIONS IN C++ Objective In this lesson You will get acquainted with an important concept of OOPS i.e. Functions, Call by value, Call by reference, Friend function . In the previous section we have seen how a class is implemented along with the usage of objects and its subsequent components. Now comes the most important building block of the program. Function. You will understand how important role a Function plays in program through the sessions below.

FUNCTION IN C++

Using functions you can structure your programs in a more modular way, accessing all the potential that structured programming in C++ can offer us. A function is a block of instructions that is executed when it is called from some other point of the program. The following is its format:
type name ( argument1, argument2, ...) statement

where:
type name

is is the

the name

type by

of it

data will be

returned possible

by to call

the the

function. function.

which

arguments

(as many as wanted can be specified). Each argument consists of a type of data

followed by its identifier, like in a variable declaration (for example, int x) and which acts within the function like any other variable. They allow passing parameters to the function when it is called. The different parameters are separated by commas.

statement

is the function's body. It can be a single instruction or a block of instructions. In

the latter case it must be delimited by curly brackets {}.

function example:
// function example #include <iostream.h> int addition (int a, int b) { int r; r=a+b; return (r); } int main () { int z; z = addition (5,3); cout << "The result is " << z; return 0;

}
output

The result is 8

Function addition declares a new variable (int r;), and by means of the expression r=a+b;, it assigns to r the result of a plus b. Because the passed parameters for a and b are 5 and 3 respectively, the result is 8. The following line of code:
return (r);

finalizes function addition, and returns the control back to the function that called it (main) following the program from the same point at which it was interrupted by the call to addition. But

additionally, return was called with the content of variable r (return (r);), which at that moment was 8, so this value is said to be returned by the function.

And here is another example about functions:


// function example #include <iostream.h> int subtraction (int a, int b) { int r; r=a-b; return (r); } int main () { int x=5, y=3, z; z = subtraction (7,2); cout << "The first result is " << z << '\n'; cout << "The second result is " << subtraction (7,2) << '\n'; cout << "The third result is " << subtraction (x,y) << '\n'; z= 4 + subtraction (x,y); cout << "The fourth result is " << z << '\n'; return 0;

}
The first result is 5 The second result is 5 The third result is 2 The fourth result is 6

Arguments passed by value and by reference..

Until now, in all the functions we have seen, the parameters passed to the functions have been passed by value. This means that when calling a function with parameters, what we have passed to the function were values but never the specified variables themselves. For example, suppose that we called our first function addition using the following code :
int x=5, y=3, z; z = addition ( x , y );

What we did in this case was to call function addition passing the values of x and y, that means 5 and 3 respectively, not the variables themselves.

This way, when function addition is being called the value of its variables a and b become 5 and 3 respectively, but any modification of a or b within the function addition will not affect the values of
x

and y outside it, because variables x and y were not passed themselves to the the function, only their

values. But there might be some cases where you need to manipulate from inside a function the value of an external variable. For that purpose we have to use arguments passed by reference, as in the function
duplicate

of the following example:

// passing parameters by reference #include <iostream.h> void duplicate (int& a, int& b, int& c) { a*=2; b*=2; c*=2; } int main () { int x=1, y=3, z=7; duplicate (x, y, z); cout << "x=" << x << ", y=" << y << ", z=" << z;

return 0;

} output
x=2, y=6, z=14

The first thing that should call your attention is that in the declaration of duplicate the type of each argument was followed by an ampersand sign (&), that serves to specify that the variable has to be passed by reference instead of by value, as usual. When passing a variable by reference we are passing the variable itself and any modification that we do to that parameter within the function will have effect in the passed variable outside it.

To express it another way, we have associated a, b and c with the parameters used when calling the function (x, y and z) and any change that we do on a within the function will affect the value of x outside. Any change that we do on b will affect y, and the same with c and z. That is why our program's output, that shows the values stored in x, y and z after the call to
duplicate, shows the values

of the three variables of main doubled.

If when declaring the following function:


void duplicate (int& a, int& b, int& c)

we had declared it thus:


void duplicate (int a, int b, int c)

that is, without the ampersand (&) signs, we would have not passed the variables by reference, but their values, and therefore, the output on screen for our program would have been the values of x, y and z without having been modified. Passing by reference is an effective way to allow a function to return more than one single value. For example, here is a function that returns the previous and next numbers of the first parameter passed.

FRIENDLY FUNCTIONS

I We have been emphasizing throughout this chapter that the private members cannot accessed from outside the class. That is, a non-member function cannot have an access to private data of a class. However, there could be a situation where we would like two classes to share a particular function. For example, consider a case where two classes, manager if scientist, have been defined. We would like to use a function income_tax( ) to operate the objects of both these classes. In such situations, C++ allows the common function made friendly with both the classes, thereby allowing the function to have access to private data of these classes. Such a function need not be a member of any of these classes. To make an outside function friendly to a class, we have to simply declare this function as a friend of the class as shown below

Class ABC { .. .. public: .. .. friend void xyz(void); }; The function declaration should be preceded by the keyword friend. The function is defined Else here in the program like a normal C++ function. The function definition does not "either the keyword friend or the scope operator ::. The functions that are declared with thekeyword friend are known as friend functions. A function can be declared as a friend in anynumber of classes. A friend function, although not a member function has full access rights to the private members of the class. Certain special characteristics of friend function : It is not in the scope of the class to which it has been declared as friend. Since it is not in the scope of the class, it cannot be called using the object of that class. //declaration

It can be invoked like a normal function without the help of any object. Unlike member functions, it cannot access the member names directly and has to object name and dot membership operator with each member name.( e.g. A.x). It can be declared either in the public or the private part of a class without affecting its meaning. Usually, it has the objects as arguments.

Example : Friend Function #include <iostream> using namespace std; class sample { int a; int b; public : void setvalue( ) { a=25; b= 40; } friend float mean(sample s); }; float mean(samp1e s) { return f1oat(s.a + s.b)/2.0; int main( ) { sample x; x.setva1ue( ); cout << Mean value = << mean (x) \n; return 0; // object X

The output of Program Mean value = 32.5 The friend function accesses the class variables a and b by using the dot operator and the object passed to it. The function call mean(x) passes the object x by value to the friend function. Member functions of one class can be friend functions of another class. In such cases, they are defined using the scope resolution operator, which is shown as follows:

c1ass x { int fun1( ); }; class Y { .. friend int X :: funl( ); .. }; The function funl( ) is a member of class X and a friend of class Y. // funl () of X // is friend of y // member function of X

We can also declare all the member functions of one class as the mend functions of anotlt class. In such cases, the class is called a friend class. This can be specified as follows: class Z { . friend class X; }; // all member functions of X are //friends to Z

program demonstrates how mend functions work as a bridge between the classes.

#include <iostream> using namespace std; class ABC; class XYZ { int x; public : void setvalue(int i) { x = i; } friend void max(XYZ, ABC); }; class ABC { //forward declaration

int a; public : void setvalue(int i) { x = i; } friend void max(XYZ, ABC); }; void max(XYZ m, ABC n) { if(m.x >= n.a) cout<<m.x; else cout<<n.a; } int main( ) { ABC abc; Abc.setvalue(10); XYZ xyz; xyz.setvalue(20); max(xyz, abc); return 0; } output 20 The function max( ) has arguments from both XYZ and ABC. When the function max( ) is declared as a friend in XYZ for the first time, the compiler will not acknowledge the presence of ABC unless its name is declared in the beginning as //definition of friend

class ABC; This is known as 'forward' declaration. As pointed out earlier, a friend function can be called by reference. In this case, local copies of the objects are not made. Instead, a pointer to the address of the object is passed and the called function directly works on the actual object used in the call. This Method can be used to alter the values of the private member of a class. Remember, altering the values of private members is against the basic principles of data hiding. It should be used only when absolutely necessary. Summary

A function is a block of instructions that is executed when it is called from some other point of the program. Passing by reference is an effective way to allow a function to return more than one single value. C++ allows the common function made friendly with both the classes, thereby allowing the function to have access to private data of these classes. Such a function need not be a member of any of these classes.

Questions 1.What is friend function? Explain its characteristic 2.state the merits and demerits of friend function 3..How member function of a class is defined? 3. point ot errors in the following program if any void main()

{ int a=30; f(); } void f() { int b=20; }

UNIT I Lesson 5 CONTROL STRUCTURES : Objective After getting an idea what function is, today we will discuss commonly used control structures of programming language such as if and else The while loop. The do-while loop. The for loop. The break instruction. The selective Structure: switch.

A program is usually not limited to a linear sequence of instructions. During its process it may bifurcate, repeat code or take decisions. For that purpose, C++ provides control structures that serve to specify what has to be done to perform our program. With the introduction of control sequences you are going to have an introduction to a new concept: the block of instructions. A block of instructions is a group of instructions separated by semicolons (;) but grouped in a block delimited by curly bracket signs: { and }. Most of the control structures that you will see in this section allow a generic statement as a parameter, this refers to either a single instruction or a block of instructions, as we want. If we want the statement to be a single instruction we do not need to enclose it between curly-brackets ({}). If you want the statement to be more than a single instruction you must enclose them between curly brackets ({}) forming a block of instructions.

Conditional structure: if and else It is used to execute an instruction or block of instructions only if a condition is fulfilled. Its form is:
if (condition) statement

where condition is the expression that is being evaluated. If this condition is true, statement is executed. If it is false, statement is ignored (not executed) and the program continues on the next instruction after the conditional structure. For example, the following code fragment prints out x is 100 only if the value stored in variable x is indeed 100:
if (x == 100) cout << "x is 100";

If we want more than a single instruction to be executed in case that condition is true we can specify a block of instructions using curly brackets { }:
if (x == 100) { cout << "x is "; cout << x; }

We can additionally specify what we want that happens if the condition is not fulfilled by using the keyword else. Its form used in conjunction with if is:
if (condition) statement1 else statement2

For example:
if (x == 100) cout << "x is 100"; else cout << "x is not 100";

prints out on the screen x is 100 if indeed x is worth 100, but if it is not -and only if not- it prints out
x is not 100.

The if + else structures can be concatenated with the intention of verifying a range of values. The following example shows its use telling if the present value stored in x is positive, negative or none of the previous, that is to say, equal to zero.

if (x > 0) cout << "x is positive"; else if (x < 0) cout << "x is negative"; else cout << "x is 0";

Remember that in case we want more than a single instruction to be executed, we must group them in a block of instructions by using curly brackets { }. Repetitive structures or loops Loops have as objective to repeat a statement a certain number of times or while a condition is fulfilled. The while loop. Its format is:
while (expression) statement

and its function is simply to repeat statement while expression is true. For example, we are going to make a program to count down using a while loop:

// custom countdown using while #include <iostream.h> int main () { int n; cout << "Enter the starting number > "; cin >> n; while (n>0) { cout << n << ", "; --n; } cout << "FIRE!"; return 0;

output

Enter the starting number > 8 8, 7, 6, 5, 4, 3, 2, 1, FIRE!

When the program starts the user is prompted to insert a starting number for the countdown. Then the while loop begins, if the value entered by the user fulfills the condition n>0 (that n be greater than 0 ), the block of instructions that follows will execute an indefinite number of times while the condition (n>0) remains true. All the process in the program above can be interpreted according to the following script: beginning in main:

1. User assigns a value to n. 2. The while instruction checks if (n>0). At this point there are two

possibilities:
o o --n;

true: execute statement (step 3,) false: jump statement. The program follows in step 5..

3. Execute statement:

cout << n << ", ";

(prints out n on screen and decreases n by 1).


4. End of block. Return Automatically to step 2. 5. Continue the program after the block: print out FIRE! and end of program.

We must consider that the loop has to end at some point, therefore, within the block of instructions (loop's statement) we must provide some method that forces condition to become false at some moment, otherwise the loop will continue looping forever. In this case

we have included --n; that causes the condition to become false after some loop repetitions: when n becomes 0, that is where our countdown ends. Of course this is such a simple action for our computer that the whole countdown is performed instantly without practical delay between numbers. The do-while loop. Format:
do statement while (condition);

Its functionality is exactly the same as the while loop except that condition in the do-while is evaluated after the execution of statement instead of before, granting at least one execution of
statement

even if condition is never fulfilled. For example, the following program echoes

any number you enter until you enter 0.


// number echoer #include <iostream.h> int main () { unsigned long n; do { cout << "Enter number (0 to end): "; cin >> n; cout << "You entered: " << n << "\n"; } while (n != 0); return 0;

} output

Enternumber(0toend):12345 Youentered:12345 Enternumber(0toend):160277 Youentered:160277 Enternumber(0toend):0 You entered:0

The do-while loop is usually used when the condition that has to determine its end is determined within the loop statement, like in the previous case, where the user input within the block of intructions is what determines the end of the loop. If you never enter the 0 value in the previous example the loop will never end. The for loop. Its format is:
for (initialization; condition; increase) statement;

and its main function is to repeat statement while condition remains true, like the while loop. But in addition, for provides places to specify an initialization instruction and an
increase

instruction. So this loop is specially designed to perform a repetitive action with a

counter. It works the following way: 1, initialization is executed. Generally it is an initial value setting for a counter finishes block of varible. and instructions This is executed is curly brackets only once. skipped.
}.

2, condition is checked, if it is true the loop continues, otherwise the loop


statement

3, statement is executed. As usual, it can be either a single instruction or a enclosed within


{

4, finally, whatever is specified in the increase field is executed and the loop gets back to step 2. Here is an example of countdown using a for loop.
// countdown using a for loop #include <iostream.h> int main () { for (int n=10; n>0; n--) { cout << n << ", "; } cout << "FIRE!"; return 0;

output 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE!

The initialization and increase fields are optional. They can be avoided but not the semicolon signs among them. For example we could write: for (;n<10;) if we want to specify no initialization and no increase; or for (;n<10;n++) if we want to include an
increase

field but not an initialization.

Optionally, using the comma operator (,) we can specify more than one instruction in any of the fields included in a for loop, like in initialization, for example. The comma operator (,) is an instruction separator, it serves to separate more than one instruction where only one instruction is generally expected. For example, suppose that we wanted to intialize more than one variable in our loop:
for ( n=0, i=100 ; n!=i ; n++, i-- ) { // whatever here... }

This loop will execute 50 times if neither n nor i are modified within the loop:

starts with 0 and i with 100, the condition is (n!=i) (that n be not equal to i). Beacuse n is

increased by one and i decreased by one, the loop's condition will become false after the 50th loop, when both n and i will be equal to 50.

Bifurcation of control and jumps.

The break instruction. Using break we can leave a loop even if the condition for its end is not fulfilled. It can be used to end an infinite loop, or to force it to end before its natural end. For example, we are going to stop the count down before it naturally finishes (an engine failure maybe):
// break loop example #include <iostream.h> int main () { int n; for (n=10; n>0; n--) { cout << n << ", "; if (n==3) { cout << "countdown aborted!"; break; } } return 0;

}
output

10, 9, 8, 7, 6, 5, 4, 3, countdown aborted

The continue instruction. The continue instruction causes the program to skip the rest of the loop in the present iteration as if the end of the statement block would have been reached, causing it to jump to the following iteration. For example, we are going to skip the number 5 in our countdown:

// break loop example #include <iostream.h> int main ()

{ for (int n=10; n>0; n--) { if (n==5) continue; cout << n << ", "; } cout << "FIRE!"; return 0;

}
10, 9, 8, 7, 6, 4, 3, 2, 1, FIRE!

The goto instruction. It allows making an absolute jump to another point in the program. You should use this feature carefully since its execution ignores any type of nesting limitation. The destination point is identified by a label, which is then used as an argument for the goto instruction. A label is made of a valid identifier followed by a colon (:). This instruction does not have a concrete utility in structured or object oriented programming aside from those that low-level programming fans may find for it. For example, here is our countdown loop using goto:
// goto loop example #include <iostream.h> int main () { int n=10; loop: cout << n << ", "; n--; if (n>0) goto loop; cout << "FIRE!"; return 0;

}
Output 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE

The exit function. exit is a function defined in cstdlib (stdlib.h) library. The purpose of exit is to terminate the running program with an specific exit code. Its prototype is:
void exit (int exit code);

The exit code is used by some operating systems and may be used by calling programs. By convention, an exit code of 0 means that the program finished normally and any other value means an error happened. The selective Structure: switch. The syntax of the switch instruction is a bit peculiar. Its objective is to check several possible constant values for an expression, something similar to what we did at the beginning of this section with the linking of several if and else if sentences. Its form is the following:

switch (expression) { case constant1: block of instructions 1 break; case constant2: block of instructions 2 break; . . . default: default block of instructions }

It works in the following way: switch evaluates expression and checks if it is equivalent to
constant1,

if it is, it executes block of instructions 1 until it finds the break keyword, then the will jump to the end of the switch selective structure.

program

If expression was not equal to constant1 it will check if expression is equivalent to constant2.

If it is, it will execute block of instructions 2 until it finds the break keyword. Finally, if the value of expression has not matched any of the previously specified constants (you may specify as many case sentences as values you want to check), the program will execute the instructions included in the default: section, if this one exists, since it is optional. Both of the following code fragments are equivalent:

switch example
switch (x) { case 1: cout << "x is 1"; break; case 2: cout << "x is 2"; break; default: cout << "value of x unknown";

} if-else equivalent
if (x == 1) { cout << "x is 1"; } else if (x == 2) { cout << "x is 2"; } else { cout << "value of x unknown";

} We have mentioned before that the syntax of the switch instruction is a bit peculiar. Notice the inclusion of the break instructions at the end of each block. This is necessary because if, for example, we did not include it after block of instructions 1 the program would not jump to the end of the switch selective block (}) and it would continue executing the rest of the blocks of instructions until the first appearance of the break instruction or the end of the switch selective block. This makes it

unnecessary to include curly brackets { } in each of the cases, and it can also be useful to execute the same block of instructions for different possible values for the expression evaluated. For example:
switch (x) { case 1: case 2: case 3: cout << "x is 1, 2 or 3"; break; default: cout << "x is not 1, 2 nor 3";

Notice that switch can only be used to compare an expression with different constants. Therefore we cannot put variables (case (n*2):) or ranges (case (1..3):) because they are not valid constants. If you need to check ranges or values that are not constants use a concatenation of if and else if sentences.

Summary C++ provides control structures that serve to specify what has to be done to perform our program. If & else is used to execute an instruction or block of instructions only if a condition is fulfilled The if + else structures can be concatenated with the intention of verifying a range of values Loops have as objective to repeat a statement a certain number of times or while a condition is fulfilled. The do-while loop is usually used when the condition that has to determine its end is determined within the loop statement, like in the previous case, where the user input within the block of instructions is what determines the end of the loop

Using break we can leave a loop even if the condition for its end is not fulfilled The continue instruction causes the program to skip the rest of the loop in the present iteration as if the end of the statement block would have been reached, causing it to jump to the following iteration

Switch objective is to check several possible constant values for an expression, something similar to what we did at the beginning of this section with the linking of several if and else if sentences

Questions 1.Discus various control structure available in C++ 2.Explain implementation of switch statement with syntax and example 1 22 333 444 5555 write a program to print following using for loop

UNIT I Lesson 6 REPRESENTATION OF ABSTRACT DATA TYPES & SCOPE OF ATTRIBUTES Objective Concept of abstraction Abstract Data type. Designing an Abstract type Choice of representation

Uptil now you have learned some basic concepts like operator set, control structure etc. now lets have a look to the advanced feature of object oriented programming. One of them is abstract data tpye. Here in this chapter I will explain its concept along with examples. The Concept of Abstraction The concept of abstraction is fundamental in programming Two kinds of abstraction: process abstraction and data abstraction Nearly all programming languages support process abstraction with subprograms Nearly all programming languages designed since 1980 have supported data abstraction with some kind of module Introduction to Data Abstraction Abstract data type: an encapsulation that includes only the data representation of one specific data type and the subprograms that provide the operations for that type. Built-in types are abstract data types Example: floating-point types Actual format of the data value is hidden (users cannot directly manipulate actual representation) The only operations available are those provided by the language (users cannot create new operations)

User-defined abstract data types must have the same characteristics as built-in abstract data types

An Example ADT for a stack Abstract operations Queue ADT /* create (allocate storage) and possible initialize */ /* dealloacte storage */ /* predicate */ /* remove top element */ /* returns a copy of top element */

create(stack) destroy(stack) empty(stack) pop(stack) top(stack)

push(stack, element) /* push element */

Implementation of stack can be changed (e.g., from array to linked list) without changing the client code.

Abstract Data Types in C++ Since it is based on object-oriented programming, it supports ADTs by classes.

ADTs allows the creation of instances with well-defined properties and behaviour. In objectorientation ADTs are referred to as classes. Therefore a class defines properties of objects which are the instances in an object-oriented environment. ADTs define functionality by putting main emphasis on the involved data, their structure, operations as well as axioms and preconditions. Consequently, object-oriented programming is ``programming with ADTs'': combining functionality of different ADTs to solve a problem. Therefore instances (objects) of ADTs (classes) are dynamically created, destroyed and used. Encapsulation

o o o o o

Data members and member functions Class instances (or objects) can be stack dynamic or heap dynamic Stack-dynamic instances are referenced directly with variables Heap-dynamic instances are referenced through pointers A stack-dynamic instance may have heap-dynamic data members

Information Hiding o o o o A class can have both hidden and visible entities Private for hidden entities Public for interface entities Protected for inheritance

Constructors: o o o o o o o Functions to initialize the data members of instances May also allocate storage if part of the object is heap-dynamic Can include parameters to provide parameterization of the objects Implicitly called when an instance is created Can be explicitly called Can be more than one constructor Name is the same as the class name

Destructors o o o o o Functions to cleanup after an instance is destroyed; usually just to reclaim heap storage Implicitly called when the objects lifetime ends Can be explicitly called Name is the class name, preceded by a tilde (~) All heap-dynamic objects must be explicitly deallocated by delete

C++ Example

#include <iostream.h> class stack { private: int *stackPtr; int maxLen; int topPtr; public: stack() { stackPtr = new int [100]; maxLen 99; topPtr = -1; } // stack ~stack() { delete [] stackPtr; } void push (int number) { if (topPtr == maxLen) cerr << error in push stack is full\n; else stackPtr[++topPtr] = number; } void pop() { if (topPtr = = -1) cerr << error in pop stack is empty\n; else topPtr--; } int top()

{ return (stackPtr[topPtr]); } int empty() { return (topPtr == -1); } } // stack void main() { int topOne; stack stk; stk.push(42); stk.push(17); topOne = stk.top(); stk.pop(); }

Designing an Abstract Type Designing an abstract type involves choosing good operations and determining how they should behave. A few rules of thumb o Its better to have a few, simple operations that can be combined in powerful ways than lots of complex operations. o o Each operation should have a well-defined purpose, and should have a coherent behavior rather than a panoply of special cases. The set of operations should be adequate; there must be enough to do the kinds of computations clients are likely to want to do. A good test is to check that every property of an object of the type can be extracted. For example, if there were no get operation, we would not

be able to find out what the elements of the list are. Basic information should not be inordinately difficult to obtain. The size method is not strictly necessary, because we could apply get on increasing indices, but this is inefficient and inconvenient. o The type may be generic: a list or a set, or a graph, for example. Or it may be domain-specific: a street map, an employee database, a phone book, etc. But it should not mix generic and domain-specific features. Choice of Representations So far, we have focused on the characterization of abstract types by their operations. In the code a class that implements an abstract type provides a representation: the actual data structure that supports the operations. The implementation of an ADT provides a representation of the type and implementations of the functions. It is written in the programming language that you are using, such as C/C++. Linked lists are a common representation of lists, for example. The following object model shows a linked list implementation similar (but not identical to) the Linked List class in the standard library.

List header Entry Object element The list object has a field header that references an Entry object. An Entry object is arecord with three fields: next and prev which may hold references to other Entry objects(or be null), and element, which holds a reference to an element object. The next and prevfields are links that point forwards and backwards along the list. In the middle of the list,following next and then prev will bring you back to the object you started with. Lets assume that the linked list does not store null references as elements. There is always a dummy Entry at the beginning of the list whose element field is null, but this is not interpreted as an element.

next

prev

Summary The implementation of an ADT provides a representation of the type and implementations of the functions. It is written in the programming language that you are using, such as C/C++. ADTs allows the creation of instances with well-defined properties and behaviour In object-orientation ADTs are referred to as classes. Therefore a class defines properties of objects which are the instances in an object-oriented environment. Questions 1. State the concept of abstract data type along with its types

Lesson 7 GROUP DISCUSSION ON Basic concept of OOPS Classe s and objects Features of C++

UNIT I LESSON 8 CONSTRUCTOR Objectives Concept of constructor Parameterized constructor Multiple constructors in a class

We will now discuss about special member functions of a class called Constructors

Constructors Each time when you write a program you create a function, which is responsible for initializing the variable, and before the end of the program you call a function to destroy the allocated variables. To automate this feature C++ provides a concept of constructors and destructors. C++ provides a constructor is a 'special' member function whose task is to initialize the objects of its class. It is special because its name is the same as the class name. The constructor is invoked whenever an object of its associated class is created. It is called constructor because it constructs the values of data members of the class. A constructor is declared and defined as follows: / / class with a constructor class integer { int m, n; public: integer(void); . . / / constructor declared

}; integer:: integer(void) { m = 0; n = 0; } / / constructor defined

When a class contains a constructor like the one defined above, it is guaranteed that an object created by the class will be initialized automatically. For example, the declaration integer int1 ; / / object int1 created

not only creates the object int1 of type integer but also initializes its data members m and n to zero. There is no need to write an Y, statement to invoke the constructor function (as we do with the normal member functions): If a 'normal' member function is defined for zero initialization, we would need to invoke this function for each of the objects separately. This would be very inconvenient, if there are a large number of objects. A constructor that accepts no parameters is called the default constructor. The default constructor for class A is A::AO. If no such constructor is defined, then the compiler supplies a default constructor. Therefore a statement such as A a; invokes the default constructor of the compiler to create the object a. Special characteristics of constructor functions : They should be declared in the public section. They are invoked automatically when the objects are created. They do not have return types, not even void and therefore, and they cannot return values.

They cannot be inherited, though a derived class can call the base class constructor. . Like other C++ functions, they can have default arguments. Constructors cannot be virtual. (Meaning of virtual will be discussed later in Chapter 9.) We cannot refer to their addresses. An object with a constructor (or destructor) cannot be used as a member of a union. . They make 'implicit calls' to the operators new and delete when memory allocation is required.

Remember, when a constructor is declared for a class, initialization of the class objects becomes mandatory. Parameterized Constructors Constructor integer(), which we defined above, initializes the data members of all the objects to zero. However, in practice it may be necessary to initialize the various data elements of different objects with different values when they are created. C++ permits us to achieve this objective by passing arguments to the constructor function when the objects are created. The constructors that can take arguments are called parameterized constructors. Constructor integer() may be modified to take arguments as shown below: class integer { int m, n; public: integer(int x, int y); }; integer :: integer(int x, int y) { m = x; n = y ; } When a constructor has been parameterized, the object declaration statement such as integer intl ; / / parameterized constructor

may not work. We must pass the initial values as arguments to the constructor function when an object is declared. This can be done in two ways: By calling the constructor explicitly. By calling the constructor implicitly.

The following declaration illustrates the first method: integer intl = integer(0,l00); / / explicit call

This statement creates an integer object int1 and passes the values 0 and 100 to it. The second is implemented as follows: integer intl(0,l00); / / implicit call

This method, sometimes called the shorthand method, is used very often as it is shorter, looks better and is easy to implement. Remember, when the constructor is parameterized, we must provide appropriate arguments for the constructor. Program demonstrates the passing of arguments to the constructor functions. Ex. Of parameterized constructor # include<iostream> using namespace std; class integer { int m, n; public: integer(int, int); void display(void) { cout m= m<<"\n"; // constructor declared

cout n=" n \n"; } }; integer :: integer(int x. int y) { m = x; n= y; } int main() { integer int1(O.l00); // constructor called implicitly // constructor defined

integer int2 = integer(25,75); // constructor called explicitly cout \nOBJECTl " "\n"; int1.dtsplay(); cout "\nOBJECT2" '"\n"; int2.display(); return 0; } Program output: OBJECT l m =0 n = 100

OBJ ECT2 m = 25 n = 75 The constructor functions can also be defined as inline functions. Example: class integer { int m, n; public: integer(int x, int y) { m = x; Y = n; } . . }; The parameters of a constructor can be of any type except that of the class to which it belongs. For example, class A public: A(A); }; is illegal. However, a constructor can accept a reference to its own class as a parameter. Thus, the statement Class A { public: A(A&); }; is valid. In such cases, the constructor is called the copy constructor. // Inline constructor

MULTIPLE CONSTRUCTORS IN A CLASS So far we have used two kinds of constructors. They are: integer () ; // No arguments

jnteger(int, int); // Two arguments In tbe first case, the constructor itself supplies the data values and no values are passed by the calling program. In the second case, the function call passes the appropriate values fromMain(). C++ permits us to use both these constructors in the same class. For example, wecould define a class as follows: class integer { int m, n; public : integer() { m=0; n=0; } integer(int a, int b) // constructor 2 { m=a;n=b; } integer (integer & i) // constructor 3 { m = i.m; n = i.n; } This declares three constructors for an integer object. The first constructor receives no Inguments, the second receives two integer arguments and the third receives one integer ~Ject as an argument. // constructor 1

For example, the declaration integer I1; would automatically invoke the first constructor and set both m and n of I1 to zero. The statement integer I2(20,40); would call the second constructor which will initialize the data members m and n of I2 to 20 and 40 respectively. Finally, the statement integer I3(12); would invoke the third constructor which copies the values of I2 into I3. In other words, it sets the value of every data element of I3 to the value of the corresponding data element of I2. As mentioned earlier, such a constructor is called the copy constructor. We learned in Chapter 4 that the process of sharing the same name by two or more functions is referred to as function overloading. Similarly, when more than one constructor function is defined in aclass, we say that the constructor is overloaded. I #include<iostream> using namespace std; class complex { float x ,y; public : complex() // constructor no arg { } complex(float a) // constructor one argument

{ x = y = a; } complex( float real, float imag) // constructor two arg { x = real; y = imag; } friend complex sum(complex ,complex); friend void show(complex); }; complex sum(complex c1,complex c2) // friend { complex c3; c3.x=c1.x+c2.x; c3.y=c1.y+c2.y; return(c3); } void show(complex c) // friend { cout <<c.x<<+j<<c.y<<\n; } int main() { complex A(2.7,3.5); //define & initialize complex B(1.6); //define and initialize complex C; //define C=sum(A,B);

Cout << A=; show(A); //sum() is a friend Cout << B=; show(B); //sum() is a friend cout << C=; show(C); //sum() is a friend

//another way to give initial values (second method) complex P,Q,R; // define P, Q ,R

p= complex(2.5,3.9); // initialize P Q= complex(1.6,2.5); // initialize Q R= sum(P,Q); Cout <<\n; Cout <<P = ; show(P); Cout <<Q = ; show(Q); Cout <<R = ; show(R); Return 0; } output will be A=2.7+J3.5 B=1.6+J1.6 C=4.3+J5.1 P=2.5+J3.9 Q=1.6+J2.5 R=4.1+J6.4

There are three constructors in the class complex. The first constructor, which takes no arguments, is used to create objects which are not initialized; the second, which takes one argument, is used to create objects and initialize them; and the third, which takes two arguments, is also used to create objects and initialize them to specific values. Note that the second method

Summary C++ provides a constructor is a 'special' member function whose task is to initialize the objects of its class. It is special because its name is the same as the class name. The constructor is invoked whenever an object of its associated class is created. It is call constructor because it constructs the values of data members of the class. A constructor that accepts no parameters is called the default constructor for class A is A::AO. constructor. The default

Questions 1 . Deifne constructor concept along with example 2 What is parameterised constructor ? explain with example.

UNIT I Lesson 9 CONSTRUCTOR II Objectives Constructor with default arguments Copy constructor Destructor

CONSTRUCTORS WITH DEFAULT ARGUMENTS It is possible to define constructors with default arguments. For example, the constructor complexO can be declared as follows: complex(float real, float imag=0); The default value of the argument imag is zero. Then, the statement complex C(5.0); I assigns the value 5.0 to the real variable and 0.0 to imag (by default). However, the statement complex C(2.0,3.0); assigns 2.0 to real and 3.0 to imag. The actual parameter, when specified, Overrides the default value. As pointed out earlier, the missing arguments must be the trailing ones. . COPY CONSTRUCTOR A copy constructor is used to declare and initialize an object from another object. For example, the statement integer 12(11);

would define the object 12 and at the same time initialize it to the values of Il. Another form of this statement is integer I2 = 11; The process of initializing through a copy constructor is known as copy initialization. Remember, the statement I2 = 11; will not invoke the copy constructor. However, if Il and I2 are objects, this statement is legal and simply assigns the values of I1 to I2, member-by-member. This is the task of the overloaded assignment operator(=). We shall see more about this later. A copy constructor takes a reference to an object of the same class as itself as an argument. Let us consider a simple example of constructing and using a copy constructor # include<iostream> using namespace std; class code { int id; public: code() // constructor { } code(int a) // constructor { id = a; } code( code & x) // copy constructor { id=x.id; // copy in the value }

void display (void) { cout <<id; } }; int main() { code A(100); // object A is created and initialized code B(A); // copy constructor called code C=A; // copy constructor called again code D; // D is created not initialized D=A; // copy constructor not called Cout <<\n id of A:; A.display(); Cout <<\n id of B:; B.display(); Cout <<\n id of C:; C.display(); Cout <<\n id of D:; D.display(); Return 0; }

DESTRUCTORS A destructor, as the name implies, is used to destroy the objects that have been created by a constructor. Like a constructor, the destructor is a member function whose name is the same as the class name but is preceded by a tilde. For example, the destructor for the class integer can be defined as shown below: ~integer( ) { } A destructor never takes any argument nor does it return any value. It will be invoked implicitly by the compiler upon exit from the program (or block or function as the case may be) to clean up storage that is no longer accessible. It is a good practice to declare destructors in a program since it releases memory space for future use. Whenever new is used to allocate memory in the constructors, we should use delete to free that memory. For example, the destructor for the matrix class discussed above may be defined as follows: matrix :: ~matrix() { for (int I=0;I<d1;I++) delete p[I]; delete p; } This is required because when the pointers to objects go out of scope, a destructor is not called implicitly. The example below illustrates that the destructor has been invoked implicitly by the compiler. Implementation of destructor

#include <iostream> using namespace std; int count = 0; class alpha { public: { \ cout++; cout "\nNo.of object created" count . -alpha() { cout "\nNo,of object destroyed" count; cout--; } }; int main() { alpha A1, A2, A3, A4; { cout "\n\nENTERBLOCK1\n". alpha A5; } { cout "\n\nENTER BLOCK2\n"; alpha A6; } cout "\n\nRE-ENTER MAIN\n"; return 0; } output of the program is

ENTER MA I N No.of object created 1 No.of object created 2 No.of object created 3 No.of object created 4 ENTER BLOCKl No.of object created 5 No.of object destroyed 5 ENTER BLOCK2 No.of object created 5 No.of object destroyed 5 RE-ENTER MAIN No.of object destroyed 4 No.of object destroyed 3 No of object destroyed 2 No.of object destroyed 1 As the objects are created and destroyed. they increase and decrease the count. Notice that after the first group of objects is created, A5 is created, and then destroyed, A6 is created, and then destroyed. Finally, the rest of the objects are also destroyed. When the closing brace of a scope is encountered, the destructors for each object in the scope are called. Note that the objects are destroyed in the reverse order of creation.

Summary It is possible to define constructors with default arguments. For example, the constructor complexO can be declared as follows: complex(float real, float imag=0); A copy constructor is used to declare and initialize an object from another object. A destructor, as the name implies, is used to destroy the objects that have been created by a constructor.

Questions what is Destructor? Why it is necessary to define destructor in a program explain copy constructor with suitable example?

UNIT I Lesson 10

OVERLOADING
Objective

Constructor Overloading Operator Overloading Overloading Unary Operators Overloading Binary Operators

By now you all must have got a fair idea of how a function and its subsequent components viz., arguments/parameters play an important part when used in a C++ program. We also discussed about function returning value by referring directly to the variable called as By Val and returning value by referring through the address of the variable called as By Ref. The topic, which we are covering, now, is an important and unique feature of object-oriented programming. Lets explore it now. OVERLOADED CONSTRUCTORS IN A CLASS when more than one constructor function is defined in a class, we say that the constructor is overloaded. Overloaded constructor are also known as multiple constructor in a class we have used two kinds of constructors. They are: integer () ; // No arguments

jnteger(int, int); // Two arguments In the first case, the constructor itself supplies the data values and no values are passed by The calling program. In the second case, the function call passes the appropriate values from Main(). C++ permits us to use both these constructors in the same class. For example, we could define a class as follows: class integer

{ int m, n; public : integer() { m=0; n=0; } integer(int a, int b) // constructor 2 { m=a;n=b; } integer (integer & i) // constructor 3 { m = i.m; n = i.n; } This declares three constructors for an integer object. The first constructor receives no arguments, the second receives two integer arguments and the third receives one integer object as an argument. For example, the declaration integer I1; would automatically invoke the first constructor and set both m and n of I1 to zero. The statement integer I2(20,40); would call the second constructor which will initialize the data members m and n of I2 to 20 and 40 respectively. Finally, the statement integer I3(12); would invoke the third constructor which copies the values of I2 into I3. In other words, it sets the value of every data element of I3 to the value of the corresponding data element of I2. As mentioned earlier, such a constructor is called the copy constructor. We learned that that the process of sharing // constructor 1

the same name by two or more functions is referred to as function overloading. Similarly, when more than one constructor function is defined in a class, we say that the constructor is overloaded. #include<iostream> class complex { float x ,y; public : complex() { } complex(float a) { x = y = a; } complex( float real, float imag) { x=real; y=imag; } friend complex sum(complex ,complex); friend void show(complex); }; complex sum(complex c1,complex c2) // friend { complex c3; c3.x=c1.x+c2.x; c3.y=c1.y+c2.y; return(c3); // constructor two arg // constructor one argument // constructor no arg

} void show(complex c) // friend { cout <<c.x<<+j<<c.y<<\n; } int main() { complex A(2.7,3.5); //define & initialize complex B(1.6); //define and initialize complex C; //define C=sum(A,B); Cout << A=; show(A); Cout << B=; show(B); cout << C=; show(C); //sum() is a friend //sum() is a friend //sum() is a friend

//another way to give initial values (second method) complex P,Q,R; p= complex(2.5,3.9); Q= complex(1.6,2.5); R= sum(P,Q); Cout <<\n; Cout <<P = ; show(P); Cout <<Q = ; show(Q); Cout <<R = ; show(R); Return 0; // define P, Q ,R // initialize P // initialize Q

} output will be A=2.7+J3.5 B=1.6+J1.6 C=4.3+J5.1 P=2.5+J3.9 Q=1.6+J2.5 R=4.1+J6.4 There are three constructors in the class complex. The first constructor, which takes no arguments, is used to create objects which are not initialized; the second, which takes one argument, is used to create objects and initialize them; and the third, which takes two arguments, is also used to create objects and initialize them to specific values. Operator Overloading Operator overloading is one of the many exciting features of C++ language. It is an importanttechnique that has enhanced the power of extensibility of C++. We have stated more once that C++ tries to make the user-defined data types behave in much the same way as built-in types. For instance, C++ permits us to add two variables of user-defined types! the same syntax that is applied to the basic types. This means that C++ has the ability to provide the operators with a special meaning for a data type. The mechanism of giving such special Meanings to an operator is known as operator overloading. Operator overloading provides a flexible option for the creation of new definitions for of the C++ operators. We can almost create a new language of our own by the creative use the function and operator overloading techniques. We can overload (give additional meaning to) all the C++ operators except the following: Class member access operators (., . *). Scope resolution operator (::).

Size operator (sizeof). Conditional operator (?:).

The excluded operators are very few when compared to the large number of operators, which qualify for the operator overloading definition. Although the semantics of an operator can be extended, we cannot change its syntax, the grammatical rules that govern its use such as the number of operands, precedence and associativity. For example, the multiplication operator will enjoy higher precedence than the addition operator. Remember, when an operator is overloaded, its original meaning is not lost. For instance, the operator +, which has been overloaded to add two vectors, can still be used to aid two integers. DEFINING OPERATOR OVERLOADING To define additional task to an operator, we must specify what it means in relation to the class to which the operator is applied. This is done with the help of a special function, called Operator function, which describes the task. The general form of an operator function is: return type classname :: operator (op-arg1ist) { Function body } where return type is the type of value returned by the specified operation and op is the operator being overloaded. The op is preceded by the keyword operator. operator op is the function name. Operator functions must be either member functions (non-static) or friend functions. A basic difference between them is that a friend function will have only one argument for unary operators and two for binary operators, while a member function has no arguments for unary operators and only one for binary operators. This is because the object used to invoke the member function is passed implicitly and therefore is available for the member function. This is not the case with friend functions. II task defined

Arguments may be passed either by value or by reference. Operator functions are declared in the class using prototypes as follows: vector operator+(vector); vector operator-(); friend vector operator+(vector, vector) ; friend vector operator-(vector); vector operator-(vector &a); int operator= =(vector); friend int operator.== (vector , vector) I I vector addition I I unary minus I I vector addition I I unary minus I I subtraction II comparison I I comparison

vector is a data type of class and may represent both magnitude and direction (as in ph' and engineering) or a series of points called elements (as in mathematics). The process of overloading involves the following steps: a. Create a class that defines the data type that is to be used in the overloading operation b. Declare the operator function operator op() in the public part of the class. It may be either a member function or a friend function. c. Define the operator function to implement the required operations Overloaded operator functions can be invoked by expressions such as op x or x op for unary operators and x op Y for binary operators. op x (or x op) would be interpreted as operator op (x) for friend functions. Similarly, the expression x op y would be interpreted as either

x.operator op (y) in case of member , or operator op (x, y) in case of friend functions. When both the forms are declared, standard argument matching is applied to resolve any ambiguity. OVERLOADING UNARY OPERATORS Let us consider the unary minus operator. A minus operator when used as a unary, takes just one operand. We know that this operator changes the sign of an operand when applied to a basic data item. We will see here how to overload this operator so that it can be applied to an object in much the same way as is applied to an int or float variable. The unary minus when applied to an object should change the sign of each of its data items. Program shows how the unary minus operator is overloaded. OVERLOADING UNIARY MINUS # incl,ude <iostream> using namespace std; class space { int x; int y; int z; public: void getdata(int a, int b, int c); void display(void);

void operator -(); }; void space::getdata(int a, int b, int c) { x = a; y = b; z = c; } void space :: display(void) { cout<< x<< ; cout<< y << ; cout<<z <<\n ; } void space::operator-() { x = -x; y = -y; z = -z; } int main() { space S; S.getdata(10, -20, 30); Cout<< S : ; S.display(); -S; cout<< S :; S.display(); return 0; }

//overload unary minus

//activates operator-() function

The Program produces the following output: S : 10 -20 30 S : -10 20 30 Remember: The function operator- ( ) takes no argument. Then, what does this operator function do? It changes the sign of data members of the object S. Since this function is a member function of the same class, it can directly access the members of the object which activated it. Remember, a statement like S2 = -S1; will not work because, the function operator-() does not return any value. It can work if the function is modified to return an object. It is possible to overload a unary minus operator using a friend function as follows: friend void operator-(space &s); void operator- (space &s) { s . x = -s. x ; s . y = -s. y ; s . z = -s. z; } Note that the argument is passed by reference. It Will not work if we pass argument by value because only a copy of the object that activated the call is passed to operator-(). Therefore, the changes made inside the operator function will not reflect in the called object. OVERLOADING BINARY OPERATORS //dec1a ration // definition

We have just seen how to overload a unary operator. The same mechanism can be used to overload a binary operator. Here, we illustrated, how to add two complex numbers using a friend function. A statement like C = sum(A, B); // functional notation.

was used. The functional notation can be replaced by a natural looking expression C = A + B; // arithmetic notation

by overloading the + operator using an operator+()function. The Program illustrates how this is accomplished. Overloading + operator include <iostream> using namespace std; class complex { float x; float y; publ ic: complex() { } complex operator+(complex); void display(void); } complex complex:: operator+(complex c) { complex temp; temp. x = x + c.x; temp.y = y + c.y; return (temp); //temporary //these are //float additions / / constructor 1 complex(float real ,float imag) { x = real; y =imag; } / / constructor 2 / / real part 1/ imaginary part

} void complex :: display(void) { cout << x <<"+ j << y <<"\n "; } int main() { complex Cl, C2, C3; Cl = complex(2.5, 3.5); C2 =complex(1.6, 2.7); C3 = Cl + C2; cout << "Cl = "; Cl.display(); cout << "C2 = "; C2.display(); cout << "C3 = ; C3.display(); return 0; } The output of Program would be: C1 = 2.5 + j3.5 C2 = 1. 6 + j 2.7 C3 = 4.1 + j 6.2 Let us have a close look at the function operator+( ) and see how the operator overloading is implemented. complex complex :: operator+(complex c) { complex temp; temp.x = x + c.x; temp.y = y + c.y; return(temp); // invokes constructor 1 // invokes constructor 2

} We should note the following features of this function: 1. It receives only one complex type argument explicitly. 2. It returns a complex type value. 3. It is a member function of complex. The function is expected to add two complex values and return a complex value as I result but receives only one value as argument. Where does the other value come from?. Now let us look at the statement that invokes this function: C3 = C1 + C2; / / invokes operator+() function

We know that a member function can be invoked only by an object of the same class. Here the object Cl takes the responsibility of invoking the function and C2 plays the role of: argument that is passed to the function. The above invocation statement is equivalent to C3 = C1.operator+(C2); / / usual function call syntax

Therefore, in the operator+() function, the data members of Cl are accessed directly the data members of C2 (that is passed as an argument) are accessed using the dot operator Thus, both the objects are available for the function. For example, in the statement temp.x = x + c.x; c.x refers to the object C2 and x refers to the object Cl.temp.x is the real part of temp has been created specially to hold the results of addition of C land C2. The function return the complex temp to be assigned to C3. As a rule, in overloading of binary operators, the left-hand operand is used to invoke operator function and the right- hand operand is passed as an argument.

Summary

when more than one constructor function is defined in a class, we say that the constructor is overloaded. The process of overloading involves the following steps: a. b. c. Create a class that defines the data type that is to be used in the overloading operation Declare the operator function operator op() in the public part of the class. It may be either a member function or a friend function. Define the operator function to implement the required operations

Questions

Explain concept of Constructor Overloading Explain concept of Operator Overloading Explain concept of Unary and Binary Operator Overloading

UNIT I LESSON 11 OVERLOADING II Objective Concept of function overloading

In the previous lecture of ovrloading we have got concept of constructor and operator oveloading. Here in this second part we will discuss most powerful application of OOP viz. Function Oveloading, by which we can do variety of tasks . Lets go through it. FUNCTION OVERLOADING Overloading refers to the use of the same thing for different purposes. C++ also permits overloading of functions. This means that we can use the same function name to create functions that perform a variety of different tasks. This is known as function polymorphism in OOP. The ability to have various functions with the same name in the same program is called function overloading. The most important rule about function overloading is to make sure that each one of these functions has a different number or different type(s) of arguments. Using the concept of function overloading; we can design a family of functions with one function name but with different argument lists. The function would perform different, operations depending on the argument list in the function call. The correct function to invoked is determined by checking the number and type of the arguments but not on the function type. For example, an overloaded add() function handles different types of data shown below: / / Declarations int add(int a, int b); int add(int a, intb, int c); double add (double x, double y); double add(int p, double q); double add(double p, int q); / / Function calls cout add(5, 10); cout add(15, 10.0); / / uses prototype 1 / / uses prototype 2 / / prototype 1 / / prototype 2 / / prototype 3 / / prototype 4 / / prototype 5

cout add(12.5, 7.5); cout add(5, 10. 15); cout add(0.75, 5);

/ / uses prototype 3 / / uses prototype 4 / / uses prototype 5

A function call first matches the prototype having the same number and type of argument and then calls the appropriate function for execution. A best match must be unique. The function Selection involves following steps 1. 2. The complier first tries to find an exact match in which the types of actual argument are the same, and use that function. If an exact match is not found, the compiler uses the integral promotions to the actual argument, such as, char to int Float t to double d. When either of them fails, the compiler tries to use the built-in conversions(the implicit assignment. conversion) to the actual arguments and then uses function whose match is unique. If the conversion is possible to have multimatches, then the compiler will generate an error message. e. Suppose we use following two functions: long square(long n) double square (double x) A function call such as square(10) will cause an error because int argument can be converted to either long or double, thereby creating an ambiguous situation as to which version of square() should be used.

4.

If all of the steps fail, then the compiler will try the user-defined conversions in combination with integral promotions and built-in conversions to find a unique match. User-defined conversions are often used in handling class objects.

Program illustrates function overloading. // Function volume() is overloaded three times #include <iostream> using namespace std; // Declaration (prototypes) int volume(int); double volume( double, int) ; long volume (long, int , int); int main() ( cout volume(10) "\n"; cout volume(2.5,8) "\n"; cout volume(100L,75,15) "\n"; return 0; } / / Function definitions int volume(int s) // cube ( return(s*s*s); } I

double volume(double r. int h) { return (3 .14519,*r*r*h) ; }

//cylinder

1ong volume (long l, int b, int h) //rectangular box { return (l*b*h); } The output of program: 1000 157.26 112500 Overloading of function should be done with caution. We should not overload unrelated functions and should reserve function overloading for function that performs closely related tasks. Sometime, the default arguments may be used instead of overloading. This may reduce the number of functions to be defined.

Summary The ability to have various functions with the same name in the same program is called function overloading. The most important rule about function overloading is to make sure that each one of these functions has a different number or different type(s) of arguments. Overloading of function should be done with caution. We should not overload unrelated functions and should reserve function overloading for function that performs closely related tasks. Questions

Explain the concept of Function Overloading with example

UNIT I LESSON 12 ARRAYS Objectives. Concept of Arrays Multidimensional Arrays Strings of Characters

Arrays are a series of elements (variables) of the same type placed consecutively in memory that can be individually referenced by adding an index to a unique name. For example, an array to contain 5 integer values of type int called billy could be represented this way:

where each blank panel represents an element of the array, that in this case are integer values of type
int.

These are numbered from 0 to 4 since in arrays the first index is always 0, independently of its

length . Like any other variable, an array must be declared before it is used. A typical declaration for an array in C++ is:
type name [elements];

where type is a valid object type (int, float...), name is a valid variable identifier and the elements field, that is enclosed within brackets [], specifies how many of these elements the array contains. Therefore, to declare billy as shown above it is as simple as the following sentence:
int billy [5];

NOTE: The elements field within brackets [] when declaring an array must be a constant value, since arrays are blocks of static memory of a given size and the compiler must be able to determine exactly how much memory it must assign to the array before any instruction is considered.

Initializing arrays. When declaring an array of local scope (within a function), if we do not specify otherwise, it will not be initialized, so its content is undetermined until we store some values in it. If we declare a global array (outside any function) its content will be initialized with all its elements filled with zeros. Thus, if in the global scope we declare:
int billy [5];

every element of billy will be set initialy to 0:

But additionally, when we declare an Array, we have the possibility to assign initial values to each one of its elements using curly brackets { }. For example:
int billy [5] = { 16, 2, 77, 40, 12071 };

this declaration would have created an array like the following one:

The number of elements in the array that we initialized within curly brackets { } must match the length in elements that we declared for the array enclosed within square brackets [ ]. For example, in the example of the billy array we have declared that it had 5 elements and in the list of initial values within curly brackets { } we have set 5 different values, one for each element. Because this can be considered useless repetition, C++ includes the possibility of leaving the brackets empty [ ] and the size of the Array will be defined by the number of values included between curly brackets { }:
int billy [] = { 16, 2, 77, 40, 12071 };

Access to the values of an Array. In any point of the program in which the array is visible we can access individually anyone of its values for reading or modifying as if it was a normal variable. The format is the following:
name[index]

Following the previous examples in which billy had 5 elements and each of those elements was of type
int, the name which we can use to refer

to each element is the following:

For example, to store the value 75 in the third element of billy a suitable sentence would be:
billy[2] = 75;

and, for example, to pass the value of the third element of billy to the variable a, we could write:
a = billy[2];

Therefore, for all purposes, the expression billy[2] is like any other variable of type int.

Notice that the third element of billy is specified billy[2], since first is billy[0], the second is
billy[1],

and therefore, third is billy[2]. By this same reason, its last element is billy[4]. Since

if we wrote billy[5], we would be acceding to the sixth element of billy and therefore exceeding the size of the array. In C++ it is perfectly valid to exceed the valid range of indices for an Array, which can create problems since they do not cause compilation errors but they can cause unexpected results or serious errors during execution. The reason why this is allowed will be seen farther ahead when we begin to use pointers. At this point it is important to be able to clearly distinguish between the two uses that brackets [ ] have related to arrays. They perform two differt tasks: one is to set the size of arrays when declaring them; and second is to specify indices for a concrete array element when referring to it. We must simply take care not to confuse these two possible uses of brackets [ ] with arrays:

int billy[5]; type name) billy[2] = 75;

// declaration of a new Array (begins with a // access to an element of the Array.

Other valid operations with arrays:


billy[0] = a; billy[a] = 75; b = billy [a+2]; billy[billy[a]] = billy[2] + 5;

// arrays example #include <iostream.h> int billy [] = {16, 2, 77, 40, 12071}; int n, result=0; int main () { for ( n=0 ; n<5 ; n++ ) { result += billy[n]; } cout << result; return 0;

output 12206

Multidimensional Arrays Multidimensional arrays can be described as arrays of arrays. For example, a bidimensional array can be imagined as a bidimensional table of a uniform concrete data type.

jimmy

represents a bidimensional array of 3 per 5 values of type int. The way to declare this array

would be:
int jimmy [3][5];

and, for example, the way to reference the second element vertically and fourth horizontally in an expression would be:

jimmy[1][3]

(remember that array indices always begin by 0). Multidimensional arrays are not limited to two indices (two dimensions). They can contain as many indices as needed, although it is rare to have to represent more than 3 dimensions. Just consider the amount of memory that an array with many indices may need. For example:
char century [100][365][24][60][60];

assigns a char for each second contained in a century, that is more than 3 billion chars! This would consume about 3000 megabytes of RAM memory if we could declare it. Multidimensional arrays are nothing more than an abstraction, since we can obtain the same results with a simple array just by putting a factor between its indices:
int jimmy [3][5]; int jimmy [15];

is equivalent to

(3 * 5 = 15)

with the only difference that the compiler remembers for us the depth of each imaginary dimension. Serve as example these two pieces of code, with exactly the same result, one using bidimensional arrays and the other using only simple arrays:

// multidimensional array #include <iostream.h> #define WIDTH 5 #define HEIGHT 3 int jimmy [HEIGHT][WIDTH]; int n,m; int main () { for (n=0;n<HEIGHT;n++) for (m=0;m<WIDTH;m++) { jimmy[n][m]=(n+1)*(m+1); } return 0;

} program above do not produce any output on the screen, but both assign values to the memory block called jimmy in the following way:

We have used defined constants (#define) to simplify possible future modifications of the program, for example, in case that we decided to enlarge the array to a height of 4 instead of 3 it could be done by changing the line:
#define HEIGHT 3

to
#define HEIGHT 4

with no need to make any other modifications to the program.

Arrays as parameters At some moment we may need to pass an array to a function as a parameter. In C++ is not possible to pass by value a complete block of memory as a parameter to a function, even if it is ordered as an array, but it is allowed to pass its address. This has almost the same practical effect and it is a much faster and more efficient operation. In order to admit arrays as parameters the only thing that we must do when declaring the function is to specify in the argument the base type for the array, an identifier and a pair of void brackets []. For example, the following function:
void procedure (int arg[])

admits a parameter of type "Array of int" called arg. In order to pass to this function an array declared as:
int myarray [40];

it would be enough to write a call like this:


procedure (myarray);

Here you have a complete example:

// arrays as parameters #include <iostream.h> void printarray (int arg[], int length) { for (int n=0; n<length; n++) cout << arg[n] << " "; cout << "\n"; } int main () { int firstarray[] = {5, 10, 15};

int secondarray[] = {2, 4, 6, 8, 10}; printarray (firstarray,3); printarray (secondarray,5); return 0;

} output
5 10 15 2 4 6 8 10

As you can see, the first argument (int arg[]) admits any array of type int, whatever its length is. For that reason we have included a second parameter that tells the function the length of each array that we pass to it as the first parameter. This allows the for loop that prints out the array to know the range to check in the passed array. In a function declaration is also possible to include multidimensional arrays. The format for a tridimensional array is:
base_type[][depth][depth]

for example, a function with a multidimensional array as argument could be:


void procedure (int myarray[][3][4])

notice that the first brackets [] are void and the following ones are not. This must always be thus because the compiler must be able to determine within the function which is the depth of each additional dimension. Arrays, both simple or multidimensional, passed as function parameters are a quite common source of errors for less experienced programmers. Strings of Characters In all programs seen until now, we have used only numerical variables, used to express numbers exclusively. But in addition to numerical variables there also exist strings of characters, that allow us to represent successions of characters, like words, sentences, names, texts, et cetera. Until now we have only used them as constants, but we have never considered variables able to contain them.

In C++ there is no specific elemental variable type to store strings of characters. In order to fulfill this feature we can use arrays of type char, which are successions of char elements. Remember that this data type (char) is the one used to store a single character, for that reason arrays of them are generally used to make strings of single characters. For example, the following array (or string of characters):
char jenny [20];

can store a string up to 20 characters long. You may imagine it thus:

This maximum size of 20 characters is not required to always be fully used. For example, jenny could store at some moment in a program either the string of characters "Hello" or the string "Merry
christmas".

Therefore, since the array of characters can store shorter strings than its total length, a

convention has been reached to end the valid content of a string with a null character, whose constant can be written 0 or '\0'. We could represent jenny (an array of 20 elements of type char) storing the strings of characters
"Hello"

and "Merry Christmas" in the following way:

Notice how after the valid content a null character ('\0') it is included in order to indicate the end of the string. The panels in gray color represent indeterminate values. Initialization of strings Because strings of characters are ordinary arrays they fulfill all their same rules. For example, if we want to initialize a string of characters with predetermined values we can do it just like any other array:
char mystring[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

In this case we would have declared a string of characters (array) of 6 elements of type char initialized with the characters that compose Hello plus a null character '\0'. Nevertheless, strings of characters have an additional way to initialize their values: using constant strings.

In the expressions we have used in examples in previous chapters constants that represented entire strings of characters have already appeared several times. These are specified enclosed between double quotes ("), for example:
"the result is: "

is a constant string that we have probably used on some occasion. Unlike single quotes (') which specify single character constants, double quotes (") are constants that specify a succession of characters. Strings enclosed between double quotes always have a null character ('\0') automatically appended at the end. Therefore we could initialize the string mystring with values by either of these two ways:
char mystring [] = { 'H', 'e', 'l', 'l', 'o', '\0' }; char mystring [] = "Hello";

In both cases the array or string of characters mystring is declared with a size of 6 characters (elements of type char): the 5 characters that compose Hello plus a final null character ('\0') which specifies the end of the string and that, in the second case, when using double quotes (") it is automatically appended. Before going further, notice that the assignation of multiple constants like double-quoted constants ( ") to arrays are only valid when initializing the array, that is, at the moment when declared. Expressions within the code like:
mystring = "Hello"; mystring[] = "Hello";

are not valid for arrays, like neither would be:


mystring = { 'H', 'e', 'l', 'l', 'o', '\0' };

So remember: We can "assign" a multiple constant to an Array only at the moment of initializing it. The reason will be more comprehensible when you know a bit more about pointers, since then it will be clarified that an array is simply a constant pointer pointing to an allocated block of memory. And because of this constantnes, the array itself can not be assigned any value, but we can assing values to each of the elements of the array. The moment of initializing an Array it is a special case, since it is not an assignation, although the same equal sign (=) is used. Anyway, always have the rule previously underlined present.

Assigning values to strings Since the lvalue of an assignation can only be an element of an array and not the entire array, it would be valid to assign a string of characters to an array of char using a method like this:
mystring[0] = 'H'; mystring[1] = 'e'; mystring[2] = 'l'; mystring[3] = 'l'; mystring[4] = 'o'; mystring[5] = '\0';

But as you may think, this does not seem to be a very practical method. Generally for assigning values to an array, and more specifically to a string of characters, a series of functions like strcpy are used. strcpy (string copy) is defined in the cstring (string.h) library and can be called the following way:
strcpy (string1, string2);

This does copy the content of string2 into string1. string2 can be either an array, a pointer, or a constant string, so the following line would be a valid way to assign the constant string "Hello" to
mystring: strcpy (mystring, "Hello");

For example:
// setting value to string #include <iostream.h> #include <string.h> int main () { char szMyName [20]; strcpy (szMyName,"J. Soulie"); cout << szMyName; return 0;

}
output

J. Soulie

Notice that we needed to include <string.h> header in order to be able to use function strcpy. Although we can always write a simple function like the following setstring with the same operation as cstring's strcpy:
// setting value to string #include <iostream.h> void setstring (char szOut [], char szIn []) { int n=0; do { szOut[n] = szIn[n]; } while (szIn[n++] != '\0'); } int main () { char szMyName [20]; setstring (szMyName,"J. Soulie"); cout << szMyName; return 0;

} output
J. Soulie

Summary Arrays are a series of elements (variables) of the same type placed consecutively in memory that can be individually referenced by adding an index to a unique name. since arrays are blocks of static memory of a given size and the compiler must be able to determine exactly how is considered. Multidimensional arrays can be described as arrays of arrays. For example, a bidimensional array can be imagined as a bidimensional table of a uniform concrete data type.

Questions 1. Explain Array with example 2. What is multidiamentional array concept Explain with suitable example. 3. Find errors in each of the following a) Assume that Char str[5]; Cin >>str; // User types hello b) assume that int a[3]; cout <<a[1]<< <<a[2]<< a[3]<< endl;

UNIT I Lesson 13 Pointers In C++ In the last lecture you learnt what is the concept of Arrays Now we shift our focus to the most important topic from a programmers point of view, its about memory management. What do you percieve when we are talking about memory management? Is it related to managing storage spaces in the memory? To answer these questions, you will have to nose-dive into the memory block. Objective Introduction to the concept of Pointer

Introduction to Pointers An Overview of Pointers When writing a program, you declare the necessary variables that you will need in order to accomplish your work. When declaring variables, you are simply asking the computer to reserve a set amount of space in its memory for a particular object you want to use. When you declare a variable, the computer reserves an amount of space for that variable, and uses the variable's name to refer to that memory space. This will allow you to store something, namely the value of that variable, in that space. Indeed, the computer refers to that space using an address. Therefore, everything you declare has an address, just like the address of your house. You can find out what address a particular variable is using. Here are a few things you know already about writing a program:

To use a variable, you declare it first to tell the compiler what kind of variable you are planning to use and what its name is . Once you declare a variable, the compiler reserves and assigns it a portion of space in memory and locates it there so that whenever you need that variable, you just call it and then use it.

To use a function, you have to define it, tell the compiler what the function is supposed to do, and whether the function is supposed to give back a result or not, after it has performed its assignment.

To see a variable's address, you can use the & operator followed by the name of the variable. For example, int after declaring an integer as

NumberOfStudents;

you can find the address where the NumberOfStudents variable is located by using: cout << &NumberOfStudents; This program would give you the address of the declared variable: #include <iostream.h> int main( ) { int Value; cout << "Value lives at " << &Value; cout << "\n\n"; return 0; }
After executing the program, you could get:

Value lives at: Press any key to continue Definition Unfortunately, I will explain later on "WHY" use pointers. This is because we first need to know WHAT a pointer is, HOW to declare it inside of a function, and HOW to use it. Pointers are not particularly useful when declared and used inside of one function. They show their capabilities when different functions (and/or objects) exchange data stored in those pointers. As you can see from the execution of the program above, the address of a variable is very difficult to read and interpret. Fortunately, we don't need to know that address and we don't need to know what it means or where the variable is located. C++ provides an alternative to this problem. Instead of referring to a variable's address directly, you are allowed to declare another variable, and

then use that new variable to refer to the address of the variable you are interested in. A pointer is a variable that refers to another variable's address. Just like any variable in C++, you should declare and initialize a pointer variable before using it. To declare a pointer variable, use an identifier, followed by an asterisk (*), followed by the name of the pointer, and a semi-colon. Here is the formula: DateType * PointerName; The identifier should be one of those we have learned already. This means it could be an int, a char, a double, etc. The identifier should be the same type of identifier the pointer variable will point to. Therefore, if you are declaring a pointer that will point to an integer variable, the pointer identifier should be an integer. The asterisk (*) lets the compiler know that the variable that follows is a pointer. There are three ways you can type the asterisk. These are DateType* PointerName; DateType * PointerName; DateType *PointerName; By default, it does not matter how you append the *, the compiler will know that the thing that follows is a variable. Be careful when declaring various pointers. If you declare a few of them on the same line, like this: DateType* Pointer1, Pointer2; Only the first variable is a pointer, the second is a regular variable. If you want to declare different variables, you use: DateType* Pointer1, *Pointer2; Or DateType* Pointer1; DateType* Pointer2;

Since the name of the pointer is indeed the name of a variable, you will follow the naming rules that govern every C++ variable. #include <iostream.h> int main( ) { int Value; int *Pointer; cout << "Value lives at " << &Value << "\n"; cout << "Pointer lives at " << &Pointer; cout << "\n\n"; return 0; } After executing the program, you might get: Value lives at: Pointer lives at: Press any key to continue

Initializing a Pointer The reason you are using a pointer is to find an alternative to knowing the address of a variable. Therefore, from now on, we are not interested in a variable's real address. Instead, we will use a pointer to point to that variable.

As we have learned already, a variable should be initialized before being used. This allows the compiler to put something into the memory space allocated for that variable.

To use a pointer P effectively, for its intended purpose, you need to tell the compiler that: pointer P will be used to point to the address of variable V. You do this by initializing the pointer. A pointer is initialized (almost) like any other variable, using the assignment operator (=).

There are two main ways you can initialize a pointer. When declaring a pointer like this:

int* Pointer; initialize it by following the assignment operator with & operator and the name of the variable, like this int* Pointer = &Variable;

You can also initialize a pointer on a different line, after declaring it. This time, you should not use the asterisk on the Pointer, but the compiler should know that the pointer will point to a variable's address; therefore, the name of the variable will still use the &. #include <iostream.h> int main( ) { int Value = 12; int *Pointer = &Value; cout << "Value lives at: " << Value << "\n"; cout << "Pointer lives at: " << *Pointer; cout << "\n\n"; return 0; } The program would produce: Value lives at: 12 Pointer lives at: 12 Press any key to continue This program could also have the pointer initialized as: #include <iostream.h> int main( ) { int Value = 12; int *Pointer; cout << "Value lives at: " << Value << "\n"; Pointer = &Value; cout << "Pointer lives at: " << *Pointer; cout << "\n\n"; return 0;

} And it would produce the same result. As another of the program, you can first declare both variables, then initialize them later on, when needed: #include <iostream.h> int main( ) { int Value; int *Pointer; Pointer = &Value; Value = 26; cout << "Value = " << Value << "\n"; cout << "*Pointer = " << *Pointer << "\n"; cout << "\n"; return 0; } Once you have declare a variable and assign it to a pointer, during the course of your program, the value of a variable is likely to change, you can therefore assign it a different value: #include <iostream.h> int main( ) { int Value; int *Pointer; Pointer = &Value; Value = 26; cout << "Value = " << Value << "\n"; cout << "*Pointer = " << *Pointer << "\n"; Value = 35; cout << "Value = " << Value << "\n"; cout << "*Pointer = " << *Pointer << "\n"; cout << "\n"; return 0; } As you know now, both *Pointer and Value have the same value. This allows you to change the value of the pointer directly and affect the main variable meanwhile. Therefore, you can safely change the value of the pointer and it will be assigned accordingly. To see an example, make the following change to the file:

#include <iostream.h> int main( ) { int Value; int *Pointer; Pointer = &Value; Value = 26; cout << "Value = " << Value << "\n"; cout << "*Pointer = " << *Pointer << "\n"; Value = 35; cout << "Value = " << Value << "\n"; cout << "*Pointer = " << *Pointer << "\n"; *Pointer = 144; cout << "Value = " << Value << "\n"; cout << "*Pointer = " << *Pointer << "\n"; cout << "\n"; return 0; } This would produce: Value = 26 *Pointer = 26 Value = 35 *Pointer = 35 Value = 144 *Pointer = 144

Operations on Pointers Consider that, added just a few rules, a pointer is a variable like any other: it can get its value from the user (indirectly), you can apply any of the algebraic operations we have learned, it can be incremented, it can be applied on a function, etc.

A variable is a value that is supposed to change some time to time. Since a pointer is a variable whose value points to another variable, the value of a pointer is affected by the variable it points to. You can use this indirection to change the value of a pointer when changing its main variable.

To get a value from the user, we have already learned that you can use the cin operator. When using a pointer to get a value from the user, don't forget the * operator, otherwise, the compiler would get confused.

We have already learned how to request and display the value of a regular variable from the user: #include <iostream.h> int main( ) { int Students; cout << "Number of students: "; cin >> Students; cout << "\nNumber of students: " << Students; cout << "\n\n"; return 0; } Once you have gotten a value and store it in a variable, it is available: #include <iostream.h> int main( ) { int Students; int *ptrStudents; ptrStudents = &Students; cout << "Number of students: "; cin >> Students; cout << "\nNumber of students: " << Students << "\nThat is: " << *ptrStudents << " students."; cout << "\n\n"; return 0; }

This could produce:

Number of students: 24 Number of students: 24 That is: 24 students Press any key to continue In the same way, you can request a value from the user and store it in the pointer. To see an example, make the following change to the file:< #include <iostream.h> int main( ) { int Students; int *ptrStudents; ptrStudents = &Students; cout << "Number of students: "; cin >> *ptrStudents; cout << "\nNumber of students: " << Students << "\nThat is: " << *ptrStudents << " students."; cout << "\n\n"; return 0; } Of course, you can use various pointers on the same program. Apply an example by making the following changes: #include <iostream.h> int main( ) { int Boys; int Girls; int *ptrBoys; int *ptrGirls; ptrBoys = &Boys; ptrGirls = &Girls; cout << "Number of male students: "; cin >> *ptrBoys; cout << "Number of female students: "; cin >> *ptrGirls; cout << "\nNumber of students:";

cout << "\nBoys:" << "\t" << Boys << "\nThat is: " << *ptrBoys << " students."; cout << "\nGirls:" << "\t" << Girls << "\nThat is: " << *ptrGirls << " students."; cout << "\n\n"; return 0; } We have learned how to perform algebraic calculations and expressions in C++. When performing these operations on pointers, remember to use the * for each pointer involved. The calculation should be as smooth: #include <iostream.h> int main( ) { int Boys; int Girls; int Total; int *ptrBoys; int *ptrGirls; int *ptrTotal; ptrBoys = &Boys; ptrGirls = &Girls; ptrTotal = &Total; cout << "Number of male students: "; cin >> *ptrBoys; cout << "Number of female students: "; cin >> *ptrGirls; cout << "\nNumber of students:"; cout << "\nBoys:" << "\t" << Boys << "\nThat is: " << *ptrBoys << " students."; cout << "\nGirls:" << "\t" << Girls << "\nThat is: " << *ptrGirls << " students."; Total = Boys + Girls; *ptrTotal = *ptrBoys + *ptrGirls; cout << "\n\nTotal number of students: " << Total; cout << "\nThere are " << *ptrTotal << " students"; cout << "\n\n"; return 0;

} This would produce: Number of male students: 26 Number of female students: 24 Boys: 26 That is: 26 students Girls: 24 That is: 24 students Total number of students: 50 There are 50 students

Why Use Pointers? Every time you declare a variable, the compiler puts it somewhere, which you can now refer to as an address. Once you know that address, you can use it. Like a reference, when you pass an argument to a function, the argument is passed using its address. This allows the calling function to dig into the address of the variable (the argument) and use the value directly. This transaction, like that of passing an argument by reference, allows the calling function to alter the real value of the argument. Using this ability, a pointer can allow you to return many values from a function; as opposed to a regular argument passing where the data, although changed inside of the calling function, will regain its previous value once the calling function is exited. Therefore, passing arguments as pointers allows a function to return many values, even if a function is declared as void. When you declare an array, you must specify the dimension of the array. That's already a problem: what if you don't know and don't want to know the dimension of the array? Pointers provide an ability that regular arrays do not have. Since pointers have a different and better system of managing memory, a pointer can store an array of almost any size; this is tremendous when dealing with arrays of characters or a whole text. Using this feature, when declaring a pointer in replacement of an array, you do not have to worry about the size of the array, the compiler will take care of that. Again, this feature allows you to pass pointers to a function (just like arrays) and return a value that has been altered even if the function is declared as void. This is even more dynamic with multidimensional arrays. Passing Pointers to Functions

We know that a function uses arguments in order to carry its assignment. The arguments are usually provided to the function. When necessary, a function also declares its own variable to get the desired return value. Like other variables, pointers can be provided to a function, with just a few rules. When declaring a function that takes a pointer as an argument, make sure you use the asterisk for the argument or for each argument. When calling the function, use the references to the variables. The function will perform its assignment on the referenced variable(s). After the function has performed its assignment, the changed value(s) of the argument(s) will be preserved and given to the calling function. Here is a starting file from what we have learned so far: #include <iostream.h> int main( ) { int Shirts = 12; int Pants = 5; cout << "Shirts = " << Shirts << endl; cout << "Pants = " << Pants << endl; cout << endl; return 0; } This would produce: Shirts = 12 Pants = 5 Press any key to continue To pass arguments to a function, you can make the following changes: #include <iostream.h> int main( ) { int Shirts = 3; int Pants = 5; void Deposit(int s, int p); cout << "When starting, within main( ):\n"; cout << "\tShirts = " << Shirts << endl; cout << "\tPants = " << Pants << endl;

Deposit(Shirts, Pants); cout << "\n\nAfter calling Deposit( ), within main( ):\n"; cout << "\tShirts = " << Shirts << endl; cout << "\tPants = " << Pants << endl; cout << endl; return 0; } void Deposit(int s, int p) { s = 8; p = 12; cout << "Within Deposit( )" << "\n\tShirts = " << s << "\n\tPants = " << p; } After executing, the program would produce: When starting, within main( ): Shirts = 3 Pants = 5 Within Deposit( ) Shirts = 8 Pants = 12 After calling Deposit( ), Within main( ): Shirts = 3 Pants = 5 Press any key to continue To pass pointer arguments, use the asterisks when declaring the function, and use the ampersand & when calling the function. Here is an example: #include <iostream.h> int main( ) { int Shirts = 12; int Pants = 5; void Deposit(int s, int p); void Pickup(int *sht, int *pt); cout << "When starting, within main( ):\n"; cout << "\tShirts = " << Shirts << endl; cout << "\tPants = " << Pants << endl;

Deposit(Shirts, Pants); cout << "\n\nAfter calling Deposit( ), within main( ):\n"; cout << "\tShirts = " << Shirts << endl; cout << "\tPants = " << Pants << endl; Pickup(&Shirts, &Pants); cout << "\n\nAfter calling Pickup( ), within main( ):\n"; cout << "\tShirts = " << Shirts << endl; cout << "\tPants = " << Pants << endl; cout << endl; return 0; } void Deposit(int s, int p) { s = 8; p = 5; cout << "\nWithin Deposit( )" << "\n\tShirts = " << s << "\n\tPants = " << p; } void Pickup(int *sht, int *pt) { *sht = 26; *pt = 17; cout << "\nWithin Pickup( )" << "\n\tShirts = " << *sht << "\n\tPants = " << *pt; } The result of executing the program is: When starting, within main( ): Shirts = 12 Pants = 5 Within Deposit( ) Shirts = 8 Pants = 5 After calling Deposit( ), within main( ): Shirts = 12 Pants = 5 Within Pickup( ) Shirts = 26

Pants = 17

After calling Pickup( ), within main( ): Shirts = 26 Pants = 17

Summary A pointer is a variable that refers to another variable's address. Just like any variable in C++, you should declare and initialize a pointer variable before using it. To declare a pointer variable, use an identifier, followed by an asterisk (*), followed by the name of the pointer, and a semi-colon. passing arguments as pointers allows a function to return many values, even if a function is declared as void. Pointers provide an ability that regular arrays do not have. Since pointers have a different and better system of managing memory, a pointer can store an array of almost any size; this is tremendous when dealing with arrays of characters or a whole text.

Questions 4. Explain the concept of Pointer 5. Predict the output of the following program. Class test { private: int m; public: void getdata() { cout<<Enter number:; cin>>m; } void display() { cout << m; } }; main() { test T; T->getdata(); T->display(); Test *p; P=new test; p.getdata(); (*p).display(); }

UNIT I Lesson 14 INHERITANCE Objective Concept of Inheritance Types of Inheritance

Now we take on from all the previous topics in C++ to the most inquisitive and exiting topic in C++ which is students favorite topics. Inheritance. What do you recollect when you talk about inheritance? Doesnt it immediately relate to imbibing/inheriting certain characteristics from our parents? Absolutely we are talking about taking over certain characteristics from the parent body to the child body. Lets explore this phenomenon of Inheritance in C++ now. INTRODUCTION Reusability is yet another important feature of OOP. It is always nice if we could reuse something that already exists rather than trying to create the same all over again. It, saves time and money but also increase reliability. For instance the reuse of a class that has already been tested, debugged and used many times can the effort of developing and testing the same again. Fortunately, C++ strongly supports the concept of reusability. The C++ classes reused in several ways. Once a class has been written and tested, it can be adapted by other programmers to suit their requirements. This is basically done by creating new reusing the properties of the existing ones The mechanism of deriving a new class from an old one is called inheritance (or derivation). The old class is referred to as the base class and the new one is called the derived class or subclass. The derived class inherits some or all of the traits from the base class. A class can also inherit properties from more than one class or from more than one level. A derived class with one base class, is called single inheritance and one with several base classes is called multiple inheritance. On

the other hand, the traits of one class may be inherited by more than one class . This process is known as hierarchical inheritance. The mechanism of deriving from another 'derived class' is known as multilevel inheritance. Fig . shows forms of inheritance that could be used for writing extensible programs. The direction , indicates the direction of inheritance. (Some authors show the arrow in opposite Authors show the arrow in opposite direction meaning "inherited from".)

B C

b) multiple inheritance

(a) single inheritance

(c) Hirarchical inheritance

B B D

C (d) Multilevel inheritance fig.

(e) Hybrid inheritance Forms of inheritance

DEFINING DERIVED CLASSES . Derived class can be defined by specifying its relationship with the base class in addition own details. The general form of defining a derived class is: c1ass der ved class-name { // // members of derived class // }; The colon indicates that the derived-class-name is derived from the base-class-nam, visibility-mode is optional and, if present, may be either private or public. The default visibility, mode is private. Visibility mode specifies whether the features of the base class are privately derived or publicly derived. Examples: class ABC: private XYZ { members of ABC }; class ABC: public XYZ { members of ABC }; class ABC: XYZ { members of ABC }; // private derivation by default // public derivation // private derivation : visibility-mode base-c1ass-name

When a base class is privately inherited by a derived class, 'public members' of the class become 'private members' of the derived class and therefore the public members of base class can only be accessed by the member functions of the derived class. They are inaccessible to the objects of the derived class. Remember, a public member of a class can accessed by its own objects using the dot operator. The result is that no member of the class is accessible to the objects of the derived class.

SINGLE INHERITANCE Let us consider a simple example to illustrate inheritance. Program shows a base class B and derived class D. The class B contains one private data member, one public data member and three public member functions. The class D contains one private data member and two public member functions. #include <iostream> using namespace std; class B { int a; public: int b; //public; ready for inheritance void get_ab(); int get_a(void); void show_a(void); }; class D : public B { int c; // public derivation //private ; not inheritable

public : void mul(void); void display(void); }; void B :: get_ab(void) { a=5;b=10; } int b :: get_a() { return a; } void B :: show_a() { cout <<a= <<a<<\n; } void D :: mul() { c=b*get_a(); } void D :: display() { cout <<a=<<get_a()<<\n; cout <<b=<<b <<\n; cout <<c=<<c <<\n \n ; } int main()

{ D d; d.get_ab(); d.mul(); d.show_a(); d.display(); d.b=20; d.mul(); d.display(); return 0; } Given below is the output of above Program : a=5 a=5 b = 10 c = 50 a=5 b = 20 c = 100 The class D is a public derivation of the base class B. Therefore, D inherits all the public members of B and retains their visibility. Thus a public member of the base class B is also a public member of the derived class D. The private members of B cannot be inherited by D.

Questions 1. Discuss overview of the Inheritance

UNIT I

LESSON 15 INHERITANCE II Objective Types of inheritance

MULTILEVEL INHERITANCE It is not uncommon that a class is derived from another derived class as shown in Fig. The class A serves as a base class for the derived class B, which in turn serves as a base class for the derived class C. The class B is known as intermediate base class since it provides a link for the inheritance between A and C. The chain ABC is known as inheritance path. A derived class with multilevel inheritance is declared as follows: class A{ }; }; }; // Base class // B derived from A // C derived from B class B: public A { class C: public B {

This process can be extended to any number of levels.

Base class

A B

Grandfather

Intermediate base class C

Father

Derived class Multilevel inheritance

Child

Let us consider a simple example. Assume that the test results of a batch of students are stored in three different classes. Class student stores the roll-number, class test stores the marks obtained in two subjects and class result contains the total marks obtained in the test. The class result can inherit the

details of the marks obtained in the test and the roll number of students through multilevel inheritance. Example: class student { protected: int roll_number; public: void get number(int); void put_number{void); }; void student :: get_number(int a) { roll_number = a; } void student :: put_numberO { cout << "Roll Number: " << roll number << "\n"; } class test : public student { protected: float subl; float sub2; public: void get_marks(float, float); void put_marks(void); }; void test :: get_marks(float x, float y) { subl = X; sub2 = y; } // First level derivation

void test :: put marks 0 { cout << "Marks in SUBl = " << subl << "\n"; cout << "Marks in SUB2 = " << sub2 <<"\n"; } class result : public test { float total; public: void display(void); }; The class result, after inheritance from 'grandfather' through 'father', would contain following members: private: float tota1; protected: int roll_number; float subl; float sub2; public: void get_number(int); void put_number(void); void get marks(float, float); void put-marks(void); void display(void); // from student via test // from student via test // from test // from test // own member // inherited from student via test // inherited from test // inherited from test // own member // private by default // Second level derivation

The inherited functions put_number() and put_marks() can be used in the definition of display() function: void result :: display(void) { total = subl + sub2;

put_number(); put_marks(); cout <<"Total = " << total << "\n"; } Here is a simple main() program: int main() { result student1; studentl.get_number(111); studentl.get_marks(75.0, 59.5); studentl.display(); return 0; } This will display the result of student1. The complete program is shown below MULTILEVEL INHERITANCE # include <iostream> using namespace std; class student { protected: int roll_number; public: void get_number(int); void put_number(void); }; / / student1 created

void student :: get_number(int a) { roll_number = a; } void student :: put_number(int a) { cout << Roll number: << roll_number << \n; } class test : public student { protected: float sub1; float sub2; public: void get_marks(float, float); void put_marks(void); }; void test :: get_marks(float x, float y) { sub1 = x; sub2 = y; } void test :: put_marks() { cout << Marks in SUB1 = << sub1 << \n; cout << Marks in SUB2 = << sub2 << \n; } class result : public test { // Second level derivation // First level derivation

float total; public: void display(void); }; void result :: display(void) { total = sub1 + sub2; put_number(); put_marks(); cout << Total = << total << \n; } int main() { result student1; student1.get_number(111); student1.get_marks(75.0, 59.5); student1.display(); return 0; }

// private by default

// student1 created

Program displays the following output: Roll Number: 111 Marks in SUB1 = 75 Marks in SUB2 = 59.5 Total = 134.5 MULTIPLE INHERITANCE

A class can inherit the attributes of two or more classes as shown in Fig.This is known as multiple inheritance. Multiple inheritance allows us to combine the features of several existing classes as a starting point for defining new classes. It is like a child inheriting the physical features of one parent and the intelligence of another. B1 B-2 B-n

Multiple inheritance

The syntax of a derived class with multiple base classes is as follows:

Class D visibility B-1, visibility B-2. { (body of D) };

where, visibility may be either public or private. The base classes are separated by commas. Example: class P : public M, public N { public:

void display(void); }; Classes M and N have been specified as follows: class M { protected: int m; public: void get_m(int); }; void M :: get_m(int x) { m = x; } class N { protected: int n; public: void get_n(int); }; void N :: get_n(int y) { n = y; } The derived class P, as declared above, would, in effect, contain all the members of M and N in addition to its own members as shown below: class P {

protected: int m; int n; // from M // from M public: void get_m(int); void get_n(int); void display(void); // from M // from N // own member }; The member function display() can be defined as follows: void P :: display(void) { cout << "m = " << m <<"\n"; cout << "n = " << n << "\n"; cout << "m*n =" << m*n << "\n"; }; The main() function which provides the user-interface may be written as follows: main () { P p; p.get_m(l0) ; p.get_n(20) ; p.display () ; }

summary A class can inherit the attributes of two or more classes .This is known as multiple inheritance. Multiple inheritance allows us to combine the features of several existing classes as a starting point for defining new classes. It is like a child inheriting the physical features of one parent and the intelligence of another. A class can inherit the attributes of two or more classes.This is known as multiple inheritance.

Questions 1.What is Inheritance? Explain its types in brief 2.what is multiple inheritance? Explain

UNIT I LESSON 16 INHERITANCE III Objective


Hierarchical Inheritance Hybrid Inheritance Constructors In Derived Classes

HIERARCHICAL INHERITANCE We have discussed so far how inheritance can be used to modify a class when it did not satisfy the requirements of a particular problem on hand. Additional members are added through inheritance to extend the capabilities of a class. Another interesting application of inheritance is to use it as a support to the hierarchical design of a program. Many programming problem can be cast into a hierarchy where certain features of one level are shared by many others below that level. As an example, following Fig. shows a hierarchical classification of students in a university

Students

Arts

Engineering

Medical

Mech.

Elec.

Civil

Hierarchical classification of students Another example could be the classification of accounts in a commercial bank.

Account

Savings Account

Fixed Deposit Account

Current Account

Short Term

Medium Term Classification of bank accounts

Long Term

All the students have certain things in common and, similarly, all the account possess certain common features. In C++, such problems can be easily converted into class hierarchies. The base class will include all the features that are common to the subclasses. A subclass can be constructed by inheriting the properties of the base class. A subclass can serve as a base class for the lower level classes and so on. HYBRID INHERITANCE There could be situations where we need to apply two or more types of inheritance to design a program. For instance, consider the case of processing the student results. Assume that we have to give weightage for sports before finalising the results. The weightage for sports is stored in a separate class called sports. The new inheritance relationship between the various classes would be as shown. Student

Test

Student

Result Multilevel. multiple inheritance

The sports class might look like: class sports { protected: float score; public: void get_score(f1oat); void put_score(void); }; The result will have both the multilevel and multiple inheritances and its declaration would be as follows: class sports: public test, public sports { }; Where test itself is a derived class from student. That is class test : pub1ic student { }; Program illustrates the implementation of both multilevel and multiple inheritance. #include <iostream> using namespace std;

class student { protected: int roll_number; public: void get_number(int a) { roll_number = a; } void put_number(void) { cout << Roll No: << roll_number << \n; } }; class test : public student { protected: f1oat part1, part2; public: void get marks (float x, float y) { partl = x; part2 = y; } void put marks(void) { cout << "Marks obtained: " << "\n" << Part1 = << part1 << "\n" << Part2 = << part2 << "\n"; } };

class sports : public virtual student { protected: float score; public: void get_score (float s) { score = s; } void put score(void) { cout << "Sports wt: " << score << "\n\n"; } }; class result : public test, public sports { float tota1; public: void display(void); }; void result :: display(void) { total = part1 + part2 + score; put_number(); put_marks(); put_score(); cout << "Total Score: " << total << "\n; }

int main() { resu1t student _1 ; student_l.get score(7.0); student_1.display(); return 0; }

CONSTRUCTORS IN DERIVED CLASSES As we know, the constructors play an important role in initializing objects. We did not use them earlier in the derived classes for the sake of simplicity. One important thing to note here is that, as long as no base class constructor takes any arguments, the derived class need not have a constructor function. However, if any base class contains a constructor with one or more arguments, then it is mandatory for the derived class to have a constructor and pass the arguments to the base class constructors. Remember, while applying inheritance we usually create objects using the derived class. Thus, it makes sense for the derived class to pass arguments to the base class constructor. When both the derived and base classes contain constructors, the base constructor is executed first and then the constructor in the derived class is executed. . Incase of multiple inheritance, the base classes are constructed in the order in which they appear in the declaration of the derived class. Similarly, in a multilevel inheritance, the constructors will be executed in the order of inheritance Since the derived class takes the responsibility of supplying initial values to its base classes, we supply the initial values that are required by all the classes together, when a derived class is declared. How are they passed to the base class constructors so that they can do their job? C++ supports a special argument passing mechanism for such situations. The constructor of the derived class receives the entire list of values as its arguments and passes them on to the base constructors in the order in which they are declared in the derived class. The base constructors are called and executed before executing the statements in the body of the derived constructor. The general form of defining a derived constructor is:

Derived-constructor

(Arglist1,

Arglist2,

ArglistN,

Arglist(D)

base1(arglist1), base1(arglist1), arguments for base(N) baseN(arglistN), { Body of derived constructor }

The header line of derived-constructor function contains two parts separated by a colon(;), The first part provides the declaration of the arguments that are passed to the derived, constructor and the second part lists the function calls to the base constructors. basel(arglistl), base2(arglist2)... are function calls to base constructors basel(),base2(), ... and therefore arglistl, arglist2, ... etc. represent the actual parameters that are passed to the base constructors. Arglistl through ArglistN are the argument declarations for base constructors base1 through baseN. ArglistD provides the parameters that are necessary to initialize the members of the derived class. Example: D(int a1, int a2, float bl, float b2, int d1): A(al, a2), B(bl, b2) { d = d1; } A(al, a2) invokes the base constructor A() and B(bl, b2) invokes another base constructor B(). The constructor D() supplies the values for these four arguments. In addition, it has one argument of its own. The constructor D() has a total of five arguments. D() may be invoked as follows: // executes its own body /* call to constructor A */ /* call to constructor B */

D obj D (5, 12, 2.5, 7.54, 30); These values are assigned to various parameters by the constructor D() as follows: 5 12 2.5 7.54 30 a1 a2 b1 b2 d1

The constructors for virtual base classes are invoked before any non-virtual base classes. If Ther are multiple virtual base classes, they are invoked in the order in which they are declared. Any non-virtua1 bases are then constructed before the derived class constructor is executed. See Table below: Method of inheritance Class B: public A { }; Class A : public B, public C { }; Class A : public B, virtual public C { }; Order of execution A() ; base constructor B() ; derived constructor B() : base(first) C() : basae (second) A() :derived C() : virtual base B() : ordinary base A() : derived CONSTRUCTORS IN DERIVED CLASS Program below illustrates how constructors are implemented when the classes are inherited. #inc1ude <iostream> using namespace std;

class alpha { int x; pub1ic : a1pha(int i) { x = I; cout << "alpha initialized \n"; } void show x(void) { cout << "x = " << x << "\n"; } }; c1ass beta { float y; public: beta(float j) { y = j; cout << "beta initialized \n"; } void show_y(void) { cout << "y = " << y << "\n"; } }; class gamma: public beta, public alpha { int m, n; public: gamma(int a, float b, int c, int d): alpha(a), beta(b)

{ m = c; n = d; cout << m = << m << \n << n = << n << \n; } }; int main() { gamma g(5, 10.75, 20, 30): cout << \n; g.show_x(); g.show_y(); g.show_mn(); return 0; } The output of the program would be: beta initialized alpha initialized gamma initialized x=5 y = 10.75 m = 20 n = 30

Summary Application of inheritance is to use it as a support to the hierarchical design of a program. Many programming problem can be cast into a hierarchy where certain features of one level are shared by many others below that level. Incase of multiple inheritance, the base classes are constructed in the order in which they appear in the declaration of the derived class. Similarly, in a multilevel inheritance, the constructors will be executed in the order of inheritance Questions 1. Explain hybrid inheritance with example 2. What is hierarchical inheritance? 3. Explain Constructors In Derived Classes 4. Briefly define each of the following terminologies i. Inheritance ii. Multiple Inheritance iii. Base class iv. Derived Class 5 Distinguish between Single Inheritance and Multiple Inheritance

UNIT I Lesson 17 Tutorial based on the concept of Constructor and Inheritance

UNIT I LESSON 18 VIRTUAL FUNCTIONS Objective


Concept of virtual functions Rules of virtual functions Pure virtual functions

The concept of polymorphism in C++ is the capability to create member functions with identical names that perform slightly different operations. This is achieved by using virtual functions. A virtual function can only be defined in a parent class. When a parent class declares a virtual function, it is enabling any derived classes of the parent class the capability to create a different function with the same name as the virtual function. If a derived class does not declare a new function, the parent class function is used just like any other non-virtual function would be. In essence, a virtual function allows a derived classes the option of overriding a parent class function. Virtual functions must be called in a slightly different fashion than non-virtual functions. VIRTUAL FUNCTIONS An essential requirement of polymorphism is therefore the ability to refer to objects without any regard to their classes. This necessitates the use of a single pointer variable to refer to the objects of different classes. Here, we use the pointer to base class to refer to all the derived objects. But, we just discovered that a base pointer, even when it is made to contain the address of derived class, always executes the function in the base class. The compiler simply ignores the contents of the pointer and chooses the member function that matches the type of the pointer. How do we then achieve polymorphism? It is achieved using what is known as 'virtual' functions. When we use the same function name in both the base and derived classes, the function in base class is declared as virtual using the keyword virtual preceding its normal declaration. When a function is made virtual, C++ determines which function to use at run time based on the type of object pointed to by the base pointer, rather than the type of the pointer. Thus, by making the base pointer to point to

different objects, we can execute different versions of the virtual function. Program illustrates this point. #include<iostream.h> class Base { void display() {cout<< \n display Base ;} void show() {cout << \n show Base";} } class derived : public Base { public : void display() {cout<< \n display Derived ;} void show() {cout << \n show Derived";} }; int Main() { Base B; Derived D; Base *bptr; cout << \n bptr points toBase\n; bptr =&B; bptr -> display(); bptr -> show(); //calls Base version //calls Base version

cout "\n\n bptr poini:s Derived\n"; bptr = &D; bptr -> display(); bptr -> show(); return 0; // calls Base version // calls Derived version

} The output of Program would be: bptr points to Base Display base Show base bptr points to Derived Display base Show derived Note that When bptr is made to point to the object D, the statement bptr -> display(); calls only the function associated with the Base (i.e. Base :: display( )), whereas the statement bptr -> show(); calls the Derived version pf show(). This is because the function display () has not been made virtual in the Base class. One important point to remember is that, we must access virtual functions through the use of a pointer declared as a pointer to the base class. Why can't we use the object name (with the dot operator) the same way as any other member function to call the virtual functions? We can, but remember, run time polymorphism is achieved only when a virtual function is accessed through a pointer to the base class. Let us take an example where virtual functions are implemented in practice. Consider a book shop which sells both books and video-tapes. We can create a class known as media that stores the title and price of a publication. We can then create two derived classes, one for storing the number of pages in a book and another for storing the playing time of a tape.

Figure shows the class hierarchy for the book shop. media

book

tape

The class hierarchy for the book shop The classes are implemented in Program. A function display() is used in all the classes to display the class contents. Notice that the function display() has been declared virtual in media, the base class. In the main program we create a heterogeneous list of pointers of type media as shown below: media *list[2]; = { &book1; [1], &tape1}; The base pointers list[0] and list[1] are initialized with the addresses of objects bookl and tapel respectively. #include <iostream> #include <cstring> class media { protected : char title [501; float price; public : media (char *s, float a ) { strcpy(title, s); price = a; } virtual void display() { } / / empty virtual function

}; class book: public media { int pages; public: book(char *s, float a. int p) :media(s, a) { pages = p; } void display().; }; class tape :public media { float time; public: tape(char * s, float a, float t):media(s, a) { time = t; } void display(); }; void book:: display() { cout << "\n Title: " << title; cout << "\n Pages: " << pages; cout<< \n Price: "<< price; } void tape::display {

cout << \n Title: "<< title; cout <<\n play time: " << time "mins"; cout<< \n Price: "<< price; } int main() { char *title = new char[30]; float price, time int pages; // Book details cout <<\n Enter Book Details \n; cout <<\n Titles: ; cin >>title; cout <<\n Price : ; cin >>Price; cout<< \n pages: ; cin>> pages book book1(title, price, pages) // Tape details cout <<\n Enter Tape Details \n; cout <<\n Titles: ; cin >>title; cout <<\n Price : ; cin >>Price; cout<< Play time (mins): ; cin>> time; tape tape1(title, price, time); media* list[2]; list[0] = &book1; list[1] = &tape1; cout<<\n MEDIA DETALS;

cout<<\n BOOK; list[0]->display(); // display book details

cout<<\n TAPE; list[0]->display(); result 0; } The output of program // display Tape details

ENTER BOOK DETAILS Title: Programming in ANSI C Price: 88 Pages: 400 ENTER TAPE DETAILS Title: Computing_Concepts Price: 90 Play time (mi ns): 55 MEDIA DETAILS ....BOOK.... Title: Programming in ANSI C Pages: 400 Price: 88 .TAPE.... Title: Computing_Concepts Play time: 55mins Price: 90

Rules for Virtual Functions When virtual functions are created for implementing late binding, we should observe some basic rules that satisfy the compiler requirements: 1. The virtual functions must be members of some class. 2. They cannot be static members. 3. They are accessed by using object pointers. 4. A virtual function can be a friend of another class. 5. A virtual function in a base class must be defined, even though it may not be used. 6. The prototypes of the base class version of a virtual function and all the derived class versions must be identical. If two functions with the same name have different prototypes, C++ considers them as overloaded functions, and the virtual function mechanism is ignored. 7. We cannot have virtual constructors, but we can have virtual destructors. 8. While a base pointer can point to any type of the derived object, the reverse is not true. That is to say, we cannot use a pointer to a derived class to access an object of the base type. 9. When a base pointer points to a derived class, incrementing or decrementing it will not make it to point to the next object of the derived class. It is incremented or decremented only relative to its base type. Therefore, we should not use this method to move the pointer to the next object. 10. If a virtual function is defined in the base class, it need not be necessarily redefined in the derived class. In such cases, calls will invoke the base function.

PURE VIRTUAL FUNCTIONS


It is normal practice to declare a function virtual inside the base class and redefine it in the derived classes. The function inside the base class is seldom used for performing any task. It only serves as a placeholder. For example, we have not defined any object of class medial therefore the function display() in the base class has been defined 'empty'. Such functions called "do-nothing" functions.

A "do-nothing" function may be defined as follows: virtual void display() = 0; Such functions are called pure virtual functions. A pure virtual function is a function declared in a base class that has no definition relative to the base class. In such cases, the compiler requires each derived class to either define the function or re declare it as a pure virtual function. Remember that a class containing pure virtual functions cannot be used declare any objects of its own. As stated earlier, such classes are called abstract base c/asses. The main objective of an abstract base class-is to provide some traits to the derived classes and to create a base pointer required for achieving run time polymorphism.

Summary When we use the same function name in both the base and derived classes, the function in base class is declared as virtual using the keyword virtual preceding its normal declaration. When a function is made virtual, C++ determines which function to use at run time based on the type of object pointed to by the base pointer, rather than the type of the pointer Remember that a class containing pure virtual functions cannot be used declare any objects of its own. As stated earlier, such classes are called abstract base c/asses. The main objective of an abstract base class-is to provide some traits to the derived classes and to create a base pointer required for achieving run time polymorphism.

Questions 1. What do you, mean by Virtual function? Why do we need virtual functions 2. explain pure virtual function 3. distingwish between virtual functions and pure virtual function

UNIT I

Lesson 19 POLYMORPHISM Objective


Concept of polymorphism Static and Dynamic Binding

INTRODUCTION Polymorphism is one of the crucial features of OOP. It simply means 'one name, multiple forms'. you have already seen how the concept of polymorphism is implemented using the overloaded functions and operators. The overloaded member functions are selected for invoking by matching arguments, both type and number. This information is known to the compiler at the compile time and, therefore, compiler is able to select the appropriate function for a particular .Call at the compile time itself. This is called early binding or static binding or static linking. Also known as compile time polymorphism, early binding simply mean that an object is bound to its function call at compile time. It would be nice if the appropriate member function could be selected while the program is running. This is known as run time polymorphism. How could it happen? C++ supports a mechanism known as virtual function to achieve run time polymorphism.

Polymorphism

Compile time polymorphism

Run time polymorphism

Function overloading

Operator overloading

Virtual functions Achieving polymorphism

At run time, when it is known what class objects are under consideration,. the appropriate version of the function is invoked. Since the function is linked with a particular class much iter after the

compilation, this process is termed as late binding. It is also known as dynamic binding because the selection of the appropriate function is done dynamically at run time. Dynamic binding is one of the powerful features of C++. This requires the use of pointers to objects. We shall discuss in detail how the object pointers and virtual functions are used to implement dynamic binding. Static and Dynamic Binding In a strongly typed programming languages you typically have to declare variables prior to their use. This also implies the variable's definition where the compiler reserves space for the variable. For example, in Pascal expressions like var i : integer; declares variable i to be of type integer. Additionally, it defines enough memory space to hold an integer value. With the declaration we bind the name i to the type integer. This binding is true within the scope in which i is declared. This enables the compiler to check at compilation time for type consistency. For example, the following assignment will result in a type mismatch error when you try to compile it: var i : integer; ... i := 'string'; We call this particular type of binding static because it is fixed at compile time. Definition (Static Binding) If the type T of a variable is explicitly associated with its name N by declaration, we say, that N is statically bound to T. The association process is called static binding. There exist programming languages, which are not using explicitly typed variables. For example, some languages allow to introduce variables once they are needed: ... /* No appearance of i */

i := 123 /* Creation of i as an integer */ The type of i is known as soon as its value is set. In this case, i is of type integer since we have assigned a whole number to it. Thus, because the content of i is a whole number, the type of i is integer.

Definition (Dynamic Binding) If the type T of a variable with name N is implicitly associated by its content, we say, that N is dynamically bound to T. The association process is called dynamic binding. Both bindings differ in the time when the type is bound to the variable. Consider the following example, which is only possible with dynamic binding: if somecondition( ) == TRUE then n := 123 else n := 'abc'

The type of n after the if statement depends on the evaluation of somecondition( ). If it is TRUE, n is of type integer whereas in the other case it is of type string. Polymorphism allows an entity (for example, variable, function or object) to take a variety of representations. Therefore we have to distinguish different types of polymorphism, which will be outlined here. The first type is similar to the concept of dynamic binding. Here, the type of a variable depends on its content. Thus, its type depends on the content at a specific time:
v := 123 ... v := 'abc' ... /* v is integer */ /* use v as integer */ /* v "switches" to string */ /* use v as string */

Definition (Polymorphism (1)) The concept of dynamic binding allows a variable to take different types dependent on the content at a particular time. This ability of a variable is called polymorphism. Another type of polymorphism can be defined for functions. For example, suppose you want to define a function isNull( ) which returns TRUE if its argument is 0 (zero) and FALSE otherwise. For integer numbers this is easy: boolean isNull(int i) { if (i == 0) then return TRUE else

return FALSE endif }

However, if we want to check this for real numbers, we should use another comparison due to the precision problem:
boolean isNull(real r) { if (r < 0.01 and r > -0.99) then return TRUE else return FALSE endif }

In both cases we want the function to have the name isNull. In programming languages without polymorphism for functions we cannot declare these two functions because the name isNull would be doubly defined. Without polymorphism for functions, doubly defined names would be ambiguous. However, if the language would take the parameters of the function into account it would work. Thus, functions (or methods) are uniquely identified by:

the name of the function (or method) and the types of its parameter list.

Since the parameter list of both isNull functions differ, the compiler is able to figure out the correct function call by using the actual types of the arguments:
var i : integer var r : real i = 0 r = 0.0 ... if (isNull(i)) then ... ... if (isNull(r)) then ... /* Use isNull(real) */ /* Use isNull(int) */

Definition (Polymorphism (2)) If a function (or method) is defined by the combination of


its name and the list of types of its parameters

we speak of polymorphism. This type of polymorphism allows us to reuse the same name for functions (or methods) as long as the parameter list differs. Sometimes this type of polymorphism is called overloading. The last type of polymorphism allows an object to choose correct methods. Consider the function move( ) again, which takes an object of class Point as its argument. We have used this function with any object of derived classes, because the is-a relation holds.

Now consider a function display( ) which should be used to display drawable objects. The declaration of this function might look like this:
display(DrawableObject o) { ... o.print( ) ... }

We would like to use this function with objects of classes derived from DrawableObject: Circle acircle Point apoint Rectangle arectangle display(apoint) display(acircle) /* Should invoke apoint.print( ) */ /* Should invoke acircle.print( ) */

display(arectangle) /* Should invoke arectangle.print( ) */ The actual method should be defined by the content of the object o of function display( ). Since this is somewhat complicated, here is a more abstract example: class Base { attributes:

methods: virtual foo( ) bar( ) } class Derived inherits from Base { attributes: methods: virtual foo( ) bar( ) } demo(Base o) { o.foo( ) o.bar( ) } Base abase Derived aderived demo(abase) demo(aderived) In this example we define two classes Base and Derived. Each class defines two methods foo( ) and bar( ). The first method is defined as virtual. This means that if this method is invoked its definition should be evaluated by the content of the object. We then define a function demo( ) which takes a Base object as its argument. Consequently, we can use this function with objects of class Derived as the is-a relation holds. We call this function with a Base object and a Derived object, respectively. Suppose, that foo( ) and bar( ) are defined to just print out their name and the class in which they are defined. Then the output is as follows:
foo( ) of Base called.

bar( ) of Base called. foo( ) of Derived called. bar( ) of Base called.

Why is this so? Let's see what happens. The first call to demo( ) uses a Base object. Thus, the function's argument is ``filled'' with an object of class Base. When it is time to invoke method foo( ) it's actual functionality is chosen based on the current content of the corresponding object o. This time, it is a Base object. Consequently, foo( ) as defined in class Base is called. The call to bar( ) is not subject to this content resolution. It is not marked as virtual. Consequently, bar( ) is called in the scope of class Base. The second call to demo( ) takes a Derived object as its argument. Thus, the argument o is filled with a Derived object. However, o itself just represents the Base part of the provided object aderived. Now, the call to foo( ) is evaluated by examining the content of o, hence, it is called within the scope of Derived. On the other hand, bar( ) is still evaluated within the scope of Base. Definition (Polymorphism (3)) Objects of superclasses can be filled with objects of their subclasses. Operators and methods of subclasses can be defined to be evaluated in two contextes: 1. Based on object type, leading to an evaluation within the scope of the superclass. 2. Based on object content, leading to an evaluation within the scope of the contained subclass. So now we will derive a program in C++ to explain how polymorphism works. Polymorphism allows more than one function to have the same name, provided all functions are either distinguishable by the typing or the number of their parameters. Using a function name more than once is sometimes referred to as overloading the function name. Here's an example: #include<iostream> using namespace std; int average(int first_number, int second_number, int third_number);

int average(int first_number, int second_number); /* MAIN PROGRAM: */ int main( ) { int number_A = 5, number_B = 3, number_C = 10; cout << "The integer average of " << number_A << " and "; cout << number_B << " is "; cout << average(number_A, number_B) << ".\n\n"; cout << "The integer average of " << number_A << ", "; cout << number_B << " and " << number_C << " is "; cout << average(number_A, number_B, number_C) << ".\n"; return 0; } /* END OF MAIN PROGRAM */ /* FUNCTION TO COMPUTE INTEGER AVERAGE OF 3 INTEGERS: */ int average(int first_number, int second_number, int third_number) { return ((first_number + second_number + third_number)/3); } /* END OF FUNCTION */ /* FUNCTION TO COMPUTE INTEGER AVERAGE OF 2 INTEGERS: */ int average(int first_number, int second_number) { return ((first_number + second_number) / 2); } /* END OF FUNCTION */

When the same function is repeatedly executed for different purposes, as mentioned in above explanation, the function is then supposed to be overloaded.

Summary Polymorphism is one of the crucial features of OOP. It simply means 'one name, multiple forms'. It would be nice if the appropriate member function could be selected while the program is running. This is known as run time polymorphism. At run time, when it is known what class objects are under consideration,. the appropriate version of the function is invoked. Since the function is linked with a particular class much iter after the compilation, this process is termed as late binding. It is also known as dynamic binding because the selection of the appropriate function is done dynamically at run time. The overloaded member functions are selected for invoking by matching arguments, both type and number. This information is known to the compiler at the compile time and, therefore, compiler is able to select the appropriate function for a particular .Call at the compile time itself. This is called early binding or static binding or static linking. Questions 1. What do you mean by polymorphism? explain 2 3 Discuss the different ways by which we can access public member function of an object How does polymorphism promote extensibility?

UNIT I LESSON 20 VIRTUAL BASE CLASSES, NESTING OF CLASS Objective Abstract Classes Virtual Base Classes Member Classes

ABSTRACT CLASSES An abstract class is one that is not used to create objects. An abstract class is designed only to act as a base class (to be inherited by other classes). It is a design concept in program development and provides a base upon which other classes may be built. In the previous example, the student class is an abstract class since it was not used to create any objects. Basic abstract classes are something very similar to the class CPolygon of our previous example. The only difference is that in our previous example we have defined a valid area() function for objects that were of class CPolygon (like object poly), whereas in an abstract base class we could have simply left without defining this function by appending =0 (equal to zero) to the function declaration. The class CPolygon could have been thus: // abstract class CPolygon class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area (void) =0; };

Notice how we have appended =0 to virtual int area (void) instead of specifying an implementation for the function. This type of function is called a pure virtual function, and all classes that contain a pure virtual function are considered abstract base classes. The greatest difference of an abstract base class is that instances (objects) of it cannot be created, but we can create pointers to them. Therefore a declaration like: CPolygon poly; would be incorrect for the abstract base class declared above. Nevertheless the pointers: CPolygon * ppoly1; CPolygon * ppoly2 are be perfectly valid. This is because the pure virtual function that it includes is not defined and it is impossible to create an object if it does not have all its members defined. Nevertheless a pointer that points to an object of a derived class where this function has been defined is perfectly valid. Here you have the complete example: // virtual members #include <iostream.h> class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area (void) =0; }; class CRectangle: public CPolygon { public: int area (void) { return (width * height); } }; class CTriangle: public CPolygon { public: int area (void)

{ return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; return 0; } output 20 10

If you review the program you will notice that we can refer to objects of different classes using a unique type of pointer (CPolygon*). This can be tremendously useful. Imagine, now we can create a function member of CPolygon that is able to print on screen the result of the area() function independently of what the derived classes are. // virtual members #include <iostream.h> class CPolygon { protected: int width, height; public: void set_values (int a, int b)

{ width=a; height=b; } virtual int area (void) =0; void printarea (void) { cout << this->area() << endl; } }; class CRectangle: public CPolygon { public: int area (void) { return (width * height); } }; class CTriangle: public CPolygon { public: int area (void) { return (width * height / 2); } }; int main() { CRectangle rect; CTriangle trgl; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); ppoly1->printarea(); ppoly2->printarea(); return 0; } Output

20 10 Remember that this represents a pointer to the object whose code is being executed. Abstract classes and virtual members grant to C++ the polymorphic characteristics that make object-oriented programming such a useful instrument. Of course we have seen the simplest way to use these features, but imagine these features applied to arrays of objects or objects assigned through dynamic memory. VIRTUAL BASE CLASSES We have just discussed a situation which would require the use of both the multiple and multilevel inheritance. Consider a situation where all the three kinds of inheritance, namely, multilevel, multiple and hierarchical inheritance, are involved. This is illustrated in fig. The 'child' has two direct base classes 'parent1' and 'parent2' which themselves nave a common base class 'grandparent'. The 'child' inherits the traits of 'grandparent' via two separate paths. It can also inherit directly as shown by the broken line. The 'grandparent' is sometimes referred to as indirect base class. Grandparent Parent 1 Child Parent 2

Multipath inheritance Inheritance by the 'child' as shown in Fig. above might pose some problems. All the public and protected members of, grandparent' are inherited into 'child' twice, first via 'parent1' and again via 'parent2'. This means, 'child' would have duplicate sets of the members inherited from 'grandparent'. This introduces ambiguity and should be avoided.

The duplication of inherited members due to these multiple paths can be avoided by making the common base class (ancestor class) as virtual base class while declaring the direct or intermediate base classes which is shown as follow: class A { }; class B1 : virtual public A { }; class B2 : public virtual A { }; class C : public BI, public B2 { }; When a class is made a virtual base class, C++ takes necessary care to see that only one copy of that class is inherited, regardless of how many inheritance paths exist between virtual base class and a derived class. Note: The keywords virtual and public may be used in either order. // only one copy of A // will be inherited // child // parent2 // parentl // grandparent

For example, consider again the student results processing system discussed. Assume that the class sports derives the roll number from the class student. Then, inheritance relationship will be as shown below. Student As virtual base class Test As virtual base class Sports

Result

Virtual base class A program to implement the concept of virtual base class is illustrated below: VIRTUAL BASE CLASS #include <iostream> using namespace std; class student { protected: int roll_number; public: void get_number(int a) { roll_number = a; } void put_number (void) {

cout << Roll No: << roll_number << \n; } }; class test : virtual public student { protected: float part1, part2; public: void get_marks(float x, float y) { part1 = x; } void put_marks(void) { cout << Marks obtained: << \n << Part1 = << \n <<Part2 = << \n; } }; class sports : public virtual student { protected: float score; public: void get_score(float s) { score = s; } void put_score(void) { cout << Sports wt: << score << \n\n; part2 = y;

} }; class result : public test, public sports { float total; public: void display(void); }; void result :: display(void) { total = part1 + part2 + score; put_number(); put_marks(); put_score(); cout << Total Score: << total << \n; } int main() { result student_!; student_1.get_number(678); student_1.get_marks(30.5, 25.5); student_1.get_score(7.0); student_1.display(); return 0; } The output of program would be:

Roll No: 678 Marks obtained: Part1 = 30.5 Part2 = 25.5 Sport wt: 7 Total Score: 63 MEMBER CLASSES: NESTING OF CLASSES Inheritance is the mechanism of deriving certain properties of one class into another. We have seen in detail how this is implemented using the concept of derived classes. C++ supports yet another way of inheriting properties of one class into another. This approach takes a view that an object can be a collection of many other objects. That is, a class can contain objects of other classes as its members as shown below: class alpha { class beta { c1ass gamma { alpha a; beta b; }; All objects of gamma class will contain the objects a and b. This kind of relationship is called containership or nesting. Creation of an object that contains another object is very different than the creation of an independent object. An independent object is created by its constructor when it is declared with arguments. On the other hand, a nested object is created in two stages. First, the member objects are created using their respective constructors and then the other 'ordinary' members are created. This means, constructors of all the member objects should be called before its own constructor body is executed. This is accomplished using an initialization list in the constructor of the nested class. // a is an object of alpha class // b is an object of beta class }; };

Example: class gamma { alpha a; beta b; public: gamma (arg1ist): , a(arg1istl), b(arg1ist2) { // constructor body } }; arglist is the list of arguments that is to be supplied when a gamma object is defined. These parameters are used for initializing the members of gamma. arglistl is the argument list for, the constructor of a and arglist2 is the argument list for the constructor of b. arglistl and arglist2 may or may not use the arguments from arglist. Remember, a(arglistl) and b(arglist2) are function calls and therefore the arguments do not contain the data types. They are simply variables or constants. Example: gamma (int x, int y, float z) : a(x), b(x,z) { Assignment section (for ordinary other members) } We can use as many member objects as are required in a class. For each member object we add a constructor call in the initializer list. The constructors of the member objects are called in the order in which they are declared in the nested class. // a is object of alpha // b is object of beta

Summary An abstract class is one that is not used to create objects. An abstract class is designed only to act as a base class (to be inherited by other classes). C++ supports yet another way of inheriting properties of one class into another. This approach takes a view that an object can be a collection of many other objects. That is, a class can contain objects of other classes as its members Questions 1. What is virtual base class? 2. what do you mean by abstract class? 3. when do we make a class virtual?

UNIT I LESSON 21 STREAMS Objective


C++ streams C++ stream class

INTRODUCTION Every program takes some data as input and generates processed data as output following the familiar input-process-output cycle. It is, therefore, essential to know how to provide the input data and how to present the results in a desired form. We have, in the earlier chapters, used cin and cout with the operators >> and << for the input and output operations. But we have not so far discussed as to how to control the way the output is printed. C++ supports a rich set of I/O functions and operations to do this. Since these functions use the advanced features of C++ (such as classes, derived classes and virtual functions), we need to know a lot about them before really implementing the C++ I/O operations. Remember, C++ supports all of C's rich set of I/O functions. We can use any of them in the C++ programs. But we restrained from using them due to two reasons. First, I/O methods in C++ support the concepts of OOP and secondly, I/O methods in C cannot handle the user-defined data types such as class objects. c++ uses the concept of stream and stream classes to implement its I/O operations with the console and disk files. We will discuss in this chapter, how stream classes support the console- oriented input-output operations. File-oriented I/O operations will be discussed in the next chapter. C++ STREAMS The I/O system in C++ is designed to work with a wide variety of devices including terminals, disks, and tape drives. Although each device is very different, the I/O system supplies an interface to the programmer that is independent of the actual device being accessed. This interface is known as stream. A stream is a sequence of bytes. It acts either as a source from which the input data can be obtained or as a destination to which the output data can be sent. The source stream that provides data to the

program is called the input stream and the destination stream that receives output from the program is called the output stream. In other words, a program extracts the bytes from an input stream and inserts bytes into an output stream as illustrated in Fig. 10.1.

output stream insertion into Output stream Fig. Data streams The data in the input stream can come from the keyboard or any other storage device. Similarly, the data in the output stream can go to the screen or any other storage device. As mentioned earlier, a stream acts as an interface between the program and the inputJoutput device. Therefore, a C++ program handles data (input or output) independent of the devices used. C++ contains several pre-defined streams that are automatically opened when a program begins its execution. These include cin and cout which have been used very often in our earlier programs. We know that cin represents the input stream connected to the standard input device (usually the keyboard) and cout represents the output stream connected to the standard output device (usually the screen). Note that the keyboard and the screen are default options. We can redirect streams to other devices or files, if necessary. Buffers and Synchronization What is a buffer?..Lets understand the working of a buffer memory. A buffer is a temporary holding area in memory which acts as an intermediary between a program and a file or other I/0 device. Information can be transferred between a buffer and a file using large chunks of data of the size most efficiently handled by devices like disc drives. Typically, devices like discs transfer information in blocks of 512 bytes or more, while program often processes information one byte at a time. The buffer helps match these two desperate rates of information transfer. On output, a program first fills the buffer and then transfers the entire block of data to a hard disc, thus clearing the buffer for the next batch of output. C++ handles input by connecting a buffered

stream to a program and to its source of input. similarly, C++ handles output by connecting a buffered stream to a program and to its output target. When we operate with file streams, these are associated to a buffer of type streambuf.. For example, with an out stream, each time the member function put (write a single character) is called, the character is not written directly to the physical file with which the stream is associated. Instead of that, the character is inserted in the buffer for that stream. When the buffer is flushed, all data that it contains is written to the physic media (if it is an out stream) or simply erased (if it is an in stream). This process is called synchronization and it takes place under any of the following circumstances: When the file is closed: before closing a file all buffers that have not yet been completely written or read are synchronized. When the buffer is full: Buffers have a certain size. When the buffer is full it is automatically synchronized. Explicitly with manipulators: When certain manipulators are used on streams a synchronization takes place. These manipulators are: flush and endl. Explicitly with function sync(): Calling member function sync() (no parameters) causes an immediate syncronization. This function returns an int value equal to -1 if the stream has no associated buffer or in case of failure C++ STREAM CLASSES The C++ I/O system contains a hierarchy of classes that are used to define various streams to deal with both the console and disk files. These classes are called stream classes. Figure shows the hierarchy of the stream classes used for input and output operations with the console unit.

ios

pointer istream Input streambuf ostream output

iostream

istream_withassign

iostream_withassign

ostream_withassign

Fig. Stream classes for console I/O operations These classes are declared in the header file iostream. This file should be included in all the programs that communicate with the console unit. As seen in the Fig. ios is the base class for istream (input stream) and ostream (output stream) which are, in turn, base classes for iostream (input/output stream). The class ios is declared as the virtual base class so that only one copy of its members are inherited by the iostream. The class ios provides the basic support for formatted and unformatted I/O operations. The class istream provides the facilities for formatted and unformatted input while the class ostream (through inheritance) provides the facilities for formatted output. The class iostream provides the facilities for handling both input and output streams. Three classes, namely, istream- withassign, ostreamwithassign, and iostream- withassign add assignment operators to these classes. Table gives the details of these classes. Table Class name 1. IOS (input/output stream Contents Contains basic facilities that are (General used by all other input and output

class) .

classes.

Also contains a pointer to a buffer object (streambuf object). Declares constants and functions that are necessary for handling formatted input and output operations. 2. istream (input stream) inherits the properties of ios. Declares input functions such as get(), getline() and read(). Contains overloaded extraction operator.

3. ostream (output stream)

inherits the properties of ios. Declares output functions put() and write().

4. iostream (input / output stream)

inherits the properties of ios istream and ostream through multiple inheritance ,and thus contains all the input and output functions. 5. streambuf Provides an interface to physical devices through buffers. Acts as a base for filebuf class used ios files.

Summary

C++ supports all of C's rich set of I/O functions. First, I/O methods in C++ support the concepts of OOP and secondly, I/O methods in C The I/O system in C++ is designed to work with a wide variety of devices including A stream is a sequence of bytes. It acts either as a source from which the input data can The source stream that provides data to the program is called the input stream and the

cannot handle the user-defined data types such as class objects.

terminals, disks, and tape drives.

be obtained or as a destination to which the output data can be sent.

destination stream that receives output from the program is called the output stream.

A buffer is a temporary holding area in memory which acts as an intermediary between When we operate with file streams, these are associated to a buffer of type streambuf When the buffer is flushed, all data that it contains is written to the physic media (if it is The C++ I/O system contains a hierarchy of classes that are used to define various ios is the base class for istream (input stream) and ostream (output stream) which are,

a program and a file or other I/0 device.


an out stream) or simply erased (if it is an in stream)

streams to deal with both the console and disk files.

in turn, base classes for iostream (input/output stream). Question


What is stream?. Explain C++ stream classes? Describe briefly the features of I/O system supported by C++.

UNIT I LESSON 22 STREAMS II Objective


Put & Get Function Getline & Write function

put() and get() Functions The classes istream and ostream define two member functions get() and put() respectively to handle the single character input/output operations. There are two types of get() functions. We can use both get(char *) and get (void) prototypes to fetch a character including the blank space, tab and the newline character. The get (char *) version assigns the input character to its argument and the get (void) version returns the input character. Since these functions are members of the input/output stream classes, we must invoke them using an appropriate object. Example: char c; cin.get(c) ; while(c != '\n') { cout c; cin.get(c); } This code reads and displays a line of text (terminated by a newline character). Rememter, the operator >> can also be used to read a character but it will skip the white spaces and newline character. The above while loop will not work properly if the statement ci n >> c; // display the character on screen // get another character // get a character from keyboard and assign it to c

is issued in place of cin.get(c) ; The get(void) version is used as follows: cha r c; c=cin/get(); The value returned by the function get() is assigned to the variable c. The function put(), a member of ostream class, can be used to output a line of text, character by character. For example, cout.put( x); displays the character x and cout. put (ch) ; displays the value of variable ch. The variable ch must contain a character value. We can also use a number as an argument to the function put(). For example, cout. put (68) ; displays the character D. This statement will convert the int value 68 to a char value display the character whose ASCII value is 68. The following segment of a program reads a line of text from the keyboard and displays on the screen. char c; cin.get(c); while (c ! = \n ) { cout.put(c) ; cin.get(c); / / display the character on screen / / read a character // cin.get(c); replaced

} Program illustrates the use of these two character-handling functions. # include <iostream> int main() { int count = 0; char c; cout << "INPUT TEXT\n; cin.get{c); while(c!=\n) { cout.put(c); count++ ; cin.get( c); } cout <<"\n Number of characters = << cout << \n; return 0; } Input Object Oriented Programming Output Object Oriented Programming Number of characters = 27

Getline() and write() Functions

We can read and display a line of text more efficiently using the line-oriented input / output functions getline() and write(). The getline() function reads a whole line of text that ends with a newline character (transmitted by the RETURN key). This function can be invoked by using the object cin as follows: Cin.getline(line,size);

This function call invokes the function getline() which reads character input into the variable line. The reading is terminated as soon as either the newline character '\n' is encountered or size-1 characters are read (whichever occurs first). The newline character is read but not saved. Instead, it is replaced by the null character. For example, consider the following code: char name [20] ; cin.getl i ne(name, 20); Assume that we have given the following input through the keyboard: Bjarne Stroustrup <press RETURN> This input will be read correctly and assigned to the character array name. Let us suppose the input is as follows: Object Oriented Programming <press RETURN>

In this case, the input will be terminated after reading the following 19 characters: Object Oriented Pro Remember, the two blank spaces contained in the string are also taken into account. We can also read strings using the operator as follows: cin >> name; But remember cin can read string that do not contain white spaces. This means that cin Can read just one word and not a series of Word such as Bjarne Stroustrup. But it can read the following string correctly.

Bjarne_Stroustrup After reading the string, cin automatically adds the terminating null character to the character array. #include <iostream.h> int main() { int size = 20; char city[20]; cout<< enter city name : \n; cin>> city; cout<<city name:<<city<<\n\n; cout<< enter city name again : \n; cin.getline(city, size); cout<<city name now : <<city << \n\n; cout<<enter another city name:\n; cin.getline(city, size); cout<<new city name : << city << \n\n; return 0; }

output first run enter city name: Delhi City name: Delhi enter city name again: city name now: enter another city name: chennai

new city name: chennai Second run enter city name: New Delhi City name: New enter city name again: city name now: Delhi enter another city name: Greater Mumbai new city name: Greater Mumbai During first run, the newline character '\n' at the end of "Delhi" which is waiting in the input queue is read by the getline() that follows immediately and therefore it does not wait for any response to the prompt 'Enter city name again:'. The character '\n' is read as an empty line. During the second run, the word "Delhi" (that was not read by cin) is read by the function getline() and, there(ore, here again it does not wait for any input to the prompt 'Enter city name again:'. Note that the line of text "Greater Bombay" is correctly read by the second cin.getline(city,size); statement. Write() function displays an entire line and has the following form: Cout.write (line, size) First argument line represents the name of the string to be displayed and the second argument size indicates the number of characters to display. Note that it does not stop displaying the Characters automatically when the null character is encountered. If the size is greater than the line, then it displays beyond the bounds of line. Program illustrates how write() displays a string. Displaying string with Write() #include<iostream,h>

#include<string.h> int Main() { char * string1 = C++ char * string2 = Programming; int m = strlen(string1); int n = strlen(string2); for(int i=1; i<n; i++) { cout.write(string2,i); cout<< \n; } for(int i=n; i>0; i--) { cout.write(string2,i); cout<< \n; } cout.write(string1,m).write(string2,n); cout<< \n; cout. write(string1,10); return 0; } output P Pr Pro Prog Progr Progra Program

Programm Programmi Programmin Programming Programmin Programmi Programm Program Progra Progr Prog Pro Pr P C++ Programming C++ Progr The last line of the output indicates that the statement cout.write(string1, 10); displays more characters than what is contained in stringl. It is possible to concatenate two strings using the write() function. The statement cout.write(string1, m).write(string2, n); is equivalent to the following two statements: cout.write(string1, m); cout.write(string2, n); Summary

The classes istream and ostream define two member functions get() and put() The function put(), a member of ostream class, can be used to output a line of text,

respectively to handle the single character input/output operations.

charac-ter by character.

We can read and display a line of text more efficiently using the line-oriented input / The getline() function reads a whole line of text that ends with a newline character Write() function displays an entire line

output functions getline() and write().


Question

Discuss the various forms of get() function supported by the input stream. How are they used? How do the following two statements differ in operation? cin>>c; cin.get(c); Both cin & getline() function can be used for reading a string. Comment?

UNIT I Lesson 23 Tutorial on polymorphism and Streams

UNIT I LESSON 24 WORKING WITH FILES Objectives Opening a file with constructors File stream classes INTRODUCTION Many real-life problems handle large volumes of data and, in such situations, we need to use some devices such as floppy disk or hard disk to store the data. The data is stored in these devices using the concept of files. A file is a collection of related data stored in a particular area on the disk, Programs can be designed to perform the read and write operations on these files. A program typically involves either or both of the following kinds of data communication: 1. Data transfer between the console unit and the program. 2. Data transfer between the program and a disk file. This is illustrated in Fig. below External memory

Data files

Program file interaction Read data (from files)

Write Data (to files) Internal Memory Program + Data

cout<< (put data to screen)

Console program interaction

Sceen cin>> (get data from keyboard)

Keyboard Console program file interaction We have already discussed the technique of handling data communication between the console unit and the program. In this chapter, we will discuss various methods available for storing and retrieving the data from files. The I/O system of C++ handles file operations, which are very much similar to the console input and output operations. It uses file streams as an interface between the programs and the files. The stream that supplies data to the program is known as input stream and the one that receives data from the program is known as output stream. In other words, the input stream extracts (or reads) data from the file and the output stream inserts (or writes) data to the file. This is illustrated in Fig. below

Input stream Read data Data input

Disk files Output stream Write data File input and output streams

Program Data O/P

The input operation involves the creation of an input stream and linking it with the program and the input file. Similarly, the output operation involves establishing an output stream with the necessary links with the program and the output file.

ios

Iostream file

istream

streambuf

ostream

iostream

Fstream file ifstream

fstream

ofstream

filebuf

Fstream base

Fig. Stream classes for file operations CLASSES FOR FILE STREAM OPERATIONS The I/O system of C++ contains a set of classes that define the file handling methods. These include ifstream, ofstream and fstream. These classes are derived from fstreambase and from the corresponding iostream class as shown in Fig. 11.3. These classes, designed to manage the disk files are declared in fstream and therefore we must include this file in any program that uses files.

Table shows the details of file stream classes. Note that these classes contain many more features. Class content

Filebuf Its purpose is to set the file buffers to read and write. Contains Openprot constant used in the open() of file stream classes. Also contain close() and open() as member. fstreambase Provides operations common to the file streams. Serves as a base for fstream, if stream and of stream class. Contains open() and close() functions. Provides input operations. Contains openO with default input mode. Inherits the functions getO, getlineO, readO, seekgO and tellgO functions from istream. Provides output operations. Contains openO with default output mode. Inheritsput(), see}(p(), !~llP(),. and writ~(), functions from ostream. Provides support for simultaneous input and output operations. Contains open() with default input mode. Inherits all the functions from istream and ostream classes through iostream.

ifstream

Ofstream Fstream

OPENING AND CLOSING A FILE If we want to use a disk file, we need to decide the following things about the file and its intended use: 1. 2. 3. 4. Suitable name for the file. Data type and structure. Purpose. Opening method.

The filename is a string of characters that make up a valid filename for the operating system. It may contain two parts, a primary name and an optional period with extension. Examples: Input.data Test.doc INVENT.ORY Student salary OUTPUT As stated earlier, for opening a file, we must first create a file stream and then link it to the filename. A file stream can be defined using the classes ifstream, of stream, and ofstream that are contained in the header file (stream. The class to be used depends upon the purpose, that is, whether we want to read data from the file or write data to it. A file can be opened in two ways:

Using the constructor function of the class. Using the member function open() of the class. The first method is useful when we use only one file in the stream. The second method is used when we want to manage multiple files using one stream. Opening Files Using Constructor We know that a constructor is used to initialize an object while it is being created. Here, a filename is used to initialize the file stream object. This involves the following steps: 1. Create a file stream object to manage the stream using the appropriate class. That is to say, the class ofstream is used to create the output stream and the class ifstream to create the input stream. 2. Initialize the file object with the desired filename. For example, the following statement opens a file named "results" for output: ofstream outfile("results"); / / output only

This creates outfile as an ofstream object that manages the output stream. This object can be any valid C++ name such as o_file, myfile or fout. This statement also opens the file results and attaches it to the output stream outfile. This is illustrated in Fig. Disk Output stream Results file

program Input stream Data file

Two file streams working on separate files Similarly, the following statement declares infile as an if stream object and attaches it to the file data for reading (input), Ifstream infile ("data") ; // input only

The program m~y contain statements like:

outfile << "TOTAL"; outfile <<sum; infile >>number; infile >>string; program1 . . program2 get data .. infile put data outfile Salary file

Two file streams working on one file We can also-use the same file for both reading and writing data as shown in Fig. 11.5. The programs would contain the following statements: Program 1 ------------------ofstream outfile ("salary"); --------------------Program 2 ------------------ifstream infile ("salary"); ---------------------

// creates outfi1e and connects // "salary" to it

// creates infi1e and connects // "salary" to it

The connection with a file is closed automatically when the stream object expires (when the program terminates). In the above statement, when the program l is terminated, the salary file is disconnected from the outfile stream. Similar action takes place when the program 1 terminates.

Instead of using two programs, one for writing data (output) and another for reading data (input), we can use a single program to do both the operations on a file. Example. ------------------outfile.close(); ifstream infile ("sa1ary") ; ------------------infile.closeO; // Disconnect salary from infile

// Disconnect salary from outfile // and connect to infile

Although we have used a single program, we created two file stream objects, outfile (to put data to the file) and infile (to get data from the file). Note that the use of a statement like outfile.close(); disconnects the file salary from the output stream outfile. Remember, the object outfile still exists and the salary file may again be connected to outflle later or to any other stream. In this example, we are connecting the salary file to infile stream to read data. Program uses a single file for both writing and reading the data. First, it takes data from the keyboard and writes it to the file. After the writing is completed, the file is closed. The program again opens the same file, reads the information already written to it and displays the same on the screen.

Working with single file // Creating files with constructor function #include <iostream.h> #include <fstream.h> int main() { ofstream outf("ITEM"); cout "Enter item name:" ; char name [30] ;

cin >> name; outf << name "\n"; cout << "Enter item cost:"; float cost; cin >> cost; outf << cost "\n."; outf.close(); ifstream inf ("ITEM") ; inf>> name; inf >>cost; cout << "\n."; cout << "Item name: <<name <<\n; cout "Iterm cost: << cost <<\n; inf.close(); return 0; } The output of Program would be: Enter itern name: CD-ROM Enter item cost : 250 Item name:CD-ROM Item cost:250 When a file is opened for writing only, a new file is created if there is no file of that name. If a file by that name exists already, then its contents are deleted and the file is presented as a dean file. We shall discuss later how to open an existing file for updating it without losing its original contents. Opening Files Using open() As stated earlier, the function open() can be used to open multiple files that use the same stream object. For example, we may want to process a set of files sequentially. In such cases, we may create a single stream object and use it to open each file in turn. This is done as follows Example: File-stream-class stream-objects; Stream-object.open (filename); Example: ofstream outfile; outfile.open("DATAl"); ------------------------//Create stream (for output) // Connect stream to DATAl

outfile.close() ; outfile.open("DATA2); ------------------------outfile.close() ; --------------------------

// Disconnect stream from DATA1 // Connect stream to DATA2

// Disconnect stream from DATA2

The above program segment opens two files in sequence for writing the data. Note that the first file is closed before opening the second one. This is necessary because a stream can be connected to only one file at a time. See following Program.

// Creating files with open() function #include <iostream.b> #include <fstream.h> int main() { ofstream fout; fout.open ("country") //create output stream // connect "country" to it

fout << "United States of America \n"; fout <<; "United Kingdom \n"; fout << "South Korea \n"; fout.close(); fout.open ("capital") ; fout<< "Washi ngton\n"; fout <<london \n"; fout <<"Seoul \n"; fout.close(); // Reading the files const int N= 80; char 1ine [N]; ifstream fin; fin.open ("country"); cout <<"contents of country file \n"; whi1e (f in) //disconnect "country" and //connect" capita1 "

// disconnect "capital" II size of line // create input stream // connect "country" to let

{ fin.getline(line, N); cout<< line ; } fin.close(); fin.open("capital "); cout "\nContents of capital file \n"; while{fin) { fin.getline(line, N); cout << 1ine ; } fin.close(); return 0; } The output of Program would be: Contents of country file United States of America United Kingdom South Korea Contents of capital file Washington London Seoul

// check end of file // read a line //display it // disconnect "country" and // connect "capital"

Disk Country file

connect 1 file to fout

fout program

Capital file Connect 1 file to fin Fig. Streams working on multiple files

fin program

At times we may require to use two or more files simultaneously. For example, we may require to merge two sorted files into a third sorted file. This means, both the sortedfilesha1!1 to be kept open for reading and the third one kept open for writing. In such cases, we need create two separate input streams for handling the two input files and one output stream for handling the output file.

// Reads the files created in Program #include <iostream.h> #include <fstream.h> #include <stdlib.h> int main() { const int SIZE = 80; char line[SIZE]; ifstream fin1, fin2; fin1.open(country") ; fin2.open(capital"); for(int i=l; i<=10; i++) { if(fin1.eof() ! = 0) { cout <<Exit from country \n"; exit(1); } fin1.getline(line.SIZE); cout<< "Capital of "<<line; if(fin2.eof() != 0)

/ / for exit() function

create two input streams

{ cout<< "Exit from capital\n"; exit (1) ; } fin2.getline(line, SIZE); cout << 1ine << "\n"; .} return 0; The output of Program would be: Capital of United States of America Washington Capital of United Kingdom London Capita] of South Korea Seou1 1.4 DETECTING END-OF FILE Detection of the end-of-file condition is necessary for preventing any further attempt to read data from the file. This was illustrated in Program by using the statement while(fi n) An ifstream object, such as fin, returns a value of 0 if any error occurs in the file operation including the end-of-file condition. Thus, the while loop terminates when fin returns a valuezero on reaching the end-of-file condition. Remember, this loop may terminate due to other failures as well. (We will discuss other error conditions later.) There is another approach to detect the end-of-file condition. Note that we have used the following statement in above Program if(fin1.eof() ! = 0) { exit(l); } eof() is a member function of ios class. It returns a non-zero value if the end-of-file (EOF) condition is encountered, and a zero, otherwise. Therefore, the above statement terminates the program on reaching the end of the file.

Summary . The C++ I/O system contains classes such as ifstream, ofstream and fstream todeal with file handling. These classes are derived from fstreambase class and aredeclared in a header file iostream. A file can be opened in two. ways by using the constructor function of the class andusing the member function open() of the class. While opening the file using constructor, we need to pass the desired filename as a parameter to the constructor. The openO function can be used to open multiple files that use the same stream object. The second argument of the openO function called file mode, specifies the purpose for which the file is opened. If we do not specify the second argument of the openO function, the default values specified in the prototype of these class member functions are used while opening the file. Questions

1 What are input and output streams? 2 What are the steps involved in using a file in a C++ program? 3 Describe the various classes available for file operations? 4 What is the difference between opening a file with a constructor function and opening a file with openO function? When is one method preferred over the other?

UNIT I Lesson 25 Working with files II Objective File modes file pointers sequential access file Random access file

MORE ABOUT OPEN(): FILE MODES We have used ifstream and of stream constructors and the function open() to create new files as well as to open the existing files. Remember, in both these methods, we used only one argument that was the filename. However, these functions can take two arguments, the second one for specifying the file mode. The general form of the function open() with two arguments is: stream-object.open("filename", mode); The second argument mode (called file mode parameter) specifies the purpose for which file is opened. How did we then open the files without providing the second argument in the previous examples? The prototype of these class member functions contain default values for the second argument and therefore they use the default values in the absence of the actual values. The default valuel are as follows: ios::in for ifstream functions meaning open for reading only. ios::out for ofstream functions meaning open for writing only. The file mode parameter can take one (or more) of such constants defined in the class ios. lists the file mode parameters and their meanings. Table File mode parameters Parameter
ios::app ios::ate ios::in

Meaning Append data to the end of the output file. Go to the end of the file when opened. Open for reading only

ios::out ios::binary ios::trunc ios::nocreate ios::noreplace

Open file for output Binary file (if not present, the file is opened as an ASCII file). See the later section "Binary I/O" for a definition of a binary file. Delete contents of existing file when opening for write. Fail if the file does not exist. (Output files only. Opening an input file always fails if there is no file.) Open files if the file already exists

1. Opening a file in ios::out mode also opens it in the ios::trunc mode by default. 2. Both ios:app and ios::ate take us to the end of the file when it is opened, The difference between the two parameters is that the ios::app allows us to add data to the end of the file only, while ios::ate mode permits us to add data or to modify the existing data anywhere in the file. In both the cases, a file is created by the specified name, if it does not exist. 3. The parameter ios::app can be used only with the files capable of output. 4. Creating a stream using ifstream implies input and creating a stream using ofstream implies output. So in these cases it is not necessary to provide the mode parameters. 5. The fstream class does not provide a mode by default and therefore, we must provide the mode explicitly when using an object of fstream class. 6. The mode can combine two or more parameters using the bitwise OR operator (symbol I ) shown as follows: fout.open("data", ios::app | ios:: nocreate) This opens the file in the append mode but fails to open the file if it does not exist. FILE POINTERS AND THEIR MANIPULATIONS Each file has two associated pointers known as the file pointers. One of them is called the input pointer (or get pointer) and the other is called the output pointer (or put pointer). We can use pointers to move through the files while reading or writing. The input pointer is used for reading the contents of a given file location and the output pointer is used for writing to a given location. Each time an input or output operation takes place, the appropriate pointer is

automa tically advanced. Default Actions When we open a file in read-only mode, the input pointer is automatically set at the beginning So that we can read the file from the start. Similarly, when we open a file in write-only mode, the existing contents are deleted and the output pointer is set at the beginning. This enables us to it write to the file from the start. In case, we want to open an existing file to add more data, the file is opened in 'append' mode. This moves the output pointer to the end of the file (i.e. the end of the existing contents). "hello" file Open for reading only H E L L O input pointer Open in append mode (for writing more data) W O R L D

H E L L O

W O R L D output pointer

Open for writing only output pointer

Action on file pointers while opening a file Functions for Manipulation of File Pointers All the actions on the file pointers as shown in Fig. take place automatically by default. How do we then move a file pointer to any other desired position inside the file? This is possible only if we can take control of the movement of. the file pointers ourselves. The file stream classes support the following functions to manage such situations: seekg() seekp() tellg() Moves get pointer (input) to a specified location. Moves put pointer(output) to a specified location. Gives the current position of the get pointer.

Tellp()

Gives the current position of the put pointer.

For example, the statement infile.seekg (10 ); moves the file pointer to the byte number 10. Remember, the bytes in a file are numbered beginning from zero. Therefore, the pointer will be pointing to the 11th byte in the file.

Consider the following statements: ofstream fileout; fileout.open("hello", ios::app); int p = fileout.tellp(); On execution of these statements, the output pointer is moved to the end of the file "hello" an! the value of p will represent the number of bytes in the file. Specifying the offset We have just now seen how to move a file pointer to a desired location using the 'seek' functions. The argument to these functions represents the absolute position in the file. This is shown Fig file file pointer start outfile.seekp(m); m-bytes File pointer end

'Seek' functions seekg() and seekp() can also be used with two arguments as follows: seekg (offset, ref position); seekp (offset, refposition); The parameter offset; represents the number of bytes the file pointer is to be moved from the location specitied by the-parameter refposition.. The refposition takes one of the following three constants defined in the ios class:

ios::beg ios::cur ios::end

start of the file current position of the pointer end of the file

The seekg() function moves the associated file's 'get' pointer while the seekp() function moves the associated file's 'put' pointer. SEQUENTIAL INPUT AND OUTPUT OPERATIONS File stream classes support a number of member functions for performing the input and output operations on files. One pair of functions, put() and get(), are designed for handling a single character at a time. Another pair of functions, write() and read(), are designed to write and read blocks of binary data. Put() and get() Functions Tbe function put() writes a single character to the associated stream. Similarly, the function getO reads a single character from the associated stream. Program below illustrates how these fnctions work on a file. The program requests for a string. On reeiving the string, the program writes it, character by character, to the file using the put() function in a for loop. Note that the length of the string i& used to terminate the for loop. The program then displays the contents of the file on the screen. It uses the function get() to fetch a character from the file and continues to do so until the end-of-file condition is reached. The character read from the file is displayed on the screen using the operator <<.

#include <iostream.h> #i nclude <fstream.h> #i nclude <string.h> int main() { char string[80]; cout<< n Enter a string \n "; cin>>string;

int len = strlen(string); fstream file; // input and output stream file.open(TEXT", ios::in | ios::out); for(int i=0; i<len; i++) fi1e.put(string [i]); // put a character to file file.seekg(0); char ch; while(file) { file.get(ch) ; cout << ch; } return 0; } // go to the start

// get a character from file //display it ()n screen

The output of Program would be Enter a string Cobol_Programming Cobol_Programming input output

We have useid an fstream objectto open the file. Since an fstream object can handle both the input and output simultaneously, we have opened the file in ios::in | ios::out mode. After writing the file, we want to read the entire file and display its content. Since the file pointer has already moved to the end of the file, we must bring it back to the start of the file. This is done by the statement file.seekg(0); Write() and read() Functions for Binary files The functions write() and read(), unlike the functions put() and get(), handle the data in binary form. This means 'that the values are stored in the disk file in the same format in which they are stored in the internal memory. The binary format is more accurate fro storing the numbers as they are stored in the exact internal representation. There are no conversions while saving the data and therefore saving is much faster.

The binary input and output functions takes the following form: infile. read ((char *) & V, sizeof (V)); outfile.write ((char *) & V, sizeof (V)); These functions take two arguments. The first is the address of the variable V, and the second is the length of that variable in bytes. The address of the variable must be cast to type char' (i.e. pointer to character type). Program 11.5 illustrates how these two functions are used to save an array of float numbers and then recover them for display on the screen. Prog.: I/O operation on Binary Files # include<iostream.h> # include<fstream.h> # include<iomainp.h> const char * filename = "BINARY"; int main() { float height[4] = {175.5,153.0, 167.25, 160.70}; ofstream outfile; outfile.open(filename); outfile.write ((char *) & height, sizeof(height)); outfile.close(); for(int i;=0; i<4; i++) / / clear array from memory height[i] = 0; outfile.close(); ifstream infile; infile.open (fi1ename) ; infile.read((char *) & height. sizeof(height)); for(i=0;i<4;i++) { cout.setf (ios::showpoint); cout<< setw(10) << setprecision(2) << height[i]; } return 0; The output of Program 175.50 153.00 167.25

Reading and Writing a Class Object

We mentioned earlier that one of the shortcomings of the I/O system of C is that it cannot handle userdefined data types such as class objects. Since the class objects are the central element C++ programming, it is quite natural that the language supports features for writing to a reading from the disk files objects directly. The binary input and output functions read() and write() are designed to do exactly this job. These functions handle the entire structure of object as a single unit, using the computer's internal representation of data. For instance, function write() copies a class object from memory byte by byte with no conversion. one important point to remember is that only data members are written to the disk me and member functions are not. Program illustrates how class objects can be written to and read from the disk file!. The length of the object is obtained using the sizeof operator. This length represents them total of lengths of all data members of the object. #include <iostream.h> #include <fstream.h> #include <iomainp.h> class INVENTORY { char name,[10]; int code;

// item name // item code

float cost; public: void readdata(void); void writedata(void);

/ / cost of each item

}; void INVENTORY:: readdata(void) { //read from keyboard cout << "Enter name: ; cin >> name; cout << " Enter code:; cin >> code; cout <<"Enter cost:; cin>> cost; } void INVENTORY:: writedata (void) / / formatted { / / screen cout << setiosflags(ios::left) << setw(10) << name. << setiosflags(ios: :right) << setw(10)<< code << setprecision(2} << setw(lO) << << endl; } int main () { INVENTORY item[3]; fstream fi1e; file.open (STOCK.DAT , ios::in | ios::out); cout << ENTER DETAILS FOR THREE ITEMS \n ; for(int i =0; i <3; i ++) { item[i].readdata(); file.write((char*) & item[i] .sizeof(item[i])); } file. seekg (0); cout << \nOUTPUT\n\n; for(i= 0; i < 3;I++) { file. read [(char *) & item[ih sizeof(i tem[i]; i tem[i] .writedata 0; return 0; }

The output of Program ENTER DETAILS FOR THREE ITEMS Enter name: C++ Enter code: 101 Enter cost: 175 Enter name: FORTRAN Enter code: 102 Enter cost: 150 Enter name: JAVA Enter code: 115 Enter cost: 225 OUTPUT C++ FORTRAN JAVA 101 102 115 175 150 225

The program uses 'for' loop for reading and writing objects. This is possible because we Know the exact number of objects in the file. In case, the length of the file is not known, we can determine the file-size in terms of objects with the help of the file pointer functions and use it in the 'for' loop or we may use while (file) test approach to decide the end of the file. These techniques are discussed in the next section. UPDATING A FILE: RANDOM ACCESS Updating is a routine task in the maintenance of any data file. The updating would include one or more of the following tasks:

Displaying the contents of a file. Modifying an existing item. Adding a new item. Deleting an existing item.

These actions require the file pointers to move to a particular location that corresponds to the item/object under consideration. This can be easily implemented if the file contains a collection of

items/objects of equal lengths. In such cases, the size of each object can be obtained using the statement int object_length = sizeof(object); Then, the location of a desired object, say the mth object, may be obtained as follows: int location = m * object_length; The location gives the byte number of the first byte of the mth object. Now, we can set the file pointer to reach this byte with the help of seekg() or seekp(). We can also find out the total number of objects in a file using the object_length as follows: int n = file_size/object_length; Tbe file_size can be obtained using the function tellgO or tellpO when the file pointer is located at the end of the file. Program illustrates how some of the tasks described above are carried out. The program uses the "STOCKDAT" file created using Program for five items and performs following operations on the file: 1. Adds a new item to the file. 3. Modifies the details of an item. 4. 3, Displays the contents of the file #include <iostream. h> #include <fstream.h> #inc1ude <iomanip. h> c1ass INVENTORY { char name[l0] ; int code; float cost; public: void getdata(void) { cout << "Enter name: ; ci n >> name ; cout << Enter code:; cin >> code; cout<<"Enter cost :; cin >> cost; } void putdata (void) { cout << setw(10) << name << setw(l0) << code << setprecision(2)<< setw(10) << cost << endl; }

}; // End of class definition int main() { INVENTORY item; fstream inoutfile;

inoutfile.open("STOCK.DAT", ios:: ate | ios:: in | ios::out | ios::binary); inputfile.seekg(0,ios:: beg) ; // go to start cout << "CURRENT CONTENTS OF STOCK" << "\n"; while(inoutfile.read((char *) & item, sizeof item)) { item.putdataO; } inoutfi1e.c1ear(); // turn of EOF flag /* > Add one more item * / cout << "\n ADD AN ITEM \n; item.getdata(); char ch; cin.get(ch); inoutfile.write( (char & item, si zeof item); / / Display the appened file inoutfi1e.seekg(Q). // go to the start cout << "CONTENTS OF APPENDED FILE \n"; while (inoutfile.read((char *) & item , sizeof item)) { item.putdata(); } //find number of objects in the fi1e int last= inoutfile.tellg(); int n = last/sizeof(item); cout << "Number of objects = " n "\n"; cout <<Total bytes in the file = <<last<<\n;

/*<<<<<<<<<<<<MODIFY THE DETAILS OF AN ITEM <<<<<<<<<<< */ cout <<Enter object number to be updated \n"; int object; cin>>object; cin.get(ch); int location=(object-1)*-sizeof(item); if(inoutfile.eof()) inoutfile.clear(); cin.get(ch); I int location" (object-I) * sizeof(item); if(inout fi1e .eof()) inoutfile.clear() ; inoutfi1e.seekp(location) ; cout << "Enter new values of object \n"; item.getdata(); cin.get(ch); inoutfile.writechar *) & item, sizeof item)?<< flush; /-*> SHOW UPDATED FILE <<<<<<< */ inoutfile.seekg(O); // go to the start cout << "CONTENTS OF. UPDATED FILE \n; while(inoutfile.read((char *) & item sizeof item)) { item.putdata() ; } inoutfile.close(); return 0; } //End of main The output of Program would be: CURRENT CONTENTS OF STOCK AA 11 100 BB 22 200

CC 33 300 DO 44 400 XX 99 900 ADD AN ITEM Enter name: YY Enter code: 10 Enter cost: 101 CONTENTS OF APPENDED FI LE AA 11 100 BB 22 200 CC 33 300 DD 44 400 XX 55 500 YY 66 600 Number of objects = 6 Tota1 bytes in the fi1es = 96 Enter object number to be updated 6 Enter new values of the object Enter name: ZZ Enter code: 20 Enter cost: 201 CONTENTS OF UPDATED FI LE AA 11 100 SS 22 200 CC 33 300 DD 44 400 XX 99 900 ZZ 20 201 We are using the fstream class to declare the me streams. The fstream class inherits two buffers, one for input and another for output, and synchronizes the movement of the file pointers on these buffers. That is, whenever we read from or write to the file, both the pointers move in tandem. Therefore, at any point of time, both the pointers point to the same byte. Since we have to add new objects to the file as well as modify some of the existing objects, we open the file using ios::ate option for input and output operations. Remember, the option ios::app allows us to add data to the end of the file only. The ios::ate mode sets the file pointers at the end of the file

when opening it. We must therefore move the 'get' pointer to the.beginning of the file using the function seekg() to read the existing contents of the file. At the end of reading the current contents of the file, the program sets the EOF flag on. This prevents any further reading from or writing to the file. The EOF flag is turned off by using the function clear(), which allows access to the file once again. After appending a new item, the program displays the contents of the appended file and also the total number of objects in the file and the memory space occupied by them. To modify an object we should reach to the first byte of that object. This is achieved using the statements . int location = (object-1) * sizeof(item}; inoutfile.seekp(location};

The program accepts the number and the new values of the object to be modified and updates it finally , the contents of the appended and modified file are displayed. Remember , we are opening an existing file for reading and updating the values. It is, therefore, essential that the data members are of the same type and declared in the same order as in the , file. Since, the member functions are hot stored, they can be different.

Summary

When a file is opened for writing only, a new file is created only if there is no file of that name. If a file by that name already exists, then its contents are deleted and the file is presented as a clean file. To open an existing file for updating without losing its original contents, we need to open it in an append mode. The fstream class does not provide a mode by default and therefore we must provide the mode explicitly when using an object off stream class. We can specify more than one file modes using bitwise OR operator while opening a file.

Each file has associated two file pointers, one is called input or get pointer, while the other is called output or put pointer. These pointers can be moved along the files by member functions. putO and getO functions handle single character at a time. writeO and readO functions write and read blocks of binary data

Questions

1 .What is a file mode? Describe the various file mode options available. 2 Write a statement that will create an object called fob/or writing, and associate it with a file name DATA. How many file objects would you need to create to manage the following situations? (a) To process four files sequentially. (b) To merge two sorted files into a third file. Explain. Both ios::ate and ios::app place the file pointer at the end of the file (when it is opened). What then, is the difference between them?

UNIT I

Lesson 26 Working with file III

Objectives Error handling Command line arguments

ERROR HANDLING DURING FILE OPERATIONS So far we have been opening and using the files for reading and writing on the assumption that everything is fine with the files. This may not be true always. For instance, one of the Following things may happen when dealing with the files: 1. A file which we are attempting to open for reading does not exist. 2, The file name used for a new file may already exist. 3, We may attempt an invalid operation such as reading past the end-of-file. 4. There may not be any space in the disk for storing more data. 5. We may use an invalid file name. 6. We may attempt to perform an operation when the file is not opened for that purpose. The c++ file stream inherits a 'stream-state' member from the class ios. This member records information on the status of a file that is being currently used. The stream state member uses bit fields to store the status of the error conditions stated above. The class ios supports several member functions that can be used to read the status ! recorded in a file stream. These functions along with their meanings are listed in Table Table Error handling functions function Return value and meaning Returns true (non-zero value) if end-of-file is encountered eofO while reading; Otherwise returns false(zero) Returns true when an input or output operation has Fail() failed BadO Returns true if an invalid operation is attempted or any Unrecoverable error has occurred. However, if it is false, it

goodO

May be possible to recover from any other error reported, And continue operation. Returns true if no error has occurred. This means, all the Above functions are false. For instance, if file.goodO is True, all is well with the stream file and we can ,proceed to Perform I/O operations. When it returns false, no further Operations can be carried out. .

These functions may be used in the appropriate places in a program to locate the status of a file stream and thereby to take the necessary corrective measures. Example: ifstream infile; infile.open("ABC"); while(!infile.fail ()) { (process the fi 1 e) .. .. } i f(infi1e.eof()) { (terminate program normally) } else if(infile.bad()) { } else { infile.clear() ; .. } .. (report fatal error) // clear error state

The function clear() (which we used in the previous section as well) resets the error stateSil that further operations can be attempted. Remember that we have already used statements such as while(infile) { . .. } and while(infile.read()) { . Here, infile becomes false (zero) when end of the file is reached ( and eofO becomes true).

COMMAND-LINE ARGUMENTS Like C, C++ too supports a feature that facilitates the supply of arguments to the main() function. These arguments are supplied at the time of invoking the program. They are typically used to pass the names of data files. Example: C> exam data results

Here, exam is the name of the file containing the program to be executed, and data and results are the filenames passed to the program as command-line arguments. The command-line arguments are typed by the user and are delimited by a space. The first argument is always the filename (command name) and contains the program to be executed. How do these arguments get into the program? The main() functions which we have been using up to now without any arguments can take two arguments as shown below: main(int argc, char * argv[]) The first argument argc (known as argument counter) represents the number of arguments in the command line. The second argument argv (known as argument vector) is an array of char type pointers that points to the command line arguments. The size of this array will be equal to the value of argc. For instance, for the command line . C > exam data results

the value of argc would be 3 and the argv would be an array of three pointers to strings as shown below: argu [0]_> exam argu [1] n_> data argu[2] ---> results Note that argv[0] always represents the command name that invokes the program. The character pointers argv[l] and argv[2] can be used as file names in the file opening statements as shown below: .. .. infile.open(argv[l]); outfile.open(argv[2]);

// open data fi 1 e for reading // open results file for writing

Program illustrates the use of the command-line arguments for supplying the The command line is Test ODD EVEN The program creates two files called ODD and EVEN using the command-line arguments and a set of numbers stored in an array are written to these files. Note that the odd numbers are written to the file ODD and the even numbers are written to the file EVEN. The then displays the contents of the files.

#include <iostream.h> #include <fstream.h> #include <stdlib.h> main(int argc, char * argv[]) { int number [9] = {1l.22.33.44.55!66.77 .88.99}; It(argc != 3) { cout<<argc=<<argc<<\n; cout <<Error in arguments \n; exit(1); } ofstream foutl. fout2; fout1.open(argv[1]); if(fout1.fail()) {

cout << could not open. the file << argv[2] << \n; exit(1); } for ( int i=0; i<9;i++) { if(number[ i ] % 2 == 0) fout2 number[i] "; e1se fout 1<< number[i]<< ; } fout1.close(); fout2.close(); ifstream. fin; char ch; for(i=1; i<argc; i++) { fin.open(argv[i]);

// write to. EVEN file // write to ODD file

cout "Contents of << argv[i] << \n; do . { fin.get(ch); cout << ch; } while(fin); cout << ''\n\n; fin.close(); } return 0; }

/ / read a value / / display it

The output of Program would be: Cantents af ODD 11 33 55 77 99 Cantents af EVEN 22 44 66 88

Summary . The class ios supports many member functions for managing errors that may occur during file operations. . File names may be supplied as arguments to the main() function at the time of invoking the program. These arguments are known as command-line arguments.

Questions 1. What does the "current position" mean when applied to files? 2. Write statements using seekg() to achieve the following: (a) To move the pointer by 15 positions backward from current position. (b) To go to the beginning after an operation is over. (c). To go backward by 20 bytes from the end. (d) To go to byte number 50 in the file.

UNIT I LESSON 27 TEMPLATE I Objective


Need of Template Class template

Templates INTRODUCTION (Need of Template) Templates is one of the features added to C++ . It is a new concept which enable us define generic classes and functions and thus provides support for generic programming. Generic programming is an approach where generic types are used as parameters in algorithms so that they work for a variety of suitable data types and data structures. Support for generic programming in C++ is considered by some to be as important a language goal for C++ as is support for object-oriented programming (using base/derived classes and virtual functions). Templates are a powerful but complex feature, about which we will have more to say. Languages like C or Java(tm), that do not have templates, typically use macros or rely on using base class pointers and virtual functions to synthesize some of the properties of templates. A template can be used to create a family of classes or functions. For example, a class template for an array class would enable us to create arrays of various data types such as int Array and float array. Similarly, we can define a template for a function, say mul( ), that would help us create various versions of mul( ) for multiplying, int, float and double types.

A template can be considered as a kind of macro. When an object of a specific type is led for actual use, the template definition for that class is substituted with the required type. Since a template is defined with a parameter that would be replaced by a specified type at the time of actual use of the class or function, the templates are sometimes called parameterized classes or functions.

CLASS TEMPLATES Consider a vector class defined as follows: class vector { int *v; int size; public: vector(int m) { v = new int[size = m]; for(int i=0; i<size; i++) v[i] = 0; } vector(int *a) { for(int i=O; i<size; i++) v[i] = a[i]; } int operator*(vector &y) { int sum = 0; for(int i=0; i<size; i++) sum += this -> v[i] * Y - v[i]; / / scalar product / / create a vector from an array / /, create a null vector

return sum; } }; The vector class can store an array of int numbers and perform the scalar product of vectors as shown below: int main( ) { int x[3] = {1,2,3}; int y[3] = {4,5,6}; vector v1(3); vector v2(3); v1= x; v2= y; int R = v1 * v2; cout<< R = R; return 0; } Now suppose we want to define a vector that can store an array of float values. We can do this by simply replacing the appropriate int declarations with float in the vector class. This means that we have to redefine the entire class all over again. Assume that we want to define a vector class with the data type as a parameter and then use this class to create a vector of any data type instead of defining a new class every time. The template mechanism enables us to achieve this goal. As mentioned earlier, templates allow us to define generic classes. It is a simple process to create a generic class using a template with an anonymous type. The general format of a class template is: template<class T> class classname { // ......... / / Creates v 1 from the array x / / Creates a nuII vector of 3 integers

// class member specification // with anonymous type T // wherever appropriate // ......... ); The template definition of vector class shown below illustrates the syntax of a template: template<class T> class vector { T* v; int size; public: vector(int m) { v = new T [size = m]; for(int i=0; i<size; i++) v[i] = 0; } vector(T* a) { for(int i=0; i<size; i++) v[i]=a[i]; } T operator*(vector &y) { T sum = 0; for(int i=0; i<size; i++) sum += this -> v[i] * Y - v[i]; return sum; } }; / / Type T vector

Remember: Class template definition is very similar to an ordinary class definition except. prefix template<class T> and the use of type T. This prefix tells the compiler Iii we are going to declare a template and use T as a type name in the declaration, Thus vector has become a parameterized class with the type T as its parameter, T may be substituted by any data type including the user-defined types. Now, we can create vectors for holding different data types. Example: vector <int> v1(10); // 10 element int vector // 25 element float vector

vector <float> v2 (25) ; Remember:

The type T may represent a class name as well. Example: vector <complex> v3(5); // vector of 5 complex numbers

A class created from a class template is called a template class. The syntax for defining, object of a template class is: classname<type> objectname (arglist) ; This process of creating a specific class from a class template is called instantiation, compiler will perform the error analysis only when an instantiation takes place. So it is, advisable to create and debug an ordinary class before converting it into a template. Following Programs illustrate the use of a vector class template for performig scalar product of int type vectors as well as float type vectors. #include <iostream> const size = 3;

Template.<class T> Class vector { T* V; Public : Vector( ) { v = new T[size]; for(int i=0;i<size;i++) { v[i]= 0 } } vector(T* a) { for(int i=0;i<size;i++) { v[i]= a[i]; } } T operator* (vector &y) { T sum = 0; for(int i=0;i<size;i++) { sum + = this-> v[i] * y.v[i]; return sum; } }; int main() { int x[3] = {1,2,3); // type T vector

int y[3] = {4,5,6); vector <int> v1; vector <int> v2; vl = X; v2 = Y; int R = v1 * v2; cout << R = << R << \n; return 0; } Output R= 32

Here is another example of class template While implementing class template member functions, the definitions are prefixed by the keyword template. Here is the complete implementation of class template Stack: //stack.h #pragma once template <class T> class Stack { public: Stack(int = 10) ; ~Stack( ) { delete [] stackPtr ; } int push(const T&); int pop(T&) ; // pop an element off the stack int isEmpty( )const { return top == -1 ; } int isFull( ) const { return top == size - 1 ; } private: int size ; // Number of elements on Stack int top ; T* stackPtr ;

}; //constructor with the default size 10 template <class T> Stack<T>::Stack(int s) { size = s > 0 && s < 1000 ? s : 10 ; top = -1 ; // initialize stack stackPtr = new T[size] ; } // push an element onto the Stack template <class T> int Stack<T>::push(const T& item) { if (!isFull( )) { stackPtr[++top] = item ; return 1 ; // push successful } return 0 ; // push unsuccessful } // pop an element off the Stack template <class T> int Stack<T>::pop(T& popValue) { if (!isEmpty( )) { popValue = stackPtr[top--] ; return 1 ; // pop successful } return 0 ; // pop unsuccessful }

Using a class template

Using a class template is easy. Create the required classes by plugging in the actual type for the type parameters. This process is commonly known as "Instantiating a class". Here is a sample driver class that uses the Stack class template. #include <iostream> #include "stack.h" using namespace std ; void main( ) { typedef Stack<float> FloatStack ; typedef Stack<int> IntStack ; FloatStack fs(5) ; float f = 1.1 ; cout << "Pushing elements onto fs" << endl ; while (fs.push(f)) { cout << f << ' ' ; f += 1.1 ; } cout << endl << "Stack Full." << endl << endl << "Popping elements from fs" << endl ; while (fs.pop(f)) cout << f << ' ' ; cout << endl << "Stack Empty" << endl ; cout << endl ; IntStack is ; int i = 1.1 ;

cout << "Pushing elements onto is" << endl ; while (is.push(i)) { cout << i << ' ' ; i += 1 ; } cout << endl << "Stack Full" << endl << endl << "Popping elements from is" << endl ; while (is.pop(i)) cout << i << ' ' ; cout << endl << "Stack Empty" << endl ; }

Program Output
Pushing elements onto fs 1.1 2.2 3.3 4.4 5.5 Stack Full. Popping elements from fs 5.5 4.4 3.3 2.2 1.1 Stack Empty Pushing elements onto is 1 2 3 4 5 6 7 8 9 10 Stack Full Popping elements from is 10 9 8 7 6 5 4 3 2 1 Stack Empty

Summary Templates is one of the features added to C++ . It is a new concept which enable us define generic classes and functions and thus provides support for generic programming. Generic programming is an approach where generic types are used as parameters in algorithms so that they work for a variety of suitable data types and data structures. Templates are a powerful but complex feature

A template can be used to create a family of classes or functions. This process of creating a specific class from a class template is called instantiation. While implementing class template member functions, the definitions are prefixed by the keyword template.

Question What is Template? Define Class template with suitable example? Define class template? Give an example of class stack template?

UNIT I LESSON 28 TEMPLATE II Objective


Function template Implementing function template Template Instantiation

FUNCTION TEMPLATES Like class templates, we can also define function templates that could be used to create family of functions with different argument types. To perform identical operations for each type of data compactly and conveniently, use function templates. You can write a single function template definition. Based on the argument types provided in calls to the function, the compiler automatically instantiates separate object code functions to handle each type of call appropriately. The STL algorithms are implemented as function templates. The general format of a function template is: template<class T> returntype functioname (arguments of type T) { // ..... // Body of function // with type T // wherever appropriate // ..... } The function template syntax is similar to that of the class template except that we are defining functions instead of classes. We must use the template parameter T as and when necessary in the function body and in its argument list.

Implementing Template Functions Function templates are implemented like regular functions, except they are prefixed with the keyword template. Here is a sample with a function template.

#include <iostream> using namespace std ; //max returns the maximum of the two elements template <class T> T max(T a, T b) { return a > b ? a : b ; } Following example declares a swap( ) function template that will swap two values of given type of data. template<class T> void swap (T&x, T&y) { T temp = X; X = Y; Y = temp; } This declares a set of overloaded functions, one for each type of data, We can invoke the Swap( ) function like any ordinary function. For example, we can apply the swap Function as follows: void f(int m, int n, float a, float b) { swap(m,n); swap(a,b); // swap two integer values. // swap two float values

//.. } This will generate a swap() function from the function template for each set of argument types. Following shows how a template function is defined and implemented. Example Function Template # <inc1ude<iostream> using namespace std; template <class T> Void swap(T &x. T &y) { T temp = x; x =y; y = temp; } void fun (int m. int n, float a, float b) { cout << m and n before swap: " << m << " << n<<\n; swap(m.n); cout << m and n after swap:" << m << " " << n << "\n"; cout "a and b before swap:" << a << " " << b << "\n"; swap(a.b); cout "a and b after swap:" << a << " << b << "\n"; } int main( ) { fun(l00,200,l1.22,33.44) ; return 0; }

The output of Program m and n before swap: 100 200 m and n after swap: 100 200 a and b before swap: 11.22 33.439999 a and b after swap: 33.439999 11.22 Another function often used is sort() for sorting arrays of various types such as int and double. The following example shows a function template for bubble sort template<class T> bubble(T a[], int n) { for(int i=0; i<n-l; i++) for(int j=n-l; i<j; j--) if(a[j] < a[j-l]) { T temp = v[j]; v [j] = v [j -1] ; v[j-l] = temp; } } Note that the swapping statements T temp = v[j]; v[j] = v[j-l]; v[j-l] = temp; may be replaced by the statement swap(v[j],v[j-l]);

where swap() has been defined as a function template.

Ex.] Program returns the maximum of the two elements using template function. #include <iostream> using namespace std ; //max returns the maximum of the two elements template <class T> T max(T a, T b) { return a > b ? a : b ; } void main( ) { cout << "max(10, 15) = " << max(10, 15) << endl ; cout << "max('k', 's') = " << max('k', 's') << endl ; cout << "max(10.1, 15.2) = " << max(10.1, 15.2) << endl ; }

Program Output
max(10, 15) = 15 max('k', 's') = s max(10.1, 15.2) = 15.2

Template Instantiation

When the compiler generates a class, function or static data members from a template, it is referred to as template instantiation.

A class generated from a class template is called a generated class. A function generated from a function template is called a generated function. A static data member generated from a static data member template is called a generated static data member.

The compiler generates a class, function or static data members from a template when it sees an implicit instantiation or an explicit instantiation of the template.

This is an example of implicit instantiation of a class template. template <class T> class Z { public: Z( ) {} ; ~Z( ) {} ; void f( ){} ; void g( ){} ; }; int main( ) { Z<int> zi ; //implicit instantiation generates class Z<int> Z<float> zf ; //implicit instantiation generates class Z<float> return 0 ; } Summary Function templates are implemented like regular functions, except they are prefixed with the keyword template

When the compiler generates a class, function or static data members from a template, it is referred to as template instantiation. A function generated from a function template is called a generated function

Question What is Template? Define Function template with suitable example? Show how template function is define & implemented ?

UNIT I LESSON 29 TEMPLATE III Objective


Class with multiple arguments Function with multiple arguments Overloading Of Template Functions

MULTIPLE ARGUMENTS : CLASS TEMPLATES WITH MULTIPLE PARAMETERS We can use more than one generic data type in a class template. They are declared as a comma separated list within the template specification as shown below: template<class T1, class T2, ...> class classname { .(Body of the class) . . }; Following program demonstrates the use of a template class with two generic data types. # include<iostream> using namespace std;

template <class T1 , class T2> class test { Tl a; T2 b; publ ic: Test(Tl x, T2 y) { a = x; b = y; } void show() { cout a and b "\n"; } }; int main() { Test <.float , int> test (1.23,123); Test <int, char> test2 (l00,'W'); test1.show(); test2.show() ; return 0; }; The output will be: 1.23 and 123 100 and W FUNCTION TEMPLATES WITH MULTIPLE PARAMETERS Like template classes, we can use more than one generic data type in the template statement, using a comma-separated list as shown below:

template<class T1, class T2, ...> return type functi onname (arguments of types T1, T2,) { (Body of function) . } Program illustrates the concept of using two generic types in template functions. #<include <iostream> #<include <string> using namespace std; template<class T1, class T2> void display(T1 x, T2 y) { cout X y \n; } int main() { display(1999, EBG); display(12.34. 1234); return 0; } The output of Program would be: 1999 12.34 EBG 1234

C++ templates allow one to implement a generic Queue<T> template that has a type parameter T. T can be replaced with actual types, for example, Queue<Customers>, and C++ will generate the class Queue<Customers>. For example, template <class T> class Stack { }; Here T is a template parameter, also referred to as type-parameter. 1. C++ allows you to specify a default template parameter, so the definition could now look like: 2. template <class T = float, int elements = 100> Stack { ....} ;

Then a declaration such as Stack<> mostRecentSalesFigures ; would instantiate (at compile time) a 100 element Stack template class named mostRecentSalesFigures of float values; this template class would be of type Stack<float, 100>. Note, C++ also allows non-type template parameters. In this case, template class Stack has an int as a non-type parameter. If you specify a default template parameter for any formal parameter, the rules are the same as for functions and default parameters. Once a default parameter is declared all subsequent parameters must have defaults. Default arguments cannot be specified in a declaration or a definition of a specialization. For example, template <class T, int size> class Stack { }; OVERLOADING OF TEMPLATE FUNCTIONS A template function may be overloaded either by template functions or ordinary function of its name. In such cases, the overloading resolution is accomplished as follows:

1. Call an ordinary function that has an exact match. 2. Call a template function that could be created with an exact match. 3. Try normal overloading resolution to ordinary functions and call the one that ma' An error is generated if no match is found. Note that no automatic conversions are applied to arguments to the template functions. Following Program shows how a template function overloaded with an explicit function. #include<iostream> #include<string> using namespace std; template < class T> void display (T x) { cout <<Template display :<<x<<\n; } void display (int x) { cout <<Explicit display : <<x<<\n; } int main( ) { display(100); display(12.34); display(C); return 0; } The output will be Explicit display : 100 Template display :12.34 Template display:C //overloads the generic display( )

Remember: version.

The call display (100) invokes the ordinary version of display() and not the template

Summary They are declared as a comma separated list within the template specification Like template classes, we can use more than one generic data type in the template statement, using a comma-separated list C++ templates allow one to implement a generic Queue<T> template that has a type parameter T T can be replaced with actual types, for example, Queue<Customers> If you specify a default template parameter for any formal parameter, the rules are the same as for functions and default parameters. A template function may be overloaded either by template functions or ordinary function of its name Question Explain class template & function template with multiple arguments? Shows how a template function can be overloaded with an explicit function.

UNIT I LESSON 30 EXCEPTION HANDLING Objective What is exception handling? Exception Handling Mechanism. Throw Mechanism.

INTRODUCTION We know that it is very rare that a program works correctly first time. It might have bu~, The two most 'Common types of bugs are logic errors and syntactic errors. The logic error occur due to poor understanding of the problem and solution procedure. The syntactic error arise due to poor understanding of the language itself. We can detect these errors by using exhaustive, debugging and testing procedures. We often come across some peculiar problems other than logic or syntax errors. They are Known as exceptions.. Exceptions are run time anomalies or unusual conditions that a program may encounter while executing. Anomalies might include conditions such as division by zero,Access to an array outside of its bounds, or running out of memory or disk space. When a Program encounter an exceptional condition, it is important that it is identified and dealt effectively. ANSI C++ provides built-in language features to detect and handle exceptions, which are basically run time errors. Exception handling was not part of the original C++. It is a new feature added to ANSI C++ Today, almost all compilers support this feature. C++ exception handling provides a type-safe Integrated approach, for coping with the unusual predictable problems that arise while executing a program. BASICS OF EXCEPTION HANDLING Exceptions are of two kinds, namely, synchronous exceptions and asynchronous exceptions. I such as "out-of-range index" and "over-flow" belong to the synchronous type exceptions.errors that are caused by events beyond the control of the program (such as keyboard interrupts) are called asynchronous exceptions. The proposed exception handling mechanism, in C++ is designed to handle only synchronous exceptions.

The purpose of the exception handling mechanism is to provide means to detect and report exceptional circumstance so that appropriate action can be taken. The mechanism Suggest a separate error handling code that performs the following tasks: 1. Find the problem (Hit the exception). 2. Inform that an error has occurred (Throw the exception). 3. Receive the error information (Catch the exception). 4. Take corrective actions (Handle the exception). The error handling code basically consists of two segments, one to detect errors and to throw exceptions, and the other to catch the exceptions and to take appropriate actions. EXCEPTION HANDLING MECHANISM In C there are several ways to have a program react to situations which break the normal unhampered flow of the program:

The function may notice the abnormality and issue a message. This is probably the least disastrous reaction a program may show.

The function in which the abnormality is observed may decide to stop its intended task, returning an errorcode to its caller. This is a great example of postponing decisions: now the calling function is faced with a problem. Of course the calling function may act similarly, by passing the error-code up to its caller.

The function may decide that things are going out of hand, and may call exit() to terminate the program completely. A tough way to handle a problem.

The function may use a combination of the functions setjmp() and longjmp()) to enforce nonlocal exits. This mechanism implements a kind of goto jump, allowing the program to proceed at an outer section, skipping the intermediate levels which would have to be visited if a series of returns from nested functions would have been used.

In C++ all the above ways to handle flow-breaking situations are still available. However, the last way,

using setjmp() and longjmp() isn't often seen in C++ (or even in C) programs, due to the fact that the program flow is completely disrupted. In C++ the alternative to using setjmp() and longjmp() are exceptions. Exceptions are a mechanism by which a controlled non-local exit is realized within the context of a C++ program, without the disadvantages of longjmp() and setjmp(). Exceptions are the proper way to bail out of a situation which cannot be handled easily by a function itself, but which are not disastrous enough for the program to terminate completely. Also, exceptions provide a flexible layer of flow control between the short-range return and the crude exit(). C++ exception handling mechanism is basically built upon three keywords, namely, try, throw, and catch. The keyword try is used to preface a block of statements (surrounded by braces), which may generate exceptions. This block of statements is known as try block. When an error is detected, it is thrown using a throw statement in the try block. Throw followed by an expression of a certain type, throws the expression value as an exception. The throw statement should be executed somewhere within the try-block: either directly or from within a function called directly or indirectly from the tryblock. A catch block defined by the keyword catch 'catches' the exception 'thrown' by the throw statement in the try block, and handles it appropriately. The relationship is shown in Fig. try block Detects and throws an exception

catch block try { .. throw exception; Catches and handles the exception

Try block throwing Exception / / Block of statements which

/ / detects and throws an exception The catch block that catches an exception must immediately follow the try block that throws the exception. } general forms of these two blocks are as follows: The catch (type arg) / / Catches exception { / / Block of statements that / / handles the exception }

When the try block throws an exception, the program control leaves the try block and enters the catch statement of the catch block. Note that exceptions are objects used to transmit information about a problem. If the type of object thrown matches the arg type the catch statement, then catch block is executed for handling the exception. If they do not match, the program is aborted with the help of the abort( )function which is invoked by default. When no exception is detected and thrown, the control goes to the statement immediately after the catch block. That is, the catch block is skipped. This simple try-catch mechanism is illustrated in Program. Try Block Throwing An Exception. #include <iostream.h> using namespace std; int main( ) { int a,b; cout<< enter values of a and b \n cin>>a; cin>>b; int x = a b; try

{ if(x ! = 0) { cout<< result (a/x) = << a/x << \n; } else { throw(x); } } catch (int i) { cout<<Exception caught : x = x << \n; } cout<< END; return 0; } The output of Program First Run Enter Values of a and b 20 15 Result (a/x) = 4 END Second Run Enter Values of a and b 10 10 Except; on caught: x = 0 END //Catches the exception //Throws int object //There is an Exception

Program detects and catches a division-by-zero problem. The output of first run shows a successful execution. When no exception is thrown, the catch block is skipped and execution resumes with the first line after the catch. In the second run, the denominator x becomes zero and therefore a division-by-zero situation occurs: This exception is thrown using the object x. Since the exception object is an int type, the catch statement containing int type argument catches the exception and displays necessary message. Most often, exceptions are thrown by functions that are invoked from within the try blocks. The point at which the throw is executed is called the throw point. Once an exception is thrown to the catch block, control cannot return to the throw point. This kind of relationship js shown in Fig.
Throw point

Function that causes an exception

try block

Invokes a function that contains an exception

Type function(arg list) { . throw(object); . } .

// function with exceptin

catch object //throws block

Catches and handles the exception

Function invoked by try block throwing exception try { . invoke function here . The general format of code for this kind of relationship is shown below }
catch (type arg) //catches exception { . handles exception here . } .

Remember : Try block is immediately followed by the catch block, irrespective of the location of the throw point. Program demonstrate how a try block invokes a function that generates an exception. // Invoking function that generates exception. #include <iostream> using namespace std; void divide(int x, int y , int z) { cout<< \n we r inside the function \n if((x-y) != 0) { int R = z / (x-y); // it is ok

cout<< Result = << R <<\n; } else { Throw(x-y) } } int main( ) { try { cout<< we r inside the Try block \n; divide(10,20,30); divide(10,20,30); } catch(int i) { cout<< caught the exception \n; } return 0; } Output We r inside the try Block We r inside the function Result = -3 We r inside the function Caught the exception //catches the exception //invoke divide( ) //invoke divide( ) //throw point //There is a problem

THROWING MECHANISM When an exception that is desired to be handled is detected, it is thrown using the throw statement in one of the following forms: throw(exception); throw except ion; throw; // used for rethrowing an exception

The operand object exception may be of any type, including constants. It is also possible to Throw objects not intended for error handling. When an exception is thrown, the catch statement associated with the try block will catch it. That is, the control exits the current try block, and is transferred to the catch block after that try block.

Objects defined locally in functions are automatically destroyed once exceptions are thrown within these functions. However, if the object itself is thrown, the exception catcher receives a copy of the thrown object. This copy is constructed just before the local object is destroyed. The next source illustrates this point. Within the function Object::fun() a local Object toThrow is created, which is thereupon thrown as an exception. The exception is caught outside of Object::fun(), in main(). At this point the thrown object doesn't actually exist anymore, Let's first take a look at the sourcetext: #include <iostream.h> #include <string> class Object { public: Object(string name)

name(name) { cout << "Object constructor of " << name << "\n"; } Object(Object const &other) name(other.name + " (copy)") { cout << "Copy constructor for " << name << "\n"; } ~Object() { cout << "Object destructor of " << name << "\n"; } void fun() { Object toThrow("'local object'"); cout << "Object fun() of " << name << "\n"; throw toThrow; } void hello() { cout << "Hello by " << name << "\n"; } private: string name; }; int main()

{ Object out("'main object'"); try { out.fun(); } catch (Object o) { cout << "Caught exception\n"; o.hello(); } } The class Object defines some simple constructors and members. The copy constructor is special in that it adds the text " (copy)" to the received name, to allow us to monitor the construction and destruction of objects somewhat more closely. The member function fun() generates the exception, and throws its locally defined object. Just before the exception the following output is generated by the program: Object constructor of 'main object' Object constructor of 'local object' Object fun() of 'main object' Then the exception is generated, resulting in the next line of output: Copy constructor for 'local object' (copy) The throw clause receives the local object, and treats it as a value argument: it creates a copy of the local object. Next, the exception is processed. The local object is destroyed, and the catcher catches an Object, which again is a value parameter. Hence, another copy is created. We see the following lines:

Object destructor of 'local object' Copy constructor for 'local object' (copy) (copy) Now the message inside the catcher is displayed, and the hello member of the object received by the catcher is called, showing us once again that we received a copy of the copy of the local object of the fun() member function: Caught exception Hello by 'local object' (copy) (copy) Now the program terminates, and the still living objects are destroyed in their reversed order of creation: Object destructor of 'local object' (copy) (copy) Object destructor of 'local object' (copy) Object destructor of 'main object'

If the catcher would have implemented so as to receive a reference to an object (catch (Object &o)), the double copy would have been avoided. In that case the output of the program would have been: Object constructor of 'main object' Object constructor of 'local object' Object fun() of 'main object' Copy constructor for 'local object' (copy) Object destructor of 'local object' Caught exception Hello by 'local object' (copy) Object destructor of 'local object' (copy) Object destructor of 'main object' showing that only a single copy of the local object is used.

Of course it's a bad idea to throw a pointer to a locally defined object: the pointer is thrown, but the object to which the pointer refers dies once the exception is thrown, and the catcher receives a wild pointer. Bad news. Summarizing, local objects are thrown as copied objects, pointers to local objects should not be thrown. However, it is possible to throw pointers or references to dynamically generated objects, taking care that the generated object is properly deleted when the generated exception is caught. Exceptions are thrown in situations where a function can't continue its normal task anymore, although the program is still able to continue. Imagine a program which is an interactive calculator. The program continuously requests expressions, which are then evaluated. In this case the parsing of the expression may show syntax errors, and the evaluation of the expression may result in expressions which can't be evaluated, e.g., because of the expression resulting in a division by zero. A bit more sophistication would allow the use of variables, and non-existing variables may be referred to. Throw point can be in a deeply nested scope within a try block or in a deeply nested function call. In. any case, control is transferred to the catch statement.

Summary Exceptions are peculiar problems that a program may encounter at run time. Exceptions are of two types: synchronous and asynchronous. c++ provides mechanism for handling synchronous exceptions. An exception is typically caused by a faulty statement in a try block. The statement discovers the error and throws it, which is caught by a catch statement. The catch statement defines a block of statements to handle the exception appropriately. When an exception is not caught, the program is aborted. A try block may throw an exception directly or invoke a function that throws an exception. Irrespective of location of the throw point, the catch block is placed immediately after the try block. Question Explain basic concept on exception handling in c++ with suitable example? What are the advantages of using exception-handling mechanism in a program? What should be placed inside Try Block Explain Throwing mechanism?

UNIT I LESSON 31 EXCEPTION HANDLING II Objective

Catching Mechanism

CATCHING MECHANISM As stated earlier, code for handling exceptions is included in catch blocks. A catch block looks like a function definition and is of the form catch(type arg) { // Statements for // managing except ions } The type indicates the type of exception that catch block handles. The parameter arg is an optional parameter name. Note that the exception-handling code is placed between two braces. The catch statement catches an exception whose type matches with the type of catch argument. When it is caught, the code in the catch block is executed. If the parameter in the catch statement is named, then the parameter can be used in the exceptionhandling code. After executing the handler, the control goes to the statement immediately following the catch block. Due to mismatch, if an exception is not caught, abnormal program termination will occur. 11isimportant to note that the catch block is simply skipped if the catch statement does not catch an exception.

Multiple Catch Statements It is possible that a program segment has more than one condition to throw an exception. In such cases, we can associate more than one catch statement with a try (much like the conditions in a switch statement) as shown below: Try { // try block } catch(typel arg) { // catch blockl } catch (type2 arg) { // catch b1ock2 } . . catch(typeN arg) { // catch b1ockN }

When an exception is thrown, the exception handlers are searched in order for an appropriate match. The first handler that yields a match is executed. After executing the handler, the control goes to the first statement after the last catch block for that try. (In other words, all other handlers are bypassed). When no match is found, the program is terminated.

It is possible that arguments of several catch statements match the type of an exception. In such cases, the first handler that matches the exception type is executed. Program shows a simple example where multiple catch statements are used to handle; various types of exceptions. Multiple catch statement Program #include <iostream.h> using namespace std; void test(int x) { try { if(x = = 1) throw x; else if(x = = 0) throw x; else if(x = = -1) throw 1.0; cout<< end of try block \n; } catch(char c) { cout<< Caught a character \n } catch(int m) { cout<< Caught an integer \n } //catch 2 //catch 1 // double // char // int

catch(double d) {

//catch 3

cout<< Caught a double \n } cout<< End of try-catch system \n\n; } } int main( ) { cout<< Testing Multiple Catches

cout<< x= = 1 \n; test( 1 ); cout<< x= = 0 \n; test( 0 ); cout<< x= = -1 \n; test( -1 ); cout<< x= = 2 \n; test( 2 ); return 0; } The output of the Program Testing Multiple Catches x==1 Caught an integer End of try-catch system

x==0 Caught a character End of try-catch system x = = -1 Caught a double End of try-catch system0 x==2 End of try-block End of try-catch system The program when executed first, invokes the function test( ) with x = 1 and therefore throws x an int exception. This matches the type of the parameter m in catch2 and therefore catch2 handler is executed. Immediately after the execution, the function test( ) is again invoked with x = 0. This time, the function throws 'x', a character type exception and therefore the first handler is executed. Finally, the handler catch3 is executed when a double type exception is thrown. Note that every time only the handler, which catches the exception, is executed and all other handlers are bypassed. When the try block does not throw any exceptions and it completes normal execution, control passes to the first statement after the last catch handler associated with that try block. Point : Try block does not throw any exception, when the test( ) is invoked with x = 2.

The default catcher

In cases where different types of exceptions can be thrown, only a limited set of handlers may be required at a certain level of the program. Exceptions whose types belong to that limited set are to be processed, all other exceptions are treated differently, e.g., they are passed on to an outer level of exception handling.

Here is an example showing the use of a default exception handler: try { // this code may throw // different types of // exceptions } catch (char *message) { // code to process // char pointers } catch (int value) { // code to process // ints } catch (...) { // code to process other exceptions, // often passing the exception on // to outer level exception handlers: throw; }

The reason for passing unspecified exceptions on to outer level exception handlers is simply the fact that they are unspecified: how would you process an exception if you don't know its type? In these situations the outer level exception handlers should of course know what exceptions other than char *s and ints to expect. Catch All Exceptions In some situations, we may not be able to anticipate all possible types of exceptions and therefore may not be able to design independent catch handlers to catch them. In such circumstances, we can force a catch statement to catch all exceptions instead of a certain type alone. This could be achieved by defining the catch statement using ellipses as follows: catch(...) { // Statements for processing // all exceptions }

Program illustrates the functioning of catch () include <iostream> using namespace std; void test(int x) { try { if(x = = 1) throw x; if(x = = 0) throw x; if(x = = -1) throw 1.0; } catch(...) { // catch all // int // char // double

cout << "Caught an exception \n"; } } int main( ) { cout << Testing Generic Catch \n"; test(-1); test(0); test(1); return 0; } The output of the Program Testing Generic Catch Caught an except ion Caught an exception Caught an except ion Note that all the throws were caught by the catch(...) statement. It may be a good idea to use the catch(...) as a default statement along with other catch handler so that it can catch all those exceptions which are not handled explicitly. Note Remember, catch(...) should always be placed last in the list of handlers. Placing it before other catch blocks would prevent those blocks from catching exceptions. Summary A catch block defined by the keyword catch 'catches' the exception 'thrown' by the throw statement in the try block, and handles it appropriately

An exception is typically caused by a faulty statement in a try block. The statement discovers the error and throws it, which is caught by a catch statement. The catch statement defines a block of statements to handle the exception appropriately. When an exception is not caught, the program is aborted. We can place two or more catch blocks together to catch and handle multiple types of exceptions thrown by a try block. It is also possible to make a catch statement to catch all types of exceptions using ellipses as its argument. It may be a good idea to use the catch(...) as a default statement along with other catch handler so that it can catch all those exceptions which are not handled explicitly Remember, catch(...) should always be placed last in the list of handlers

Question Explain multiple catch statement? When catch handler is used? When do we use multiple catch statement? Give a key advantage and key disadvantage of catch(.) List the advantages of exception handling

UNIT I LESSON 32 Group discussion on topics covered Like Exceptional handling Templates

UNIT II LESSON 33 CLASS IMPLEMENTATION Objective

Implementation of classes

An object, such as a CD Player, a printer, a car, etc, is built from assembling various parts. In the same way, C++ allows you to group various variables and create a new object called a class. Imagine a company that manufactures shoeboxes hires you to write a program that would help design and identify those shoeboxes. A shoebox is recognized for its dimensions (length, width, height), color, and shoe size that a particular box can contain, etc. The variables that characterize such an object are defined in the program below:

#include <iostream> #include <iomanip> #include <string> using namespace std; int main( ) { // Define the characteristics of a shoe box // The following characteristics are COMPLETELY random double Length(12.55), Width(6.32), Height(8.74); string Color("Yellow Stone"); float ShoeSize = 10.50;

// Display the characteristics of the shoe box cout << "Characteristics of this shoe box"; cout << setiosflags(ios::fixed) << setprecision(2); cout << "\n\tLength = " << Length << "\n\tWidth = " << Width cout << "\n\tHeight = " << Height << "\n\tVolume = " << Length * Width * Height cout << "\n\tColor = " << Color << "\n\tSize = " << ShoeSize << "\n\n"; return 0; } The program would produce: Characteristics of this shoebox Length = 12.55 Width = 6.32 Height = 8.74 Volume = 693.22 Color = Yellow Stone Size = 10.50 Press any key to continue... Unless dealing with one shoebox, this program would be rudimentary to run for each object. The solution is to create an object called box that groups everything that characterizes the object. Now we will learn how to implement a class. To create a class, use the class keyword followed by a name for the object. Like any other declared variable, the class declaration ends with a semi-colon. The name of a class follows the rules we have applied so far for variable and function names. To declare a class called ShoeBox, you would
following: type the

class ShoeBox;

As a name that represents a group of items, a class has a body that would be used to define the items that compose it. The body of a class starts with an opening curly bracket "{" and ends with a closing one "}". Therefore, another way to create a class is: class ClassName { }; This could also be created as: Class ClassName {

}; Either of these techniques produces the same effect. Since a class is built from combining other identifiers, you will list each variable inside of the body of the class. Each item that composes the class is represented as a complete variable declared with a data type and a name. As a variable, each declaration must end with a semi-colon. Continuing with our shoebox object, you could create it using the class as follows: class ShoeBox { double Length, Width, Height; char Color[12]; float ShoeSize; };

The

items

that

compose

class

are

called

members

of

the

class.

Now that we have understood how to implement a class, we will now understand about accessing the class and the components within it.. Accessing a Class A common object in real life is visibly made of two categories of parts: those you can see or touch and those you do not have access to. The parts you can see or touch are considered visible or accessible. In C++, such parts are referred to as public. Those you cannot see or touch are considered hidden. In C++, such parts are referred to as private. Like objects in real life, a class is made of sections that the other functions or other objects cannot see and those the other objects can access. The other objects of of the program are sometimes referred to as the clients of the object. The parts the client of an object can touch in a class are considered public and the others are private. When creating a class, you will define which items are public and which ones are private. The items that are public are created in a section that starts with the public keyword followed by a semi-colon. The others are in the private section. If you do not specify these sections, all of the members of a class are considered private. For example, all of the members of the previously defined ShoeBox class are private. Using the public and private sections, our shoebox object can be created as:

class ShoeBox { public: double Length, Width, Height; string Color; private: float ShoeSize;

}; The public and private keywords are referenced by their access level because they control how much access a variable allows. You can create as many public sections or as many private sections as you want. For example, the above class could be created as:

class ShoeBox { public: double Length, Width, Height; public: string Color; double Volume; private: float ShoeSize; private: char Material; string Color; }; When creating a class with different public and private sections, all of the declared variables under an access level keyword abide by the rules of that access level. The fact that you use different public sections does not by any means warrant different public levels to the variables. A variable declared as public in one public section has the same public level of access as any other variable that is declared in another public section. A variable that is declared in a class is called a member of the class. Once the class has been defined, you can use it as an individual variable.
Now

lets understand how class members are declared..

After defining a class, you can declare it as a variable using the same syntax we have used for any other variable. A class is declared using its name followed by a name for the defined variable and ending with a semi-colon. For example, our ShoeBox class can be declared as follows: ShoeBox Shake; When an object has been declared, you can access any of its members using the member access operator "." [Dot operator]. First, type the name of the object variable, followed by a period, followed by the name of the member you want to access. For example, to access the member Length of the above class, you would write: Shake.Length; Using this syntax, you can display the value of a class member: cout << Shake.Length; or you can request its value from the user, using the cin operator. Here is an example: cin >> Shake.Lengh; Using the cout extractor to display the values of the object members, our program could be as follows:

#include <iostream> #include <string> using namespace std; class ShoeBox

{ public: double Length, Width, Height; string Color; private: float ShoeSize; }; int main( ) { ShoeBox Shake; // Display the characteristics of the shoe box cout << "Characteristics of this shoe box"; cout << "\n\tLength = " << Shake.Length << "\n\tWidth = " << Shake.Width << "\n\tHeight = " << Shake.Height << "\n\tVolume = " << Shake.Length * Shake.Width * Shake.Height << "\n\tColor = " << Shake.Color << "\n\tSize = " << Shake.ShoeSize << "\n\n"; return 0; } At this time, if you observe very carefully there is a problem? The problem is because we are trying to access a private member of the class, and we know the restrictions of a private section of a class its obvious that the program would produce the following error. [C++ Error] <filename.cpp>(30): E2247 'ShoeBox::TShoeSize' is not accessible

Even if you change the ShoeSize member access from private to public, the program would render unpredictable results because the members have not been given appropriate values. Characteristics of this shoe box Length = 0 Width = 1.79571e-307 Height = 4.17266e-315 Volume = 0 Color = Size = 3.58732e-43Press any key to continue...

Techniques of Initializing a Class Now that we have learnt how to declare a class and its members, we will now concentrate on class initialization.

There are various techniques used to initialize a class: initializing individual members or initializing the class as a whole. To initialize a member of a class, access it and assign it an appropriate value.

#include <iostream> #include <string> using namespace std; class ShoeBox { public: double Length, Width, Height; string Color; float ShoeSize; private: }; int main( ) {

ShoeBox Shake; double Volume; // Initializing each member of the class Shake.Length = 12.55; Shake.Width = 6.32; Shake.Height = 8.74; Shake.Color = "Yellow Stone"; Shake.ShoeSize = 10.50; Volume = Shake.Length * Shake.Width * Shake.Height; // Display the characteristics of the shoe box cout << "Characteristics of this shoe box"; cout << "\n\tLength = " << Shake.Length << "\n\tWidth = " << Shake.Width << "\n\tHeight = " << Shake.Height << "\n\tVolume = " << Volume << "\n\tColor = " << Shake.Color << "\n\tSize = " << Shake.ShoeSize << "\n\n"; return 0; } This time, the program would render a reasonable result. You can also initialize an object as a variable. This time, type the name of the variable followed by the assignment operator, followed by the desired values of the variables listed between an opening and a closing curly brackets; each value is separated with a comma. The first rule you must keep in mind is that the list of variables must follow the order of the declared members of the class. The second rule you must observe is that none of the members of the class must be another class. In the following example, one of the members of the class is another class, namely a string. Because of the way a variable of the class is declared, the program would not compile:

#include <iostream>

#include <string> using namespace std; class ShoeBox { public: double Length, Width, Height; string Color; float ShoeSize; private: }; int main( ) { // Declaring and initializing the class as a variable ShoeBox LadyShake = { 12.55, 6.32, 8.74, "Yellow Stone", 10.50 }; Double Volume = LadyShake.Length * LadyShake.Width * LadyShake.Height; // Display the characteristics of the shoe box cout << "Characteristics of this shoe box"; cout << "\n\tLength = " << LadyShake.Length << "\n\tWidth = " << LadyShake.Width << "\n\tHeight = " << LadyShake.Height << "\n\tVolume = " << Volume << "\n\tColor = " << LadyShake.Color << "\n\tSize = " << LadyShake.ShoeSize << "\n\n"; return 0;

Summary

To create a class, use the class keyword followed by a name for the object. Like any Each item that composes the class is represented as a complete variable declared with Like objects in real life, a class is made of sections that the other functions or other The other objects of of the program are sometimes referred to as the clients of the

other declared variable, the class declaration ends with a semi-colon.

a data type and a name

objects cannot "see" and those the other objects can access

object. The parts the client of an object can touch in a class are considered public and the others are private.

When creating a class, you will define which items are public and which ones are The public and private keywords are referenced by their access level because they A variable that is declared in a class is called a member of the class When an object has been declared, you can access any of its members using the You can also initialize an object as a variable.

private.

control how much access a variable allows.


member access operator "." [Dot operator].

Question

Define class? Explain implementation of class with suitable example? Explain the access modifier in class & explain how they differ from each other?

UNIT II LESSON 34 IMPLEMENTATION II Objective

Object concepts

Making instance of object: #include <iostream> #include <string> class ShoeBox { private: double Length, Width, Height; public: ShoeBox() { } ShoeBox(double L1, double W1, double H1) { Length=L1; Width= W1; Height=H1; } void display() { cout<<endl<<Length<<Width<<Height; } };

void main( ) { ShoeBox s1(10,20.66,15); ShoeBox s1(5,3.89,9); Cout<<endl<<sizeof(s1); Cout<<endl<<sizeof(s2); } In our program there are Two objects of the type ShoeBox, so there are two instance of Length, Width, Height in memory. So Length, Width & Height are instance of object. However there is only one instance of two constructor functions and the display() function. All the objects of class share these functions.

Tuning Objects Similar to tuning a radio set in order to get clear and error free reception, we can tune objects of a class by specifying applying certain techniques and implementing certain tools which make object programming all the more powerful. There are other features you can apply to make your objects more professional and less prone to errors. These include constant arguments, constant, private, and inline methods, etc.

Constant Arguments When studying functions, we learned that when a function receives an argument that it does not modify, the argument should be declared as constant. This allows the compiler to make sure the argument would not be modified. The same technique applies to an argument used by a method of an object. To declare an argument of an objects method as constant, type the const keyword on the left of the arguments data type. To improve our ShoeBox object, we would like to know the area of each side

because different things will be displayed on each side and we need to know how much space is available. If we were dealing with a rectangle, we would just declare an Area( ) method as follows: Double Area( );

On a box (rectangular parallelepiped), we have three rectangles types that represent the six faces. We can declare one method that takes any two sides and calculates their area. Such a method would be declared as follows:

double Area(Double Side1, Double Side2); After declaring it in the public section, we would define it as follows:

double ShoeBox::Area(Double Side1, Double Side2) { return Side1 * Side2; } In the Display( ) method, we could display the area of the length by the height using: cout << \n\tArea = << Area(Length, Height);

As you can see, the Side1 and Side2 arguments are not modified; therefore, they should be declared as constants. To declare each as constant, we would change the declaration of the method as follows: Double Area(const Double Side1, const Double Side2);

And we would define it as follows:

double ShoeBox::Area(const Double Side1, const Double Side2)

{ return Side1 * Side2; } For an example such as this one, the const keyword can be typed before or after the data type, the result would be the same. If a method is receiving more than one argument, their constancy is independent: the fact that one of them needs to be constant does not imply anything about the other(s). To help the method specify what side it is calculating the area, we could provide a string that names the void side. Area(const We Double could Side1, declare const the Double method Side2, as PChar follows: SideName);

We would then define the new method as follows: void ShoeBox::Area(const Double S1, const Double S2, PChar n) { cout << "\nThe area of the " << n << " side is: " << S1 * S2; } In the Display( ) method, we could specify the name of the side and provide the corresponding measures as follows: Area(Length, Height, "front");Area(Length, Width, "top");Area(Width, Height, "left"); Here is the complete implementation:

#include <iostream> #include <string> using namespace std; class ShoeBox

{ public: double CalcVolume( ) { return Length * Width * Height; } void Area(const double Side1, const double Side2, char SideName[]); float CalcShoeSize( ) { return Length - 0.35; } void Display( ); private: double Length; double Width; double Height; char Color[32]; }; void ShoeBox::Area(const double S1, const double S2, char N[]) { cout << "\nThe area of the " << N << " side is: " << S1 * S2; } void ShoeBox::Display( ) { // Initializing the dimensions

Length = 10.42; Width = 5.28; Height = 5.88; Color = "Yellow Stone"; // Display the characteristics of the shoe box cout << "Characteristics of this shoe box"; cout << "\nDimensions(L*H*W) = " << Length << " * " << Height << " * " << Width; Area(Length, Height, "front"); Area(Length, Width, "top"); Area(Height, Width, "left"); cout << "\n\tVolume = " << CalcVolume( ) << "\n\tColor = " << Color << "\n\tSize = " << CalcShoeSize( ); } int main( ) { ShoeBox Bambou; Bambou.Display( ); return 0; } Constant Methods Some of the method members of an object, though using member variables of the same object, do not modify them. To make sure that such a method does not alter the value of a member variable, the method should be declared and implemented as constant.

To declare a method as a constant, add the const keyword to the right side of the method when declaring it. Here is an example: string SpecFullName( ) const; The CalcVolume( ) and the CalcShoeSize( ) methods do not modify the member variables they receive. You can reinforce this by declaring them as const: double CalcVolume( ) const;float CalcShoeSize( ) const; When implementing the method, type the const keyword on the right side of the methods closing parenthesis:

double ShoeBox::CalcVolume( ) const { return Length * Width * Height; } float ShoeBox::CalcShoeSize( ) const { return Length - 0.35; } If you decide to define constant methods locally (inline), the only difference is to remove the semicolon of the end of the declaration and define the method normally. Notice that the Display( ) method assigns values to the member variables, which means it alters their values. Therefore, it cannot be declared or defined as constant. Here is the new version of our ShoeBox object:

class ShoeBox { public: double CalcVolume( ) const { return Length * Width * Height; } void Area(const double Side1, const double Side2, char SideName[]); float CalcShoeSize( ) const { return Length - 0.35; } void Display( ); private: double Length; double Width; double Height; string Color; }; The program would still produce the same result. Private Methods At this time, we know that one of the responsibilities of a member method of an object is to carry assignments. Another job performed by methods is to communicate with the clients of an object. As you might have found out, some of the methods of an object are exclusively used to carry assignments. The external functions or other objects do not call such methods and do not

communicate with them. If you create a class and know that a particular member method is not used to transfer data to the client methods, you can declare such a method as private, just like you would do with a member variable. To declare a method as private, include it in the private section of the object. To implement it, follow the same rules we have learned about implementing the methods of an object. The biggest difference you must keep in mind (which will also be very important when we learn about inheritance) is that this function method is not available to the outside world. Here is an example:

class Employee { public: void IdentifyEmployee( ); string FullName( ) const { return FirstName + " " + LastName; } void GetHourlySalary( ); void CalcTotalHours( ); void Display( ); void CalcNetPay( ) { if( IsMarried( ) == false ) NetPay = GrossPay - (GrossPay * 30 / 100); else NetPay = GrossPay; } private: void CalcGrossPay( ); bool inline IsMarried( ) const; string FirstName; string LastName; double TotalHours; double HourlySalary;

double WeeklySalary; double GrossPay; double NetPay; };

Objects and Their Implementations An object is made of the material that compose it and the actual structure of the object, which defines how the object is built and used. This means, a class is be made of two parts: its building block and its definition. These two parts of a class can be kept in different files that have access to each other.

Class' Header File The building block or foundation of an class is made of the class' creation, listing all of its members. This foundation is created in a file called a header file, similar to the one we learned when studying functions. The name of the file follows the naming rules we have applied so far. The header file has an extension of .h. You create an objects header file the same we did when studying functions. To create the header file, you can just define the class as an object. If some of the members are defined in files outsde of the object, include their header file(s).

Here is what our ShoeBox header file would look like:

#include <iostream> #include <string> using namespace std; class ShoeBox { public:

double CalcVolume( ) const { return Length * Width * Height; } void Area(const double Side1, const double Side2, char SideName[32]); float CalcShoeSize( ) const { return Length - 0.35; } void Display( ); private: double Length; double Width; double Height; string Color; }; Class Source Code This file used to implement the object is called a source file. It is used to define what the object is supposed to do. It contains all or some of the methods and their implementations. To create the source file, from the New property page of the New Items dialog box, click the Cpp File icon and click OK. By default, the (first) file is called File1.cpp. To change that name, you must save the project and replace the name of the file with the desired name. A source file should at least start with a line that specifies the name of the header file that it is implementing. Since this file is usually created in the same project, it is specified with an include line that is encloses the file name with double-quotes. An example would be:

#include "Book.h" The main area of the file is made of the class' implementation. Here is what the source file of our ShoeBox would look like: #include "File1.h" void ShoeBox::Area(const Double S1, const Double S2, PChar N) { cout << "\nThe area of the " << N << " side is = " << S1 * S2; } void ShoeBox::Display( ) { // Initializing the dimensions Length = 14.32; Width = 8.36; Height = 6.54; Color = "Brown Carpet"; // Display the characteristics of the shoe box cout << "Characteristics of this shoe box"; cout << "\nDimensions(L*H*W) = " << Length << " * " << Height << " * " << Width; Area(Length, Height, "front"); Area(Length, Width, "top"); Area(Height, Width, "left"); cout << "\n\tVolume = " << CalcVolume( ) << "\n\tColor = " << Color << "\n\tSize = " << CalcShoeSize( ); } The main( ) function of our shoe box project is reduced to simply calling the appropriate ShoeBox method member: #include <iostream.h> #include "ShoeBox.h" int main( )

{ ShoeBox Sala; Sala.Display( ); return 0; } Summary

To declare an argument of an object's method as constant, type the const keyword on some of the methods of an object are exclusively used to carry assignments. The

the left of the argument's data type.

external functions or other objects do not call such methods and do not communicate with them.

To declare a method as private, include it in the private section of the object. An object is made of the material that compose it and the actual structure of the a class is be made of two parts: its building block and its definition. These two parts

object, which defines how the object is built and used

of a class can be kept in different files that have access to each other.

Question

what is an object? Explain implementation of objects & instance of object? What do u understand instance of objects?

UNIT II LESSON 35 DATA DRIVEN Objective Data driven concept

Introduction A Dynamic Data Driven Application System (DDDAS) is an application software system capable of accepting and effectively utilizing remote data in real time (i.e., during the execution of the application software). Many software systems currently utilize static input data, i.e., input data which is specified a priority. The key concept of DDDAS is the generalization of application software systems to dynamically utilize real-time data arising from remote experiment and simulation, and to control such remote experiment and simulation to improve the performance of the application software system. The concept is illustrated schematically in Fig. 1. Dynamic Data Driven Application Systems have become a major subject of research interest due to the continuing rapid advances in technology. These include, for example, improvements in computer processor performance (i.e. doubling every 18 to 24 months (Berkowitz 1996)), network bandwidth, Rapid Prototyping (RP) and real-time data acquisition and control (e.g., using Micro-Electro Mechanical Systems (MEMS)). These rapid technological advances provide the means to revolutionize the use of existing and future application software systems. For example, the NSF TeraGrid1 is a multi-year e_ort to deploy20 TFlops of computing capacity at five sites connected through a 40 Gbps network. The Tera Grid will o_er unprecedented remote computing capability which can be utilized in realtime by application software systems executing at users sites. The incorporation of the NSF Tera grid into an application software system is therefore an example of a Dynamic Data Driven Application System. 1 http://www.ncsa.uiuc.edu/About/TeraGrid/

Conventional Engineering Design Optimization Engineering design is a potential Dynamic Data Driven Application System Where in remote real-time input from high performance computing resources (e.g., NSF Tera grid) and experiment (e.g., using capability for rapid fabrication of new experimental configurations) can produce a better design in shorter time with lower cost than the conventional approach. Fig. 2 illustrates the conventional approach to engineering design. An initial design is typically evaluated using simulation software executing on local computer resources. An example is Computational Fluid Dynamics (CFD) simulation using one of the several available commercial CFD software packages (e.g., fluent, gasp, star-cd). The results of the simulation are reviewed by the designer and additional simulations performed as needed. An experiment is then planned and executed, and the results compared with the simulation. The process is iterated until a satisfactory design has been achieved. A major limitation of the conventional approach is the absence of synergistic real-time use of remote experimental data and high performance computer resources (e.g., the NSF Tera Grid).

4 Data Driven Design Optimization Methodology We are developing an integrated software system, denoted Data Driven DesignOptimization Methodology (DDDOM), to synergistically incorporate remote experiment and simulation into an automated design optimization methodology. The DDDOM is comprised of six elements as illustrated in Fig. 3 and are summarized below. Controller The DDDOM Controller provides direction and control of the design optimization process. It is written in Perl (Wall et al 2000), a powerful systems programming language which enables robust program control on local and remote systems. The Controller utilizes the Globus software system (Foster and Kesselman 1997) to link to the NSF Tera Grid. User Interface The User Interface provides for the initiation and monitoring of the design optimization. It also provides visualization of the intermediate results of the design optimization process. The interface is written in Perl/Tk (Lidie and Walsh 2002). Both Perl and Perl/Tk operate on virtually every platform and operating system.

Optimizer A Multi-Criteria Design Optimization (MDO) algorithm is used to search the design space to define the Pareto Set. Both local (i.e., gradient-based) and global (i.e., stochastic-based) algorithms are used. Examples are CFSQP(Lawrence et al 1994) and GADO (Rasheed and Hirsh 1999), respectively.Surrogate Model Surrogate Models of the objective functions f are developedduring the design optimization using experiment and simulation. Thesemodels are utilized by the optimizer to search the design space for the ParetoSet. We utilize Response Surfaces (Myers and Montgomery 1995) and Radial Basis Function Artificial Neural Networks (Hertz et al 1991). The SurrogateModel incorporates the measure of uncertainty _ in the results generated by theexperiment and simulation. Experiment : Experiments are performed in real-time with the conditions of the experiment defined by the Controller. The interface with experiments is typically National Instruments Lab View (Travis 2002). Rapid Prototyping is used to build new models as needed with minimal delay (e.g., one day).

Simulation :

Simulations can be performed locally (i.e., at the same site as the DDDOM is

operated) or remotely (e.g., on the NSF Tera Grid). The simulations are performed in real-time with the conditions of the simulation defined by the Controller. 5 Example A five minute demonstration has been developed to illustrate the principle of operation of the DDDOM. The limited duration of the demonstration precludes the actual use of RP which typically requires several hours for fabrication of the prototype for experiment. Therefore, we have selected a single experimental configuration. Nonetheless, the experiment provides data to the DDDOM Controller in real time, and the Controller directs the experiment, thereby illustrating the DDDOM concept. The specific problem is defined as follows. Consider the flow of air in a converging-diverging nozzle attached to a stagnation chamber as illustrated in Fig.The nozzle is designed to achieve Mach 2 at the exit assuming isentropic expansion throughout the nozzle. Depending upon the ratio of stagnation pressure pt1 to ambient pressure pa, the flow in the diverging section of the nozzle can be 1) subsonic everywhere, 2) supersonic and subsonic with a normal shock at some location in the diverging section, and 3) supersonic everywhere (Anderson 2003). In the latter case, the theoretical exit Mach number is two. A one-dimensional simulation based upon inviscid gas dynamics (Liepmann and Roshko 1957) indicates that the exit pressure ratio pe vs stagnation pressure pt1 behaves as shown by the curve denoted Simulation in Fig. 5. This behavior is idealized, however, due to the neglect of the viscous boundary layer on the nozzle walls and the e_ect of the interaction of the normal shock wave (if it exists) with the boundary layers. Consequently, the actual exit pressure pe vs stagnation pressure pt1 curve di_ers substantially from the idealized shape.

Data Driven Design Optimization Methodology A Dynamic Data Driven Application System 1 Introduction

A Dynamic Data Driven Application System (DDDAS) is an application softwaresystem capable of accepting and effectively utilizing remote data in realtime (i.e., during the execution of the application software). Many software systemscurrently utilize static input data, i.e., input data which is specified apriori. The key concept of DDDAS is the generalization of application softwaresystems to dynamically utilize real-time data arising from remote experiment andsimulation , and to control such remote experiment and simulation to improvethe performance of the application software system. The concept is illustratedschematically in Fig. 1.

Dynamic Data Driven Application Systems have become a major subject of research interest due to the continuing rapid advances in technology. These include, for example, improvements in computer processor performance (i.e., doubling every 18 to 24 months (Berkowitz 1996)), network bandwidth, Rapid Prototyping (RP) and real-time data acquisition and control (e.g., using Micro- Electro Mechanical Systems (MEMS)). These rapid technological advances provide the means to revolutionize the use of existing and future application software systems. For example, the NSF

TeraGrid1 is a multi-year e_ort to deploy 20 TFlops of computing capacity at five sites connected through a 40 Gbps network. The TeraGrid will o_er unprecedented remot computing capability which can be utilized in real-time by application software systems executing at users sites. The incorporation of the NSF Teragrid into an application software system is therefore an example of a Dynamic Data Driven Application System.

Group discussion session on the article Function between two

Decomposition and the differences

Summary

6 Conclusions Engineering design is an example of a Dynamic Data Driven Application System Where in real-time data from experiment and simulation can be effectively utilized to yield better designs in shorter time. A Data Driven Design Optimization Methodology (DDDOM) is being developed which incorporates experiment and simulation in a real-time, synergistic manner. The theory and organization of DDDOM is described. An example demonstration is described.

UNIT II LESSON 36 ANALYSIS AND DESIGN METHODS Formal(OMT) object based design methods Objective

Purpose of method S/W life cycle

What is the Purpose of a Method? A method defines a reproducible path for obtaining reliable results. All knowledge-based activities use methods that vary in sophistication and formality. Cooks talk about recipes, pilots go through checklists before taking off, architects use blueprints, and musicians follow rules of composition. Similarly, a software development method describes how to model and build software systems in a reliable and reproducible way. In general, methods allow the building of models from model elements that constitute the fundamental concepts for representing systems or phenomena.. The object-oriented approach to software development proposes the equivalent of notes objects to describe software. Methods also define a representation often graphical that allows both the easy manipulation of models, and the communication and exchange of information between the various parties involved. A good representation seeks a balance between information density and readability. Over and above the model elements and their graphical representations, a method defines the rules that describe the resolution of different points of view, the ordering of tasks and the allocation of responsibilities. These rules define a process that ensures harmony within a group of cooperating elements, and explains how the method should be used. As time goes by, the users of a method develop a certain 'know-how' as to the way it should be used. This know-how, also called experience, is not always clearly formulated, and is not always easy to pass on. From Functional to Object-Oriented Methods

Although object-oriented methods have roots that are strongly anchored back in the 60s, structured and functional methods were the first to be used. This is not very surprising, since functional methods are inspired directly by computer architecture (a proven domain well known to computer scientists). The separation of data and code, just as exists physically in the hardware, was translated into the methods; this is how computer scientists got into the habit of thinking in terms of system functions. This approach is natural when looked at in its historical context, but today, because of its lack of abstraction, it has become almost completely anachronistic. There is no reason to impose the underlying hardware on a software solution. Hardware should act as the servant of the software that is executed on it, rather than imposing architectural constraints. More recently, towards the beginning of the 80s, object-oriented methods started re-emerging. History with a big H is said to repeat itself. The lesser history of methods repeats itself as well: the paths followed by functional methods and object-oriented methods are similar. To begin with, there was programming, with subprograms and objects as alternatives for the basic elements of structure. A few years later, software scientists pushed the idea of structure towards design as well, and invented structured design in one instance, and object-oriented design in the other. Later again, progress was made in the area of analysis, always using the same paradigm, either functional or objectoriented. Both approaches are therefore able to provide a complete path across the whole

software lifecycle. The evolution of methods, whether object-oriented or not, always progresses from programming towards analysis.

In practice, the situation is a bit more complex methods often do not cover the full lifecycle. This results in methods being mixed and matched: method A is used for analysis followed by method B, which is used for the design. As long as it uses a single paradigm the functional approach or the object-oriented approach this compartmentalization remains reasonable. Although it may remain understandable, the mixture of paradigms is clearly less reasonable.

Towards the mid-80s, the benefits of object-oriented programming began to gain recognition, and object design seemed like a sensible approach for people who wanted to use an object-oriented programming language such as Smalltalk. However, from the analysis standpoint, the concept of object-orientation was still only vapor and supposition. At that time, corporations had developed a strong knowledge of functional analysis and semantic data modeling methods. Computer scientists were inclined to follow a functional analysis phase with an object-oriented design phase. This approach has serious drawbacks attached to the paradigm shift. Moving from a functional approach to an object-oriented one requires a translation of the functional model elements into object model elements, which is far from being straightforward or natural. Indeed, there is no direct relationship between the two sets, and it is therefore necessary to break the model elements from one approach in order to create model element fragments that can be used by the other. This paradigm shift, right in the middle of the development effort, can greatly hinder the navigation from the statements of requirements obtained early in the analysis phase, to the satisfaction of those Requirements in the design phase. Moreover, an object-oriented design obtained after translation very often lacks abstraction, and is limited to the encapsulation of low-level objects available in the implementation and execution environments. All this implies a great deal of effort in order to obtain results that are not very satisfactory. The combination of a functional approach for analysis and an object-oriented approach for design and implementation does not need to exist today, as modern object-oriented methods cover the full software lifecycle

During the past decade, object-oriented applications going from requirements analysis to implementation have been developed in all sectors of programming. The experience acquired on these projects has helped the understanding of how to join together the various activities required to support a fully object-oriented approach. To date, the evolution of these practices is not complete, and there are still a few advocates of the mixed approach, prisoners beneath the weight of their habits. Corporations that are on the brink of the transition to object-orientation should not reproduce this flaw. It is far easier to deploy an approach that is completely object-oriented. In addition, software developed using this approach is simpler, more reliable and more easily adapted to the expectations of its users. The Proliferation of Object-Oriented Methods The first few years of the 90s saw the blossoming of around fifty different object-oriented methods. This proliferation is a sign of the great vitality of object-oriented technology, but it is also the fruit of a multitude of interpretations of exactly what an object is. The drawback of this abundance of methodologies is that it encourages confusion, leading users to adopt a 'wait and see' attitude that limits the progress made by the methods. The best way of testing something is still to deploy it; methods are not cast in stone they evolve in response to comments from their users. Fortunately, a close look at the dominant methods allows the extraction of a consensus around common ideas. The main characteristics of objects, shared by numerous methods, are articulated around the concepts of class, association (described by James Rumbaugh), partition into subsystems (Grady Booch), and around the expression of requirements based on studying the interaction between users and systems (Ivar Jacobson's use cases). Finally, well-deployed methods, such as Booch and OMT (Object Modeling Technique), were reinforced by experience, and adopted the methodology elements that were most appreciated by the users.

Booch and OMT Getting Closer

The second generations of the Booch and OMT methods, called Booch'93 and OMT-2, were far more similar to one another than their predecessors had been. The remaining differences were minor, and pertained primarily to terminology and notation. Booch'93 was influenced by OMT and

adopted associations, Harel diagrams and event traces. In turn, OMT-2 was influenced by Booch and introduced message flows, hierarchical models and subsystems, and model components. More importantly, it removed data flow diagrams from the functional model. These were inherited functional baggage and were not well integrated with the overall OMT approach. By this stage, both methods offered complete lifecycle coverage, but with a notable distinction in focus. Booch'93 focused on implementation, while OMT-2 concentrated on analysis and abstraction. Nonetheless, there were no serious incompatibilities between the two methods. Object-oriented concepts have a history that is often complex and intricate. The elements presented in the table below emerged from the experience of deploying the various methods, and have influenced the effort to unify the Booch and OMT methods

Origin Booch Embley Fusion Gamma et al Harel Jacobson Meyer Odell OMT Shlaer-Mellor Wirfs-Brock

Element Categories and subsystems Singleton classes and composite objects Operation descriptions, message numbering Frameworks, patterns and notes Statecharts Use cases Pre- and post-conditions Dynamic classification, emphasis on events Associations Objects lifecycles Responsibilities and collaborations Summary

Methods also define a representation often graphical that allows both the easy manipulation of models, and the communication and exchange of information between the various parties involved. The evolution of methods, whether object-oriented or not, always progresses from programming towards analysis.

The second generations of the Booch and OMT methods, called Booch'93 and OMT-2, were far more similar to one another than their predecessors had been. OMT-2 was influenced by Booch and introduced message flows, hierarchical models and subsystems, and model components. More importantly, it removed data flow diagrams from the functional model. Questions 1. discuss S/W life cycle 2. Give the details of OMT design method

UNIT II LESSON 37 ANALYSIS AND DESIGN METHODS CRC Methods Objective :


Conceptual Overview of CRC cards Design and analysis method

Conceptual Overview A CRC cards is an index card that is use to represent the responsibilities of classes and the interaction between the classes. CRC cards are an informal approach to object oriented modeling. The cards are created through scenarios, based on the system requirements, that model the behavior of the system. The name CRC comes from Class, Responsibilities, and Collaborators which the creators found to be the essential dimensions of object oriented modeling. CRC cards where introduced by Kent Beck and Ward Cunningham in there paper "A Laboratory for Teaching Object-Oriented Thinking" released in OOPLSA '89. There original purpose was to teach programmers the object-oriented paradigm. When Kent Beck wrote the draft version of their paper he change Collaborators to helpers. Ward Cunningham changed it back to Collaborators when he reviewed the paper. The initials of Cunningham's son are CRC. Why uses CRC cards? They are portable... No computers are required so they can be used anywhere. Even away from the office. They allow the participants to experience first hand how the system will work. No computer tool can replace the interaction that happens by physically picking up the cards and playing the roll of that object... They are a useful too for teaching people the object-oriented paradigm.

They can be used as a methodology them selves or as a front end to a more formal methodology such as Booch, Wirfs-Brock, Jacobson, etc. Although CRC cards where created for teaching, they have proven useful for much more. They become an accepted method for analysis and design. The biggest contributing factor to their success is the fact that they provide an informal and non threatening environment that is productive to working and learning. 1. The CRC card session. The Group The ideal group size for a CRC card session is five or six people. This size generally allows everyone to productively participate. In groups of large size the productive is cut by more disagreements and the amount of participation by everyone is lower. If there are more than six people, one solution is to have the extra people be present strictly as observers. The group five or six people in the core group should be composed of developers, domain experts, and an object-oriented technology facilitator. In the initial Analysis phase there should be two or three domain experts, one object-oriented technology facilitator, and the rest of the group made up of people how are responsible for delivering the system. As the project moves more in to the design phase, some of the domain experts can be replaced with developers. There should always be at least one domain expert in the group to clarify an question that arise about the behavior of the system. The Cards The cards should look something like this:

The exact format of the card can be customized to the preferences of the group, but the minimal required information is the name of the class, it's responsibilities and the collaborators. The back of the card can be used for a description of the class. During the design phase attributes of the class can be recorded on the back as well. One way to think of the card is the front as the public information, and the back as the encapsulated, implementation details. The Session Before starting a session there needs to be some kinds of requirements for the systems. Weather they are implicitly or explicitly define the people participating in the group need to be familiar with them. A session also needs to focus on one part of the problem at a time. So a subset of the problem needs to be chosen to explored during the CRC card session. Creating class The first step in modeling an system in the object-oriented paradigm is to identify the class in the problem domain. So this is the first step in a CRC card session. Using the problem statement or requirements document, identify the classes that are obvious in the subset of the problem that is going to explored in this session. One useful tool is to find all of the nouns and verbs in the problem statement. The nouns are a good key to what class are in the system, and the verbs show what there responsibilities are going to be. Use this information for the basis of a brainstorming session and identify all the class that you see. Remember in a brainstorming session there should be no or little

discussion of the ideas. Record them and filter the results after the brainstorming. After the classes have been chosen pass out cards and assign the class to the member of the group. Each person should be responsible for at least on class. They are the owner of that class for the session. Each person records the name of their class on a card. One class per card. Responsibilities Once a reasonable set of classes have be assigned to the group, responsibilities can be added. Add responsibilities that are obvious from the requirements or the name of the class. You don't need to find them all or any. The scenarios will make them more obvious. The advantage of finding some in the beginning is that it help provide a starting place. Super classes and Subclasses Super classes and subclasses can be defined at any time they become obvious. The scenarios will illuminate these as well. It is up to the group to decided if they want to define any hierarchical relationships now or wait till the scenarios to do this. Attributes Attributes of class don't really need to be defined any time soon. They are an implementation detail. The responsibilities of the class will help make these clear. Attributes are general not defined at all till the design phase, but they can be defined at anytime the group thinks it is appropriate. Remember these are implementation details and should go on the back of the card. Scenario execution These are the heart of the CRC card session. Scenarios are walk-throughs of the functions of the system in detail. Take required functionality from the requirements document and use this as a scenarios. Start with scenarios that are part of the systems normal operation first, and then exceptional scenarios, like error recover, later. First decide which class is responsible for this function. The owner of the class then picks up his card. When a card is in the air it is an object and can do things. The own announces that he needs to fulfill his responsibility. The responsibility is refined in to smaller tasks if possible. These smaller tasks can be fulfilled be the object is appropriate or they can be fulfilled be interacting with other objects. If no other appropriate class exist, maybe you need to make one. This is the fundamental procedure of the scenario execution. Lets move on the Analysis and try out first CRC card session. 2. CRC cards for analysis.

Analysis is the process of modeling what a system does, not how it does it. Lets start by modeling a sample system using CRC cards. Activity 1. Problem statement. This application will support the operations of a technical library for an R&D organization. This includes the searching for and lending of technical library materials, including books, videos, and technical journals. Users will enter their company ids in order to use the system; and they will enter material ID numbers when checking out and returning items. Each borrower can be lent up to five items. Each type of library item can be lent for a different period of time (books 4 weeks, journals 2 weeks, videos 1 week). If returned after their due date, the library user's organization will be charged a fine, based on the type of item( books $1/day, journals $3/day, videos $5/day). Materials will be lent to employees with no overdue lendables, fewer than five articles out, and total fines less than $100. ...(Design Constraints)... With this problem statement identify the class and assign them to the group members. Make a card for each class. Some ideas for class: application library material books videos journal company system ID numbers item borrower date

organization employee article fine This list is made up of the nouns in the problem statement. It is up to you to decide which ones if any are good classes for this problem. Now lets try our first scenario, taken from the requirement that the system bust allow users to check out lendables. "What happens when Johny Codewarrior, who has no accrued fines and one outstanding book, not overdue, checks out a book entitle Document, Your job depends on it?" More about Analysis The strength of CRC cards for analysis. Common Project Vocabulary Spread Domain Knowledge Making the Paradigm Shift Live Prototyping Identifying Holes in Requirements When is the analysis done, and time to move on to design? When all the different responsibilities are in place and the system has become stable. After all the normal behavior has been covered, exceptional behavior needs to be simulated. When you notice that the responsibilities are all in place to support the new scenarios, and there is little change to the cards, this is a sign the you are ready to start design. Activity 2. Now let do some more scenarios and try to stabilize our system. Try these: "What happens when Johny Codewarrior returns the book Document, Your job depends on it two days late? He has no other item checked out and no acquired fines." "What happens when Ivar Jacobson uses the search feature to look for the book Object-Oriented Software Engineering of which there are 2 copies available?" "What happens when Grady Booch uses the search feature to look for the book Object-Oriented Analysis and Design with Application of which there is 1 copy available and the database is down?"

3. CRC cards for Design. In the design phase, the concentration moves from what to how. In this phase developers replace some of the domain experts in the group, but there still should be one domain expert in the group. Strength of CRC card for Design Spreading Objet-Oriented Design Expertise Design Reviews Framework for Implementation Informal Notation Things to consider in Design Target Environment Language Choice of supporting software components Performance Requirements Other - memory, security... CRC Element at the Design Stage Classes Think about what class are need to make the system work. Do you need a List class to hold objects? Do you need class to handle exceptions? Do you need wrapper classes for other subsystems? New classes that are looked for in this part, are classes that support the implementation of the system. Scenarios and Responsibilities During the problem modeling in the analysis phase the distinction between class and object is blurry. Now think about the objects in your scenarios. Who create the objects? What happens when it is created and destroyed? What is the lifetime of the object vs. the lifetime of the information held be the object? Attributes Now is the time to look at what information the objects hold compared to what is requested from other classes or computed of the fly. Use the back of the card to record the attributes found for the classes. New things to record your cards

Sub responsibilities Break you responsibilities into sub responsibilities and list the sub responsibilities indented under the main responsibilities. Move the collaborators next to the sub responsibilities that use them. Collaborating Responsibilities After the Collaborator class on your card list the responsibility of the used class that is used in the collaboration. Data passed After the collaborating responsibilities on your cards, list the data past back by the collaborating object in parenthesis. Activity 3. Redo the scenarios you did in the analysis phase, but know take in to consideration all of the design heuristics discussed. Make up your own scenarios and try them... System Requirements Cards: Should be physical cards, not virtual cards. CASE tools for support of CRC cards are useful, but they cannot replace the interaction that physical cards facilitate. 3x5 or 4x6 are the perferable size. But you can really use anything you want.... Napkins??? Denny's??? Ahh the possiblities are endless...

Summary A CRC cards is an index card that is use to represent the responsibilities of classes and the interaction between the classes. CRC cards are an informal approach to object oriented modeling. office. They allow the participants to experience first hand how the system will work. No computer tool can replace the interaction that happens by physically picking up the cards and playing the roll of that object... They are a useful too for teaching people the object-oriented paradigm. Why uses CRC cards?

They are portable... No computers are required so they can be used anywhere. Even away from the

Questions 1.What is CRC card? Why we are in need of using CRC cards?

UNIT II LESSON 38 DESIGN REFINEMENT Objective: Concept of coupling and cohesion

Design Refinement Refinement presupposes that implementation is being inherited as well as abstraction. Refinement has different significance depending on whether the client is another component entirely, or is a part of B. Clearly any class can be a client of itself (self-dependency would seem to be non-problematic, but some of the concerns in refinement with base as client cast doubt on this). Coupling and Cohesion between modules (i.e., classes). Specific measures of coupling are: 1. 2. 3. 4. The number of classes that a given class inherits from; The number of classes that a given class references as data members; The number of methods that a given method calls; The number of parameters that a given method has.

Specific measures of cohesion are: 1. The degree to which all methods in a class perform a logically-related aspect of system functionality 2. The degree to which a method performs a single specific function In general, coupling should be minimized and cohesion should be maximized. Techniques to reduce coupling Limit the number of classes that communicate with (i.e, call functions of) other classes.

I.

E.g. in an MVP design, a Process-class method invoked by a View class method may forward a Model-class exception rather than catching the exception and calling a View-class method.

II.

E.g., a. In the Rolodex system, the Process-class method Rolodex Command Processor. Process Command is called from a View-class method in Rolodex Command Editor. b. The process Command method throws an Input Errors exception back to the view, rather than catching the exception and calling a View class. c. This limits coupling by not having a View class reference in the Rolodex Command Processor process class.

Limit the number of calls between classes that do need to communicate with each other. I. E.g., in the Rolodex system, the dialog button functions, such as OKAddButton, can communicate directly with the model, without having to go through a parent view class. II. III. E.g., OKAddButton. ActionPerformed can call Rolodex. Add directly More highly-coupled alternative would be some chain-of-command call such as AddCardDialog.getRolodex().add. Limit the number of public functions in each class. I. In general, make a function public only if there is a demand for it from some other class. II. Do not add public get functions "in case" they may be needed; the same goes for public set functions. III. E.g., since AddCardDialog.getRolodex is never used, it should not be provided.

Limit the types of function parameters and return values to the smallest type necessary.

I. II.

Consider the Rolodex.find operation. It returns zero or more cards, which could be returned as Rolodex object, or a simpler CardList object.

III.

The Card List object is preferable, since callers of Rolodex.find do not need all of the information in a full Rolodex, but only a simple list.

Design to limit the amount of change needed if data representations change. I. When using external process classes (e.g., C++ from Java), design wrapper classes that define a generic process class that hides details of external class. II. With a properly designed wrapper class, little or no changes to a Model class are necessary when changing underlying data representations in Process classes. Use exception handling wisely. I. Consider again the use of exception handling to communicate between models and views. II. The InputErrors exception classes provide a generic, string-based representation that can be used uniformly for error communication. Ease of debugging -- a major rationale for limiting coupling. I. Consider the debugging question: "If something goes wrong in module X, where do I look for the problem?" II. III. IV. First, look in module X for the problem. If it's caused immediately there, then look at all other modules that connect to X. Repeat this process until the source of the problem is located.

Clearly, this problem isolation process will be made more orderly, and potentially shorter if the number of directly connected modules is limited Techniques to increase coherence(Cohesion) Generally, coupling measures are easier to pinpoint exactly.

Limiting the coupling between classes in turn increases cohesiveness, since decoupling eliminates unnecessary items from classes. To address cohesion directly means to design each class to represent a single, clearly identifiable piece of data and/or encapsulate a single clearly identifiable area of functionality. To a large extent, the MVP design technique promotes cohesion, since it has welldefined functionality for each category of design class. Limiting the size of each individual scoping unit (class or function), per our design and implementation conventions, is also a way to foster cohesion. I.e., it's harder to do too much in a class or function if you can't do that much there in the first place.

Summary Coupling" and "cohesion" are terms used to denote module interconnectedness. Coupling refers to how much inter-module connection exists in a design and Cohesion refers to how much intra-module cohesiveness a design has. In general, coupling should be minimized and cohesion should be maximized. Specific measures of coupling are:

The number of classes that a given class inherits from; The number of classes that a given class references as data members; The number of methods that a given method calls; The number of parameters that a given method has.

Specific measures of cohesion are:

The degree to which all methods in a class perform a logically-related aspect of system

functionality

The degree to which a method performs a single specific function

Questions: 1. 2. 3. Define the concept of cohesion and coupling. State steps to minimize cohesion State steps to maximize coupling

UNIT III LESSON 39 STANDARD TEMPLATE LIBRARY(STL) Objective Intro to STL Components of STL

Containers Algorithms Iterators Sequential Containers

Introduction to the Standard Template Library The Standard Template Library, or STL, is a C++ library of container classes, algorithms, and iterators; it provides many of the basic algorithms and data structures of computer science. The STL is a generic library, meaning that its components are heavily parameterized: almost every component in the STL is a template. STL distinguishes general algorithms from the more specialized data and methods encapsulated by ordinary abstract data types. In this way, complex and powerful algorithms can be implemented independently of the data to which they are applied, allowing for generalization and reuse of these algorithms. You should make sure that you understand how templates work in C++ before you use the STL. The idea behind STL can easily be shown by the following consideration: Imagine software components as a three-dimensional space. One dimension represents the data types (int, double, char, ...), the second dimension represents the containers (array, linked-list, ...) and the third dimension represents the algorithms (sort, merge, search, ...).

Figure: Component space

With this scenario given, i*j*k different versions of code have to be designed - a sort algorithm for an array of int, the same sort algorithm for an array of double, a search algorithm for a linked-list of double and so on. By using template functions that are parameterized by a data type, the i-axes can be dropped and only j*k versions of code have to be designed, because there has to be only one linked-list implementation which then can hold objects of any data-type. The next step is to make the algorithms work on different containers - that means that a search algorithm should work on arrays as well as on linked-lists, etc. Then, only j + k versions of code have to be created.

Lets shortly summarize a few points about STL before we proceed further. 1. Library of classes for use in manipulating data structures 2. High level code (most of the details hidden from view -- need only know the interface) 3. Safe reusable code: 1. Minimize need to manipulate pointers 2. Minimize dangers of reading past end of arrays 3. Minimize software development time for implementation of standard data structures Templatized so can be used with variety of data types

Components of STL The STL contains several components. But at its core there are three key components They are Containers A container is an object that actually stores data. It is a way data is organized in memory. The STL containers are implemented by template classes and therefore can be easily customized to hold different types of data. Containers are classes to contain data. Examples: 1. sequential containers list vector deque set map multiset multimap stack queue priority_queue

2. associative containers

3. container adaptors Algorithms Basic algorithms that can be used to manipulate the contents of containers. An algorithm is a procedure that is used to process the data contained in the containers, The STL includes many different kinds of algorithms to provide support to tasks such as initializing, searching, copying, sorting, and merging. Algorithms are implemented by template functions. Examples:
a. copy()

b. sort()

Iterators Iterators are classes to access elements in containers. Act like pointers, but minimize the need to dereference. Minimize the need to implement loops for accessing or outputting data Containers and algorithms Like many class libraries, the STL includes container classes: classes whose purpose is to contain other objects. The STL includes the classes vector, list, deque, set, multiset, map, multimap, hash_set,
hash_multiset, hash_map,

and hash_multimap. Each of these classes is a template, and can be

instantiated to contain any type of object. You can, for example, use a vector<int> in much the same way as you would use an ordinary C array, except that vector eliminates the chore of managing dynamic memory allocation by hand.
vector<int> v(3); v[0] = 7; v[1] = v[0] + 3; v[2] = v[0] + v[1]; // v[0] == 7, v[1] == 10, v[2] == 17 // Declare a vector of 3 elements.

Characteristics of Containers Here are some general characteristics of all containers: 1. Collections of items -- numbers, names, ordered pairs of items, etc. 2. Objects are stored in different ways depending on the container. Each container has its way of storing objects. Each container has methods (member functions) to do basic tasks.

The STL also includes a large collection of algorithms that manipulate the data stored in containers. You can reverse the order of elements in a vector, for example, by using the reverse algorithm.

reverse(v.begin(), v.end()); // v[0] == 17, v[1] == 10, v[2] == 7

There are two important points to notice about this call to reverse. First, it is a global function, not a member function. Second, it takes two arguments rather than one: it operates on a range of elements, rather than on a container. In this particular case the range happens to be the entire container v. The reason for both of these facts is the same: reverse, like other STL algorithms, is decoupled from the STL container classes. This means that reverse can be used not only to reverse elements in vectors, but also to reverse elements in lists, and even elements in C arrays. The following program is also valid.
double A[6] = { 1.2, 1.3, 1.4, 1.5, 1.6, 1.7 }; reverse(A, A + 6); for (int i = 0; i < 6; ++i) cout << "A[" << i << "] = " << A[i];

This example uses a range, just like the example of reversing a vector: the first argument to reverse is a pointer to the beginning of the range, and the second argument points one element past the end of the range. This range is denoted [A, A + 6); the asymmetrical notation is a reminder that the two endpoints are different, that the first is the beginning of the range and the second is one past the end of the range. STL Example Code Look at these sample code fragments, then read the discussion points afterwards. Operations using a list class object This example instantiates a list of int and then does some operations on it. A list class stores data in the form of a linked list (Click here for a copy of the example code.):

#include < list > #include < algorithm > int main() { int num;

// std header file for STL list class // std header file for STL algorithms

list < int > numbers;

// declare an object of list class in STL

for( int i = 0; i < 10; i++ ) // read some numbers and insert in list: { cin >> num; // insert the number before current beginning numbers.insert( numbers.begin(), num ); } numbers.sort(); numbers.reverse(); numbers.remove(3); // sort the numbers (low to high): member function // reverse the order: member function // remove all instances of the number 3

numbers.erase( ++numbers.begin() ); // erase the second element ostream_iterator <int> output( cout, "\n" ); // output the list copy( numbers.begin(), numbers.end(), output ); } Points to note about this example: 1. You must include the header file list which declares the class template list. 2. You can instantiate a list object to any valid data type. The example object holds integers.
list

is an example of a container class.

3. Just like any linked list, this one will add a node as needed when a new number is inserted. 4. insert() 1. This insert member function of the list class inserts the second argument before the location specified by the first argument. 2. Its first argument is an iterator which for the list class is basically like a pointer to a node in the list.

3. The list member function begin() returns an iterator (pointer) to the first node 5. Other member functions of the list class: 1. sort() This is a member function of the list class. There is also a sort() non-member algorithm that can be used. 2. reverse() Reverse the current order of elements. 3. remove() Delete all nodes storing instances of the argument passed in. 4. erase() Delete the node occurring at the position indicated by the iterator argument. This example deletes the first node after the beginning, i.e. the second node. Note the difference between remove and erase. To delete all instances of an element, use
remove. To delete element at a given position, use erase.

6. Syntax of the iterator numbers.begin() Notice that to get the next node after the beginning, I had to use the increment operator ++. This gave a pointer to the second node in the list. 7. Output the list: Output was accomplished using another iterator. 1. Instantiate an object of type ostream_iterator <int>. 2. The call to the ostream_iterator constructor says that cout will be the ostream used and newlines \n will be the delimiters between successive outputs. 3. The ostream_iterator object is named output. 4. The STL algorithm function copy() writes all the list elements (from begin() to
end()

to output.

Operations using a vector class object

A vector is a class that stores data using an array. This example instantiates an array of string objects (Click here for a copy of the example code.).

#include < vector > #include < algorithm > #include < string > int main() {

// std header file for STL vector class // std header file for STL algorithms // header for string class

vector < string > names; // declare an object of vector class in STL char Name[10]; for( int i = 0; i < 10; i++ ) { cin >> Name; names.insert( names.begin(), Name ); } names.erase( names.end() ); // erase the last string sort( names.begin(), names.end() ); // sort the array: must use STL algorithm for( unsigned i = 0; i < names.size(); i++ ) // output the array cout << names[i] << endl; } Points to note about this example: 1. You must include the header file vector which declares the class template vector. 2. You can instantiate a vector object to any valid data type. The example object holds strings.
vector

// read some names and insert in vector:

is another example of a container class.

3. vector stores objects in an array. But unlike arrays that you are familiar with, this one grows or shrinks automatically as elements are added or removed. 4. Overloaded member subscript operator
[ ]

Notice the subscript operator in the expression names[i]. A vector object is not an array, but the overloaded subscript operator lets you have random access to the array of data elements contained within it. 5. The vector member function end() returns an iterator (pointer) to the last element in the array. 6. erase() Delete the node occurring at the position indicated by the iterator argument. This example deletes the last node. 7. size() This is a member function that returns the number of elements in the class. size() is also a member of the list class. 8. Note the member functions that are missing: Several member functions seen in the list example are missing here: 9. remove 10. sort 11. reverse This has to do with the different storage methods of a vector vs a list. Because vector elements are stored in an array, the operations listed here cannot be implemented as efficiently as they can be for data stored in linked lists. 12. STL Algorithms We were able to sort the vector using the generic STL algorithm. The vector class does not have its member sort(). 13. Output of the array: 1. Notice we used a for loop together with overloaded index operator [ ] to output the
vector

elements.

2. Output could also have been done using an ostream_iterator: 3. 4. ostream_iterator<string> out( cout, "\n" ); copy( names.begin(), names.end(), out );

Discussion of these examples These two examples have illustrated several points. We saw examples of different types of objects: 1. container objects 1. list 2. vector 2. iterator objects 1. value returned by begin() and end() 2. ostream_iterator 3. We saw that list had different member functions than vector. This was related to the different ways that list and vector store their data. 4. Thus there is an issue of which container object to use. Each has its good points and drawbacks. 5. We saw two examples of STL algorithms: 6. copy() 7. sort() Notice that the STL algorithm sort() is different from the list class member sort(). To use it, we included the header algorithm. Next we will discuss STL container objects with reference to these points. Containers These are classes for storing data. There are sequential containers that store data in the form of lists, and associative containers. Here are examples of methods common to all containers except stack, queue and
priority_queue:

1 2 3 4 5 6 7 8 9

Begin()

find the first element.

Return an iterator (like a pointer) to that element end() size() erase() find the last element. return the number of elements currently container remove an element from the container at location specified by iterator operator= assign one container to another -- do memberwise copy of objects stored in right side operator== test for equality of two containers test for inequality of two containers Return an iterator (like a pointer) to that element

10 operator!= Sequential Containers

These are containers that hold items in lists but are implemented in different ways. A list means a collection of objects in which there is a first and a last object, and each object (except first and last) has a predecessor and a successor. In other words, a list implies an ordering. Now look at three types of classes implementing lists: 1. list class 1. Implemented as a doubly linked list (non-contiguous memory). This means each node has a pointer forwards to the next node, and a pointer backwards to the previous node. 2. In addition to basic member functions above, also has these member functions: 3. sort() 4. reverse() 5. remove() sort the elements in the list reverse the current order of list delete all instances of argument object

6. Efficient insertion at beginning or end of list. 7. Linear time (O(N)) to access other elements of the list: must traverse the list. 8. List grows or shrinks automatically as elements are added or removed. 2. vector classes

1. Implemented as array (contiguous memory). 2. Efficient insertion at back of array: just add item to slot after current last. 3. Linear time(O(N)) to insert or remove element at front: must shift all the other array elements to fill up empty hole. 4. Efficient access of indexed element: random access. This is accomplished by: 5. Overloaded subscript member operator []. 6. Grows or shrinks automatically as elements are added or removed. 3. deque class 1. Implemented in non-contiguous memory 2. Combine list's efficient insert/remove of front elements with vector's efficient random access of indexed elements. 3. Has overloaded member subscript operator. 4. Grows or shrinks automatically as elements are added or removed. The method of data storage in a container influences the efficiency of operations on the data. Here is a table: Operation --------Insert at beginning Insert at end Erase at beginning Erase at end Get first element Get last element vector -----O(N) constant O(N) constant constant constant deque ----constant constant constant constant constant constant list ---constant constant constant constant constant constant

Get middle element

constant

constant

O(N)

Here O(N) means that the complexity of the operation depends upon the number of elements N stored in the container object. It is a measure of the time needed to do the task. As N grows, then the time to do the task grows roughly proportional to N.

Summary A collection of generic classes and functions is called the Standard Template Library(STL). STL components are part of C++ standard library. The STL contains several components. But at its core there are three key components They are Containers Algorithms. Iterators

The STL does, however, include several other types of components. First, the STL includes several utilities: very basic concepts and functions that are used in many different parts of the library. The concept Assignable, for example, describes types that have assignment operators and copy constructors; almost all STL classes are models of Assignable, and almost all STL algorithms require their arguments to be models of Assignable. Second, the STL includes some low-level mechanisms for allocating and deallocating memory. Allocators are very specialized, and you can safely ignore them for almost all purposes. Finally, the STL includes a large collection of function objects, also known as functors. Just as iterators are a generalization of pointers, function objects are a generalization of functions: a function object is anything that you can call using the ordinary function call syntax. There are

several different concepts relating to function objects, including Unary Function (a function object that takes a single argument, i.e. one that is called as f(x)) and Binary Function (a function object that takes two arguments, i.e. one that is called as f(x, y)). Function objects are an important part of generic programming because they allow abstraction not only over the types of objects, but also over the operations that are being performed.

Questions 1. what is STL How it is different from standard library 2. Discuss three types of containers

UNIT III Lesson 40 Standard Template Library(STL) II Objective


Algorithm Iterator Concept modeling

ALGORITHMS Algorithms are functions that can be used generally across a variety of containers for processing their contents. Although each container provides functions for its basic operations, STL provides more than sixty standard algorithms to support more extended or complex operations. Standard algorithms also permit us to work with two different types of containers at the same time. Remember, STL algorithms are not member functions or friends of containers. They are standalone template functions. STL algorithms reinforce the philosophy of reusability. By using these algorithms, programmers can save a lot of time and effort. To have access to the STL algorithms, we must include <algorithm> in our program. STL algorithms, based on the nature of operations they perform, may be categorized as under: . Retrieve or non-mutating algorithms . Mutating algorithms . Sorting algorithms . Set algorithms . Relational algorithms These algorithms are summarized in Tables. STL also contains a few numeric algorithms under the header file <numeric>. They are listed Non-mutating algorithms

Operations Adjacent_find( ) count( ) count_if( ) equal( ) find( ) for_each( ) search( )

Description Finds adjacent pair of objects that are equal Counts occurrence of a value in a sequence Counts number of elements that matches a predicate True if two ranges are the same Finds first occurrence of a value in a sequence Apply an operation to each element Finds a subsequence within a sequence

Mutating algorithms Operations copy( ) fill() generate( ) iter_swap( ) remove( ) replace( ) Description Copies a sequence Fills a sequence with a specified value Replaces all elements with the result of an operation Swaps elements pointed to by iter:'tors Deletes elements matching a predicate Replaces elements with a specified value

Sorting algorithm Operations binary _search( ) equalrange( ) merge( ) pop_heap( ) push_heap() sort( ) Description Conducts a binary search on an ordered sequence Finds a subrange of elements with a given value Merges two consecutive sorted sequences Deletes the top element Adds an element to heap Sorts a sequence I

Iterators Iterators behave like pointers and are used to access container elements. They are often used to traverse from one element to another, a process known as iterating through the container. There are five types of iterators as described Iterator Input output Forward Bidirectional Random Access method Linear Linear Linear Linear Random Direction of movement Forward only Forward only Forward only Forward & backward Forward & backward I/O capability Read only Write only Read / write Read / write Read / write Remark Cannot be saved Cannot be saved Can be saved Can be saved Can be saved

Different types of iterators must be used with the different types of containers. Note that only sequence and associative containers are traversable with iterators. In the example of reversing a C array, the arguments to reverse are clearly of type double*. What are the arguments to reverse if you are reversing a vector, though, or a list? That is, what exactly does reverse declare its arguments to be, and what exactly do v.begin() and v.end() return? The answer is that the arguments to reverse are iterators, which are a generalization of pointers. Pointers themselves are iterators, which is why it is possible to reverse the elements of a C array. Similarly, vector declares the nested types iterator and const_iterator. In the example above, the type returned by v.begin() and v.end() is vector<int>::iterator. There are also some iterators, such as istream_iterator and ostream_iterator, that aren't associated with containers at all. Iterators are the mechanism that makes it possible to decouple algorithms from containers: algorithms are templates, and are parameterized by the type of iterator, so they are not restricted to a single type of container. Consider, for example, how to write an algorithm that performs linear search through a range. This is the STL's find algorithm.
template <class InputIterator, class T> InputIterator find(InputIterator first, InputIterator last, const T& value) {

while (first != last && *first != value) ++first; return first; } Find

takes three arguments: two iterators that define a range, and a value to search for in that range. It

examines each iterator in the range [first, last), proceeding from the beginning to the end, and stops either when it finds an iterator that points to value or when it reaches the end of the range.
First

and last are declared to be of type InputIterator, and InputIterator is a template

parameter. That is, there isn't actually any type called InputIterator: when you call find, the compiler substitutes the actual type of the arguments for the formal type parameters InputIterator and T. If the first two arguments to find are of type int* and the third is of type int, then it is as if you had called the following function.
int* find(int* first, int* last, const int& value) { while (first != last && *first != value) ++first; return first; }

Concepts and Modeling One very important question to ask about any template function, not just about STL algorithms, is what the set of types is that may correctly be substituted for the formal template parameters. Clearly, for example, int* or double* may be substituted for find's formal template parameter Input
Iterator.

Equally clearly, int or double may not: find uses the expression *first, and the

dereference operator makes no sense for an object of type int or of type double. The basic answer, then, is that find implicitly defines a set of requirements on types, and that it may be instantiated with any type that satisfies those requirements. Whatever type is substituted for Input Iterator must provide certain operations: it must be possible to compare two objects of that type for equality, it must be possible to increment an object of that type, it must be possible to dereference an object of that type to obtain the object that it points to, and so on.
Find

isn't the only STL algorithm that has such a set of requirements; the arguments to for_each and

count, and other algorithms, must satisfy the same requirements. These requirements are sufficiently important that we give them a name: we call such a set of type requirements a concept, and we call this particular concept Input Iterator. We say that a type conforms to a concept, or that it is a model of a

concept, if it satisfies all of those requirements. We say that int* is a model of Input Iterator because
int*

provides all of the operations that are specified by the Input Iterator requirements.

Concepts are not a part of the C++ language; there is no way to declare a concept in a program, or to declare that a particular type is a model of a concept. Nevertheless, concepts are an extremely important part of the STL. Using concepts makes it possible to write programs that cleanly separate interface from implementation: the author of find only has to consider the interface specified by the concept Input Iterator, rather than the implementation of every possible type that conforms to that concept. Similarly, if you want to use find, you need only to ensure that the arguments you pass to it are models of Input Iterator. This is the reason why find and reverse can be used with lists,
vectors,

C arrays, and many other types: programming in terms of concepts, rather than in terms of

specific types, makes it possible to reuse software components and to combine components together. Refinement Input Iterator is, in fact, a rather weak concept: that is, it imposes very few requirements. An Input Iterator must support a subset of pointer arithmetic (it must be possible to increment an Input Iterator using prefix and postfix operator++), but need not support all operations of pointer arithmetic. This is sufficient for find, but some other algorithms require that their arguments satisfy additional requirements. Reverse, for example, must be able to decrement its arguments as well as increment them; it uses the expression --last. In terms of concepts, we say that reverse's arguments must be models of Bidirectional Iterator rather than Input Iterator. The Bidirectional Iterator concept is very similar to the Input Iterator concept: it simply imposes some additional requirements. The types that are models of Bidirectional Iterator are a subset of the types that are models of Input Iterator: every type that is a model of Bidirectional Iterator is also a model of Input Iterator. Int*, for example, is both a model of Bidirectional Iterator and a model of Input Iterator, but istream_iterator, is only a model of Input Iterator: it does not conform to the more stringent Bidirectional Iterator requirements. We describe the relationship between Input Iterator and Bidirectional Iterator by saying that Bidirectional Iterator is a refinement of Input Iterator. Refinement of concepts is very much like inheritance of C++ classes; the main reason we use a different word, instead of just calling it "inheritance", is to emphasize that refinement applies to concepts rather than to actual types.

There are actually three more iterator concepts in addition to the two that we have already discussed: the five iterator concepts are Output Iterator, Input Iterator, Forward Iterator, Bidirectional Iterator, and Random Access Iterator; Forward Iterator is a refinement of Input Iterator, Bidirectional Iterator is a refinement of Forward Iterator, and Random Access Iterator is a refinement of Bidirectional Iterator. (Output Iterator is related to the other four concepts, but it is not part of the hierarchy of refinement: it is not a refinement of any of the other iterator concepts, and none of the other iterator concepts are refinements of it.) The Iterator Overview has more information about iterators in general. Container classes, like iterators, are organized into a hierarchy of concepts. All containers are models of the concept Container; more refined concepts, such as Sequence and Associative Container, describe specific types of containers. Other parts of the STL If you understand algorithms, iterators, and containers, then you understand almost everything there is to know about the STL. The STL does, however, include several other types of components. First, the STL includes several utilities: very basic concepts and functions that are used in many different parts of the library. The concept Assignable, for example, describes types that have assignment operators and copy constructors; almost all STL classes are models of Assignable, and almost all STL algorithms require their arguments to be models of Assignable. Second, the STL includes some low-level mechanisms for allocating and deallocating memory. Allocators are very specialized, and you can safely ignore them for almost all purposes. Finally, the STL includes a large collection of function objects, also known as functors. Just as iterators are a generalization of pointers, function objects are a generalization of functions: a function object is anything that you can call using the ordinary function call syntax. There are several different concepts relating to function objects, including Unary Function (a function object that takes a single

argument, i.e. one that is called as f(x)) and Binary Function (a function object that takes two arguments, i.e. one that is called as f(x, y)). Function objects are an important part of generic programming because they allow abstraction not only over the types of objects, but also over the operations that are being performed.

STL include files


STL is divided into the following header files in order to reduce compilation time. algo.h bool.h bvector.h deque.h function.h iterator.h list.h map.h multimap.h multiset.h pair.h random.C set.h includes all the algorithms simulates bool bit_vector deque operators, function objects and function adaptors iterator tags, stream iterators and iterator adaptors list map multimap multiset pair random number generator. It should be compiled and linked if random_shuffle is used. set

stack.h tempbuf.C

container adaptors an auxiliary buffer for get_temporary_buffer; it should be compiled and linked if get_temporary_buffer, stable_partition, inplace_merge or stable_sort are used.

tempbuf.h vector.h

get_temporary_buffer vector

(There are some other STL include files besides these but they are mainly for use with DOS and/or Windows C++ compilers, for working with different memory models. They are not necessary for use with the IBM xlC or Apogee apCC compilers.)

Summary An algorithm is a procedure that is used to process the data contained in the containers, The STL includes many different kinds of algorithms to provide support to tasks such as initializing, searching, copying, sorting, and merging. Algorithms are standalone functions that are used to carry out operations on the contents of containers, such as sorting, searching, etc. Iterators behave like pointers and are used to access container elements. Iterators are the mechanism that makes it possible to decouple algorithms from containers: algorithms are templates, and are parameterized by the type of iterator, so they are not restricted to a single type of container.

Questions 1. 2. 3. what is an algorithm?. Discuss it in brief? What is an Iterator? Discuss it in brief? Write a function template palindrome that takes as a parameter a const vector

and returns true or false depending upon whether the vector does or does not read the saim forwards as backwords

UNIT IV LESSON 41 UNIFIED MODELING LANGUAGE (UML)

Objective

Concept of UML UML Goals UML Scope UML Constituents UML things

Overview of UML : The Unified Modelling Language (UML) is a general-purpose visual modelling language. UMLis used to' specify, visualize, construct, and document the artifacts of a software system. It captures decisions and understanding about systems that is to be developed. It is commonly used to understand. analyse, design, browse, configure, maintain, and control information about such systems und~ development. It is specifically' designed for use with all development methods, lifecycle stages. application domains, and media. The modelling language is oriented to unify past experience about I modelling techniques and to incorporate current software best practices into a standard approach. UML covers semantic concepts, notation, and guidelines. It has different parts such as static, dynamic, environmental, and organizational parts. It is intended to be supported by interactive visual modelling CASE tools that have code generators and report writers. The UML specification does not define a standard process however; it is intended to be useful with an iterative-development process. It is intended to support most existing 00 development processes and methodologies. I The UML captures information about the static system structure and dynamic behaviour of a system. A system is modelled as a collection of discrete objects that interact with each other to perfonn work that finally benefits an outside user. The static structure is used to define the kinds of objectsimportant to a system and to its implementation, as well as the relationships among these objects. The dynamic behaviour is used to define the history of objects over time and the communications among objects to accomplish goals. Modelling a system from several separate but related viewpoints allows it to be understood for different purposes.

The UML also includes organizational constructs for arranging models into packages that permit software teams to do following: To partition large systems into workable pieces, To understand and control dependencies among the packages To manage the versioning of model units in a complex development environment.

It conains constructs for representing implementation decisions and for organizing run-time elements into components. UML is not a programming language. Some CASE Tools such as Rational Rose can provide code generators from UML into a variety of programming languages, as well as construct reverse engineered models from existing programs. The UML is not a highly formal language intended for theorem proying. There are a number of such languages, but they are not easy to understand or to use for most purposes. The UML is a general-purpose modeling language. For specialized domains, such as GUI layout, VLSI circuit design, or rule-based artificial intelligence, a more specialized tool with a special language might be appropriate. UML is a discrete modelling language. It is not intended to model continuous systems such as those found in engineering and physics. UML is intended to be a universal general-purpose modelling language for discrete systems such as those made of software, firmware, or digital logic, etc.

What is UML ? : The Unified Modelling Language is a language that unifies the industry's best software engineering practices for modelling OO systems. UML's architecture is shown in Fig.

The UML Scope, unification

Programming Language

Process Tool/Repository Specification

The Unified Modelling Language The UML has following specifications: UML is a language: It is not simply a notation for drawing diagrams, but a complete language for capturing knowledge (semantics) about a subject and expressing knowledge (syntax) regarding the subject for the purpose of communication. UML applies to modelling and systems: Modelling involves a focus on understanding (knowing) a subject (system) and capturing and being able to communicate this knowledge. UML is the result of unifYing the information systems and technology industry's best engineering practices (principles, techniques, methods, and tools). UML is used for specifying, visualizing, constructing and documenting systems. UML is used for expressing the artifacts of system intensive process. UML is based on the object-oriented paradigm. UML is a modelling language for specifying, visualizing, constructing and documenting the artifacts of a system-intensive process. UML is an evolutionary general-purpose, broadly applicable, tool-supported, industrystandardized modelling language. UML applies to a multitude of different types of systems, domains and methods or process. UML enables the capturing, communicating and leveraging of strategic, tactical, and operational knowledge to facilitate increasing value by increasing quality, reducing costs and reducing time started the to -market while managing risks and being proactive about ever-increasing change and complexity. .

UML was originally conceived by Rational Software Corporation and the Three Amigos as Grady Booch's work has involved the ,use of Ada and the application of data abstraction and information hiding with an emphasis on iterative software development and software architecture. He has been influential in disseminating object orientation. He is the inventor of the Booch method, as expressed in his book Object-Oriented Analysis and Design. James Rumbaugh's work has involved various topics concerning research and development within the context of complex algorithms and data structures. He co-authored the Object Modelling Technique (OMT) with Mike Blaha, Bill Premerlani, Fred Eddy and Bill Lorensen. Ivar Jacobson's work has involved the application of object orientation to the context 0f business reengineering and the industrialization of software development. He is often knoWl1 as the father of use cases. He is the inventor of the Object-Oriented Software Engineering: A Use Case Driven Approach. UML is supported by the UML Partners Consortium (Rational Software Corporation, Microsoft Corporation, Hewlett-Packard Company, Oracle Corporation, Sterling Software, MCI System house Corporation, Unisys Corporation, ICON Computing.

follows :

What Does Unified Mean? : The word unified has the following relevant meanings for UML : Across historical methods and notations: The UML combines the commonly accepted concepts from many OO methods, selecting a clear definition for each concept, as well as a notation and terminology. The UML can represent most existing models as well as or better than the original methods can. Across the development lifecycle : The UML is seamless from requirements to Implementation. The same set of concepts and notation can be used in different phases of development and even mixed within a single model. It is unnecessary to translate from one stage to another. This seamlessness is critical for iterative, incremental development. Across application domains: The UML is intended to model most application domains, with the systems that are large, complex, real-time, distributed, data or computation intensive, among other

properties. There may be specialized areas in which a special-purpose language is more useful, but UML is intended to be as good as or better than any other general-purpose modelling language for most software application areas. Across implementation languages and platforms: The UML is intended to be usable for systems implemented in various implementation languages and platforms, including programming languages, databases, 4GLs, organization documents, firmware and so on. The front-end aspect should be identical or similar in all cases, while the backend work may differ somewhat for each medium. Across development processes: The UML is a modelling language, and not a description of a detailed development process. it is intended to be usable as the modelling language underlying most existing or new development processes, just as a general purpose programming language can be used in many styles of programming. It is particularly intended to support the iterative, incremental style of development that we recommend. Across internal concepts: In constructing the UML metamodel, you can see, discover and represent underlying relationships among various concepts, trying to capture model1ing concepts in a broad way applicable to many known and unknown situations. This process led to a better understanding of the concepts and a more general applicability of them. This was not the original purpose of the unification work, but it was one of the most important results.

Scope and Goals of UML : These were a number of goals behind the development of the UML. Some .of these goals are as follows: UML is a general-purpose modelling language that all modellers can use. It is intended to address current software development issues, such as large scale, distribution, concurrency, patterns, and team development. UML is not intended to be a complete development method. It does not include a systematic development process. ' A final goal of UML was to be as simple as possible while still being capable of modelling the full range of practical systems that need to the built. UML has different kinds of models; it is very difficult to master it in one day. It is more complicated than the some of its antecedents, because it is intended to be more comprehensive. However, you do not have to learn it al1 at once, any more than you would a programming language, an operating system, or a complex user application.

UML Goals: . The goals of the UML are to Be a ready-to-use expressive visual modelling language that is simple and extensible. Have extensibility and specialization mechanisms for extending, rather than modifying, core concepts. Fonnalize a core set of concepts that constitute the object-oriented paradigm. Extensions will not require reimplementation of the core object oriented paradigm (analysis and design) concepts in order to be applicable to a broad set of applications. Instead, practitioners can extend this core set of concepts based on varying interpretations without having to be repeatedly redefined the fundamental concepts. Allow adding new concepts and notation beyond the core. Allow variant interpretations of existing concepts when there is no clear consensus. Allow specialization of concepts, notation, and constraints for particular domains. Be implementation independent (programming language). Be process independent (development). Encourage the growth of the object-oriented tools market. Support higher-level concepts (collaborations, frameworks, patterns and components). Address recurring architectural complexity problems (physical distribution and distributed systems, concurrency and concurrent systems, replication, security, load balancing and fault tolerance) using component technology, visual programming, patterns, and frameworks. Be scalable. Be widely applicable (general purpose and powerful) and usable (simple, widely accepted, evolutionary). Integrate the best engineering practices. The UML Scope: The scope of the UML encompasses Combines the concepts of Booch, OMT, and OOSE

Focusing on a standard modelling language (common notation) and not a standard process Incorporating the object-oriented community's consensus on core modelling concepts Providing sufficient notation to address contemporary modelling issues directly and economically Providing sufficient semantics to address the following issues directly and economically: Contemporary modelling issues Future modelling issues (specifically related to component technology, distributed computing, frameworks and executability) Model interchange among tools Repository interfaces (to modelling artifacts) among tools Providing extensibility mechanisms to address the following issues directly and economically Current deviations within the object-oriented community Extending the UML for individual projects Future modelling approaches (on top of the UML)

What the UML Is Not: The UML is not A visual programming language, but a visual modelling language o A programming language communicates im implementation or solution. o A modelling language communicates a model (or conceptualisation or specification). A tool or repository specification, but a modelling language specification o A tool or repository specification specifies tools or repository's interface, storage, runtime behaviour and so forth. o A modelling language specification specifies modelling elements, notation, and usage guidelines. A process, but enables processes.

o A process provides guidance regarding the order of activities, specification of artifacts to be developed, direction of individual developer and team tasks (or activities) and monitoring and measuring criteria of project artifacts and activities. o Processes are organization, culture, and domain specific and dependent. o The UML enables and promotes (but does not require nor mandate) a use-case.driven, architecture-centric, iterative, and incremental process that is object oriented and component based.

UML Constituents:

UML consists of following things:

The UML Definition: The UML is defined by a set of documents as shown in follow Fig. 2 from Rational Software Corporation and the Object Management Group. UML varients UML Notation Guide : UML Semantics Objects Constraint Language Specification UML Extension for Objectory Process for Software Engineering UML Extension for Business modelling User-Defined UML Extensions

The UML Definition The UML definition Is expressed by the following documents (the UML-defining artifacts)

UML Semantics UML Notation Guide UML Introduction UML Extension for the Objectory Process for Software Engineering UML Extension for Business Modelling. Uses the Object Constraint Language (OCL) defined by the Object Constraint Language specification document. May be obtained from Rational Software Corporation or the Object Management Group via the World Wide Web (see the www.omg.org) The UML Semantics Document: The UML semantics document constitutes the single, common, definitive, formal, comprehensive and precise specification of the UML (called the inside view). The UML semantics document. Is primarily used by tool vendors; however, it maybe used by practitioners since it is the Specifies the UML has layered architecture, organization (using packages) and defined modelling elements. Includes the following inside-view information for a given UML package: o Overview: General introduction o Abstract syntax: Concept definitions, relationships, and constraints expressed using the UML's graphical notation and English prose. o Well-formed ness rules: Rules and constraints expressed using English prose and the OCL. Semantics: Meanings expressed using English prose. o Standard elements: Applicable standard extension mechanisms. o Notes: Other commentary Also contains appendices on the standard elements and the UML glossary. Enables the development of complex systems, consistent usage of the UML, and tool interchange definitive definition of the UML.

The UML Notation Guide:

The UML Notation Guide constitutes the notational or visual representation of the UML and provides examples (called the outside view). The UML Notation Guide o o o Is primarily used by practitioners applying the UML Specifies the UML's diagrams and their modelling elements Includes the following outside-view information for each modelling element:

o Semantics: Summarizes the UML semantics. o Notation (concrete syntax) : Explains the notational representation (forward mapping to notation). o Presentation options: Describe option in presenting modelling information. o Style guidelines: Suggest stylistic markers and options. o Examples: Provide notation samples. o Mapping: Explains the mapping of the notation to the semantics document (reverse mapping from notation). o Enables the use of the UML . The UML Extension Documents: The UML extension documents provide user-defined extensions (using extension mechanisms). These documents UML Introduction o Extend the UML to the objectory process for software engineering. o Extend the UML to business modelling. A UML extension is a set of extensions (stereotypes, tagged values, and constraints) that extend, customize, or tailor the UML for a specific domain or process. A UML variant is a semantically well-defined language (expressed as a metamodel) based on (and built on top of) the UML metamodeI. It specialized the UML but does not change the UML terms or redefine their meanings.

The Object Constraint Language: The Object Constraint Language (OCL) is a formal, easily readable and writable, non. programming, implementation-independent language. The OCL o Is used for expressing typed, pure, side-effect-free (precise and unambiguous) constraints and Expressions o Is used for attaching constraints and other expressions to the UML models and modelling elements (or objects) o Is used to specify the well-formedness rules of the UML within the UML semantics document o Is formally specified in the Object Constraint Language specification document, which provides the following information: Connection with the UML semantics, basic values and types, objects and properties, collection operations, predefined OCL types, and the grammar for the OCL. Scope and Purpose of UML as a Modelling Language:

The UML is a language for . Visualizing . Specifying . Constructing . Documenting

the artifacts of a software-intensive system.

The UML is a Language: A language provides a vocabulary and the rules for combining words in that vocabulary for the purpose of communication. A modelling language is a language whose vocabulary and rules focus on

the conceptual and physical representation of a system. A modelling language such as the UML is thus a standard language for software blueprints. Modelling yields an understanding of a system. No one model is ever sufficient. Rather, you often need multiple models that are connected to one another in order to understand anything but the most trivial system. For software-intensive systems, this requires a language that addresses the different views of a system's architecture as it evolves throughout the software development life cycle. The vocabulary and rules of a language such as the UML tell you how to create and read wellformed models, but they do not tell you what models you should create and when you should create them. That is the role of the software development process. A well-defined process will guide you in deciding what artifacts to produce, what activities and what workers to use to create them and manage them, and how to use those artifacts to-measure and control the project as a whole. The UML is a Language for Visualizing: For many programmers, the distance between thinking of an implementation and then pounding lout in code is close to zero. You think it, you code it. In fact, some things are best cast directly in code. Text is a wonderfully minimal and direct way to write expression and algorithms. In such cases, the programmer is still doing some modelling, albeit entirely mentally. He or she )ay even sketch out a few ideas on white board or on a napkin. However, there are several problems than this. First, communicating those conceptual models to others is error-prone unless everyone envolved speaks the same language. Typically, projects and organizations develop their own language and it is difficult to understand what is going on if you are an outsider or new to the group. Second, there are some things about a software system you cannot understand unless you build models that transcend the textual programming language. For example, the meaning of a class hierarchy can be il1ferred, but not directly grasped, by starting at the. code for all the classes in the hierarchy. Similarly,the physical distribution and possible migration of the objects in a Web-based system can be inferred, but not directly grasped, by studying the system's code. Third, if the developer who cut the code never l\\Tote down the models that are in his or her head, that information would be lost forever or at best only partially recreatable from the implementation, once that developer moved on. Writing models in the UML addresses the third issue: An explicit model facilitates communication. Some things are best modelled textually; others are best modelled graphically. Indeed, in all interesting systems there are structures that transcend what can be represented in a programming language. The UML is such a graphical language. This addresses the second problem described earlier.

The UML is more than just a bunch of graphical symbols. Rather, behind each symbol in the UML notation is a well-defined semantics. In this manner, one developer can write a model in the UML and another developer or even another tool can interpret that model unambiguously. This address the first issue described earlier.

The UML is a Language for Specifying: In this context, specifying means building models that are precise, unambiguous and complete. In particular, the UML address the specification of all the important analysis design and implementation decisions that must be made in developing and deploying a software-intensive system. The UML is a Language for Constructing: The UML is not a visual programming language but its models can be directly connected to a variety of programming languages. This means that it is possible to map from a model in the UML to programming language such as Java, C++, or Visual Basic, or even to tables in a relational database or the persistent store of an object-oriented database. Things that are best expressed graphically are done so graphically in the UML, whereas things that are best expressed textually are done so in the programming language. This mapping permits forward engineering: The generation of code from a UML model into' a programming language. The reverse is also possible: You can reconstruct a. model from an implementation back into the UML. Reverse engineering is not magic. Unless you encode that information in the implementation, information is lost when moving forward from models to code. Reverse engineering thus requires tool support with human intervention. Combining these two paths of forward code generation and reverse engineering yields round-trip engineering, meaning the ability to work in either a graphical or a textual view, while tools keep the two views consistent. In addition to this direct mapping, the UML is sufficiently expressive and unambiguous to permit the direct execution of models, the simulation of systems and the instrumentation of running systems. The UML is a Language for Documenting: A healthy software organization produces all sorts of artifacts in addition to raw executable code. These artifacts include (but are not limited to)

. . .

Requirements . Source code Prototypes . .

Architecture Project plans Releases

Design tests

Depending on the development culture, some of these artifacts are treated more or less formalIy than others. Such artifacts are not only the deliverables of a project, they are also critical in controlling,. measuring and communicating about a system during its development and after its deployment. The UML addresses the documentation of a system's architecture and all of its details. The UML also provides a language for expressing requirements and for tests. Finally, the UML provides a language for modelling the activities of project planning and release management.

UML Applications: The UML is intended primarily for software intensive systems. It has been used effectively for such domains as : Management information systems Business Information systems . Transportation . Retail . Scientific . . Banking and financial services Telecommunications Defence/aerospace. Medical electronics Distributed Web-based services

The UML is not limited to modelling software. In fact, it is expressive enough to model non-software systems, such as workflow in the legal system, the structure, and behavior of a patient health care system and the design of hardware. . . . A conceptual Model of UML :

To understand the UML, you need to form a conceptual model of the language, and this requires learning three major elements: the UML's basic building blocks, the rules that dictate how those

building blocks may be put together and some common mechanisms that apply throughout the UML. Once you have grasped these ideas, you will be able to read UML models and create some basic ones. As you gain more experience in applying the UML, you can build on this conceptual model using more advanced features of the language.

Building Blocks of the UML : The vocabulary of the UML encompasses three kinds of building blocks:

UML Introduction Things Relationships Diagrams Things are the abstractions that are first-class citizens in a model; relationships tie these things together; diagrams group interesting collections of things.

Things Included in the UML :

There are Four Kinds of Things in the UML as follows: Structural things Behavioural things Grouping things Annotational things

These things are the basic object-oriented building blocks of the UML. You can use them to write well-formed models. .

Structural Things are the nouns of UML models. These are the mostly static parts of a model, representing elements that are either conceptual or physical. In all, there are seven kinds of structural things. A class is a description of a set of objects that share the same attributes, operations, relationships, and semantics. A class is used to implement one or more interfaces. Graphically a class is rendered as a rectangle usually including its name, attributes, and operations. Class is shown in Fig. Window ongm size open ( ) close ( ) move ( ) display ( ) Fig.: Classes An interface is a collection of operations that specify a service of a class or component. An interface describes the externally visible behavior of that element. An interface can represent the complete behavior of a class or component or only a part of that behavior. An interface defines a set of operation specifications (that is, their signatures) but never a set of operation implementations. Graphically an interface is rendered as a circle together with its name. An interface rarely stands alone. Rather it is typically attached to the class or component that realizes the interface as shown in Fig

Ispelling Fig. Interfaces Collaboration defines an interaction and is a society of roles and other elements that work together to provide some co-operative behavior that is bigger than the sum of all the elements. Collaborations have structural as well as behavioural dimensions. A given class might participate in several collaborations. These collaborations therefore represent the implementation of patterns that make up a system. Graphically collaboration is rendered as an ellipse with dashed lines usually including only its name as shown in Fig.

Chain of resposibility

Fig. Collaborations A use case is a description of set of sequence of actions that a system performs that yields an observable result of value to a particular actor. A use case is used to structure the behavioral things in a model. A use case is realized by collaboration. Graphically a use case is rendered as an ellipse with solid lines usually including only its name as shown in Fig.

Place order

Fig.: Use Cases

The remaining three things active classes, components, and nodes are all class-like because they also describe a set of objects that share the same attributes, operations, relationships, and semantics. However, these three are different enough and are necessary for modeling certain aspects of an object oriented system and so they warrant special treatment. An active class is a class whose objects own one or more processes or threads and therefore can initiate control activity. An active class is just like a class except that its objects represent elements whose behavior is concurrent with other elements. Graphically an active class is rendered just like a class but with heavy lines usually including its name attributes and operations as shown in Fig.

Event Manager

Suspend() Flush()

Fig.: Active Classes The remaining two elements. component and nodes are also different. They represent physical things whereas the previous five things represent conceptual or logical things.

A component is a physical and replaceable part of a system that conforms to and provides the realization of a set of interfaces. In a system, you will encounter different kinds of deployment components, such as COM+ components or Java Beans as well as components that are artifacts of the development process such as source code files. - A component typically represents the physical packaging' of other Wise logical elements such as classes interfaces and collaborations. Graphically a. component is rendered as a rectangle with tabs usually including only its name as shown in Fig. . orderform.java

Fig : Components

A node is a physical element that exists at run time and represents a computational resource, generally having at least some memory and often processing capability. A set of components may reside on a node and may migrate from node to node. Graphically a node is rendered as a cube usually including only its name as in shown Fig

server

Fig. Nodes

These seven elements classes, interfaces, collaborations, use cases, active classes, components and nodes are the basic structural things that you can include in a UML model. There are also variations .on these seven such as actors signals and utilities (kinds of classes) processes and threads (kinds of active classes) and applications documents files libraries pages and table (kinds of components). Behavioral Things are the dynamic parts of UML models. These are the verbs of a model, representing behavioral over time and space. In all, there are two primary kinds of behavioral things. An interaction is a behavior that comprises a set of messages exchange among a set of objects within a particular context to accomplish a specific purpose. The behavior of a society of objects or have an individual operation may specify with an interaction. An interaction involves a number of other elements, including messages, action sequences (the behaviour invoked by a message) and links (the connection between objects). Graphically a message is rendered as a directed line usually including the name of its operation as shown in Fig.

display.

Fig. : Messages

A state machine is a behavior that specifies the sequences of states an object or an interaction goes through during its lifetime in response to events, together with its responses to those events. The behavior of individual class or a collaboration of classes may be specified with a state machine. A state machine involves a number of other elements, including states, transitions (the flow from state to state), events(things that trigger a transition) and activities (the response to a transition). Graphically a state is rendered as a rounded rectangle, usually including its name and its substates, if any as shown in Fig. These two elements interactions and state machines are the basic behavioural things that you may include in a UML model. Semantically, these elements are usually connected to various structural elements, primarily classes, collaborations and objects. Grouping Things are the organizational parts of UML models. A model can be decomposed into these boxes. In all there is one primary kind of grouping thing namely packages. waiting

States A package is a general-purpose mechanism for organizing elements into groups. Structural things, behavioural things and even other grouping things may be placed in a package. Unlike components, (which exist at run time) a package is purely conceptual (meaning that it exists only at development time). Graphically a package is rendered as a tabbed folder usually including only its name and sometimes its contents as shown in Fig.

Fig.: Packages

Packages are the basic grouping things with which you can organize a UML model. There are also variations such as frameworks models and subsystems (kinds of packages). Annotational Things are the explanatory parts of UML models. These are the comments you may apply to describe, illuminate, and remark about any element in a model. There is one primary kind of annotational thing, called a note. A note is simply a symbol for rendering constraints and comments attached to an element or a collection of elements. Graphically a note is rendered as a rectangle with a dog-eared comer together with a textual or graphical comment as shown in Fig.

Fig. : Notes

This element is the one basic annotational thing you may include in a UML model. You will typically use notes to adorn your diagrams with constraints or comments that are the best expressed in informal or formal text. There are also variations on this element, such as requirements (which specify some desired behavior from the perspective of outside of model).

Summary The Unified Modelling Language (UML) is a general-purpose visual modelling language. UML is used to' specify, visualize, construct, and document the artifacts of a software system UML is not a programming language. Some CASE Tools such as Rational Rose can provide code generators from UML into a variety of programming languages, as well as construct reverse engineered models from existing programs. The UML is a Language: Who provides a vocabulary and the rules for combining words in that vocabulary for the purpose of communication. A modelling language is a language whose vocabulary and rules focus on the conceptual and physical representation of a system. A modelling language such as the UML is thus a standard language for software blueprints.

There are Four Kinds of Things in the UML as follows: Structural things Behavioural things Grouping things Annotational things

Question 1. 2. 3. Explain the concept of UML? Explain Its scope and Goal Discuss UML things

UNIT V LESSON 42 UML II Objective UML diagrams UML relationships Object Oriented Software Engineering

UML Diagrams

This part introduces you to the 9 standard diagrams in the UML 1.4 specification. These diagrams can be divided into two groups: Structural diagrams, which model the organization of the solution, and Behavioral diagrams, which model the functionality of the solution. Structural Diagrams Class Diagram Object Diagram Component Diagram Deployment Diagram Behavioral Diagrams Use Case Diagram Sequence Diagram Collaboration Diagram Statechart Diagram Activity Diagram Class Diagrams

Class diagrams identify the class structure of a system, including the properties and methods of each class. Also depicted are the various relationships that can exist between classes, such as an inheritance relationship. The Class diagram is one of the most widely used diagrams from the UML specification. Part of the popularity of Class diagrams stems from the fact that many CASE tools, such as Rational XDE, will auto-generate code in a variety of languages, including Java, C++, and C#, from these models. These tools can synchronize models and code, reducing your workload, and can also generate Class diagrams from object-oriented code, for those "code-then-design" maintenance projects. Notation UML Notation There are many different types of UML notation. For this short presentation, a few types of notation will be covered. For a more complete description of the UML notation, you can refer to the UML 1.1 Notation Guide. When beginning to use the UML, it is helpful to start with some basic notation (e.g., class diagrams) and, then, as you become more proficient, advanced UML notation can be used. The elements on a Class diagram are classes and the relationships between them Class Classes are the building blocks in object-oriented programming. A Class is depicted using a rectangle divided into three sections. The top section is the name of the Class. The middle section defines the properties of the Class. The bottom section lists the methods of the class.

Association An Association is a generic relationship between two classes, and is modeled by a line connecting the two classes. This line can be qualified with the type of relationship, and can also feature multiplicity rules (eg. one-to-one, one-to-many, many-to-many) for the relationship.

Composition If a class cannot exist by itself, and instead must be a member of another class, then that class has a Composition relationship with the containing class. A Composition relationship is indicated by a line with a filled diamond.

Dependency When a class uses another class, perhaps as a member variable or a parameter, and so "depends" on that class, a Dependency relationship is formed. A Dependency relationship is indicated by a dotted arrow. Aggregation Aggregations indicate a whole-part relationship, and are known as "has-a" relationships. An Aggregation relationship is indicated by a line with a hollow diamond.

Generalization A Generalization relationship is the equivalent of an inheritance relationship in objectoriented terms (an "is-a" relationship). A Generalization relationship is indicated by an arrow with a hollow arrowhead pointing to the base, or "parent", class.

Consider the example of a veterinary system. Animals served, such as dogs and birds, are tracked along with their owners. The following diagram models a potential solution. Since dogs and birds are "a kind of" animal, we use a Generalization relationship.

To validate your model, you can apply real-world data into instances of the classes. In fact, there is a diagram for precisely this task, the Object Diagram. Class Diagram Class diagrams represent the static structure of the classes and their relationships (e.g., inheritance, aggregation) in a system. A class icon is divided into three componentsclass name, attributes, and operations.

The access modifier symbols +, -, and # correspond respectively to public, private, and protected

access modifiers. Realizes relationship from a class to an interface indicates that the class implements the operations specified in the interface. Associations represent relationships between instances of classes. Each association has two roles; each role is a direction on the association. A role has multiplicity (an indication of how many objects may participate in a given relationship). Examples of multiplicity indicators are: 1 (Exactly one), * (0 to any positive integer), 1..* (1 to any positive integer), 0..1 (0 or 1). Constraint specifies conditions among model elements that must be maintained as true. Constraints are shown using text enclosed in braces. Generalization relationship is an association with a small triangle next to the class being inherited from whereas an aggregation relationship is an association with a diamond next to the class representing the aggregate.

Class diagrams can be used to document a Business Object Model and are widely used in both highlevel and low-level design documents. From a Java perspective, it may not be effective to include each and every operation and attribute of a class in a class diagram because this leads to maintenance issues (e.g., if a method or attribute changes in the code then the model needs to be updated); rather, javadoc can be used to document an implementation. To maintain consistency with Java coding style, class names should begin with an uppercase letter while operations and attributes should begin with a lowercase letter. Generalization relationships can be mapped to the Java extends relationship while the realizes relationship can be mapped to the Java implements relationship.

Package Diagram Package diagrams provide a mechanism for dividing and grouping model elements (e.g., classes, use cases). In UML, a package is represented as a folder. In effect, a package provides a namespace such that two different elements in two different packages can have the same name. Packages may be nested within other packages. Dependencies between two packages reflect dependencies between any two classes in the packages. For example, if a class in Package A uses the services of a class in Package B, Package A is dependent on Package B. An important design consideration is the minimization of dependencies between packages.

Package diagrams can be used in a high-level design or architecture document to describe a systems overall structure, can support project planning and also be used as a unit to perform testing. A package can be considered logically equivalent to a Java package and dependencies between packages can be mapped to Java import statements. Use Case Diagram Use cases are used to obtain system requirements from a user's perspective. A use case can be described as a interaction that a user has with a system to achieve a goal. notation A typical use case can be documented using the It is helpful to provide a following template: template that can be used to document use cases. Note that a use case template is not part of the UML

A use case diagram provides an overview of the system's use cases and their actors; it places use cases in context. In UML, an actor is represented as a stickman while a use case is represented as an oval. An actor is a role that a user plays with respect to the system. Two types of relationships are used in use case diagrams. The extends relationship is used when one use case is similar to another use case but does a bit more or to describe optional behavior (e.g., forward a mail message). The uses relationship occurs when you have common behavior that exists in multiple use cases that can be factored out into a separate use case (e.g., login use case). Note that actors have relationships to use cases that are being extended whereas there is often no actor associated with a common use case.

Use case diagrams can be used in product specifications, software architecture documents, and system test documents to provide an overview of the system requirements. Use cases can specify prioritization that can support a phased delivery of a system. Use cases can also be used to develop test plans and user guides. Interaction Diagrams: Sequence and Collaboration Interaction diagrams show how objects interact with one another. There are two types of interaction diagrams: Collaboration Diagram and Sequence Diagram. Collaboration diagrams can be used to show how objects in a system interact over multiple use cases. Collaboration diagrams are helpful during the exploratory phases of a development process (i.e., trying

to search for objects and their relationships). Since there is no explicit representation of time in Collaboration Diagrams, the messages are numbered to denote the sending order.

A Sequence diagram is typically used to show object interactions in a single use case and it is easier to see the order in which activities occur. The emphasis of sequence diagrams is on the order of message invocation. The vertical axis of a sequence diagram represents time whereas the horizontal axis represents objects.

Interaction diagrams can be used during the high-level design (e.g., for business object model development) as well as for low-level design activities (e.g., developing an implementation for a use case). Interaction diagrams are helpful for showing the collaborations between objects but fall short in terms of a complete definition of the behavior. Activity Diagrams Activity diagrams show behavior with control structure. Activity diagrams can be used to show behaviors over many use case, model business workflows, or describe complicated methods. Activities in a diagram may or may not correspond to methods. Specific notation found in this type of diagram includes guards which are logical expressions that evaluate to true or false. A synchronization bar indicates that the outbound trigger occurs only after all inbound triggers have occurred.

Swimlanes (using a swimming pool analogy) allow you to vertically partition an activity diagram so that the activities in each lane represent the responsibilities of a particular class or department.

Activity diagrams are helpful early in the modeling of a process to help you understand the overall process. Useful when you want to show parallel processes or for multithreaded programs. Disadvantage of activity diagrams is that they do not make explicit which objects execute which activities, and the way that the messaging works between them. Relationships in UML

Dependency The most general is called a dependency relationship and applies uniformly to all the model elements. Association and generalization apply to all types, in particular classes and use cases. The last two relationships transitions and links apply to certain model elements pertaining to behavior. This section is limited to the description of static relationships between classes, shown in the diagram below. Links and transitions are discussed later on in this chapter. Simplified metamodel representation of relationships between classes Association

An association specifies a bi-directional, semantic connection between types. An association has at least two roles, which describe the part played by the types that participate in the association.

Each role comprises the following attributes: Multiplicity specifies the number of instances that participate in the relationship

Navigability specifies if links (association instances) may be navigated along in the direction of the role being considered. Aggregation indicator specifies if the instances of the type associated to the role correspond to the whole in a (whole, part) relationship. Only one of the roles of an association may have an aggregation indicator set to True. If the multiplicity is larger than 1, several instances play the role of the whole and share the parts.

Changeability specifies if the semantics of the association are preserved when an instance of the type that participates in the role is replaced by another instance Ordering applies when the multiplicity value is greater than 1, to mean that the instances are ordered An association role may also include a set of attributes whose values implement a partition of the set of objects of the associated class. Generalization Generalization specifies a classification relationship in which an instance of a subtype may be substituted for an instance of a supertype. A supertype may have several subtypes, and a subtype may have several supertypes.

Simplified metamodelrepresentation of the generalization relationship and of elements prone to generalization. Any element that may be generalized includes the following Boolean attributes:

Abstract the value True specifies that the element cannot be instantiated directly Leaf the value specifies that the element may not have subtypes

True

Root the value True specifies that the element may not have supertypes UML defines three kinds of generalizable elements: Stereotypes allow the classification of a model element and, eventually, the definition of a particular graphical representation. A stereotype cannot have a subtype.

Packages provide a general mechanism for grouping elements (both model and visual elements). A package cannot have supertypes. Types specify a definition domain and the operations applicable to that domain. Dependency Dependency is a unidirectional usage relationship between elements (both model and visual). The dependency relationship connects elements within the same model.

Simplified metamodelrepresentation of dependency relationships

UML also provides a 'trace' relationship between elements that belong to different models. Notably, the trace may be used to represent the history of current constructions in various models. This trace relationship is a stereotyped dependency relationship.

Simplified metamodelthe trace relationship is a stereotyped dependency relationship. UML is a consistent language for denoting the artifacts of a system. System architects can use it to specify, visualize, construct and document designs. The language is most commonly used to denote the artifacts of software systems, as a part of the software development process. The Unified Modeling Language includes: Model elements, that capture the fundamental modeling concepts and semantics. A notation, for visual rendering of model elements. Rules, that describes idioms of usage. It also provides extensibility and specialization mechanisms to extend the core concepts. UML does not provide, define nor dictate: A Programming Language. UML has a semantics model that maps well to a family of OO languages, but in itself does not require the use of a specific language tools. UML neither specifies the design of CASE tools, nor specifies the use of them. However, it is natural to expect that CASE tools supporting UML follows the UML semantics closely. A development process. Defining a standard process was not a goal of UML, and UML has intentionally been made process independent.

Object oriented software engineering

Object-Oriented Concepts And Princlples we live in a world of objects. these objects exist in nature, in humanmade entities, in business, and in the products that we use. they can be categorized, described, organized, combined, manipulated, and created. therefore, it is no surprise that an object-oriented view would be proposed for the creation of computer software-an abstraction that enables us to model the world in ways that help us to better understand and navigate it. an object-oriented approach to the development of software was first proposed in the late 1960s. however, it took almost 20 years for object technologies to become widely used. throughout the 1990s, object-oriented software engineering became the paradigm of choice for many software product builders and a growing number of information systems and engineering professionals. as time passes, object technologies are replacing classical software development approaches. an important question is why? the answer (like many answers to questions about software engineering) is not a simple one. some people would argue that software professionals simply yearned for a "new" approach, but that view is overly simplistic. object technologies do lead to a number of inherent benefits that provide advantage at both the management and technical levels. what is it? there are many ways to look at a problem to be solved using a software-based solution. One widely used approach to problem solving takes an object-oriented viewpoint. The problem domain is characterized as a set of objects that have specific attributes and behaviors. The objects are manipulated with a collection of func tions (called methods, operations, or services) and communicate with one another through a messaging protocol. Objects are categorized into classes and subclasses. Who does It? The definition of objects encompasses a description of attributes, behaviors, operations, and messages. This activity is performed by a sOftware engineer. Why is it important? An object encapsulates both data and the processing that is applied to the data. This important characteristic enables classes of objects to be built and inherently leads to libraries of reusable classes and objects. Because reuse is a critically important attribute of modern software engineering, the object-oriented paradigm is attractive to many software development organizations. In addition, the software components derived using the object-oriented paradigm exhibit design

characteristics (e.g., functional independence, information hiding) that are associated with high-quality software. What are the steps? Object-orientect software engineering follows the same steps as conventional approaches. Analysis identifies objects and classesdomain; design provides the architecture, interface, and component-level detail; that are relevant to the problem implementation (using an object-oriented language) transforms design into code; and testing exercises the object-oriented architecture, interfaces and components. What is the work product? A set of object oriented models is produced. These models describe the requirements, design. code. and test process a system or product. How do I ensure that I've done It right? At each stage, object-oriented work products are reviewed for clarity, correctness, completeness. and corm tency with customer requirements and with one another. Object technologies lead to reuse, and reuse (of program components) leads to faster software development and higher-quality programs. Object-oriented software is easier to maintain because its structure is inherently decoupled. This leads to fewer side effects when changes have to be made and less frustration for the software engineer and the customer. In addition, object-oriented systems are easier to adapt and easier to scale (ie., large systems can be created by assembling reusable sub sys tems). Three important concepts differentiate the OO approach from conventional software engineering. Encapsulation packages data and the operation that manipulate the data into single named object. Inheritance enables the attribute and operations to be inherited by all subclasses and the objects that are instantiated from them. Polymorphism enables a number of different operations to have the same name, reducing the number of lines of code required to implement a system and facilitating changes when they are made. Object oriented product and systems are engineered using and evolutionary model, sometimes called a recursive/ parallel Summary UML is a modeling language for specifying, visualizing, constructing, and documenting the artifacts of a system-intensive process. model. OO software evolves iteratively and must be managed with the recognition that the final product will be developed over a series of increments

UML represents a unification of the concepts and notations of Booch, Rumbaugh, and Jacobson. Notation plays an important role in modeling and the goal of the UML is to become a universal notation for creating models of object-oriented (OO) software. UML gives 9 standard diagrams These diagrams can be divided into two groups: Structural diagrams, which model the organization of the solution, and Behavioral diagrams, which model the functionality of the solution.

Questions 1. 2. 3. What is UML? Explain different types of UML diagram. Give details of different notatios used . Discuss concept OO software Engineering

UNIT V Lession 43

Group Discussion on the concept of analysis ans design method and UML concepts in Detail.

References : 1. Object Oriented Progarmming With C++ - E Balguruswami 2. Lets C++ - Y. Kanetkar 3. Object Oriented Modelling & Design- S.D. Joshi 4. C++ How To Program Deitel & Deitel

You might also like