87
OOPS Concepts using C++ C++ as better C ................................................................................................................... 2 Keys to Object..................................................................................................................... 6 Defining a class in C++ .................................................................................................... 10 Objects and Encapsulation ................................................................................................ 16 Messages and Polymorphism............................................................................................ 17 Data Abstraction ............................................................................................................... 19 Natural Building Blocks ................................................................................................... 20 Polymorphism in an application ....................................................................................... 61 Program Using Polymorphism.......................................................................................... 74 L & T Infotech Page 1 of 87

Oops index

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Oops index

OOPS Concepts using C++

C++ as better C ................................................................................................................... 2 Keys to Object..................................................................................................................... 6 Defining a class in C++ .................................................................................................... 10 Objects and Encapsulation................................................................................................ 16 Messages and Polymorphism............................................................................................ 17 Data Abstraction ............................................................................................................... 19 Natural Building Blocks ................................................................................................... 20 Polymorphism in an application ....................................................................................... 61 Program Using Polymorphism.......................................................................................... 74

L & T Infotech Page 1 of 87

Page 2: Oops index

OOPS Concepts using C++ C++ as better C

C++ as better C C has been in use for over 25 years. Therefore, there is a huge amount of legacy C code in place. However, once people learn C++, they find its features more powerful than those of C, so they choose to move to C++. C++ is a hybrid language, so it is possible to program in either a C-style, an object-oriented style, or both. Most programmers take advantage of rich collections of existing classes and functions in C++ classes and the ANSI C standard function library (which C++ borrows from ANSI C).

Therefore, there are two parts to learning C++:

• learning C++ itself • learning how to use the classes in various C++ class libraries and the functions in the ANSI C standard library

If you want to mix C and C++ code in a program,

• your C++ compiler should direct the linking process (so it can access its special libraries) • your C and C++ compilers probably need to come from the same vendor and have

compatible versions (so they have the same calling conventions) You can include a standard C header file in your C++ code.

Using C functions in C++ Let's now consider using C functions in C++. It is possible to call functions written and compiled with a C compiler from a C++ program. However, C++ specially encodes function names for type-safe linkage while C doesn't encode its function names. So a function compiled in C will not be recognized when an attempt is made to link C code with C++ code because the C++ code expects a specially encoded function name.

This function name encoding is often referred to as name mangling

C++ enables you to provide linkage specifications to

• inform the compiler that a function was compiled on a C compiler • prevent the function name from being encoded by the C++ compiler

Linkage specifications are particularly useful when large libraries of specialized functions have been developed. They are useful also when another programmer doesn't have access to the source code of those library functions for recompilation into C++ or time to convert them from C to C++. To tell a C++ compiler that one or several functions have been compiled in C, precede the function prototypes with storage class specifier extern.

L & T Infotech Page 2 of 87

Page 3: Oops index

OOPS Concepts using C++ C++ as better C

extern "C" function prototype //Single function extern "C" //Multiple functions { function prototypes }

Using extern means

• name encoding (or name mangling) won't be performed on the functions listed in the linkage specification

• the specified functions can be linked properly with the program

extern "C" function prototype //Single function extern "C" //Multiple functions { function prototypes }

C++ compilers normally include the standard C libraries, so no need to use linkage specifications for those functions.

Object-Oriented Technology Object oriented programming is essentially building a program around self-contained collections of data and code to modify that data; this programming model is in contrast to a model that uses function that act on data scattered throughout a program. Object-oriented programming (or coding, as programming is commonly referred to) is an organizational style, but it helps programmers create reusable code because the code to do a specific thing is entirely contained within a single section of code, and to use the code to perform tasks - for instance, creating a menu - involves using only a small number of functions to access the internals of the class.

A black box that can be easily carried from place to place, and that performs complex actions simply at the press of a button: for instance, a microwave lets you heat food for a specified time limit - say, two minutes - by typing in the time and pressing the heat button. You do not need to know how the microwave operates or why the physics works. In the same way that self-contained appliances simplify life for the consumer, object-oriented programming simplifies the transfer of source code from one program to another program by encapsulating it - putting it all in one place. Object-oriented technology is both immense and far-reaching. End users of computer systems and computer-based systems notice the effects of object-oriented technology in the form of increasingly easy-to-use software applications and operating systems and in more flexible services being provided by such industries as banking, telecommunications, and cable television.

L & T Infotech Page 3 of 87

Page 4: Oops index

OOPS Concepts using C++ C++ as better C

For the software engineer, object-oriented technology encompasses object-oriented programming languages, object-oriented development methodologies, management of object-oriented projects, object-oriented computer hardware, and object-oriented computer aided software engineering, among others. It is not surprising, therefore, that there is some confusion regarding object-oriented terms and concepts. Many of the terms commonly used in object-oriented technology were originally used to describe object-oriented programming (coding) concepts. Specifically, although the terms were borrowed from a non-computer-software perspective, they were first used extensively to describe concepts embodied in object-oriented programming languages, such as Smalltalk, C++, and Eiffel. However, these terms are quite useful even if one never intends to write any software at all.

The progress of abstraction All programming languages provide abstractions. It can be argued that the complexity of the problems you’re able to solve is directly related to the kind and quality of abstraction. Assembly language is a small abstraction of the underlying machine. Many so-called “imperative” languages that followed (such as Fortran, BASIC, and C) were abstractions of assembly language. These languages are big improvements over assembly language, but their primary abstraction still requires you to think in terms of the structure of the computer rather than the structure of the problem you are trying to solve. The programmer must establish the association between the machine model (in the “solution space,” which is the place where you’re modeling that problem, such as a computer) and the model of the problem that is actually being solved (in the “problem space,” which is the place where the problem exists). The effort required to perform this mapping, and the fact that it is extrinsic to the programming language, produces programs that are difficult to write and expensive to maintain, and as a side effect created the entire “programming methods” industry. The alternative to modeling the machine is to model the problem you’re trying to solve. Early languages such as LISP and APL chose particular views of the world (“All problems are ultimately lists” or “All problems are algorithmic”). PROLOG casts all problems into chains of decisions. Languages have been created for constraint-based programming and for programming exclusively by manipulating graphical symbols. (The latter proved to be too restrictive.) Each of these approaches is a good solution to the particular class of problem they’re designed to solve, but when you step outside of that domain they become awkward. The object-oriented approach goes a step farther by providing tools for the programmer to represent elements in the problem space. This representation is general enough that the programmer is not constrained to any particular type of problem. We refer to the elements in the problem space and their representations in the solution space as “objects.” (Of course, you will also need other objects that don’t have problem-space analogs.) The idea is that the program is allowed to adapt itself to the lingo of the problem by adding new types of objects, so when you read the code describing the solution, you’re reading words that also express the problem. This is a more flexible and powerful language abstraction than what we’ve had before. Thus, OOP allows you to describe the problem in terms of the problem, rather than in terms of the computer where the solution will run. There’s still a connection back to the computer, though. Each object looks quite a bit like a little computer; it has a state, and it has operations that you can ask it to perform. However, this doesn’t seem like such a bad analogy to objects in the real world; they all have characteristics and behaviors. Some language designers have decided that object-oriented programming by itself is not adequate to easily solve all programming problems, and advocate the combination of various approaches into multiparadigm programming languages.[4] Alan Kay summarized five basic characteristics of Smalltalk, the first successful object-oriented language and one of the languages upon which C++ is based. These characteristics represent a pure approach to object-oriented programming:

L & T Infotech Page 4 of 87

Page 5: Oops index

OOPS Concepts using C++ C++ as better C

1. Everything is an object.

Think of an object as a fancy variable; it stores data, but you can “make requests” to that object, asking it to perform operations on itself. In theory, you can take any conceptual component in the problem you’re trying to solve (dogs, buildings, services, etc.) and represent it as an object in your program.

2. A program is a bunch of objects telling each other what to do by sending messages.

To make a request of an object, you “send a message” to that object. More concretely, you can think of a message as a request to call a function that belongs to a particular object.

3. Each object has its own memory made up of other objects. Put another way, you create a new kind of object by making a package containing existing objects. Thus, you can build complexity in a program while hiding it behind the simplicity of objects.

4. Every object has a type. Using the parlance, each object is an instance of a class, in which “class” is synonymous with “type.” The most important distinguishing characteristic of a class is “What messages can you send to it?”

5. All objects of a particular type can receive the same messages. This is actually a loaded statement, as you will see later. Because an object of type “circle” is also an object of type “shape,” a circle is guaranteed to accept shape messages. This means you can write code that talks to shapes and automatically handles anything that fits the description of a shape. This substitutability is one of the most powerful concepts in OOP.

L & T Infotech Page 5 of 87

Page 6: Oops index

OOPS Concepts using C++ Keys to Object

Keys to Object

Why Objects? The chasm between conventional software development and true, object-oriented development is not easily crossed. A company really has to want to be on the other side in order to make the leap successfully. So, it's only fair to begin with the most basic question: Why bother? The answer, in a nutshell, is this: Objects are the enabling technology for adaptive business systems.

The Adaptive Organization Natural selection, the engine of adaptation in all living systems, has just shifted into high gear. It is now operating at the level of organizations rather than organisms, and the cycle of adaptations is measured in months rather than millennia. The competitive environment of business is continuously changing, and the pace of that change is increasing at an accelerating rate. Where it was once possible for a company to stake out its marketing turf and defend its position for years, static positioning is now viable only in a few isolated industries. For most companies today, the only constant is change. How is a company to cope with this kind of change? The message from the management gurus is clear and consistent: The key to survival in today's chaotic business environment is rapid adaptation. The adaptive organization can move quickly into new market niches, deliver custom solutions instead of fixed products, and continuously outmaneuver its competition in the ongoing battle for market share. Unfortunately, it's a lot easier to preach the benefits of adaptivity than to realize them. Organizations have a natural inertia that inhibits any change in direction, and that inertia increases with the mass of the company. Much of the resistance stems from human nature—people stake out their turf within organizations and tend to oppose any change that threatens their position. Reward structures keyed to quarterly earnings only serve to reinforce the status quo and discourage rapid change. But even if all the human and organizational barriers to change could be overcome, there is another source of inertia with a mass approximating that of a black hole—namely, corporate information systems.

From Productivity to Adaptivity The software construction primer in the appendix offers a quick overview of the way we build information systems and how that approach has evolved over the past 50 years. Although information systems now allow organizations to do things that would have been unthinkable prior to the advent of computers, there is one thing they hinder far more than help: the process of change. Large information systems are notoriously resistant to change, so much so that many companies find themselves locked in place by the very systems that helped them to become competitive just a few short years ago. For many years, the standard answer to this problem was to increase the speed of software development. Fourth-generation languages (4GLs), computer-aided software engineering (CASE) tools, and yes, object technology, have all promised and failed to deliver the "order-of-magnitude productivity improvement" that has long served as the holy grail of software development. Although I remain convinced that objects can deliver on that promise, I no longer believe it is the right goal. We have passed the point where building new applications faster can solve the problem. No matter how much we accelerate the development process, the increasing pace of business change will continue to outstrip our ability to create new software. The only enduring solution to the challenge of constant change lies in the development of adaptive business systems—systems that can change at least as fast as the organizations they

L & T Infotech Page 6 of 87

Page 7: Oops index

OOPS Concepts using C++ Keys to Object

support. This is a radical departure from the time-honored practice of developing new applications from scratch to meet new business requirements. It requires us to construct software systems of sufficient flexibility that they can quickly be modified in response to new opportunities and challenges. In short, the answer lies not in productivity but in adaptivity.

The Enabling Technology The key benefit of object technology is that it is the enabling technology for adaptive business systems. However, this adaptivity is not an automatic consequence of adopting objects. Many companies are using objects simply as a different tool for doing what they have always done—creating new applications to solve specific business problems. Objects themselves are naturally adaptive units of software, but they lose all their flexibility if they are locked into conventional applications. The key to building adaptive systems is to understand and uphold the principles of object technology at every level of a system, from the lowest-level object to the enterprise itself. Fortunately, this isn't very hard to do. The most difficult part is simply getting out of the way—setting aside our preconceptions of how software should be built and discovering where objects will take us if we remain true to their principles as we build our way up to the enterprise.

The Three Keys The definition of object technology has been a source of debate throughout its history. However, there is an industry-standard definition of object-oriented technology, and it can be summarized in terms of three key concepts:

1. Objects that provide encapsulation of procedures and data

2. Messages that support polymorphism across objects

3. Classes that implement inheritance within class hierarchies These three concepts and their associated terminology are explained in the remaining sections of this chapter. But even without further explanation, the three concepts can be used to make a distinction between languages that are and are not object-oriented. The object languages that are most widely used in commercial applications are Smalltalk, C++, and Java. Eiffel has gained widespread acceptance in Europe; the latest version of Ada qualifies as object-oriented; and Object COBOL is finally making its way into the market. Of all the object languages currently available, Java is having the greatest impact on the industry and shows the most promise for building adaptive business systems. By contrast, the original versions of C, Ada, and COBOL are anything but object-oriented. Closer to the border are languages like Visual Basic (VB), which began as a conventional language but now supports most of the mechanisms of object technology. As you can see from the examples, many languages are adding object features, so the list of options is constantly growing. Visual Basic is a good illustration of this—all that version 5 lacks is inheritance, and VB could very well be fully object-oriented in its next release. The important point is not whether a language is "truly" object-oriented but how easy it is to apply the principles of objects in the environment provided by the language.

