Sending Information to a Function


The printMessage function in the Hello World program outputs Hello world! It does not need any further information to do its job.

Let s make the printMessage function more useful so that it does not always output Hello world but instead outputs whatever message we ask it to. Of course, the printMessage function is not a mind reader; we need to tell it the message we want it to output.

Let s try to write a program in which the user enters in main the string to be outputted, that user input is stored in a string variable str, and then the printMessage function attempts to output the value of that str variable. One approach is to make the variable str global so it can be accessed in both the main and printMessage functions:

 #include <iostream> #include <string> using namespace std; void printMessage();  string str; int main () {   cout << "Enter a string: ";  cin >> str;  printMessage();   return 0; } void printMessage () {  cout << "You inputted " << str; } 
Note  

With a string variable, a statement cin >> str does not compile unless you include the <string> standard library. Additionally, the cin object and the stream insertion operator (>>) will only accept the input of a string variable up to the first embedded white space. Therefore, if the input were Jeff Kent, the output still would be only Jeff. In Chapter 10, we will cover the getline function, which will work with string input that has embedded spaces.

Here is some sample input and output:

 Enter a string: Jeff  You inputted Jeff 

While this works, as discussed in the previous section, global variables can make it more difficult to fix problems with your programs. There is a better alternative here, involving passing arguments.

As discussed earlier in this chapter, the parentheses following the function name in the function header contain the function s arguments. Arguments are information that is provided to a function so that it may perform its task.

As also discussed earlier, some functions don t need further information to do their job, such as the printMessage function in the Hello World program, which simply outputs Hello world! It does not need any further information to do its job.

However, when we want to modify the printMessage function so that it does not always output Hello world! but instead outputs whatever message we ask it to, we need to tell it the message we want it to output. We can do so by passing the function an argument that specifies the message.

This chapter will discuss two ways of passing arguments, by value and by reference. A third way, passing arguments by address, will be covered after we discuss pointers in Chapter 11.

Passing Arguments by Value

The following is a modification of the program that uses the printMessage function to output a message. This time, the content of the message to be output is passed to the printMessage function as an argument:

 #include <iostream> #include <string> using namespace std; void printMessage(string);  int main () {  string str;  cout << "Enter a string: ";  cin >> str;  printMessage(str);   return 0; } void printMessage (string s) {  cout << "You inputted " << s; } 

Here is some sample input and output:

 Enter a string: Jeff  You inputted Jeff 

The Function Prototype and Header

Both the function prototype and the function header have one argument, of the string data type. However, the function prototype s argument just has the argument s data type (string), whereas the function header s argument has both a data type and an argument name (string s).

The function prototype may include an argument name as well as data type, as in:

 void printMessage(string someArg); 

However, that argument is called a dummy argument because it serves no purpose.

By contrast, the function header s argument must include an argument name as well as a data type. The purpose of that argument name in the function header s argument is explained next .

Using the Function Argument

The following code calls the printMessage function:

 printMessage(str); 

The string variable str, whose value previously was assigned by user input, is passed as an argument to the printMessage function. The value of str then is passed to the string variable s, which is the argument name in the function header of the printMessage function:

 void printMessage (string s) 

The string variable s then is used in the body of the printMessage function to output the message:

 cout << "You inputted " << s; 

Figure 9-2 shows how the value of the argument of the function call is passed to the argument in the function header and then used in the body of the called function.

click to expand
Figure 9-2: The passing of the function argument

The function header must include an argument name as well as a data type so the value which is being passed by the function call, stored in str in main, may be stored in a variable that can be used in the printMessage function. Otherwise, the value passed would have no place to be stored for use in the printMessage function.

The argument name in the function header can be the same as the name of the variable passed in the function argument:

 printMessage(str); void printMessage (string str) 

Even if so, the str in main is a separate variable from the str in printMessage. Nevertheless, I recommend, to avoid confusion, using different names in the program.

Using Multiple Function Arguments

The program we just discussed used one function argument. However, a function may have two or even more function arguments.

The following modification of the printMessage function uses two arguments, one for the first name and one for the last name:

 #include <iostream> #include <string> using namespace std; void printMessage(string, string);  int main () {  string name1, name2;  cout << "Enter first name: ";  cin >> name1;  cout << "Enter last name: ";  cin >> name2;  printMessage(name1, name2);   return 0; } void printMessage (string firstName, string lastName) {  cout << "Your name is " << firstName << " " << lastName << endl; } 

Here is some sample input and output:

 Enter first name: Jeff  Enter last name: Kent Your name is Jeff Kent 

The order of arguments in the function call must correspond to the order of the arguments in the function header. The function call and the function header here are

 printMessage(first, last); void printMessage (string firstName, string lastName) 

The first variable in the function call is name1. Therefore, the value of name1 in main is copied into the first variable in the printMessage function header, firstName. Similarly, since the second variable in the function call is name2, the value of name2 in main is copied into the second variable in the printMessage function header, lastName.

If the arguments in the function call were reversed , as in:

 printMessage(last, first); 

then the sample input and output instead would be

 Enter first name: Jeff  Enter last name: Kent Your name is Kent Jeff 

In this example, not paying careful attention to the correspondence between the order of arguments in the function call and the order of the arguments in the function header resulted in my name being outputted backwards . However, the consequences of a lack of correspondence between the order of arguments in the function call and the order of the arguments in the function header is more drastic when the multiple function arguments have different data types.

