1. Trang chủ
  2. » Công Nghệ Thông Tin

Absolute C++ (4th Edition) part 16 pptx

10 303 1
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 207,14 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Whenever you give two or more definitions to the same function name, the various function definitions must have different specifications for their arguments; that is, any two function de

Trang 1

Now suppose your program also requires a function to compute the average of three numbers You might define a new function called ave3 as follows:

double ave3( double n1, double n2, double n3) {

return ((n1 + n2 + n3)/3.0);

}

This will work, and in many programming languages you have no choice but to do something like this However, C++ overloading allows for a more elegant solution In C++ you can simply use the same function name ave for both functions In C++ you can use the following function definition in place of the function definition ave3: double ave( double n1, double n2, double n3)

{ return ((n1 + n2 + n3)/3.0);

}

so that the function name ave then has two definitions This is an example of overload-ing In this case we have overloaded the function name ave Display 4.6 embeds these two function definitions for ave into a complete sample program Be sure to notice that each function definition has its own declaration (prototype)

The compiler can tell which function definition to use by checking the number and types of the arguments in a function call In the program in Display 4.6, one of the functions called ave has two arguments and the other has three arguments When there are two arguments in a function call, the first definition applies When there are three arguments in a function call, the second definition applies

Whenever you give two or more definitions to the same function name, the various function definitions must have different specifications for their arguments; that is, any two function definitions that have the same function name must use different numbers

of formal parameters or have one or more parameters of different types (or both) Notice that when you overload a function name, the declarations for the two different

definitions must differ in their formal parameters You cannot overload a function name

by giving two definitions that differ only in the type of the value returned Nor can you

O VERLOADING A F UNCTION N AME

If you have two or more function definitions for the same function name, that is called overload-ing. When you overload a function name, the function definitions must have different numbers of formal parameters or some formal parameters of different types When there is a function call, the compiler uses the function definition whose number of formal parameters and types of formal parameters match the arguments in the function call.

determining

which

definition

applies

Trang 2

overload based on any difference other than the number or types of parameters You cannot overload based solely on const or solely on call-by-value versus call-by-reference parameters.1

1Some compilers will, in fact, allow you to overload on the basis of const versus no const, but you should not count on this The C++ standard says it is not allowed

Display 4.6 Overloading a Function Name

1 //Illustrates overloading the function name ave.

2 #include <iostream>

3 using namespace std;

4 double ave( double n1, double n2);

5 //Returns the average of the two numbers n1 and n2.

6

7 double ave( double n1, double n2, double n3);

8 //Returns the average of the three numbers n1, n2, and n3.

9 int main( )

10 {

11 cout << "The average of 2.0, 2.5, and 3.0 is "

12 << ave(2.0, 2.5, 3.0) << endl;

13 cout << "The average of 4.5 and 5.5 is "

14 << ave(4.5, 5.5) << endl;

15 return 0;

16 }

17 double ave( double n1, double n2)

18 {

19 return ((n1 + n2)/2.0);

20 }

21 double ave( double n1, double n2, double n3)

22 {

23 return ((n1 + n2 + n3)/3.0);

24 }

S AMPLE D IALOGUE

The average of 2.0, 2.5, and 3.0 is 2.5

The average of 4.5 and 5.5 is 5.0

Two arguments

Three arguments

Trang 3

You already saw a kind of overloading in Chapter 1 (reviewed here) with the division operator, / If both operands are of type int, as in 13/2, then the value returned is the result of integer division, in this case, 6 On the other hand, if one or both operands are

of type double, then the value returned is the result of regular division; for example,

13/2.0 returns the value 6.5 There are two definitions for the division operator, /, and the two definitions are distinguished not by having different numbers of operands but rather by requiring operands of different types The only difference between overload-ing of / and overloading function names is that the C++ language designers have already done the overloading of /, whereas you must program the overloading of your function names yourself Chapter 8 discusses how to overload operators such as +, -, and so on

A UTOMATIC T YPE C ONVERSION AND O VERLOADING

Suppose that the following function definition occurs in your program and that you have not overloaded the function name mpg (so this is the only definition of a function called mpg).

double mpg( double miles, double gallons)

//Returns miles per gallon.