Object & Class Aristotle was probably the first to begin a careful study of the concept of type; he spoke of “the class of fishes and the class of birds.” The idea that all objects, while being unique, are also part of a class of objects that have characteristics and behaviors in common was used directly in the first object-oriented language, Simula-67, with its fundamental keyword class that introduces a new type into a program.

L & T Infotech Page 7 of 87

Page 8: Oops index

OOPS Concepts using C++ Keys to Object

Simula, as its name implies, was created for developing simulations such as the classic “bank teller problem.” In this, you have a bunch of tellers, customers, accounts, transactions, and units of money – a lot of “objects.” Objects that are identical except for their state during a program’s execution are grouped together into “classes of objects” and that’s where the keyword class came from. Creating abstract data types (classes) is a fundamental concept in object-oriented programming. Abstract data types work almost exactly like built-in types: You can create variables of a type (called objects or instances in object-oriented parlance) and manipulate those variables (called sending messages or requests; you send a message and the object figures out what to do with it). The members (elements) of each class share some commonality: every account has a balance, every teller can accept a deposit, etc. At the same time, each member has its own state, each account has a different balance, each teller has a name. Thus, the tellers, customers, accounts, transactions, etc., can each be represented with a unique entity in the computer program. This entity is the object, and each object belongs to a particular class that defines its characteristics and behaviors. So, although what we really do in object-oriented programming is create new data types, virtually all object-oriented programming languages use the “class” keyword. When you see the word “type” think “class” and vice versa. Since a class describes a set of objects that have identical characteristics (data elements) and behaviors (functionality), a class is really a data type because a floating point number, for example, also has a set of characteristics and behaviors. The difference is that a programmer defines a class to fit a problem rather than being forced to use an existing data type that was designed to represent a unit of storage in a machine. You extend the programming language by adding new data types specific to your needs. The programming system welcomes the new classes and gives them all the care and type checking that it gives to built-in types. The object-oriented approach is not limited to building simulations. Whether or not you agree that any program is a simulation of the system you’re designing, the use of OOP techniques can easily reduce a large set of problems to a simple solution. Once a class is established, you can make as many objects of that class as you like, and then manipulate those objects as if they are the elements that exist in the problem you are trying to solve. Indeed, one of the challenges of object-oriented programming is to create a one-to-one mapping between the elements in the problem space and objects in the solution space. But how do you get an object to do useful work for you? There must be a way to make a request of the object so that it will do something, such as complete a transaction, draw something on the screen or turn on a switch. And each object can satisfy only certain requests. The requests you can make of an object are defined by its interface, and the type is what determines the interface. A simple example might be a representation of a light bulb:

L & T Infotech Page 8 of 87

Page 9: Oops index

OOPS Concepts using C++ Keys to Object

Light lt; lt.on();

The interface establishes what requests you can make for a particular object. However, there must be code somewhere to satisfy that request. This, along with the hidden data, comprises the implementation. From a procedural programming standpoint, it’s not that complicated. A type has a function associated with each possible request, and when you make a particular request to an object, that function is called. This process is usually summarized by saying that you “send a message” (make a request) to an object, and the object figures out what to do with that message (it executes code). Here, the name of the type/class is Light, the name of this particular Light object is lt, and the requests that you can make of a Light object are to turn it on, turn it off, make it brighter or make it dimmer. You create a Light object by declaring a name (lt) for that object. To send a message to the object, you state the name of the object and connect it to the message request with a period (dot). From the standpoint of the user of a pre-defined class, that’s pretty much all there is to programming with objects. The diagram shown above follows the format of the Unified Modeling Language (UML). Each class is represented by a box, with the type name in the top portion of the box, any data members that you care to describe in the middle portion of the box, and the member functions (the functions that belong to this object, which receive any messages you send to that object) in the bottom portion of the box. Often, only the name of the class and the public member functions are shown in UML design diagrams, and so the middle portion is not shown. If you’re interested only in the class name, then the bottom portion doesn’t need to be shown, either.

Classes Structured programming languages use functions to structure a program. C++, on the other hand, provides both functions and classes. Data abstraction is implemented in C++ by the class user-defined datatype. Classes in C++ evolved from the C struct concept. A struct represents one or more data values, which can be manipulated in a manner similar to individual variables. Access to a struct is not restricted – so once a struct variable is within scope, it can be modified. In C++, you use classes to define new datatypes as encapsulations of data and operations. Each class contains data as well as the set of functions that manipulates that data. The data components of a class are called data members. And the function components of a class are called member functions.

L & T Infotech Page 9 of 87

Page 10: Oops index

OOPS Concepts using C++ Object and Encapsulation

Defining a class in C++

1. Defining classes C++ provides data abstraction through the class construct. This is a typical class definition.

class clock { private : short tHour; short tMin; short tSec; public: void set_time(int,int,int); void disp_time(); }stopwatch; A class

• encapsulates data • names the class • controls access to functions by means of the private, public, and protected keywords • declares instances of the class (if any)

int x=20; main() { int x; x=10; } class clock { private : short tHour; short tMin; short tSec; public: void set_time(int,int,int); void disp_time(); }stopwatch;

Class instances are created when you declare a variable of the class type.

L & T Infotech Page 10 of 87

Page 11: Oops index

OOPS Concepts using C++ Object and Encapsulation

By default, the members of a class are private. This means they can only be accessed by other class members.The following are some guidelines for declaring a class:

• all members should be defined as private, public, or protected

• members that have the same access control should be kept together

int x=20; main() { int x; x=10; } #include <iostream.h> class date { private : short dd; short mm; short yy; public: void set_date(); short validate(); short find_day(); }; The code in the example declares data members. Data members of a class must not be directly initialized as in the next code.

int x=20; main() { int x; x=10; } short mm=12; #include <iostream.h> class date { private : short dd; short mm=12; short yy;

L & T Infotech Page 11 of 87

Page 12: Oops index

OOPS Concepts using C++ Object and Encapsulation

public: void set_date(); short validate(); short find_day(); }; Member function declarations are similar to function declarations. For example, the member function validate() in short validate ( ); is declared as taking no arguments and returning a value of the short datatype.

int x=20; main() { int x; x=10; } #include <iostream.h> class date { private : short dd; short mm=12; short yy; public: void set_date(); short validate(); short find_day(); };

Declaring class instances

Instances of a class can be declared in a number of ways. An instance is a single occurrence of a class. For example, an instance of the class clock could be stopwatch.

int x=20; main() { int x; x=10; } class clock {

L & T Infotech Page 12 of 87

Page 13: Oops index

OOPS Concepts using C++ Object and Encapsulation

private : short tHour; short tMin; short tSec; public: void set_time(int,int,int); void disp_time(); } stopwatch, digital, analog; You can define a class instance by specifying an instance name in the part of the structure called the instance list. The above code defines three instances of the class clock. You can define an instance of a class separately from the class declaration. A class instance may also be defined by using the keyword class followed by the class name and a unique identifier. In this case, the code is class numbers. An instance of the class numbers is declared in class numbers no;

int x=20; main() { int x; x=10; } class numbers { private : short x, y, z; public: void InitNumbers (short nx, short ny); void getZ(void); void displayZ(void); }; } void main (void) { class numbers no; no.InitNumbers (1, 2); no.getZ(); no.displayZ(); }; The datatype specifier class is dropped from the definition in numbers no;. The compiler recognizes the class name "numbers" from its previous declaration and creates an instance of that class called "no". Because of this, the keyword class is usually dropped from the definition.

L & T Infotech Page 13 of 87

Page 14: Oops index

OOPS Concepts using C++ Object and Encapsulation

Accessing classes

In a class construct you can control access to class members by using the public, private, and protected access control specifiers. Data members of a class are usually private, though they can be public. Private data members can only be accessed by other members of their class. Public functions can be accessed outside their class. This means that private members can be accessed through public access or member functions. A class's data and function members belong to that class's scope in short date :: validate () C++ requires that a member function definition specifies the class for which it is in scope. This is done by using the :: scope resolution operator in the header of the definition. Resolving the scope of the get_data() function means that the private data members dd, mm, yy can be accessed.

int x=20; main() { int x; x=10; } private: short dd; short mm; short yy; public: void get_data(short, short, short); } void date :: get_data(short d,short m,short y) { dd = d; mm = m; yy = y; } main () { short c; short day_of_the_week; date sd; }

L & T Infotech Page 14 of 87

Page 15: Oops index

OOPS Concepts using C++ Object and Encapsulation

Class members can be accessed using the dot operator (.) as in day.validate (); The dot operator accesses a class member by means of the variable name for the object or a reference to the object. The dot operator can be used to access public members of a class only when the instance of a class being accessed is named. date day ; day.validate ();

The dot operator is used with the public function to validate the user's input. A class's data and function members belong to that class's scope, C++ requires that a member function definition specify the class for which it is in scope, and class members can be accessed using the dot operator.

L & T Infotech Page 15 of 87

Page 16: Oops index

OOPS Concepts using C++ Object and Encapsulation

Objects and Encapsulation Although object technology came into the commercial limelight relatively recently, it's actually more than 25 years old. All the basic concepts of the object approach were introduced in the Simula programming language developed in Norway during the late 1960s.

Modeling Physical Objects Simula, an acronym for "simulation language," was created to support computer simulations of real-world processes. The authors of Simula, O. J. Dahl and Kristen Nygaard, wanted to build accurate working models of complex physical systems that could contain many thousands of components. It was apparent even back in the 1960s that modular programming is essential for building complex systems, and modularization played a central role in the design of Simula. What is special about Simula is the way in which modules are defined. They are not based on procedures, as they are in conventional programming. In Simula, modules are based on the physical objects being modeled in the simulation. This choice makes a lot of sense because the objects in a simulation offer a very natural way of breaking down the problem to be solved. Each object has a range of behavior to be modeled, and each has to maintain some information about its own status. The interaction of these objects defines the simulation. Why look for some other way to package procedures and data when the real world has already organized them for you?

Inside Objects The concept of software objects arose out of the need to model real-world objects in computer simulations. An object is a software package that contains a collection of related procedures and data. These procedures are often called methods to distinguish them from conventional procedures that aren't attached to objects. In keeping with traditional programming terminology, the data elements are usually referred to as variables because their values can vary over time.

Consider how you might represent an automated guided vehicle (AGV) in the simulation of a factory. The vehicle can exhibit a variety of behaviors, such as moving from one location to another or loading and unloading its contents. It must also maintain information about its characteristics (pallet size, lifting capacity, maximum speed, and so on) as well as its current state (contents, location, orientation, and velocity). To represent the vehicle as an object, you would program its behaviors as methods and declare variables to contain information about its characteristics and states. During the simulation, the object would carry out its various methods, changing its variables as needed to reflect the effects of its actions.

The concept of an object is simple yet powerful. Objects make ideal software modules because they can be defined and maintained independently of one another, with each object forming a neat, self-contained universe. Everything an object "knows" is captured in its variables, and everything it can do is expressed in its methods.

L & T Infotech Page 16 of 87

Page 17: Oops index

OOPS Concepts using C++ Data Abstraction

Messages and Polymorphism

Sending a Message Real-world objects can exhibit an infinite variety of effects on one another—creating, destroying, lifting, attaching, buying, bending, sending, and so on. This tremendous variety raises an interesting problem: How can all these different kinds of interactions be represented in software? The authors of Simula came up with an elegant solution to this problem: the message. The way objects interact with one another is to send messages asking objects to carry out their methods. A message is simply the name of an object followed by the name of a method the object knows how to execute. If a method requires any additional information in order to know precisely what to do, the message includes that information as a collection of data elements called parameters. The object that initiates a message is called the sender of that message, and the object that receives the message is called the receiver.

To make an automated vehicle move to a new location, for example, some other object might send it the following message:

vehicle104 moveTo: binB7 In this example, vehicle104 is the name of the receiver, moveTo is the method it is being asked to execute, and binB7 is a parameter telling the receiver where to go.

In order for a message to make sense, the sender and receiver must agree on the format of the message. This format is stipulated in a message signature that specifies the name of the method to be executed and the parameters to be included. The moveTo message in the present example has a simple signature: Its name is moveTo, and it sends one parameter, which must be a location. The signature requires all senders of this message to identify it by that name and to supply exactly one parameter of the correct type. In the context of object interactions, the shorter term signature is often used. An object program, then, consists of a number of objects interacting by sending messages to one another. Since everything an object can do is expressed by its methods, this simple mechanism supports all possible interactions between objects.

Responding to a Message The fact that methods are always associated with specific objects has an interesting side effect that turns out to be highly advantageous. Different objects can respond to the same generic message, but each object can interpret the message in a different way. For example, a truck object could implement its own version of the moveTo message, as could a ship, a train, an aircraft, a person, or anything else that moves. The way these real-world objects determine their routes, plan their movements, and carry out these movements differs radically. But all of them would understand a common request to go to a specified destination. The ability of different objects to respond to the same message in different ways is called polymorphism, a Greek term meaning "many forms." The term can be intimidating, and polymorphism is often considered an advanced concept in object technology. But the basic idea couldn't be simpler: Each object can have a unique response to the same message. For most business people, polymorphism is so obvious that they have a hard time seeing what is so special about it. The reason is that human communication is naturally polymorphic. You can ask a dozen people the same question and they could all determine their answers in a different way, but the meaning of the question and the form of the answer would be the same across all of

L & T Infotech Page 17 of 87

Page 18: Oops index

