Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lafore_robert_objectoriented_programming_in_c

.pdf
Скачиваний:
51
Добавлен:
27.03.2023
Размер:
8.94 Mб
Скачать

Multifile Programs

675

4.Is there is a down floor request on this floor, and we are going down, load the passengers.

5.If there are no destinations or requests above or below, stop.

6.If there are destinations above us, go up.

7.If there are destinations below us, go down.

8.If we’re stopped or going up, and there is a floor request above us, and there are no other cars going up between us and the request, or above it and going down and closer than we are, go up.

9.If we’re stopped or going down, and there is a floor request below us, and there are no other cars going down between us and the request, or below it and going up and closer than we are, go down.

10.If no other rules apply, stop.

Rules 8 and 9 are rather complicated. They attempt to keep two or more cars from rushing to answer the same floor request. However, the results are not perfect. In some situations cars are slow to answer requests because they are afraid another car is on its way, when in fact the other car is answering a different floor request. The program’s strategy could be improved by allowing the decide() function to distinguish between up and down requests when it checks whether there are requests above or below the current car. However, this would further complicate decide(), which is already long enough. We’ll leave such refinements to you.

State Diagram for the ELEV Program

We introduced UML state diagrams in Chapter 10, “Pointers.” Now let’s look at a state diagram for an elevator object. To simplify things a little, we’ll assume that there is only one person in the building and only one elevator in use. Thus there can be only one floor request at a time, and only one destination selected by the rider. The elevator car doesn’t need to worry about what the other cars are doing. Figure 13.6 shows how this looks.

In the diagram, “cd” stands for car destination, the button pushed inside the car, roughly corresponding to a value in the destination array in the program. Also, “fr” stands for floor request, the button pushed outside the car, corresponding to the floor_req variable.

The states are derived from the values of the current_dir variable plus the status of the car’s loading_timer and unloading_timer. Because all the transitions are the result of time ticks, only the guard conditions are shown. The guards represent what the car finds out about floor requests and car destinations.

13

PROGRAMS MULTIFILE

Chapter 13

676

 

[ !(fr here || cd here) ]

 

Going

 

 

up

 

[ fr above ||

[fr here ||

[cd above]

cd here]

 

cd above ]

 

 

 

 

[ no fr && no cd ]

 

Unloading

Loading

Getting

Stopped

cd

Clear cd

Clear fr

 

[cd here]

[fr here]

 

[ fr below ||

[fr here ||

 

cd here]

 

cd below ]

[cd below]

 

Going down

[ !(fr here || cd here) ]

FIGURE 13.6

State diagram of an elevator object.

Summary

Vendor-provided object libraries are often distributed as a public component (the interface) containing class declarations in an .H header file, and a private component (the implementation) containing member function definitions in an .OBJ object file or .LIB library file.

C++ compilers allow you to combine several source or object files into a single executable file. This permits files provided by one vendor to be combined with files from another, to create a final application. The project feature simplifies keeping track of what files need to be compiled. It compiles any source file that has been modified since the last linking, and links the resulting object files.

Inter-file communication requires that variables, functions and class objects be defined in one file and declared in any other file where they’re used. A class definition must be placed in every file where objects are instantiated. Care must be taken with both source files and header files to ensure that multiple definitions don’t occur.

Multifile Programs

677

Questions

Answers to these questions can be found in Appendix G.

1.Breaking a program into several files is desirable because

a.some files don’t need to be recompiled each time.

b.a program can be divided functionally.

c.files can be marketed in object form.

d.different programmers can work on a different files.

2.An .H file is associated with a .CPP file using the ________.

3.An .OBJ file is attached to a .CPP file using ________.

4.A project file contains

a.the contents of the files in the project.

b.the dates of the files in the project.

c.instructions for compiling and linking.

d.definitions for C++ variables.

5.A group of related classes, supplied as a separate product, is often called a ________.