{ return (miles/gallons);

}

If you call the function mpg with arguments of type int, then C++ will automatically convert any argument of type int to a value of type double Hence, the following will output 22.5 miles per gallon to the screen:

cout << mpg(45, 2) << " miles per gallon";

C++ converts the 45 to 45.0 and the 2 to 2.0 and then performs the division 45.0/2.0 to obtain the value returned, which is 22.5.

If a function requires an argument of type double and you give it an argument of type int, C++ will automatically convert the int argument to a value of type double This is so useful and nat-ural that we hardly give it a thought However, overloading can interfere with this automatic type conversion Let’s look at an example.

S IGNATURE

A function’s ssssiiiig gnn g n naaa attttuu u urrrreeee is the function’s name with the sequence of types in the parameter list, not including the const keyword and not including the ampersand, & When you overload a func-tion name, the two definifunc-tions of the funcfunc-tion name must have different signatures using this def-inition of signature (Some authorities include the const and/or ampersand as part of the signature, but we wanted a definition that works for explaining overloading.)

interaction of

overloading

and type

conversion

Trang 4

Self-Test Exercises

Suppose you had (foolishly) overloaded the function name mpg so that your program contained the following definition of mpg as well as the one previous:

int mpg( int goals, int misses)

//Returns the Measure of Perfect Goals //which is computed as (goals - misses).

{ return (goals - misses);

}

In a program that contains both of these definitions for the function name mpg, the following will (unfortunately) output 43 miles per gallon (since 43 is 45 - 2):

cout << mpg(45, 2) << " miles per gallon";

When C++ sees the function call mpg(45, 2), which has two arguments of type int, C++ first looks for a function definition of mpg that has two formal parameters of type int If it finds such

a function definition, C++ uses that function definition C++ does not convert an int argument to

a value of type double unless that is the only way it can find a matching function definition The mpg example illustrates one more point about overloading: You should not use the same function name for two unrelated functions Such careless use of function names is certain to even-tually produce confusion.

8 Suppose you have two function definitions with the following declarations:

double score( double time, double distance);

int score( double points);

Which function definition would be used in the following function call and why would it

be the one used? (x is of type double.) double finalScore = score(x);

9 Suppose you have two function definitions with the following declarations:

double theAnswer( double data1, double data2);

double theAnswer( double time, int count);

Which function definition would be used in the following function call and why would it

be the one used? (x and y are of type double.)

x = theAnswer(y, 6.0);

Trang 5

RULES FOR RESOLVING OVERLOADING

If you use overloading to produce two definitions of the same function name with sim-ilar (but not identical) parameter lists, then the interaction of overloading and auto-matic type conversion can be confusing The rules that the compiler uses for resolving which of multiple overloaded definitions of a function name to apply to a given func-tion call are as follows:

1 Exact match: If the number and types of arguments exactly match a definition

(with-out any automatic type conversion), then that is the definition used

2 Match using automatic type conversion: If there is no exact match but there is a match

using automatic type conversion, then that match is used

If two matches are found at stage 1 or if no matches are found at stage 1 and two matches are found at stage 2, then there is an ambiguous situation and an error message will be issued

For example, the following overloading is dubious style, but is perfectly valid: void f( int n, double m);

void f( double n, int m);

However, if you also have the invocation

f(98, 99);

then the compiler does not know which of the two int arguments to convert to a value

of type double, and an error message is generated

To see how confusing and dangerous the situation can be, suppose you add the fol-lowing third overloading:

void f( int n, int m);

With this third overloading added, you no longer get an error message, since there is now an exact match Obviously, such confusing overloading is to be avoided

The above two rules will work in almost all situations In fact, if you need more pre-cise rules, you should rewrite your code to be more straightforward However, the exact rules are even a bit more complicated For reference value, we give the exact rules below Some of the terms may not make sense until you read more of this book, but do not be concerned The simple two rules given above will serve you well until you do understand the more complete rules

1 Exact match as described earlier

2 Matches using promotion within integer types or within floating-point types, such

as short to int or float to double (Note that bool-to-int and char-to-int conver-sions are considered promotions within integer types.)

3 Matches using other conversions of predefined types, such as int to double

