132 Function Basics 6. Write a function that computes the average and standard deviation of four scores. The stan- dard deviation is defined to be the square root of the average of the four values: ( s i - a) 2 , where a is the average of the four scores s 1 , s 2 , s 3 , and s 4 . The function will have six parameters and will call two other functions. Embed the function in a program that allows you to test the function again and again until you tell the program you are finished. 7. In cold weather, meteorologists report an index called the wind chill factor, which takes into account the wind speed and the temperature. The index provides a measure of the chilling effect of wind at a given air temperature. Wind chill may be approximated by the following formula: where v = wind speed in m/sec t = temperature in degrees Celsius: t <= 10 W = wind chill index (in degrees Celsius) Write a function that returns the wind chill index. Your code should ensure that the restric- tion on the temperature is not violated. Look up some weather reports in back issues of a newspaper in your library and compare the wind chill index you calculate with the result reported in the newspaper. W 13.12 0.6215 ∗ t 11.37 ∗ v 0.16 – 0.3965 ∗ t ∗ v 0.016 ++= 4 Parameters and Overloading 4.1 PARAMETERS 134 Call-by-Value Parameters 134 A First Look at Call-by-Reference Parameters 137 Call-by-Reference Mechanism in Detail 139 Example: The swapValues Function 141 Constant Reference Parameters 142 Tip: Think of Actions, Not Code 143 Mixed Parameter Lists 144 Tip: What Kind of Parameter to Use 145 Pitfall: Inadvertent Local Variables 146 Tip: Choosing Formal Parameter Names 147 Example: Buying Pizza 147 4.2 OVERLOADING AND DEFAULT ARGUMENTS 151 Introduction to Overloading 151 Pitfall: Automatic Type Conversion and Overloading 154 Rules for Resolving Overloading 156 Example: Revised Pizza-Buying Program 157 Default Arguments 159 4.3 TESTING AND DEBUGGING FUNCTIONS 161 The assert Macro 161 Stubs and Drivers 162 CHAPTER SUMMARY 165 ANSWERS TO SELF-TEST EXERCISES 166 PROGRAMMING PROJECTS 168 04_CH04.fm Page 133 Wednesday, August 13, 2003 12:49 PM 4 Parameters and Overloading Just fill in the blanks. Common Instruction INTRODUCTION This chapter discusses the details of the mechanisms used by C++ for plug- ging in arguments for parameters in function calls. It also discusses overload- ing, which is a way to give two (or more) different function definitions to the same function name. Finally, it goes over some basic techniques for testing functions. Parameters You can’t put a square peg in a round hole. Common saying This section describes the details of the mechanisms used by C++ for plugging in an argument for a formal parameter when a function is invoked. There are two basic kinds of parameters and therefore two basic plugging-in mecha- nisms in C++. The two basic kinds of parameters are call-by-value parameters and call-by-reference parameters . All the parameters that appeared before this point in the book were call-by-value parameters. With call-by-value parame- ters , only the value of the argument is plugged in. With call-by-reference parameters , the argument is a variable and the variable itself is plugged in; therefore, the variable’s value can be changed by the function invocation. A call-by-reference parameter is indicated by appending the ampersand sign, & , to the parameter type, as illustrated by the following function declarations: void getInput(double& variableOne, int& variableTwo); A call-by-value parameter is indicated by not using the ampersand. The details on call-by-value and call-by-reference parameters are given in the following subsections. ■ CALL-BY-VALUE PARAMETERS Call-by-value parameters are more than just blanks that are filled in with the argument values for the function. A call-by-value parameter is actually a local variable. When the function is invoked, the value of a call-by-value argument 4.1 call-by- value parameter call-by- reference parameter 04_CH04.fm Page 134 Wednesday, August 13, 2003 12:49 PM Parameters 135 is computed and the corresponding call-by-value parameter, which is a local variable, is initialized to this value. In most cases, you can think of a call-by-value parameter as a kind of blank, or placeholder, that is filled in by the value of its corresponding argument in the function invocation. However, in some cases it is handy to use a call-by-value parameter as a local variable and change the value of the parameter within the body of the function definition. For example, the program in Display 4.1 illustrates a call-by-value parame- ter used as a local variable whose value is changed in the body of the function defini- tion. Notice the formal parameter minutesWorked in the definition of the function fee . It is used as a variable and has its value changed by the following line, which occurs within the function definition: minutesWorked = hoursWorked*60 + minutesWorked; Display 4.1 Formal Parameter Used as a Local Variable (part 1 of 2) 1 //Law office billing program. 2 #include <iostream> 3 using namespace std; 4 const double RATE = 150.00; //Dollars per quarter hour. 5 double fee(int hoursWorked, int minutesWorked); 6 //Returns the charges for hoursWorked hours and 7 //minutesWorked minutes of legal services. 8 int main( ) 9 { 10 int hours, minutes; 11 double bill; 12 cout << "Welcome to the law office of\n" 13 << "Dewey, Cheatham, and Howe.\n" 14 << "The law office with a heart.\n" 15 << "Enter the hours and minutes" 16 << " of your consultation:\n"; 17 cin >> hours >> minutes; 18 bill = fee(hours, minutes); 19 cout.setf(ios::fixed); 20 cout.setf(ios::showpoint); 21 cout.precision(2); 22 cout << "For " << hours << " hours and " << minutes 23 << " minutes, your bill is $" << bill << endl; 24 return 0; 25 } The value of minutes is not changed by the call to fee. 04_CH04.fm Page 135 Wednesday, August 13, 2003 12:49 PM 136 Parameters and Overloading Self-Test Exercises Call-by-value parameters are local variables just like the variables you declare within the body of a function. However, you should not add a variable declaration for the for- mal parameters. Listing the formal parameter minutesWorked in the function heading also serves as the variable declaration. The following is the wrong way to start the func- tion definition for fee because it declares minutesWorked twice: 1. Carefully describe the call-by-value parameter mechanism. 2. The following function is supposed to take as arguments a length expressed in feet and inches and to return the total number of inches in that many feet and inches. For example, totalinches(1, 2) is supposed to return 14 , because 1 foot and 2 inches is the same as 14 inches. Will the following function perform correctly? If not, why not? double totalInches(int feet, int inches) { inches = 12*feet + inches; return inches; } D i sp l ay 4.1 Formal Parameter Used as a Local Variable ( part 2 of 2 ) 26 double fee(int hoursWorked, int minutesWorked) 27 { 28 int quarterHours; 29 minutesWorked = hoursWorked*60 + minutesWorked; 30 quarterHours = minutesWorked/15; 31 return (quarterHours*RATE); 32 } S AMPLE D IALOGUE Welcome to the law office of Dewey, Cheatham, and Howe. The law office with a heart. Enter the hours and minutes of your consultation: 5 46 For 5 hours and 46 minutes, your bill is $3450.00 minutesWorked is a local variable initialized to the value of minutes. double fee(int hoursWorked, int minutesWorked) { int quarterHours; int minutesWorked; . . . Do not do this when minutesWorked is a parameter! 04_CH04.fm Page 136 Wednesday, August 13, 2003 12:49 PM Parameters 137 ■ A FIRST LOOK AT CALL-BY-REFERENCE PARAMETERS The call-by-value mechanism that we used until now is not sufficient for all tasks you might want a function to perform. For example, one common task for a function is to obtain an input value from the user and set the value of an argument variable to this input value. With the call-by-value formal parameters that we have used until now, a corresponding argument in a function call can be a variable, but the function takes only the value of the variable and does not change the variable in any way. With a call- by-value formal parameter only the value of the argument is substituted for the formal parameter. For an input function, you want the variable (not the value of the variable) to be substituted for the formal parameter. The call-by-reference mechanism works in just this way. With a call-by-reference formal parameter, the corresponding argument in a function call must be a variable, and this argument variable is substituted for the formal parameter. It is almost as if the argument variable were literally copied into the body of the function definition in place of the formal parameter. After the argument is substituted in, the code in the function body is executed and can change the value of the argument variable. A call-by-reference parameter must be marked in some way so that the compiler will know it from a call-by-value parameter. The way that you indicate a call-by-reference parameter is to attach the ampersand sign , & , to the end of the type name in the for- mal parameter list. This is done in both the function declaration (function prototype) and the header of the function definition. For example, the following function defini- tion has one formal parameter, receiver , which is a call-by-reference parameter: void getInput(double& receiver) { cout << "Enter input number:\n"; cin >> receiver; } In a program that contains this function definition, the following function call will set the double variable inputNumber equal to a value read from the keyboard: getInput(inputNumber); C++ allows you to place the ampersand either with the type name or with the parameter name, so you will sometimes see void getInput(double &receiver); which is equivalent to void getInput(double& receiver); Display 4.2 demonstrates call-by-reference parameters. The program reads in two numbers and writes the same numbers out, but in the reverse order. The parameters in ampersand, & 04_CH04.fm Page 137 Wednesday, August 13, 2003 12:49 PM 138 Parameters and Overloading Display 4.2 Call-by-Reference Parameters (part 1 of 2) 1 //Program to demonstrate call-by-reference parameters. 2 #include <iostream> 3 using namespace std; 4 void getNumbers(int& input1, int& input2); 5 //Reads two integers from the keyboard. 6 void swapValues(int& variable1, int& variable2); 7 //Interchanges the values of variable1 and variable2. 8 void showResults(int output1, int output2); 9 //Shows the values of variable1 and variable2, in that order. 10 int main( ) 11 { 12 int firstNum, secondNum; 13 getNumbers(firstNum, secondNum); 14 swapValues(firstNum, secondNum); 15 showResults(firstNum, secondNum); 16 return 0; 17 } 18 void getNumbers(int& input1, int& input2) 19 { 20 cout << "Enter two integers: "; 21 cin >> input1 22 >> input2; 23 } 24 void swapValues(int& variable1, int& variable2) 25 { 26 int temp; 27 temp = variable1; 28 variable1 = variable2; 29 variable2 = temp; 30 } 31 32 void showResults(int output1, int output2) 33 { 34 cout << "In reverse order the numbers are: " 35 << output1 << " " << output2 << endl; 36 } 04_CH04.fm Page 138 Wednesday, August 13, 2003 12:49 PM Parameters 139 the functions getNumbers and swapValues are call-by-reference parameters. The input is performed by the function call getNumbers(firstNum, secondNum); The values of the variables firstNum and secondNum are set by this function call. After that, the following function call reverses the values in the two variables firstNum and secondNum: swapValues(firstNum, secondNum); The next few subsections describe the call-by-reference mechanism in more detail and also explain the particular functions used in Display 4.2. ■ CALL-BY-REFERENCE MECHANISM IN DETAIL In most situations the call-by-reference mechanism works as if the name of the variable given as the function argument were literally substituted for the call-by-reference for- mal parameter. However, the process is a bit more subtle than that. In some situations, this subtlety is important, so we need to examine more details of this call-by-reference substitution process. C ALL - BY -R EFERENCE P ARAMETERS To make a formal parameter a call-by-reference parameter, append the ampersand sign, &, to its type name. The corresponding argument in a call to the function should then be a variable, not a constant or other expression. When the function is called, the corresponding variable argument (not its value) will be substituted for the formal parameter. Any change made to the formal parameter in the function body will be made to the argument variable when the function is called. The exact details of the substitution mechanisms are given in the text of this chapter. E XAMPLE void getData(int& firstInput, double& secondInput); Display 4.2 Call-by-Reference Parameters (part 2 of 2) S AMPLE D IALOGUE Enter two integers: 5 6 In reverse order the numbers are: 6 5 04_CH04.fm Page 139 Wednesday, August 13, 2003 12:49 PM 140 Parameters and Overloading Program variables are implemented as memory locations. Each memory location has a unique address that is a number. The compiler assigns one memory location to each vari- able. For example, when the program in Display 4.2 is compiled, the variable firstNum might be assigned location 1010, and the variable secondNum might be assigned 1012. For all practical purposes, these memory locations are the variables. For example, consider the following function declaration from Display 4.2: void getNumbers(int& input1, int& input2); The call-by-reference formal parameters input1 and input2 are placeholders for the actual arguments used in a function call. Now consider a function call like the following from the same program: getNumbers(firstNum, secondNum); When the function call is executed, the function is not given the argument names firstNum and secondNum. Instead, it is given a list of the memory locations associated with each name. In this example, the list consists of the locations 1010 1012 which are the locations assigned to the argument variables firstNum and secondNum, in that order. It is these memory locations that are associated with the formal parameters. The first memory location is associated with the first formal parameter, the second memory location is associated with the second formal parameter, and so forth. Dia- grammatically, in this case the correspondence is When the function statements are executed, whatever the function body says to do to a formal parameter is actually done to the variable in the memory location associated with that formal parameter. In this case, the instructions in the body of the function getNumbers say that a value should be stored in the formal parameter input1 using a cin statement, and so that value is stored in the variable in memory location 1010 (which happens to be the variable firstNum). Similarly, the instructions in the body of the function getNumbers say that another value should then be stored in the formal parameter input2 using a cin statement, and so that value is stored in the variable in memory location 1012 (which happens to be the variable secondNum). Thus, whatever the function instructs the computer to do to input1 and input2 is actually done to the variables firstNum and secondNum. It may seem that there is an extra level of detail, or at least an extra level of verbiage. If firstNum is the variable with memory location 1010, why do we insist on saying “the variable at memory location 1010” instead of simply saying “ firstNum”? This extra level of detail is needed if the arguments and formal parameters contain some confusing address firstNum 1010 input1 secondNum 1012 input2 04_CH04.fm Page 140 Wednesday, August 13, 2003 12:49 PM Parameters 141 Example coincidence of names. For example, the function getNumbers has formal parameters named input1 and input2. Suppose you want to change the program in Display 4.2 so that it uses the function getNumbers with arguments that are also named input1 and input2, and suppose that you want to do something less than obvious. Suppose you want the first number typed in to be stored in a variable named input2, and the second number typed in to be stored in the variable named input1—perhaps because the sec- ond number will be processed first or because it is the more important number. Now, let’s suppose that the variables input1 and input2, which are declared in the main part of your program, have been assigned memory locations 1014 and 1016. The function call could be as follows: In this case if you say “ input1,” we do not know whether you mean the variable named input1 that is declared in the main part of your program or the formal parameter input1. However, if the variable input1 declared in the main function of your program is assigned memory location 1014, the phrase “the variable at memory location 1014” is unambiguous. Let’s go over the details of the substitution mechanisms in this case. In this call the argument corresponding to the formal parameter input1 is the vari- able input2, and the argument corresponding to the formal parameter input2 is the variable input1. This can be confusing to us, but it produces no problem at all for the computer, since the computer never does actually “substitute input2 for input1” or “substitute input1 for input2.” The computer simply deals with memory locations. The computer substitutes “the variable at memory location 1016” for the formal parameter input1, and “the variable at memory location 1014” for the formal parame- ter input2. T HE swapValues F UNCTION The function swapValues defined in Display 4.2 interchanges the values stored in two variables. The description of the function is given by the following function declaration and accompanying comment: void swapValues(int& variable1, int& variable2); //Interchanges the values of variable1 and variable2. To see how the function is supposed to work, assume that the variable firstNum has the value 5 and the variable secondNum has the value 6 and consider the following function call: swapValues(firstNum, secondNum); After this function call, the value of firstNum will be 6 and the value of secondNum will be 5. int input1, input2; getNumbers(input2, input1); Notice the order of the arguments. 04_CH04.fm Page 141 Wednesday, August 13, 2003 12:49 PM . Function 141 Constant Reference Parameters 142 Tip: Think of Actions, Not Code 143 Mixed Parameter Lists 144 Tip: What Kind of Parameter to Use 145 Pitfall: Inadvertent Local Variables 146 Tip:. 145 Pitfall: Inadvertent Local Variables 146 Tip: Choosing Formal Parameter Names 147 Example: Buying Pizza 147 4.2 OVERLOADING AND DEFAULT ARGUMENTS 151 Introduction to Overloading 151 Pitfall:. used by C++ for plugging in an argument for a formal parameter when a function is invoked. There are two basic kinds of parameters and therefore two basic plugging-in mecha- nisms in C++. The