6.True or false: A header file may need to be accessed by more than one source file in a project.

7.The so-called private files of a class library

a.require a password.

b.can be accessed by friend functions.

c.help prevent code from being pirated.

d.may consist only of object code.

8.True or false: Class libraries can be more powerful than function libraries.

9.True or false: the interface is private and the implementation is public.

10.The public part of a class library usually contains

a.member function declarations.

b.member function definitions.

c.class declarations.

d.definitions of inline functions.

11.Two or more source files can be combined by ____________ them.

13

PROGRAMS MULTIFILE

Chapter 13

678

12.True or false: a variable defined within a function body can be seen thoughout the file in which it’s defined.

13.A global variable is defined in file A. To access the variable in file B, you must

a.define it in file B using the keyword extern.

b.define it in file B using the keyword static.

c.no other action is necessary (do nothing).

d.declare it in file B using the keyword extern.

14.The region in a program where a variable can be accessed by variables in other parts of the program is called its __________.

15.The files that are actually combined by the linker are called _________ files.

16.A function is defined in file A. To call it from file B, the function must first be

__________ in ________ .

17.True or false: a function declaration does not require the keyword extern.

18.To define class objects in different files, in each file you must

a.declare the class.

b.define the class.

c.declare the class using extern.

d.define the class using extern.

19.True or false: a variable defined in a header file can be accessed from two source files if they both include the header file.

20.The #if !defined()...#endif construction can be used to prevent multiple definitions when

a.Two header files are included in a source file.

b.A header file is included in two source files.

c.Two header files are included in two source files.

d.A header file is included in another header file and both are included in a source file.

21.You use namespaces to

a.Automate the naming of variables.

b.Restrict the area where program elements are visible.

c.Divide a program into separate files.

d.Prevent the use of long variable names.

Multifile Programs

679

22.To define a namespace you use a format similar to a class definition, but substitute the keyword ________ for class.

23.Using typedef allows you to

a.shorten long variable names.

b.substitute one type name for another.

c.shorten long function names.

d.substitute one class name for another.

Projects

Unfortunately, we don’t have room in this book for exercises that involve the kind of larger programs discussed in this chapter. However, here are some suggestions for projects you may wish to pursue on your own.

1.Create member functions to perform subtraction and division for the verylong class in the VERYLONG example. These should overload the - and / operators. Warning: There’s some work involved here. When you include subtraction, you must assume that any

verylong can be negative as well as positive. This complicates the addition and multiplication routines, which must do different things depending on the signs of the numbers.

To see one way to perform division, do a long-division example by hand and write down every step. Then incorporate these steps into a division member function. You’ll find that you need some comparisons, so you’ll need to write a comparison routine, among other things.

2.Rewrite the ELEV program so that it handles only one elevator. This will simplify things a great deal. Remove those parts of the program that aren’t necessary. Or you can assume there is only one elevator and also only one rider, as is done in the state diagram.

3.Modify the ELEV program to be more efficient in the way it handles requests. As an example of its current non-optimal behavior, start the program and make a down request on floor 20. Then make a down request on floor 10. Car 1 will immediately head up to 20, but car 2, which should head up to 10, waits until car 1 has passed 10 before starting. Modify decide() so this doesn’t happen.

4.Create a class library that models something you’re interested in. Create a main() or “client” program to test it. Market your class library and become rich and famous.

13

PROGRAMS MULTIFILE

Templates and Exceptions

CHAPT E R

14

IN THIS CHAPTER

• Function Templates 682

• Class Templates 690

• Exceptions 703

Chapter 14

682

This chapter introduces two advanced C++ features: templates and exceptions. Templates make it possible to use one function or class to handle many different data types. Exceptions provide a convenient, uniform way to handle errors that occur within classes. These features are combined in a single chapter largely for historical reasons: they became part of C++ at the same time. They were not part of the original specification for C++, but were introduced as “Experimental” topics in Ellis and Stroustrup (1990, see Appendix H, “Bibliography”). Subsequently they were incorporated into Standard C++.