OOPS Concepts using C++ Data Abstraction

them. You don't much care about their private mental processes; you just want to hear their answers. All polymorphism does is allow object interactions to enjoy some of the same flexibility as human interactions. The real surprise to most business people is that software doesn't normally work this way. In conventional programming, procedures aren't attached to objects, and every name must be unique. This means that you would have to call a different procedure for each kind of object in order to get it to do something different. The simple moveTo message would turn into an open-ended list of specialized requests: AGVMoveTo, truckMoveTo, shipMoveTo, trainMoveTo, aircraftMoveTo, personMoveTo, and so on. It seems like a rather cumbersome way to build software in retrospect, but there was no other way to do it prior to objects.

L & T Infotech Page 18 of 87

Page 19: Oops index

OOPS Concepts using C++ Data Abstraction

Data Abstraction Sometimes, a simulation involves only a single example of a particular kind of object. It is much more common, however, to need more than one object of each kind. An automated factory, for example, might have any number of guided vehicles. This possibility raises another concern: It would be extremely inefficient to redefine the same methods in every single occurrence of that object.

Templates for Objects Here again, the authors of Simula came up with an elegant solution: the class. A class is a software template that defines the methods and variables to be included in a particular kind of object. The methods and variables that make up the object are defined only once, in the definition of the class. The objects that belong to a class—commonly called instances of that class—contain only their own particular values for the variables.

To continue the previous example, a simulated factory might contain many automated vehicles, each of which carried out the same actions and maintained the same kinds of information. All such vehicles would be represented by a class called AutomatedVehicle, which would define its methods and variables. The actual vehicles would be represented by instances of this class, each with its own unique identity (vehicle101, vehicle102, vehicle103, and so on). Each of these instances would contain data values that represented its own particular contents and location. Another important function of classes is to specify the messages that objects of this kind will make available to other objects. The set of messages an object commits to respond to is called its message interface. This interface is specified as a collection of message signatures, each of which defines the name and parameters for a particular message. The only design requirement placed on a class is that it provide a method to implement each message specified in its interface. The internals of the class are completely hidden behind this interface and may include any number of variables as well as "invisible" methods that are used only by the object itself.

An object, then, is an instance of a particular class. Its methods and variables are defined in the class, and its values are stored in the instance. To keep my explanations simple, I usually talk about objects wherever possible, referring to classes and instances only when it's important to point out where the object's information is actually stored. For example, if I say that the object vehicle104 has a method called moveTo, this is simply a more convenient way of saying that vehicle104 is an instance of a class that defines a method called moveTo.

Inheriting Class Information Simula took the concept of classes one step further by allowing classes to be defined as special cases of each other. If you needed to represent two different kinds of automated vehicle, you could define one vehicle class in detail and then define the other as everything in the first class plus any additional methods and variables you wanted to add. Simply by declaring the second class to be a special case of the first, you would automatically give it access to everything the first class could do. The mechanism whereby one class of objects can be defined as a special case of a more general class is known as inheritance. Special cases of a class are commonly known as subclasses of that class; the more general class, in turn, is known as the superclass of its special cases. In addition to the methods and variables they inherit, subclasses may define their own methods and variables. They can also redefine any of the inherited methods, a technique known as overriding.

L & T Infotech Page 19 of 87

Page 20: Oops index

OOPS Concepts using C++ Data Abstraction

The class AutomatedVehicle could be broken down into two subclasses, PalletAGV and RollAGV, each of which will inherit the general characteristics of the parent class. Either subclass could establish its own special characteristics by adding to the parent's definition or by overriding its behavior.

Because classes define message interfaces, these interfaces are also inherited by their subclasses. This means that all the subclasses of a given class are guaranteed to respond to any messages that can be handled by the parent class. This is an extremely useful property because it allows us to treat all the specialized forms of a class as equivalent at the general level.

if we define a Product class that includes messages for production, pricing, and shipping in its interface, then we have an ironclad guarantee that all the subclasses of Product will implement all these messages. Any given subclass may use the implementations it inherits from Product, or it may define its own implementations; it doesn't matter to us at this level. What matters is that we can design our system to produce, price, and ship an unlimited variety of products without having to be concerned about how each specialized type carries out these tasks.

Hierarchies of Classes Classes can be nested to any degree, and inheritance will automatically accumulate down through all the levels. The resulting treelike structure is known as a class hierarchy. A class called Part, for example, could be broken down into special kinds of parts such as Motor, Chassis, Connector, and so on. Motor, in turn, could be divided into DriveMotor and SteppingMotor, each of which could be broken down further as needed. An instance of, say, VariableSpeedDriveMotor would inherit all the characteristics of the Part class, as well as those of Motor and DriveMotor.

Class hierarchies increase the ability of objects to reflect the way we view the real world. Human knowledge is often organized in a hierarchical manner, relying on generic concepts and their refinement into increasingly specialized cases. Object technology takes the same conceptual mechanisms we employ in everyday life and uses them to build sophisticated yet understandable software systems. This is particularly evident in the generalization and specialization provided by a class hierarchy.

Natural Building Blocks Object programming is often said to be more natural than traditional programming, and this is true on a couple of different levels. On one level, object programming is more natural because it allows us to organize information in ways that are familiar to us, as illustrated in the class hierarchies described in the preceding chapter. On a deeper level, it is more natural in that it reflects nature's own techniques for managing complexity. This chapter opens and closes with brief looks at the structure of living organisms to establish a framework for understanding the adaptive nature of objects. The remainder of the chapter looks at the actual technology underlying objects and demonstrates why objects provide a better foundation for flexible business systems. The basic building block out of which all living things are composed is the cell. Cells are organic "packages" that, like objects, combine related information and behavior. Most of the information is

L & T Infotech Page 20 of 87

Page 21: Oops index

OOPS Concepts using C++ Data Abstraction

contained in protein molecules within the nucleus of the cell. The behavior, which may range from energy conversion to movement, is carried out by structures outside the nucleus. Cells are surrounded by a membrane that permits only certain kinds of chemical exchanges with other cells. This membrane protects the internal workings of the cell from outside intrusion, and it also hides the complexity of the cell and presents a relatively simple interface to the rest of the organism. All interactions between cells take place through chemical messages recognized by the cell membrane and passed through to the inside of the cell. This message-based communication greatly simplifies the way cells function. The cells don't have to read each others' protein molecules or control each others' structures to get what they need from each other. All they do is send the appropriate chemical message, and the receiving cell responds accordingly. The cell is truly a universal building block. All cells share a common structure and operate according to the same basic principles. Within this generic structure, however, infinite variability is possible. For example, plant cells have a hard outer wall to make them rigid; blood cells are mobile and specialized to transport gases; and muscle cells are able to distort their shape to perform mechanical work. But this tremendous variability is not chaotic; it's all neatly organized—or "classified"—in a hierarchy of specialized types and subtypes. The accompanying diagram gives the merest hint of the depth and breadth of this diversity. Objects, as defined in object technology, have many of the essential characteristics of living cells. A closer look inside the structure of an object reveals some of these similarities.

The Anatomy of an Object Packaging related data and procedures together is called encapsulation. As you can see from the structure of a cell, encapsulation is an idea that has been around for a very long time. The fact that it has worked so well in natural systems suggests that we may be on the right track with this mechanism! Encapsulating Objects The key to object encapsulation is the message interface. As the accompanying illustration indicates, this interface surrounds the object and acts as the point of contact for all incoming messages. The message interface serves the same function as the membrane of a cell—to provide an essential barrier between the internal structure of the object and everything that lies outside the object. Like a cell's membrane, the message interface ensures that all interactions with the object take place through a predefined system of messages that the object is guaranteed to understand and handle correctly. The encapsulation mechanism of object technology is a natural extension of the information-hiding strategy developed in structured programming, as described in the software construction primer in the appendix. Object technology improves on this strategy with better mechanisms to pull the right kinds of information together, including all related data and procedures, and hide their details more effectively. There is simply no way for any other object to access the data or methods hidden behind an object's interface.

Data inside an object is accessed only by methods that implement the object's interface. Just as cells don't "read" each others' protein molecules, objects don't touch each others' data structures. Rather, objects send each other messages that call methods into action. These methods, in turn, access the required variables.

L & T Infotech Page 21 of 87

Page 22: Oops index

OOPS Concepts using C++ Data Abstraction

This same mechanism also controls access to methods that are used only by the object itself. For example, determining the price of a product can require a complex set of interacting calculations, each of which could involve a number of methods and variables. Allowing other objects to trigger these internal methods directly could create havoc within the object. To prevent this kind of disruption, the object hides all of its pricing logic behind an interface that only allows other objects to inquire about its current price or set a new base price for future calculations. Message interfaces offer two important kinds of protection. First, they protect an object's internal components from being corrupted by other objects. If other objects had direct access to an object's variables and internal methods, eventually one of these other objects would handle a variable incorrectly or call the wrong method and damage the object. An object protects itself from this kind of error by hiding its variables and internal methods behind its message interface. The second and less obvious kind of protection works in the opposite direction. By hiding its variables and internal methods, an object protects other objects from depending on its internal structure. For example, they are spared having to keep track of each variable's name, the type of information it contains, the amount of space it takes up in storage, and a host of other details that would complicate all their procedures for accessing an object's variables. With encapsulation, an object only needs to know how to ask another object for information. All the details about how that information is stored are neatly tucked out of sight behind the message interface.

Facilitating Changes In addition to simplifying the interactions between objects, encapsulation also makes the modification of objects much easier than it would otherwise be. Hiding all the implementation details of an object inside its message interface allows the object to be modified extensively in response to changing business needs. As long as the portions of the message interface currently in use by other objects remain intact, internal modifications won't require changes to any other part of the system. Consider making the following change to the AutomatedVehicle class discussed in the preceding chapter. When you first defined the class, you declared a fixed carrying capacity for the vehicle and stored it in a variable. Subsequently, you discover that you need to perform one of several different calculations to determine capacity depending on the kind of load involved. To make this change, you remove the capacity variable and define a set of internal methods for calculating capacity. Each of these methods might require one or more variables, so you add these variables as needed. Finally, you perform the switchover—you change the load method to call your new methods to verify that the vehicle can handle the load.

In a conventional system, this change would require significant restructuring. You would need to rewrite all the subroutines in the system that dealt with vehicle carrying capacities to make them call functions rather than access a data value. You would have to repeat the same selection logic for using the correct calculation in all the affected subroutines. Every routine that needed to determine capacity would have to be changed; all these changes would have to be made correctly; and all these changes would have to be synchronized to occur at the same time. Anything less would result in a broken system. In short, modeling the automated vehicle as a self-contained object allows you to restrict all your changes to a single object. There is no duplication of the selection logic, no doubt about whether all the necessary subroutines have been modified, and no synchronization problem. Just modify the AutomatedVehicle class, and you're done. All other objects continue to interact with it just as they did before. You have made a fundamental change in how information is handled, converting it from data to a collection of specialized procedures, and none of the other objects even "know" that a change has taken place!

L & T Infotech Page 22 of 87

Page 23: Oops index

OOPS Concepts using C++ Data Abstraction

Using Composite Interfaces In most cases, the message interface surrounding an object is a single, unbroken surface. However, it is possible to divide this interface into segments by first defining some simpler interfaces and then combining them into a composite interface for a particular object. This technique can be used to further protect the internals of objects by giving other objects access only to selected components of the object's overall interface. For example, the message interface for a Product object might be composed of four component interfaces: one for defining the product, a second for producing it, a third for selling it, and a fourth for shipping it. Each of these interfaces deals with very different aspects of the product and would be accessed by different parts of the company

manufacturing interface. Only the manufacturing object would be affected by Notice that the segmentation of the message interface increases the two kinds of protection described earlier. First, other objects can't access methods they have no right to invoke. A Sale object, for example, couldn't get access to the manufacturing interface to change the production schedule for a product. Second, other objects are protected from changes to interfaces they don't have access to. If a change in the way a product was manufactured required changes to the interface of the Product object, these changes would be restricted to the the changes—the marketing, sales, and shipping objects would be completely unaffected.

Objects Inside Other Objects The variables contained within objects can be used in two different ways. First, they can be used to store data values, such as the number 12.5 or the text string "Approved." More interestingly, they can contain references to other objects. The form of the reference is an implementation detail and varies considerably among object systems. The important point is that the reference held by a variable provides the containing object with a "handle" or effective address for the contained object, allowing the containing object to manage its component by sending it appropriate messages. Objects that contain other objects are called composite objects. Composite objects are important because they can represent far more sophisticated structures than simple objects can.

An aircraft consists of wings, engines, and other components that are far too complex to be represented as simple numbers or text.

The objects contained in composite objects may themselves be composite objects, and this nesting can be carried out to any number of levels. The major components of an aircraft, for example, are very complex objects in their own right. In any reasonable model of an aircraft, each of these components would be represented by a composite object that, in all likelihood, would be composed of still more composite objects, and so on.

Collections of Objects There is a special kind of class, often called the collection class, that can be found in the class library shipped with most commercial languages. As the name suggests, the basic function of a collection is to gather together objects that must be managed as a group. In a model of an aircraft, for example, we wouldn't create a separate named variable for every seat object. Rather,

L & T Infotech Page 23 of 87

Page 24: Oops index

OOPS Concepts using C++ Data Abstraction

we would gather all the seat objects into a collection and place a reference to that collection in a single variable called Seats.

This example illustrates how collections can simplify composite objects while also making them more flexible. In addition to reducing several hundred variables down to one, the Seats collection allows us to vary the number of seats without reprogramming the model. In addition, the collection makes it easier to carry out group operations on the seats, such as scanning them to see which ones are currently reserved. The method that performed this task would repeatedly ask the collection for its next element until the collection reported that it was empty. This is much simpler than writing a method to examine several hundred named variables.

The Benefits of Composition Because objects can be composed of other objects, object languages can represent real-world objects at the level we naturally think about them. Even a complex, deeply nested structure such as a jet aircraft can be treated as a single, unified object. And since that complex object can have its own behavior, other objects can use it with very little awareness of its internal complexity. This is a good example of how object technology can bring order to large-scale systems. Composite objects not only keep simple things simple, they can make complex things simple as well. Composite objects offer another important advantage—they lay the foundation for a mechanism called delegation, in which an object assigns a task to another object. Delegation is a very common pattern in object designs because it supports the division of labor encouraged by objects.

Determining the charge for a telephone call is a fairly complex process because the charge can be based on physical distance, arbitrary zones, or other factors. Rather than building this complexity directly into a Call object, we could give Call a component Rater to perform this task. Then, the Call could simply send its end points and duration to the Rater and get back the appropriate charge. Because it would not know anything about how the Rater did its work, any kind of Rater could be placed in the Call without affecting the behavior of the Call object in any way.

The hidden implementation It is helpful to break up the playing field into class creators (those who create new data types) and client programmers (the class consumers who use the data types in their applications). The goal of the client programmer is to collect a toolbox full of classes to use for rapid application development. The goal of the class creator is to build a class that exposes only what’s necessary to the client programmer and keeps everything else hidden. Why? Because if it’s hidden, the client programmer can’t use it, which means that the class creator can change the hidden portion at will without worrying about the impact to anyone else. The hidden portion usually represents the tender insides of an object that could easily be corrupted by a careless or uninformed client programmer, so hiding the implementation reduces program bugs. The concept of implementation hiding cannot be overemphasized. In any relationship it’s important to have boundaries that are respected by all parties involved. When you create a library, you establish a relationship with the client programmer, who is also a programmer, but one who is putting together an application by using your library, possibly to build a bigger library.

L & T Infotech Page 24 of 87

Page 25: Oops index

OOPS Concepts using C++ Data Abstraction

If all the members of a class are available to everyone, then the client programmer can do anything with that class and there’s no way to enforce rules. Even though you might really prefer that the client programmer not directly manipulate some of the members of your class, without access control there’s no way to prevent it. Everything’s naked to the world. So the first reason for access control is to keep client programmers’ hands off portions they shouldn’t touch – parts that are necessary for the internal machinations of the data type but not part of the interface that users need in order to solve their particular problems. This is actually a service to users because they can easily see what’s important to them and what they can ignore. The second reason for access control is to allow the library designer to change the internal workings of the class without worrying about how it will affect the client programmer. For example, you might implement a particular class in a simple fashion to ease development, and then later discover that you need to rewrite it in order to make it run faster. If the interface and implementation are clearly separated and protected, you can accomplish this easily and require only a relink by the user. C++ uses three explicit keywords to set the boundaries in a class: public, private, and protected. Their use and meaning are quite straightforward. These access specifiers determine who can use the definitions that follow. public means the following definitions are available to everyone. The private keyword, on the other hand, means that no one can access those definitions except you, the creator of the type, inside member functions of that type. private is a brick wall between you and the client programmer. If someone tries to access a private member, they’ll get a compile-time error. protected acts just like private, with the exception that an inheriting class has access to protected members, but not private members. In C++, an object is an instance of a user-defined class. For example, a person would be a class, but Tom (the person) would be an instance of a person class. Objects can hide their data and implementation. Only the information provided by the class (through class members) is accessible, and everything else is hidden. You can control access to a class's data members and functions, using the following access specifiers:

• public • private • protected

Public members are accessible outside the class, private and protected members are accessible within the class, and protected members are also available to subclasses. By default, all members of a class are private. Making data members private and controlling access through public member functions helps to ensure data integrity in your programs. Private data members can be manipulated only by other member functions of the class. This means that a class's implementation may change internally, but its public interface need not, minimizing the change to the class.

Attributes and behaviors A class can represent an object in the real world, such as a radio. In the class, you can declare the data that describes that object. And you can declare the operations that are possible on that data.

L & T Infotech Page 25 of 87

Page 26: Oops index

OOPS Concepts using C++ Data Abstraction

A radio has attributes and behavior. A radio has attributes, such as the volume at which it plays and the frequency to which it is tuned. These attributes are analogous to a class's data members. And it has behavior or operations (member functions), such as changing volume and tuning to a station. The real-world object – the radio – helps illustrate the concepts of encapsulation and data hiding. You can change the volume and tune to a station without having to know how the radio interprets and acts on those commands. Just as the radio is held within one unit, the data and functions are said to be encapsulated. The attributes of volume and frequency are declared as private. In other words, the way in which the radio implements them is a matter of concern only to members of the radio class, which are its internal circuits and controls. In the example of data hiding, Change_volume() and Tune_station() functions are declared as public, but "external" elements (such as the person listening to the radio) can use them.

public: void Change_volume (short nNewVolume) void Tune_station (void);

C++ program generation

Released in 1985, C++ is an object-oriented programming language created by Bjarne Stroustrup. C++ maintains almost all aspects of the C language, while simplifying memory management and adding several features - including a new datatype known as a class (you will learn more about these later) - to allow object-oriented programming. C++ maintains the features of C which allowed for low-level memory access but also gives the programmer new tools to simplify memory management. C++ is a general-purpose, strongly-typed programming language based on the C language.i.e Everything must be declared before it is used, both variables and functions. C ++ has a few basic building blocks, which can be grouped into types, operations and functions. It is the result of research into extending C to incorporate the principles of object-oriented programming.This research was carried out by Dr Bjarne Stroustrup of AT&T Bell Laboratories in the early 1980s. C++ development systems generally consist of several parts:

• a text editor

• a C++ compiler/linker

• the C standard library

• class libraries

• a debugger

L & T Infotech Page 26 of 87

Page 27: Oops index

OOPS Concepts using C++ Data Abstraction

These components are sometimes integrated into a single development environment The steps involved in generating a C++ program include

• editing • preprocessing • compiling • linking

Editing You write the source code for a C++ program in the text editor, after which it is translated into machine code by the compiler.

Preprocessing The C++ preprocessor executes before the compiler's translation phase begins. The preprocessor obeys commands called preprocessor directives, which indicate that certain manipulations are to be performed on the program before compilation. These manipulations usually involve including the contents of other source code files within the current file, and performing various text replacements. The preprocessor also performs conditional compilation, that is, it allows different sections of code to be compiled depending on preprocessor definitions. A common preprocessor directive is #include. Lines beginning with the pound sign (#) are processed by the preprocessor before the program is compiled.

Compiling The compiler translates the C++ program into machine code, also referred to as object code. Programs don't always work the first time. Each of the steps can fail because of various types of errors. The compiler reports warnings and errors. Only errors prevent a program from compiling. The compiler indicates where each error occurred, which helps you in locating and rectifying the errors.

Linking The fourth step is called linking. C++ programs typically contain references to data and to functions defined elsewhere. These may be defined in the C++ standard libraries, the private libraries of programmers working on a project, or in third-party libraries. A linker links the object code with the code for the missing functions to produce an executable file. When a compile/link succeeds, an executable module is produced. Using a debugger you can follow the source code as its machine code counterpart is executing. This enables you to step through the code to ensure that it is doing what you expect. Also, you can trace a bug or an unexpected runtime action in the program.

L & T Infotech Page 27 of 87

Page 28: Oops index

OOPS Concepts using C++ Data Abstraction

Comments and functions Let's consider how to develop a simple C++ program. You can use comments to add explanatory notes to a program. A line beginning with // indicates that a comment follows. Comments are ignored by the compiler.

// Take in a student's name, grade and percentage #include <iostream.h> main() { } A comment that begins with // is called a single-line comment because the comment ends at the end of the line. Comments can also be multi-line, but they use different symbols to represent this. The following code contains a preprocessor directive. This line tells the preprocessor to include the contents of the input/output stream header file iostream.h in the program. This file must be included for any C++ program that outputs data to the screen or receives input data from the keyboard using the proposed C++ standard stream input/output.

// Take in a student's name, grade and percentage #include <iostream.h> main() { } C++ programs contain one or more functions, one of which must be called main(). The parentheses after main() indicate that it is a function. C++ programs begin executing at main() by default, even if it isn't the first function in the program.

Some C++ compilers allow a different entry point function to be specified in the compiler settings. The left brace, {, must begin the body of every function and the right brace, }, must end each function.

// Take in a student's name, grade and percentage #include <iostream.h> main() { }

L & T Infotech Page 28 of 87

Page 29: Oops index

OOPS Concepts using C++ Data Abstraction

Variables You store data in a C++ program by assigning values to variables. A variable is a name that is associated with memory set aside for storing the variable's value. char sStudent[50]; char cGrade; short nPercentage;

Every variable has a name, a type, a value, a size and a lifetime. All variables must be declared with a name and a data type before they can be used in a program. A variable name is any valid identifier. Variable names must be unique within their scope. An identifier is a series of characters consisting of letters, digits, and underscores (_).Identifiers are case sensitive and cannot contain spaces.An identifier may not begin with a digit.

1A and A 1 are not legitimate identifiers. C++ doesn't always limit the length of identifiers, but some implementations of C++ do restrict their length. It's good programming practice to pick meaningful names for identifiers. For example, it is much clearer to call a variable that represents a student's name sStudent rather than s1.

char sStudent[50]; char cGrade; short nPercentage; A data type defines the sort of values a variable can store. char sStudent[50]; char cGrade; short nPercentage;

Fundamental data types include • int • float • char

int Variables of type int hold integer values, that is, whole numbers such as 7, -35, 0, and 23961. The int data type has a range which is system dependent. float You use the float data type to represent any number that might be expressed using a decimal point, that is, a real number, for example 2.7, 4.9, and -31.2.

char

L & T Infotech Page 29 of 87

Page 30: Oops index

OOPS Concepts using C++ Data Abstraction

A character in C++ is represented by its integer character code. The char data type stores an integer character code. The char value range is from -128 to +127.

char sStudent[50]; char cGrade; short nPercentage; int x; float y; You can assign a value to a variable using the assignment operator, =. In the following code the assignment statement calculates the sum of the variables integer1 and integer2 and assigns the result to the variable "total". Most calculations are performed in assignment statements. total = integer1 + integer2; Variables declared inside functions are local to those functions. Variables declared outside functions, including main(), are global.

int x=20; main() { int x; x=10; } Local variables may be referenced only by statements that are inside the block in which the variables are declared. This feature is known as a variable's scope. Statements outside the variable's scope have no access to that variable, and so can't use its value.

int x=20; main() { int x; x=10; }

Local variables are usually stored on the stack.The stack is a region of memory that holds, among other things, local variables.

L & T Infotech Page 30 of 87

Page 31: Oops index

OOPS Concepts using C++ Data Abstraction

int x=20; main() { int x; x=10; } When a function begins, it allocates space on the stack to hold its local variables. This space exists only while the function is active. After the function returns, it deletes the allocated stack space, thus discarding any values stored there.

int x=20; main() { int x; x=10; } Global variables exist for the duration of a program. You create global variables by declaring them outside any function.Any function may access them, regardless of what block of code that expression is in.

int x=20; main() { int x; x=10; } This fragment shows that x, within main(), is currently in scope. Also, the global x is not modified by the assignment.

int x=20; main() { int x; x=10; } You can allocate space for variables at runtime.These are called dynamic variables. They are created on demand and stored in a block of free memory known as the heap.

cout and cin stream objects The cout and cin stream objects facilitate interaction between the user and the computer.

• cout << "Enter student name:";

• cin << sStudent;

cout << "Enter student name:";

L & T Infotech Page 31 of 87

Page 32: Oops index

OOPS Concepts using C++ Data Abstraction

You use the output stream object, cout, to display on the screen the text string contained between the quotation marks. The stream insertion operator (<<) indicates that the value to the right of the operator is inserted in the output stream. cin << sStudent;

You use the input stream object, cin, and the stream extraction operator, <<, to accept input from the user. The cin object takes input from the standard input stream, which is usually the keyboard, and assigns the input to the variable.

L & T Infotech Page 32 of 87

Page 33: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Constructors and Destructors Constructor functions and destructor functions are special functions available in the C++ programming language.A constructor function, which is a member function of a class, can initialize the members of that class. A destructor function is called when program execution leaves the scope in which an instance of a class exists. The purpose of a destructor is to reclaim an object's memory space (before the system reclaims it) so that it may hold new objects.Because constructors and destructors take care of initialization and destruction responsibilities in a program, these two member functions complement each other.Often, it is necessary to initialize various data members with specific data values. Using a constructor function, you can initialize various variables when the object is created.Using C++, you can pass arguments to an object's constructor function, which are known only when the object is created. Let's say that you are defining a constructor function of an object called Time, which has data members x and y. Time:: Time (short x=0, short y=0) { nX=x; nY=y; }; You can set default values by coding the definition header. Now, if Time is constructed with no parameters being passed to it, nX and nY will be zero.

Declaring a constructor and destructor

Let's say that you want to add constructor and destructor functions to the program implementing a simple time object.

First, you need to add the constructor and destructor functions to the class declaration.

#include <iostream.h> class CClock { private: short nHours,nMinutes,nSeconds; public: CClock();

L & T Infotech Page 33 of 87

Page 34: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; The constructor function name is always that of the class,

class Cclock It is added to the list of member functions. Destructors also have the same name as the class to which they belong, but they have a (~) tilde in front of them, for example ~CClock(); In this case, the destructor is also added to the list of member functions. #include <iostream.h> class CClock { private: short nHours,nMinutes,nSeconds; public: CClock(); ~CClock(); void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; It does not matter whether you declare the constructor or the destructor first. Both the constructor and the destructor are declared as public member functions.

L & T Infotech Page 34 of 87

Page 35: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Because the constructor and destructor are public, they will be called implicitly in the function main(),

void main(void) Either the constructor or destructor could have been declared as private. If so, class objects would be created or destroyed only from within another member function.The only instance in which you could create or destroy a class object from within another function is if the member functions were static.

Constructors and destructors are usually declared as public.

Adding a constructor function

You need to define the constructor and destructor functions. You begin the constructor definition with the definition header. In this case, you use CClock::CClock() The Cclock(); line of code specifies that the constructor function CClock is a member function of the class CClock. The braces, which are to contain the specifications of the definition, are below the header. public: CClock(); ~CClock(); void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; CClock::CClock() { } Next you initialize the data members nHours, nMinutes, and nSeconds within the braces. Initializing the data members in the constructor means that you do not need to initialize the data members in the definition of the InitTime() function.

L & T Infotech Page 35 of 87

Page 36: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

{ nHours=0; nMinutes=0; nSeconds=0; } Initializing the data members in the constructor definition means that they will be automatically initialized in the function main() of the program.

Adding a destructor function

You begin the destructor definition by specifying that it is a member of the CClock class. In this case, the definition is CClock::~CClock() public: CClock(); ~CClock(); void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; CClock::CClock() { nHours=0; nMinutes=0; nSeconds=0; } CClock::~CClock() { } Then, within the braces, you define the destructor to output a message onscreen. Now destroying the clock object To do so, you use the cout statement by entering cout<< "Now destroying clock object";

L & T Infotech Page 36 of 87

Page 37: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

public: CClock(); ~CClock(); void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; CClock::CClock() { nHours=0; nMinutes=0; nSeconds=0; } CClock::~CClock() { cout<<"Now destroying the clock object"; } Constructors and destructors, like ordinary member functions, may contain any type of code. Nevertheless, it is good practice to use them only for their intended purposes and to place extraneous code in other functions. Data members of a class cannot be initialized in the class definition, but they can be initialized in a constructor of the class.

L & T Infotech Page 37 of 87

Page 38: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Inheritance The two primary characteristics of object-oriented programming are inheritance and polymorphism. Inheritance allows us to group classes into families of related types, allowing for the sharing of common operations and data. Inheritance defines a parent/child relationship. The parent defines the public interface and private implementation that are common to all its children. Each child adds to or overrides what it inherits to implement its own unique behavior. An AudioBook child class, for example, in addition to the title and author it inherits from its parent Book class, introduces support for a speaker and a count of the number of cassettes. In addition, it overrides the inherited check_out() member function of its parent. In C++, the parent is called the base class and the child is called the derived class. The relationship between the parent or base class and its children is called an inheritance hierarchy. At a design review meeting, for example, we might say, "We intend to implement an AudioBook derived class. It will override the check_out() method of its Book base class. However, it will reuse the inherited Book class data members and member functions to manage its shelf location, author's name, and title." When classes are similar, it is preferable to define them in terms of their common characteristics, rather than duplicate effort by defining individual classes in full. The mechanism provided by C++ to allow classes to reuse declarations made in other classes is called inheritance. When coding a new class, instead of creating new data members and new member functions, a programmer can specify that the new class should inherit the data members and member functions of a previously defined base class. This is called inheritance, and the new class created is called a derived class. Inheritance allows programmers to reuse software that has proven itself to work efficiently, and it is therefore a major addition to the C++ programming language.

Every derived class can potentially be a base class to another derived class.

Inheritance in computer programming works in much the same way as it does in real life.

You inherit certain characteristics from your parents. Similarly, a derived class inherits certain characteristics from its base class. The two types of inheritance are

• single inheritance • multiple inheritance

L & T Infotech Page 38 of 87

Page 39: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

When a derived class inherits properties of only one base class, this is called single inheritance. When a derived class inherits properties of more than one base class, this is called multiple inheritance. When a derived class is created, it generally contains data members and function members additional to those in its base class. A derived class tends to be bigger in size but more specific than its base class.Derived classes usually represent a smaller group of objects than their base classes. The real advantage of inheritance is its ability to define subtle changes to the features inherited by a derived class for one or more base classes. Every object of a derived class is also an object of that derived class's base class. A base-class object is not also an object of that base-class's derived class.The objects of a derived class are, on the other hand, objects of its base class.

Base and derived classes

Let's say that you are examining shapes as a class, particularly a derived class called triangle. Although a triangle is a shape, not all shapes are triangles. Conversely, considering triangles as a derived class of the shape base class, a triangle is a shape, and therefore the object of the derived class is also an object of the base class. A derived class can access the public members of its base class. And derived classes receive favored treatment over other functions in accessing protected base class members. A derived class cannot access the private members of its base class. These can be accessed by the derived class through access functions provided in the base class's public or protected interfaces. When deriving a class, you must specify which of the base class members you want the derived class to inherit. In the code Class B: public A, the derived class B is set to inherit the protected members of the base class A. The derived class will also inherit the public functions by default. A derived class can often inherit unwanted or inappropriate functions from the public interface of its base class. This is not a major problem because the unwanted inheritance can be redefined in the derived class to have an appropriate implementation.

Deriving a class

Let's say that you want to write a C++ program that implements a time object with an alarm mechanism to demonstrate how C++ derived classes inherit the characteristics of base classes. The steps involved in the program are

• include the header file

• declare the base class and its member functions

L & T Infotech Page 39 of 87

Page 40: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

• declare the derived class and its data members and member functions

• define the functions of the base class

• define the member functions of the derived class

• code the main () function

• call the function

First you must include the header file <iostream.h> in the program. #include<iostream.h> Next, you declare the class CClock with the private data members nHours, nMinutes, and nSeconds. class CClock { private: short nHours, nMinutes, nSeconds; Now you declare the member functions of the base class – CClock, ~CClock, InitTime(), AdvanceHours(), AdvanceMinutes(), and AdvanceSeconds() – for public access. public: CClock(); ~CClock(); void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); };

The base class (CClock) is placed to the right of the colon (:), whereas the derived class (CAlarmClock) is placed on the left. It means that a derived class is to inherit the public elements of the base class. #include<iostream.h> class CClock { private: short nHours, nMinutes, nSeconds; public: CClock(); ~CClock();

L & T Infotech Page 40 of 87

Page 41: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; class CAlarmClock:public CClock {

A base class can be either a direct base class or an indirect base class. The direct class's name is listed in the header of the class, whereas an indirect class's name is inherited from two or more levels up the class hierarchy.

Now you declare the data members of the derived class. #include<iostream.h> class CClock { private: short nHours, nMinutes, nSeconds; public: CClock(); ~CClock(); void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; class CAlarmClock:public CClock { private: short nAlarmHours, nAlarmMinutes; The data members nAlarmHours and nAlarmMinutes are declared as private. include<iostream.h> class CClock { private: short nHours, nMinutes, nSeconds; public:

L & T Infotech Page 41 of 87

Page 42: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

CClock(); ~CClock(); void InitTime(void); void AdvanceHours(void); void AdvanceMinutes(void); void AdvanceSeconds(void); }; class CAlarmClock:public CClock { private: short nAlarmHours, nAlarmMinutes; Declare the member functions of the class CAlarmClock. Declare the member functions for public member access. The member function CAlarmClock is a constructor function.The member function ~CAlarmClock is a destructor function.You assign the third member function SetAlarm() the parameters qHours and qMins. This means that the function can be called only if values are specified for qHours and qMins. public: CAlarmClock(); ~CAlarmClock(); void SetAlarm(short qHours, short qMins);}; Now you need to define the member functions that you declared. You define the constructor function CClock() to automatically initialize the function InitTime() CClock::CClock() { InitTime(); } Define the destructor function to display "Now destroying clock object" on screen. CClock::~CClock() { cout<<"Now destroying clock object"; }

L & T Infotech Page 42 of 87

Page 43: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Now you define the function InitTime() to attribute a zero value to the class CClock data members. void CClock::InitTime(void) { nHours=0; nMinutes=0; nSeconds=0; } In the definition of the function AdvanceHours(), you reset the value of nHours to zero when its value is no longer less than 23. void CClock::AdvanceHours(void) { nHours++; if(nHours>23){ nHours=0; } } Next you define the AdvanceMinutes() member function to reset the value of nMinutes to zero when its value is no longer less than 59. void CClock::AdvanceMinutes(void) { nMinutes++; if(nMinutes>59){ nMinutes=0; } } Now you define the member function AdvanceSeconds() to reset the value of nSeconds to zero when its value is no longer less than 59. void CClock::AdvanceSeconds(void) { nSeconds++; if(nSeconds>59){ nSeconds=0; }} Having defined the functions of the CClock class, you now need to define the member functions declared in the class declaration of CAlarmClock. First define the constructor function CAlarmClock(). CAlarmClock::CAlarmClock() { }

L & T Infotech Page 43 of 87

Page 44: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Now define the destructor function ~CAlarmClock(). CAlarmClock::~CAlarmClock() { } Now define the function SetAlarm(short qHours, short qMins) In the header of this definition, define the function SetAlarm(short qHours, short qMins) as a member function of the class CAlarmClock. void CAlarmClock::SetAlarm(short qHours, shortqMins) Then you equate the value of nAlarmHours to that of qHours and the value of nAlarmMinutes to that of qMins. { nAlarmHours=qHours; nAlarmMinutes=qMins; } Now that the base clas and the derived class have been declared and defined then, code the main() function of the program. First you name the function main() then you declare an object of class CAlarmClock[CAlarmClock] and call it clock. CAlarmClock() [CAlarmClock] is a derived class of CClock. CAlarmClock::CAlarmClock() { } CAlarmClock::~CAlarmClock() { } void CAlarmClock::SetAlarm(short nHours, short nMins) { nAlarmHours=qHours; nAlarmMinutes=qMins; } void main(void) { CAlarmClock clock; The C++ feature of inheritance has allowed CAlarmClock to inherit all the publicly defined

L & T Infotech Page 44 of 87

Page 45: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

members of the class CClock.Therefore, the function main() has full access to the publicly declared members of the class CClock. CAlarmClock::CAlarmClock() { } CAlarmClock::~CAlarmClock() { } void CAlarmClock::SetAlarm(short nHours, short nMins) { nAlarmHours=qHours; nAlarmMinutes=qMins; } void main(void) { CAlarmClock clock; Next, type the code to call the SetAlarm() function. In this case, the code is Clock.SetAlarm (10, 50); The qHours is assigned the value of 10, and qMinutes is assigned the value of 50 in the function SetAlarm() to the set function. The alarm is therefore set to sound when 10 hours and 50 minutes have elapsed. clock.SetAlarm(10, 50); The nested loop in the main method is made up of three for statements. The loop is designed to operate a 24-hour clock object with hours, minutes, and seconds. for(short h==0;h<24;h++){ clock.AdvanceHours(); for(short m==0;m<60;m++){ clock.AdvanceMinutes(); for(short s==0;s<60;s++){ clock.AdvanceSeconds(); } } }

L & T Infotech Page 45 of 87

Page 46: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Multiple inheritance

Single inheritance means that a derived class inherits elements from only one base class. Multiple inheritance, on the other hand, means that a derived class inherits elements from more than one base class.Multiple inheritance was included in the C++ Release 2.0 language definition. The addition was necessary to reflect and accommodate real-world objects, which programmers were trying to simulate.

Let's say that you're mixing different colors of paint from the three primary colors red, blue, and yellow. By mixing red and blue you get purple. purple is a derived class from the two base classes red and blue. By mixing red, blue, and yellow you get brown. In this case, brown has inherited elements of the base classes red, blue, and yellow. In the example of multiple inheritance, brown is the derived class, and red, blue, and yellow are the multiple base classes. A specific syntax is used to indicate multiple inheritance when the derived class is called. After the colon (:) inheritance indicator in the derived class declaration, the base classes being inherited are listed and separated by a comma. In the code, derived class D inherits the member functions and data members of base classes A, B, and C. Class D: public A, public B, public C{ }; As in single inheritance, classes derived from multiple base classes inherit only member functions and data members to which they have access.

Coding multiple inheritance

Let's say that you want to code a program in C++ that uses multiple inheritance. First, you need to make the header file <iostream.h> available to the program.

L & T Infotech Page 46 of 87

Page 47: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

The syntax for including the header file <iostream.h> in the program is #include<iostream.h> Next you declare the class A. class A { public: int x; void make_x(int i); }; Now declare the data members and member functions of class A for public member access. Next you declare class B. Also declare the data member int y and the member function void make_y(int i) for public member access. class B { public: int y; void make_y(int i); }; Next, declare the class C, which is a derived class with class A and class B as its multiple base classes. In the syntax, class C inherits all the public members of classes A and B. Also, declare the function make_xy() for public member access. #include<iostream.h> class A { public: int x; void make_x(int i); }; class B { public: int y; void make_y(int i); };

L & T Infotech Page 47 of 87

Page 48: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

class C:public A, public B { public: int make_xy(void); Next type the class A function make_x() Type void A::make_x(int i) and then press Enter. Now define the class B function make_y(). Define the function make_y() to set the value of y to the value of i by coding y=i; between braces. void A::make_x(int i) { x=i; } void B::make_y(int i) { y=i; } Next define the class C function make_xy(). In the definition header, you code void in the brackets.This specifies that the function takes no parameters. By coding return x*y; between the braces, you define the function make_xy() to return the value of x multiplied by y when the function is executed. void A::make_x(int i) { x=i; } void B::make_y(int i) { y=i; } void C::make_xy(void) { return x*y; } Now you code the program's main() function. main (void) { C i;

L & T Infotech Page 48 of 87

Page 49: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

i.make_x(10); i.make_y(12); cout<<i.make_xy(); } On the first line – C i; – in the main() function, you call the class C and give it the variable name i. On this line, you call the function i.make_x(10). You can call the make_x() function even though it was declared in the class A declaration, and not in the class C declaration. This is because class C inherits the member functions of class A. Next type the code to call the function make_y(). Type i.make_y(12); and then press Enter. The code – i.make_y(12) – calls the function make_y(), which is called from main(). The parameter, and therefore the value of the function, is 12. The make_y() function is not a member function of the derived class C, but it can be called because it is a member of the base class B. main (void) { C i; i.make_x(10); i.make_y(12); cout<<i.make_xy(); } The last line – cout<<i.make_xy();– in the main() function employs cout to display the result on screen. The make_xy() function was defined to return the value of x multiplied by y. main (void) { C i; i.make_x(10); i.make_y(12); cout<<i.make_xy(); }

L & T Infotech Page 49 of 87

Page 50: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Because the value of x is 10, and the value of y is 12, the return is 120.

Multiple inheritance issues

Because of its very nature, programming multiple inheritance can be difficult, so a programmer needs to pay attention to several issues. When deriving a class from one or more public base classes, public members of the base class become public members of the derived class. Protected members of the base classes become protected members of the derived class. Private members of a base class are never directly accessible from a derived class. When deriving from a protected base class, public and protected members of the base class become protected members of the derived class. When deriving from a private base class, public and protected members of the base class become private members of the derived class. In the base-class list, member access must be specified for each base class. In the code, class A is protected, class B is public, and class C defaults to private. class D: protected A, public B, private C{ }; If member access is not specified, the base class always defaults to private. class D: private C{ }; However, for clarity, it is recommended that the member access be stated explicitly. class D: protected A, public B, private C{ }; A base-class name must not be included more than once in a base-class list. In the case of an indirect base class, its name is not specified in the declaration. The name of the class, which is derived from it, is used. class D: protected A, public B, private C, public B{ Let's say that class A inherits properties directly from class B. In this case, class D inherits all the characteristics directly from class A and class C. Because class D inherits class A, class B is an indirect base class of class D. class D: protected A, public B, private C{ };

L & T Infotech Page 50 of 87

Page 51: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Calling issues

A class derived from multiple base classes may need to call multiple base-class constructors. A derived class inherits its base class's members. Let's say that there is an instance of an object of a derived class. The base-class members of the derived class object must be initialized by calling the base class's constructor. A base-class initializer may be coded in the derived class's constructor to explicitly call the base-class constructor. Otherwise, the derived class's constructor will implicitly call the base class's default constructor. A derived-class constructor always calls the constructor for its base class first to initialize the derived class's base-class members. Constructors are called in the order in which their base classes are declared. However, it is generally unwise to devise classes that depend on other class objects to be constructed in a particular order. As a rule, classes should operate as independently of each other as possible. Class D: protected A, public B, C{ }; Suppose that you're coding a class that depends on other classes' objects to be initialized in a certain order. Instead of having one class inherit other classes' properties, you might declare the dependent classes as data members of a new class. The new class could then control when and how the dependent members are initialized.

L & T Infotech Page 51 of 87

Page 52: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Virtual Functions and Polymorphism Polymorphism is an important feature of object-oriented languages. It makes it easier to reuse code. This, in turn, leads to systems that are easier to maintain and extend. // main void main(void) { CEmployee *pEmployee; pEmployee = new CHourlyWorker(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; pEmployee = new CSupervisor(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; Polymorphism can be defined as the ability of objects of different classes, related by inheritance, to respond differently to the same member function call. It allows the use of identical interfaces with different implementations. Consider the definition of a base class CEmployee which is used to define two derived classes:

• CHourlyWorker

• CSupervisor

#include <iostream.h> // class declarations // CEmployee class CEmployee{ protected: char cLastName[25]; char cFirstName[25]; float fYearlyEarnings; public: CEmployee(); virtual void Print(); float ReviseYearlyEarnings(); }; // CHourlyWorker class CHourlyWorker:public CEmployee{ private: float fWeeklyWage; // CHourlyWorker

L & T Infotech Page 52 of 87

Page 53: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

class CHourlyWorker:public CEmployee{ private: float fWeeklyWage; public: CHourlyWorker(); void Print(); }; // CSupervisor class CSupervisor:public CEmployee{ private: int nMonthlySalary; public: CSupervisor void Print(); }; CEmployee might include a function called Print() that allows you to output the contents of an object of that class. Each derived class of CEmployee can redefine this function to output its local contents. // CHourlyWorker class CHourlyWorker:public CEmployee{ private: float fWeeklyWage; public: CHourlyWorker(); void Print(); }; // CSupervisor class CSupervisor:public CEmployee{ private: int nMonthlySalary; public: CSupervisor void Print(); }; Although the contents of each derived class will be different, polymorphism allows you to treat them all as objects of the base class. The contents of any derived class can then be printed by simply making a generic call to Print() using a base-class pointer.

L & T Infotech Page 53 of 87

Page 54: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

// main void main(void) { CEmployee *pEmployee; pEmployee = new CHourlyWorker(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; pEmployee = new CSupervisor(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; } The proper behavior of the derived-class object when treated as a base-class object is polymorphism. // main void main(void) { CEmployee *pEmployee; pEmployee = new CHourlyWorker(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; pEmployee = new CSupervisor(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; } The call to function Print() can be resolved only at run time, and not at compile time. This ability to delay resolution is referred to as late or dynamic binding. Late binding is the mechanism for implementing polymorphism.

Resolving the function at compile time is called early or static binding.

L & T Infotech Page 54 of 87

Page 55: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

Virtual functions C++ supports polymorphism using virtual functions. You use the keyword virtual in a virtual function's prototype declaration. #include <iostream.h> //----------------------------- // class declarations //----------------------------- // CEmployee class CEmployee{ protected: char cLastName[25]; char cFirstName[25]; float fYearlyEarnings; public: CEmployee(); virtual void Print(); float ReviseYearlyEarnings(); }; // CHourlyWorker class CHourlyWorker:public CEmployee{ private: float fWeeklyWage; }; Unlike redefined nonvirtual functions, redefined virtual functions must have the same number of parameters and the same parameter types and return type. When a function is declared as a virtual function, it remains virtual from that point down through the hierarchy. #include <iostream.h> //----------------------------- // class declarations //----------------------------- // CEmployee class CEmployee{ protected: char cLastName[25]; char cFirstName[25];

L & T Infotech Page 55 of 87

Page 56: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

float fYearlyEarnings; public: CEmployee(); virtual void Print(); float ReviseYearlyEarnings(); }; // CHourlyWorker class CHourlyWorker:public CEmployee{ private: float fWeeklyWage; }; For the "employee" example, the function Print() is declared as a virtual function in the base class CEmployee. Print() is then redefined (or overloaded) in each derived class to print the contents specific to that class. #include <iostream.h> // class declarations // CEmployee class CEmployee{ protected: char cLastName[25]; char cFirstName[25]; float fYearlyEarnings; public: CEmployee(); virtual void Print(); float ReviseYearlyEarnings(); }; // CHourlyWorker class CHourlyWorker:public CEmployee{ private: float fWeeklyWage; public: CHourlyWorker(); void Print(); }; // CSupervisor class CSupervisor:public CEmployee{ private:

L & T Infotech Page 56 of 87

Page 57: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

int nMonthlySalary; public: CSupervisor void Print(); }; Base-class member functions that are too generic to be defined (implemented) within the base class should be declared as pure virtual functions. When a pure virtual function is included in a class, you cannot create an instance of that class. This is referred to as an abstract class as it is too generic to define a real object. // CHourlyWorker class CHourlyWorker:public CEmployee{ private: float fWeeklyWage; public: CHourlyWorker(); void Print(); }; // CSupervisor class CSupervisor:public CEmployee{ private: int nMonthlySalary; public: CSupervisor void Print(); };

Although you cannot create an object from an abstract class, you can declare a pointer to that abstract class. A virtual function that is created in a base class and redefined in one or more derived classes can act polymorphically. When the function is called as a member of the base class using a base-class pointer, C++ selects the correct redefined function in the appropriate derived class associated with that object.

// main void main(void) { CEmployee *pEmployee;

L & T Infotech Page 57 of 87

Page 58: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

pEmployee = new CHourlyWorker(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; pEmployee = new CSupervisor(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; } A call to a virtual function using a specific object name and the dot member selection operator is resolved at compile time. The virtual function used is the one defined for the class associated with that object, in this case the CSupervisor class. // CHourlyWorker CHourlyWorker::CHourlyworker() { } virtual void CHourlyWorker::Print( ) { cout << cFirstName << ' ' << cLastName << endl << "Weekly wage = " << fWeeklyWage << endl << "Expected Yearly Earnings = " << fYearlyEarnings; } void main() { CSupervisor Brown; Brown.print(); } When a nonvirtual member function of a base class is redefined in a derived class, a call to that function using a base-class pointer always uses the base-class version of the function. If a derived-class pointer is used to call the member function, the derived-class version of the function is used. This represents nonpolymorphic behavior. // CHourlyWorker CHourlyWorker::CHourlyworker() { } virtual void CHourlyWorker::Print( ) { cout << cFirstName << ' ' << cLastName << endl << "Weekly wage = " << fWeeklyWage << endl

L & T Infotech Page 58 of 87

Page 59: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

<< "Expected Yearly Earnings = " << fYearlyEarnings; } void main() { CSupervisor Brown; Brown.print(); } As an example of nonpolymorphic behavior, consider the redefinition of nonvirtual base-class member function ReviseYearlyEarnings() within class CSupervisor. A call to this function using the base-class pointer pEmployee will always access the base-class version of the function rather than the corresponding redefined version. // main void main(void) { CEmployee *pEmployee; pEmployee = new CHourlyWorker(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; pEmployee = new CSupervisor(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; } void CEmployee::REviseYearlyEarnings() { fYearlyEarnings = fYearlyEarnings + fYearlyEarnings/50 } // CSupervisor::CSupervisor() { } virtual void CSupervisor::Print() { cout << cFirstName << ' ' << cLastName << endl << "Monthly Salary = " << nMonthlySalary << endl << "Expected Yearly Earnings = " << fYearlyEarnings; } void CSupervisor::REviseYEarlyEarnings() { fYearlyEarnings = fYearlyEarnings + fYearlyEarnings/50 To access the appropriate redefined version of the function, you need to use a pointer to the derived class (CSupervisor). // main void main(void) { CEmployee *pEmployee;

L & T Infotech Page 59 of 87

Page 60: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

pEmployee = new CHourlyWorker(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; pEmployee = new CSupervisor(); pEmployee->ReviseYearlyEarnings(); pEmployee->Print(); delete pEmployee; }

Compiling considerations With polymorphism and virtual functions, a programmer can write code independently of the types of objects to which messages are sent. Dynamic binding allows virtual functions to compile without knowing the type or class of an object at compile time. At run time, the virtual function call is matched with the member function of the receiving object. This allows new objects to be added without the need to recompile the whole system. All you need to do is compile the objects being added and any code which manipulates that object type specifically.

Default function parameters A useful technique associated with C++ functions is the ability to specify default values for function parameters. You can employ this technique when a function call needs to provide only some of the expected arguments for that function. Consider a function that returns the product of three integer values. To call the function using only two arguments, say num1 and num2, the programmer first needs to determine and then supply the correct value to the unused parameter. This is cumbersome and can be prone to error. Default function arguments are designed to guard against incorrect function values being assigned to function parameters. To declare a default value, you assign the parameter the appropriate value in the function prototype. In this example, the prototype declaration indicates that Product() requires only two arguments, but can have three arguments. The default values must come last in the function's parameter list, and can only appear in the function's prototype. For example, you can't have a prototype like the one in this example. But you can use the following prototype: int Product(int X, int Y, int Z=1);

L & T Infotech Page 60 of 87

Page 61: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

If a function call specifies no arguments for function parameters with default values, then the parameters are given the default values listed in the prototype.

Polymorphism in an application

1. Shapes Let's consider a shape hierarchy as the classic example of how you can apply polymorphism to an application. The shape program needs to manage generic shape objects. All shapes can be drawn, but triangles, circles, and squares are all drawn differently. To create a program that is easy to extend, you need to be able to handle generic shape pointers while ignoring the details of the particular shape you are dealing with.

2. Coding considerations Suppose a set of shape classes CTriangle, CCircle, and CSquare are all to be derived from base class CShape. Each derived class will have its own Draw() and SetColor() functions. Using polymorphism, you want to be able to draw any shape and set its color by simply invoking the Draw() and SetColor() functions using a base-class pointer. To implement the program, you first need to define the base class, CShape, from which all other shape classes will be derived.

By declaring color as a private data member, access to it is restricted to functions that are members or friends of the base class.

#include <iostream.h> typedef enum{ Unknown, Blue, Green, Red, Yellow } Color; //-------------------------- // class declarations //-------------------------- // CShape class CShape{ private: Color color;

L & T Infotech Page 61 of 87

Page 62: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

public: Cshape(); CShape must be set up as an abstract class because member function Draw() is too generic to be defined for an object of this class. #include <iostream.h> typedef enum{ Unknown, Blue, Green, Red, Yellow } Color; //-------------------------- // class declarations //-------------------------- // CShape class CShape{ private: Color color; public: Cshape(); You make CShape an abstract class by declaring Draw() as a pure virtual function, that is, you assign its prototype a value of zero. //-------------------------- // class declarations //-------------------------- // CShape class CShape{ private: Color color; public: Cshape(); virtual ~CShape(); virtual void Draw(void)=0; virtual void SetColor(Color c); }; // CTriangle class CTriangle : public CShape{ private: //-------------------------------

L & T Infotech Page 62 of 87

Page 63: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

// class definitions //------------------------------- // CShape CShape::CShape() { } CShape::~CShape() { cout << "In ~ CShape()\n"; } void CShape::SetColor(Color c) { cout << "In CShape::Setcolor()\n"; color=c; }; // CTriangle CTriangle::CTriangle() { m_nAngle1=m_nAngle2=m_nAngle3=0;

The implementation presented here does not deal with the mechanics of how to draw each shape. Only part definitions of constructors, destructors, and other class member functions are shown. When the program is executed, the output consists of a list of "location messages" (or diagnostics), used to indicate the execution path through the program.

Base-class member function SetColor() can be defined without knowing which shape object it is being applied to.

Therefore, it can be declared as a virtual function, rather than a pure virtual function.

You can see from its definition that it outputs a location message to the screen and assigns a value to base-class data member color.

//-------------------------- // class declarations //-------------------------- // CShape class CShape{ private: Color color;

L & T Infotech Page 63 of 87

Page 64: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

public: Cshape(); virtual ~CShape(); virtual void Draw(void)=0; virtual void SetColor(Color c); }; // CTriangle class CTriangle : public CShape{ private: //------------------------------- // class definitions //------------------------------- // CShape CShape::CShape() { } CShape::~CShape() { cout << "In ~ CShape()\n"; } void CShape::SetColor(Color c) { cout << "In CShape::Setcolor()\n"; color=c; }; // CTriangle CTriangle::CTriangle() { m_nAngle1=m_nAngle2=m_nAngle3=0; In addition to Draw() and SetColor(), CShape's public interface includes the constructor CShape() and the destructor ~CShape() The destructor ~CShape needs to be declared as a virtual function to overcome a problem which occurs when virtual functions and destructors are used with class hierarchies. //-------------------------- // class declarations //-------------------------- // CShape class CShape{

L & T Infotech Page 64 of 87

Page 65: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

private: Color color; public: Cshape(); virtual ~CShape(); virtual void Draw(void)=0; virtual void SetColor(Color c); }; // CTriangle class CTriangle : public CShape{ private:

If the destructor is not marked as virtual, then an explicit call to destroy an object using the delete operator and a base-class pointer will always use the base-class destructor, irrespective of the object being pointed to.

Once CShape has been defined, you can begin to define each of the derived classes. Each derived class will inherit from the base class CShape.

//-------------------------- // class declarations //-------------------------- // CShape class CShape{ private: Color color; public: Cshape(); virtual ~CShape(); virtual void Draw(void)=0; virtual void SetColor(Color c); }; // CTriangle class CTriangle : public CShape{ private:

L & T Infotech Page 65 of 87

Page 66: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

3. Defining derived classes Let's look at how you might define CTriangle, the derived class for triangle objects. You want the public members of CShape to be public in the derived class CTriangle. So you derive CTriangle from CShape using the keyword public. // CTriangle class CTriangle : public CShape{ private: short m_nAngle1, m_nAngle2, m_nAngle3; public: CTriangle(); ~CTriangle(); void SetAngles(short nAngle1, short nAngle2, short nAngle3) void Draw(void); void SetColor(Color c); }; // CCircle class CCircle : public CShape( private: short m_nRadius; public: CCircle(); ~CCircle(); The shape of any triangle is described by the magnitude of its three angles. Therefore, CTriangle includes three data members to hold these values. // CTriangle class CTriangle : public CShape{ private: short m_nAngle1, m_nAngle2, m_nAngle3; public: CTriangle(); ~CTriangle(); void SetAngles(short nAngle1, short nAngle2, short nAngle3) void Draw(void); void SetColor(Color c); }; // CCircle class CCircle : public CShape( private: short m_nRadius;

L & T Infotech Page 66 of 87

Page 67: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

public: CCircle(); ~CCircle(); In addition to a constructor and destructor, CTriangle includes three other member functions in its public interface

• SetAngles()

• Draw()

• SetColor()

SetAngles()Draw()SetColor() // CTriangle class CTriangle : public CShape{ private: short m_nAngle1, m_nAngle2, m_nAngle3; public: CTriangle(); ~CTriangle(); void SetAngles(short nAngle1, short nAngle2, short nAngle3) void Draw(void); void SetColor(Color c); }; // CCircle class CCircle : public CShape( private: short m_nRadius; public: CCircle(); ~CCircle(); SetAngles() allows you to describe a triangle object by setting the values of CTriangle's data members m_nAngle1, m_nAngle2, and m_nAngle3. Draw() and SetColor() are overloaded versions of the corresponding base class virtual functions, which allows them to be polymorphically selected at run time. // CTriangle class CTriangle : public CShape{ private: short m_nAngle1, m_nAngle2, m_nAngle3;

L & T Infotech Page 67 of 87

Page 68: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

public: CTriangle(); ~CTriangle(); void SetAngles(short nAngle1, short nAngle2, short nAngle3) void Draw(void); void SetColor(Color c); }; // CCircle class CCircle : public CShape( private: short m_nRadius; public: CCircle(); ~CCircle(); In this example, Draw() simply outputs the message "In CTriangle::Draw()" each time it is called. SetColor() explicitly calls the base-class version of itself to assign a value to base-class private data member color. CTriangle::~CTriangle() { cout << "In ~CTriangle()\n"; } void CTriangle::SetAngles(short nAngle1, short nAngle2, short nAngle3) { m_nAngle1=nAngle1; m_nAngle2=nAngle2; m_nAngle3=nAngle3; } void CTriangle::Draw(void) { cout << "In CTriangle::Draw()\n"; } void CTriangle::SetColor(Color c) { cout << "In CTriangle::SetColor()\n" CShape::SetColor(c); } // CCircle You don't have to derive your own versions of base-class virtual functions if implementations are provided in the base class. For example, if SetColor() was not redefined here, the CShape version would be inherited.

L & T Infotech Page 68 of 87

Page 69: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

CTriangle::~CTriangle() { cout << "In ~CTriangle()\n"; } void CTriangle::SetAngles(short nAngle1, short nAngle2, short nAngle3) { m_nAngle1=nAngle1; m_nAngle2=nAngle2; m_nAngle3=nAngle3; } void CTriangle::Draw(void) { cout << "In CTriangle::Draw()\n"; } void CTriangle::SetColor(Color c) { cout << "In CTriangle::SetColor()\n" CShape::SetColor(c); } // CCircle

If Draw() was not defined in CTriangle, then CTriangle would be an abstract class as there is no definition for Draw() in CShape. Therefore, you do need to include a definition for Draw() in CTriangle.

Derived classes CCircle and CSquare are defined in a way similar to CTriangle. Each is set up to publicly inherit from the base class CShape.

// CCircle class CCircle : public CShape{ private: short m_nRadius; public: CCircle(); ~CCircle(); void SetRadius(short nRadius); void Draw(void); void SetColor(Color c); }; // CSquare class CSquare : public CShape( private: short m_nSideLength; public:

L & T Infotech Page 69 of 87

Page 70: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

CSquare(); ~CSquare(); As a circle is described by its radius, an appropriate data member is declared in the private portion of class CCircle. CCircle includes a public member function SetRadius() that you can use to describe the circle object created. // CCircle CCircle::CCircle() { m_nRadius=0; } CCircle::~CCircle() { cout << "In ~CCircle()\n"; } void CCircle::SetRadius(short nRadius) { m_nRadius=nRadius; } void CCircle::Draw(void) { cout << "In CCircle::Draw()\n"; } void CCircle::SetColor(Color c) { cout << "In CCircle::SetColor()\n"; CShape::SetColor(c); CSquare has a single data member, m_nSideLength, that describes the square object. CSquare::SetSideLength() allows you to manipulate this data member // CSquare class CSquare : public CShape( private: short m_nSideLength; public: CSquare(); ~CSquare(); void SetSideLength(short nSideLength); void Draw(void); void SetColor(Color c); }; //------------------------------- // class definitions

L & T Infotech Page 70 of 87

Page 71: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

//------------------------------- // CShape CShape::CShape() { } Base-class member functions Draw() and SetColor() are both redefined for CCircle and CSquare. The implementation of these functions is similar to those described for CTriangle. // CSquare class CSquare : public CShape( private: short m_nSideLength; public: CSquare(); ~CSquare(); void SetSideLength(short nSideLength); void Draw(void); void SetColor(Color c); }; //------------------------------- // class definitions //------------------------------- // CShape CShape::CShape() { }

4. Polymorphism in main() Let's now examine main() to see how polymorphism simplifies the code. Function main() begins with the declaration of the base-class pointer pShape. Using a base class pointer allows the use of generic calls to Draw() and SetColor() without any indication of the shape currently being referenced The first step in drawing a triangle is to create an object of class CTriangle. One way to do this is to call CTriangle's constructor using the new operator. The new operator returns the address of the object, which can be used to initialize the pointer pShape. // main function void main(void) { CShape *pShape; // create a triangle pShape=new CTriangle();

L & T Infotech Page 71 of 87

Page 72: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

The new and delete operators handle pointers rather than the objects themselves. You use new to return a pointer to the initialized object. The delete operator takes a pointer to an object that was previously created using new.

To describe the triangle, you need to access CTriangle's unique member function SetAngles(). You can do this by casting the base-class pointer, pShape, as a CTriangle pointer. This allows you to call CTriangle::SetAngles() using the pointer arrow operator "->".

// main function void main(void) { CShape *pShape; // create a triangle pShape=new CTriangle(); ((CTriangle*)pShape)->SetAngles(90,90,90); Once you have described the object, you can make use of polymorphism to set its color and then draw it. Polymorphism allows you to code a generic call to SetColor() using base-class pointer pShape. C++ will polymorphically select CTriangle::SetColor() as the correct version of SetColor() in this instance. This is because pShape will be pointing to an object of class CTriangle when the call is made. // main function void main(void) { CShape *pShape; // create a triangle pShape=new CTriangle(); ((CTriangle*)pShape)->SetAngles(90,90,90); pShape->SetColor(Blue); You can confirm the polymorphic behavior by observing the program's output. The first non-constructor function executed is CTriangle::SetColor(). This function calls the base-class version of SetColor() (that is, CShape::SetColor()) to set the color of the object.

No location messages have been included in the definition of class constructors. Therefore, there is no indication of which constructors have been executed in the program's output.

Next, pShape is used to make a generic call to base-class member function Draw(). As for SetColor(), C++ polymorphically selects CTriangle::Draw() as the correct version of Draw() in this instance.

L & T Infotech Page 72 of 87

Page 73: Oops index

OOPS Concepts using C++ Virtual Function & Polymorphism

// main function void main(void) { CShape *pShape; // create a triangle pShape=new CTriangle(); ((CTriangle*)pShape)->SetAngles(90,90,90); pShape->SetColor(Blue); pShape->Draw(); delete pShape; The delete operator is used to destroy the object currently pointed to by pShape. It automatically invokes the correct class destructor for the object. First, the derived-class destructor is called, then the destructor for the base class.

Generally, destructors are called in reverse order of their constructors.

Because of polymorphism, the code used to draw the circle and square objects is almost identical to the code used to draw the triangle object. The only difference is in the casting for calls to functions specific to each class.

// create a circle pShape=new CCircle(); ((CCircle*)pShape)->SetRadius(10); pShape->SetColor(Red); pShape->Draw(); delete pShape; // create a square pShape=new CSquare(); ((CSquare*)pShape)->SetSideLength(10); pShape->SetColor(Green); A glance at the output shows that the execution path for each of the three objects is quite different.

L & T Infotech Page 73 of 87

Page 74: Oops index

OOPS Concepts using C++ Program Using Polymorphism

Program Using Polymorphism A program to calculate the area of two-dimensional objects using polymorphism. This involves the following tasks:

• defining a base class

• defining member functions

• defining derived classes

• defining member functions

• handling a rectangle object

• handling a circle object

Suppose you have been asked to write a program to calculate the area of two-dimensional objects using polymorphism. You are required to test the design by coding a main() function that creates a rectangle and a circle. You should calculate the area of each defined object and output the details of the calculation to the screen.

Task 1: Defining a base class Your first task is to define a base class, called C2dObject, from which all two-dimensional objects will be derived.

Step 1 of 4