4 Matches using conversions of user-defined types (see Chapter 8)

Trang 6

5 Matches using ellipses (This is not covered in this book, and if you do not use it,

it will not be an issue.)

If two matches are found at the first stage that a match is found, then there is an ambig-uous situation and an error message will be issued

R EVISED P IZZA -B UYING P ROGRAM

The Pizza Consumers Union has been very successful with the program that we wrote for it in Dis-play 4.5 In fact, now everybody always buys the pizza that is the best buy One disreputable pizza parlor used to make money by fooling consumers into buying the more expensive pizza, but our program has put an end to its evil practices However, the owners wish to continue their des-picable behavior and have come up with a new way to fool consumers They now offer both round pizzas and rectangular pizzas They know that the program we wrote cannot deal with rectangu-larly shaped pizzas, so they hope they can again confuse consumers Display 4.7 is another ver-sion of our program that compares a round pizza and a rectangular pizza Note that the function name unitPrice has been overloaded so that it applies to both round and rectangular pizzas

Display 4.7 Revised Pizza Program (part 1 of 3)

1 //Determines whether a round pizza or a rectangular pizza is the best buy.

2 #include <iostream>

3 using namespace std;

4 double unitPrice( int diameter, double price);

5 //Returns the price per square inch of a round pizza.

6 //The formal parameter named diameter is the diameter of the pizza

7 //in inches The formal parameter named price is the price of the pizza.

8 double unitPrice( int length, int width, double price);

9 //Returns the price per square inch of a rectangular pizza

10 //with dimensions length by width inches.

11 //The formal parameter price is the price of the pizza.

12 int main( )

13 {

14 int diameter, length, width;

15 double priceRound, unitPriceRound,

16 priceRectangular, unitPriceRectangular;

17 cout << "Welcome to the Pizza Consumers Union.\n";

18 cout << "Enter the diameter in inches"

19 << " of a round pizza: ";

20 cin >> diameter;

21 cout << "Enter the price of a round pizza: $";

Trang 7

Display 4.7 Revised Pizza Program (part 2 of 3)

22 cin >> priceRound;

23 cout << "Enter length and width in inches\n"

24 << "of a rectangular pizza: ";

25 cin >> length >> width;

26 cout << "Enter the price of a rectangular pizza: $";

27 cin >> priceRectangular;

28 unitPriceRectangular =

29 unitPrice(length, width, priceRectangular);

30 unitPriceRound = unitPrice(diameter, priceRound);

31 cout.setf(ios::fixed);

32 cout.setf(ios::showpoint);

33 cout.precision(2);

34 cout << endl

35 << "Round pizza: Diameter = "

36 << diameter << " inches\n"

37 << "Price = $" << priceRound

38 << " Per square inch = $" << unitPriceRound

39 << endl

40 << "Rectangular pizza: Length = "

41 << length << " inches\n"

42 << "Rectangular pizza: Width = "

43 << width << " inches\n"

44 << "Price = $" << priceRectangular

45 << " Per square inch = $" << unitPriceRectangular

46 << endl;

47 if (unitPriceRound < unitPriceRectangular)

48 cout << "The round one is the better buy.\n";

49 else

50 cout << "The rectangular one is the better buy.\n";

51 cout << "Buon Appetito!\n";

52 return 0;

53 }

54 double unitPrice( int diameter, double price)

55 {

56 const double PI = 3.14159;

57 double radius, area;

58

59 radius = diameter/double(2);

60 area = PI * radius * radius;

61 return (price/area);

62 }

Trang 8

DEFAULT ARGUMENTS

You can specify a default argument for one or more call-by-value parameters in a

func-tion If the corresponding argument is omitted, then it is replaced by the default argu-ment For example, the function volume in Display 4.8 computes the volume of a box from its length, width, and height If no height is given, the height is assumed to be 1

If neither a width nor a height is given, they are both assumed to be 1 Note that in Display 4.8 the default arguments are given in the function declaration but not in the function definition A default argument is given the first time the func-tion is declared (or defined, if that occurs first) Subsequent declarafunc-tions or a following definition should not give the default arguments again because some compilers will consider this an error even if the arguments given are consistent with the ones given previously