The template concept can be used in two different ways: with functions and with classes. We’ll look at function templates first, then go on to class templates, and finally to exceptions.

Function Templates

Suppose you want to write a function that returns the absolute value of two numbers. As you no doubt remember from high school algebra, the absolute value of a number is its value without regard to its sign: The absolute value of 3 is 3, and the absolute value of –3 is also 3. Ordinarily this function would be written for a particular data type:

int abs(int n)

//absolute value of ints

{

 

return (n<0) ? -n : n;

//if n is negative, return -n

}

 

Here the function is defined to take an argument of type int and to return a value of this same type. But now suppose you want to find the absolute value of a type long. You will need to write a completely new function:

long abs(long n)

//absolute value of longs

{

 

return (n<0) ? -n : n;

 

}

 

And again, for type float:

float abs(float

n)

//absolute value of floats

{

 

 

return (n<0)

? -n : n;

 

}

 

 

The body of the function is written the same way in each case, but they are completely different functions because they handle arguments and return values of different types. It’s true that in C++ these functions can all be overloaded to have the same name, but you must nevertheless

Templates and Exceptions

683

write a separate definition for each one. (In the C language, which does not support overloading, functions for different types can’t even have the same name. In the C function library this leads to families of similarly named functions, such as abs(), fabs(), fabsl(), labs(), and cabs().

Rewriting the same function body over and over for different types is time-consuming and wastes space in the listing. Also, if you find you’ve made an error in one such function, you’ll need to remember to correct it in each function body. Failing to do this correctly is a good way to introduce inconsistencies into your program.

It would be nice if there were a way to write such a function just once, and have it work for many different data types. This is exactly what function templates do for you. The idea is shown schematically in Figure 14.1.

 

template <class T>

One function template in

 

T func(T arg)

listing (source file)

 

{

 

 

 

. . .

Argument type determines

 

}

 

 

 

function instantiation

 

 

 

 

i1 = func(i2);

c1 = func(c2); f1 = func(f2);

int func(int arg)

char func(char arg)

float func(float arg)

{

{

 

{

. . .

. . .

. . .

}

}

 

}

Many template functions in memory

FIGURE 14.1

14

AND T

E EMPLATES

XCEPTIONS

A function template.

Chapter 14

684

A Simple Function Template

Our first example shows how to write our absolute-value function as a template, so that it will work with any basic numerical type. This program defines a template version of abs() and then, in main(), invokes this function with different data types to prove that it works. Here’s the listing for TEMPABS:

//tempabs.cpp

//template used for absolute value function #include <iostream>

using namespace std; //--------------------------------------------------------------

template <class

T>

//function template

T abs(T n)

 

 

 

{

 

 

 

return

(n <

0)

? -n : n;

}

 

 

 

//--------------------------------------------------------------

 

 

 

int main()

 

 

 

{

 

 

 

int int1 = 5;

 

int int2 = -6;

 

long lon1 =

70000L;

long lon2 =

-80000L;

double

dub1

= 9.95;

double

dub2

= -10.15;

//calls instantiate functions cout << “\nabs(“ << int1 << “)=” << abs(int1); //abs(int) cout << “\nabs(“ << int2 << “)=” << abs(int2); //abs(int) cout << “\nabs(“ << lon1 << “)=” << abs(lon1); //abs(long) cout << “\nabs(“ << lon2 << “)=” << abs(lon2); //abs(long)

cout << “\nabs(“ << dub1 << “)=” << abs(dub1); //abs(double) cout << “\nabs(“ << dub2 << “)=” << abs(dub2); //abs(double) cout << endl;

return 0;

}

Here’s the output of the program:

abs(5)=5 abs(-6)=6 abs(70000)=70000 abs(-80000)=80000 abs(9.95)=9.95 abs(-10.15)=10.15