See if you can complete the line that begins the definition of the base class C2dObject.

Result

To complete the class definition you type class C2dObject{

Next, you need to declare a data member within C2dObject that will hold the value calculated for area.

Let's assume that you want derived-class member functions to have access to this base-class data member.

#include <iostream.h> //------------------------------------ // class declarations //------------------------------------ // C2dObject class C2dObject{

L & T Infotech Page 74 of 87

Page 75: Oops index

OOPS Concepts using C++ Program Using Polymorphism

Step 2 of 4

In which portion of the class do you think you would declare this data member?

Options:

1. private

2. protected

3. public

Result

The protected portion of the class declares this data member.

You declare floating-point variable, m_fArea, as a protected data member of C2dObject.

#include <iostream.h> //------------------------------------ // class declarations //------------------------------------ // C2dObject class C2dObject{ protected float m_fArea; Assume that C2dObject's public interface has already been partly defined with the declaration of a constructor and destructor. You now want to declare a member function, called CalcArea(), that will be used to calculate the area of any two-dimensional object. #include <iostream.h> //------------------------------------ // class declarations //------------------------------------ // C2dObject class C2dObject{ protected float m_fArea; public: C2dObject(); virtual ~C2dObject(); C2dObject is too generic to be a real object.

Step 3 of 4

L & T Infotech Page 75 of 87

Page 76: Oops index

OOPS Concepts using C++ Program Using Polymorphism

See if you can complete the declaration of the CalcArea() prototype.

MISSING CODE void CalcArea(void) = 0;

Result

You declare CalcArea() as a pure virtual function by entering this statement: virtual void CalcArea(void) = 0;

You are also asked to include a function PrintDetails() that will display the value calculated for the area of an object.

A generic call to PrintDetails() should also print the defining data used in the calculation of the area of the object.

#include <iostream.h> //------------------------------------ // class declarations //------------------------------------ // C2dObject class C2dObject{ protected float m_fArea; public: C2dObject(); virtual ~C2dObject(); virtual void CalcArea(void) = 0;

Step 4 of 4

How do you think you could declare PrintDetails() within the base class C2dObject, if a definition for PrintDetails() is to exist for the base class as well as for derived classes?

Options:

1. virtual void PrintDetails(void);

2. virtual PrintDetails();

3. virtual PrintDetails()=0;

4. void PrintDetails(void)=0;

Result

You could declare PrintDetails() using the code virtual void PrintDetails(void); or virtual PrintDetails();

L & T Infotech Page 76 of 87

Page 77: Oops index

OOPS Concepts using C++ Program Using Polymorphism

As a definition for PrintDetails() is to be included within C2dObject, and polymorphic behavior is required, you declare PrintDetails() as a virtual function by entering this statement.

#include <iostream.h> //------------------------------------ // class declarations //------------------------------------ // C2dObject class C2dObject{ protected float m_fArea; public: C2dObject(); virtual ~C2dObject(); virtual void CalcArea(void) = 0; virtual void PrintDetails(void); Finally, you enter the closing tag – }; – to complete the definition of the base class C2dObject. #include <iostream.h> //------------------------------------ // class declarations //------------------------------------ // C2dObject class C2dObject{ protected float m_fArea; public: C2dObject(); virtual ~C2dObject(); virtual void CalcArea(void) = 0; virtual void PrintDetails(void); };

L & T Infotech Page 77 of 87

Page 78: Oops index

OOPS Concepts using C++ Program Using Polymorphism

Task 2: Defining member functions Now, you need to define the member functions of class C2dObject. Assume that the class constructor and destructor have already been defined. //-------------------------- // class definitions //-------------------------- // C2dObject C2dObject::C2dObject() { m_fArea = 0; } C2dObject::~C2dObject() { }

Step 1 of 1

See if you can complete the code required to begin the definition of PrintDetails() for base class C2dObject.

/-------------------------- // class definitions //-------------------------- // C2dObject C2dObject::C2dObject() { m_fArea = 0; } C2dObject::~C2dObject() { } void MISSING CODE (void) {

Result

To begin the definition of PrintDetails() you type C2dObject::PrintDetails

This cout statement outputs the area of the current object.

//-------------------------- // class definitions //-------------------------- // C2dObject

L & T Infotech Page 78 of 87

Page 79: Oops index

OOPS Concepts using C++ Program Using Polymorphism

C2dObject::C2dObject() { m_fArea = 0; } C2dObject::~C2dObject() { } void C2dObject::PrintDetails(void) { cout << "Area = " << m_fArea << "\n"; }

Task 3: Defining derived classes You are now going to define derived classes CRectangle and CCircle. // CRectangle

Step 1 of 3

See if you can complete the opening line in the definition of derived class CRectangle. You want public members of the base class to be inherited as public members in the derived class.

// CRectangle class MISSING CODE C2dObject {

Result

The code to complete the definition of derived class CRectangle is CRectangle:public.

Step 2 of 3

Which of the following data members would you expect to find declared in the private portion of class CRectangle?

Options:

1. m_nLength

2. m_nWidth

3. m_nArea

4. m_nRadius

Result

A rectangle is described by its length and width. Therefore, you need to declare m_nLength and m_nWidth as private data members of CRectangle.

Derived class CRectangle inherits base-class data member m_fArea to hold the value for the area of a rectangle object.

L & T Infotech Page 79 of 87

Page 80: Oops index

OOPS Concepts using C++ Program Using Polymorphism

// CRectangle class CRectangle:public C2dObject{ private: int m_nLength, m_nWidth; Assume that the constructor and destructor for CRectangle have already been declared and defined. Also declared is the prototype for the function SetDimensions(). It will be used to set the values for the length and width of a rectangle object. // CRectangle class CRectangle:public C2dObject{ private: int m_nLength, m_nWidth; public: CRectangle(); ~CRectangle(); void SetDimensions(int nLength, int nWidth); The program needs to display polymorphic behavior when calls are made to

• calculate the area of an object

• output the details of an object to the screen

Step 3 of 3

For a polymorphic implementation, which of the following declarations do you think you should use to complete CRectangle's public interface?

Options:

1. void CalcArea(void);

2. virtual void CalcArea(void)=0;

3. void PrintDetails(void);

4. void PrintDetails();

Result

You use the declarations void CalcArea(void); and void PrintDetails(void);

You include declarations for base-class virtual member functions CalcArea() and PrintDetails() in the public portion of derived class CRectangle.

// CRectangle class CRectangle:public C2dObject{ private: int m_nLength, m_nWidth; public:

L & T Infotech Page 80 of 87

Page 81: Oops index

OOPS Concepts using C++ Program Using Polymorphism

CRectangle(); ~CRectangle(); void SetDimensions(int nLength, int nWidth); void CalcArea(void); void PrintDetails(void); Finally, you add the closing tag – }; – to complete the definition of derived class Crectangle. // CRectangle class CRectangle:public C2dObject{ private: int m_nLength, m_nWidth; public: CRectangle(); ~CRectangle(); void SetDimensions(int nLength, int nWidth); void CalcArea(void); void PrintDetails(void); };

Task 4: Defining a rectangle object Assume that the definitions for CRectangle's constructor and destructor functions have both been completed. // CRectangle CRectangle::CRectangle() { m_nLength = m_nWidth = 0; } CRectangle::~CRectangle() { }

Step 1 of 2

What statement do you think you would include in the definition of CRectangle::SetDimensions() to set the value for the length of an object?

// CRectangle CRectangle::CRectangle() { m_nLength = m_nWidth = 0; } CRectangle::~CRectangle() { } void CRectangle::SetDimensions(int nLength, int nWidth) { MISSING CODE ;

L & T Infotech Page 81 of 87

Page 82: Oops index

OOPS Concepts using C++ Program Using Polymorphism

Result

The statement that sets the value for the length is m_nLength=nLength;

Step 2 of 2

See if you can complete the definition CRectangle::CalcArea()

// CRectangle CRectangle::CRectangle() { m_nLength = m_nWidth = 0; } CRectangle::~CRectangle() { } void CRectangle::SetDimensions(int nLength, int nWidth) { m_nLength=nLength; m_nWidth=nWidth; } void CRectangle::CalcArea(void) { MISSING CODE }

Result

The code to complete the definition is m_fArea=m_nLength*m_nWidth;

You define CRectangle::PrintDetails() to output the dimensions of a rectangle object using a statement similar to this.

You can simply make a call to the base-class version of PrintDetails() to output the value calculated for the area of the rectangle object.

You have now completed the implementation of derived class CRectangle and its member functions.

// CRectangle CRectangle::CRectangle() { m_nLength = m_nWidth = 0; } CRectangle::~CRectangle() { } void CRectangle::SetDimensions(int nLength, int nWidth) { m_nLength=nLength; m_nWidth=nWidth; } void CRectangle::CalcArea(void) { m_fArea=m_nLength*m_nWidth;

L & T Infotech Page 82 of 87

Page 83: Oops index

OOPS Concepts using C++ Program Using Polymorphism

} void CRectangle::PrintDetails(void) { cout << "Rectangle of length "<< m_nLength << "\n"; cout << "and width " << m_nWidth << "\n"; C2dObject::PrintDetails(); } You implement derived class CCircle in a similar way to CRectangle. } // CCircle CCircle::CCircle() { m_nRadius = 0; } CCircle::~CCircle() { } void CCircle::SetRadius(int nRadius) { m_nRadius = nRadius } void CCircle::CalcArea(void) { m_fArea = 3.14 * m_nRadius * m_nRadius; } void CCircle::PrintDetails(void) { cout << "Circle of radius " << m_nRadius << "\n"; C2dObject::PrintDetails(); }

Task 5: Handling a rectangle object You are now ready to code a simple program for this application. // main function void main(void) {

Step 1 of 5

See if you can enter a statement declaring p2dObject as a base-class pointer.

// main function void main(void) { MISSING CODE

Result

The code to declare p2dObject as a base-class pointer is C2dObject*p2dObject. The base-class pointer is required for polymorphic operation.

L & T Infotech Page 83 of 87

Page 84: Oops index

OOPS Concepts using C++ Program Using Polymorphism

Step 2 of 5

See if you can complete the statement that creates a rectangle object and assigns its address to the base-class pointer.

// main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=MISSING CODE

Result

The code used to complete the statement is newCRectangle().

To set the length and width of the newly created rectangle object, you need to call CRectangle::SetDimensions().

Step 3 of 5

See if you can complete the function call to CRectangle::SetDimensions() using the base-class pointer.

// main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=newCRectangle(); ( MISSING CODE)>SetDimensions(4, 2)

Result

The code to complete the function call is (CRectangle*)p2dObject

Step 4 of 5

See if you can enter a statement to calculate the area of the newly created rectangle object.

// main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=newCRectangle();

L & T Infotech Page 84 of 87

Page 85: Oops index

OOPS Concepts using C++ Program Using Polymorphism

((CRectangle*)p2dObject)->SetDimensions(4, 2); MISSING CODE

Result

The statement to calculate the area of the newly created rectangle is the generic function call p2dObject->CalcArea.

You can use another generic call to output the details of the rectangle object.

// main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=newCRectangle(); ((CRectangle*)p2dObject)->SetDimensions(4, 2); p2dObject->CalcArea(); p2dObject->PrintDetails();

Step 5 of 5

See if you can enter a statement to destroy the object created.

// main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=newCRectangle(); ((CRectangle*)p2dObject)->SetDimensions(4, 2); p2dObject->CalcArea(); p2dObject->PrintDetails(); MISSING CODE

Result

To destroy the object you use the code delete p2dObject.

Task 6: Handling a circle object You now want to create a circle. // main function void main(void) { C2dObject*p2dObject;

L & T Infotech Page 85 of 87

Page 86: Oops index

OOPS Concepts using C++ Program Using Polymorphism

// create a rectangle p2dObject=newCRectangle(); ((CRectangle*)p2dObject)->SetDimensions(4, 2); p2dObject->CalcArea(); p2dObject->PrintDetails(); delete p2dObject; // create a circle

Step 1 of 1

See if you can complete the assignment statement that creates a new circle object and assigns its address to base-class pointer p2dObject.

// main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=newCRectangle(); ((CRectangle*)p2dObject)->SetDimensions(4, 2); p2dObject->CalcArea(); p2dObject->PrintDetails(); delete p2dObject; // create a circle p2dObject=MISSING CODE

Result

The code to complete the assignment statement is newCCircle();.

You can set the radius of the circle to 3 with this statement.

// main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=newCRectangle(); ((CRectangle*)p2dObject)->SetDimensions(4, 2); p2dObject->CalcArea(); p2dObject->PrintDetails(); delete p2dObject; // create a circle

L & T Infotech Page 86 of 87

Page 87: Oops index

OOPS Concepts using C++ Program Using Polymorphism

p2dObject=newCCircle(); ((CCircle*)p2dObject)->SetRadius(3); The remainder of the program is a repetition of the code used to handle a rectangle object. This completes the program. // main function void main(void) { C2dObject*p2dObject; // create a rectangle p2dObject=newCRectangle(); ((CRectangle*)p2dObject)->SetDimensions(4, 2); p2dObject->CalcArea(); p2dObject->PrintDetails(); delete p2dObject; // create a circle p2dObject=newCCircle(); ((CCircle*)p2dObject)->SetRadius(3); p2dObject->CalcArea(); p2dObject->PrintDetails(); delete p2dObject; } When the program is compiled and run, it produces this output.

L & T Infotech Page 87 of 87