In the following program, the first argument, the person s name, is a string, whereas the second argument, the person s age, is a different data type, an integer.

 #include <iostream> #include <string> using namespace std; void printMessage(string, int);  int main () {  string name;  int age;   cout << "Enter name: ";  cin >> name;  cout << "Enter age: ";  cin >> age;  printMessage(name, age);   return 0; } void printMessage (string theName, int theAge) {  cout << "Your name is " << theName   << " and your age is " << theAge << endl; } 

Here is some sample input and output (fortunately the program has no way to verify my age):

 Enter first name: Jeff Kent Enter age: 21 Your name is Jeff Kent and your age is 21 

The function call and the function header here are

 printMessage(name, age); void printMessage (string theName, int theName) 

The first argument of the printMessage function expects a string, so it is critical that the first argument in the function call is a string. Similarly, the second argument of the printMessage function expects an integer, so it is critical that the second argument in the function call is an integer. If the arguments in the function call were reversed, as in:

 printMessage(age, name); 

then the consequence would not be illogical output as in the prior example, but instead a compiler error cannot convert parameter 1 from ˜int to ˜string . This is because the compiler was expecting from the function prototype that the first argument (or parameter) would be a string, not an int.

Passing Arguments by Reference

Passing arguments by value is fine when you don t want to change their value in the called function. The printMessage function did not change the value of its arguments; it simply outputted them.

However, sometimes the intent of a function is to change the value of the argument passed to it. Consider the following example, in which the doubleIt function is supposed to double the value of the argument passed to it:

 #include <iostream> using namespace std; void doubleIt(int);  int main () {  int num;  cout << "Enter number: ";  cin >> num;  doubleIt(num);  cout << "The number doubled in main is " << num << endl;  return 0; } void doubleIt (int x) {  cout << "The number to be doubled is " << x << endl;  x *= 2;  cout << "The number doubled in doubleIt is "  << x << endl; } 

Here is some sample input and output:

 Enter number: 3 The number to be doubled is 3 The number doubled in doubleIt is 6 The number doubled in main is 3 

As the sample input and output reflects, the value of num was not changed by the doubling of its counterpart argument in the doubleIt function.

The reason the value of num was not changed in main is that a copy of it was passed to doubleIt. The change was made to the copy, but the original, the variable num in main, was not affected by the doubling of the copy. The logic is the same as if I gave you a copy of this page, which you then proceeded to rip up. The original I kept would be unaffected.

In order for the called function to change the value in main of a variable passed to it, the variable must be passed by reference. The variable in the called function is called a reference variable. The reference variable is not a copy of the variable in main. Instead, the reference variable is an alias for the variable in main. You may recall from television that an alias is another name a person may use, such as James Bond s alias of 007. However, whether you refer to him as James Bond or 007, you are still referring to the same person.

In order to pass a variable by reference, the data type in the argument, both in the function header and in the prototype, is followed by an ampersand. Yes, this is the same ampersand that is used as the address operator. Here, however, the ampersand is used in a different context.

The following program passes the variable to be doubled by reference:

 #include <iostream> using namespace std; void doubleIt(int&);  int main () {  int num;  cout << "Enter number: ";  cin >> num;  doubleIt(num);  cout << "The number doubled in main is " << num << endl;  return 0; } void doubleIt (int& x) {  cout << "The number to be doubled is " << x << endl;  x *= 2;  cout << "The number doubled in doubleIt is " << x << endl; } 

Here is some sample input and output:

 Enter number: 3 The number to be doubled is 3 The number doubled in doubleIt is 6 The number doubled in main is 6 

There were only two changes. The prototype and function header for doubleIt when the argument is passed by value is

 void doubleIt(int);  void doubleIt (int x) 

By contrast, the prototype and function header for doubleIt when the argument is passed by reference each includes the ampersand following the data types:

 void doubleIt(int&);  void doubleIt (int& x) 

However, the function call is the same whether the variable is passed by value or by reference; there is no ampersand in either case. Whether the program passes an argument in a function call by value or by reference is dictated by the function s prototype.

You can pass multiple values by reference as well as by value. Indeed, you can pass some values by reference and others by value. You pass by reference those values you need to change, and you pass by value those values you are not changing.

Note  

There is another difference between passing by value and passing by reference. You can pass by value expressions and constants (constants are covered in Chapter 10) as well as variables. However, you can only pass variables by reference.

For example, in the following program the function addNumbers has three arguments. The first two arguments are the numbers to be added, and are passed by value. The third argument will be the sum of the two numbers and will be passed by reference, since its value is being changed in the called function:

 #include <iostream> using namespace std; void addNumbers(int, int, int&);  int main () {  int firstNum, secondNum, sum = 0;  cout << "Enter first number: ";  cin >> firstNum;  cout << "Enter second number: ";  cin >> secondNum;  addNumbers (firstNum, secondNum, sum);  cout << firstNum << " + " << secondNum << " = " << sum;  return 0; } void addNumbers (int x, int y, int& z) {  z = x + y; } 

Here is some sample input and output:

 Enter first number: 3 Enter first number: 6 3 + 6 = 9 



C++ Demystified(c) A Self-Teaching Guide
C++ Demystified(c) A Self-Teaching Guide
ISBN: 72253703
EAN: N/A
Year: 2006
Pages: 148

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net