You may have more than one default argument, but all the default argument posi-tions must be in the rightmost posiposi-tions Thus, for the function volume in Display 4.8,

we could have given default arguments for the last one, last two, or all three parameters, but any other combinations of default arguments are not allowed

Display 4.7 Revised Pizza Program (part 3 of 3)

63 double unitPrice( int length, int width, double price)

64 {

65 double area = length * width;

66 return (price/area);

67 }

S AMPLE D IALOGUE

Welcome to the Pizza Consumers Union.

Enter the diameter in inches of a round pizza: 10

Enter the price of a round pizza: $8.50

Enter length and width in inches

of a rectangular pizza: 6 4

Enter the price of a rectangular pizza: $7.55

Round pizza: Diameter = 10 inches

Price = $8.50 Per square inch = $0.11

Rectangular pizza: Length = 6 inches

Rectangular pizza: Width = 4 inches

Price = $7.55 Per square inch = $0.31

The round one is the better buy.

Buon Appetito!

default argument

Trang 9

If you have more than one default argument, then when the function is invoked, you must omit arguments starting from the right For example, note that in Display 4.8 there are two default arguments When only one argument is omitted, it is assumed

to be the last argument There is no way to omit the second argument in an invocation

of volume without also omitting the third argument

Display 4.8 Default Arguments

1

2 #include <iostream>

3 using namespace std;

4 void showVolume( int length, int width = 1, int height = 1);

5 //Returns the volume of a box

6 //If no height is given, the height is assumed to be 1.

7 //If neither height nor width is given, both are assumed to be 1.

8 int main( )

9 {

10 showVolume(4, 6, 2);

11 showVolume(4, 6);

12 showVolume(4);

13 return 0;

14 }

15 void showVolume( int length, int width, int height)

16 {

17 cout << "Volume of a box with \n"

18 << "Length = " << length << ", Width = " << width << endl

19 << "and Height = " << height

20 << " is " << length*width*height << endl;

21 }

S AMPLE D IALOGUE \

Volume of a box with

Length = 4, Width = 6

and Height = 2 is 48

Volume of a box with

Length = 4, Width = 6

and Height = 1 is 24

Volume of a box with

Length = 4, Width = 1

and Height = 1 is 4

Default arguments

A default argument should not

be given a second time.

Trang 10

Self-Test Exercises

Default arguments are of limited value, but sometimes they can be used to reflect your way of thinking about arguments Default arguments can only be used with call-by-value parameters They do not make sense for call-by-reference parameters Any-thing you can do with default arguments can be done using overloading, although the default argument version will probably be shorter than the overloading version

10 This question has to do with the programming example entitled Revised Pizza-Buying

Program Suppose the evil pizza parlor that is always trying to fool customers introduces a

square pizza Can you overload the function unitPrice so that it can compute the price per square inch of a square pizza as well as the price per square inch of a round pizza? Why

or why not?

Testing and Debugging Functions

I beheld the wretch—the miserable monster whom I had created.

Mary Wollstonecraft Shelley, Frankenstein

This section reviews some general guidelines for testing programs and functions

THE assert MACRO

An assertion is a statement that is either true or false Assertions are used to document

and check the correctness of programs Preconditions and postconditions, which we discussed in Chapter 3, are examples of assertions When expressed precisely and in the syntax of C++, an assertion is simply a Boolean expression If you convert an assertion

to a Boolean expression, then the predefined macro assert can be used to check

whether or not your code satisfies the assertion (A macro is very similar to an inline

function and is used just like a function is used.) The assert macro is used like a void function that takes one call-by-value parame-ter of type bool Since an assertion is just a Boolean expression, this means that the argument to assert is an assertion When the assert macro is invoked, its assertion argument is evaluated If it evaluates to true, then nothing happens If the argument evaluates to false, then the program ends and an error message is issued Thus, calls to the assert macro are a compact way to include error checks within your program

For example, the following function declaration is taken from Programming Project 3:

void computeCoin( int coinValue, int & number, int & amountLeft);

//Precondition: 0 < coinValue < 100; 0 <= amountLeft < 100.

//Postcondition: number has been set equal to the maximum number

4.3

assertion

macro

Ngày đăng: 04/07/2014, 05:21

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN