📄 ch05.htm
字号:
it is defined. Thus, if you define a variable inside a set of braces within the function,
that variable is available only within that block. Listing 5.4 illustrates this idea.</P>
<P><A NAME="Heading23"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 5.4. Variables
scoped within a block.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: // Listing 5.4 - demonstrates variables
2: // scoped within a block
3:
4: #include <iostream.h>
5:
6: void myFunc();
7:
8: int main()
9: {
10: int x = 5;
11: cout << "\nIn main x is: " << x;
12:
13: myFunc();
14:
15: cout << "\nBack in main, x is: " << x;
16: return 0;
17: }
18:
19: void myFunc()
20: {
21:
22: int x = 8;
23: cout << "\nIn myFunc, local x: " << x << endl;
24:
25: {
26: cout << "\nIn block in myFunc, x is: " << x;
27:
28: int x = 9;
29:
30: cout << "\nVery local x: " << x;
31: }
32:
33: cout << "\nOut of block, in myFunc, x: " << x << endl;
<TT>34: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: In main x is: 5
In myFunc, local x: 8
In block in myFunc, x is: 8
Very local x: 9
Out of block, in myFunc, x: 8
Back in main, x is: 5
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>This program begins with
the initialization of a local variable, <TT>x</TT>, on line 10, in <TT>main()</TT>.
The printout on line 11 verifies that <TT>x</TT> was initialized with the value <TT>5</TT>.<BR>
<TT>MyFunc()</TT> is called, and a local variable, also named <TT>x</TT>, is initialized
with the value <TT>8</TT> on line 22. Its value is printed on line 23.</P>
<P>A block is started on line 25, and the variable <TT>x</TT> from the function is
printed again on line 26. A new variable also named <TT>x</TT>, but local to the
block, is created on line 28 and initialized with the value <TT>9</TT>.</P>
<P>The value of the newest variable <TT>x</TT> is printed on line 30. The local block
ends on line 31, and the variable created on line 28 goes "out of scope"
and is no longer visible.</P>
<P>When <TT>x</TT> is printed on line 33, it is the <TT>x</TT> that was declared
on line 22. This <TT>x</TT> was unaffected by the <TT>x</TT> that was defined on
line 28; its value is still <TT>8</TT>.</P>
<P>On line 34, <TT>MyFunc()</TT> goes out of scope, and its local variable <TT>x</TT>
becomes unavailable. Execution returns to line 15, and the value of the local variable
<TT>x</TT>, which was created on line 10, is printed. It was unaffected by either
of the variables defined in <TT>MyFunc()</TT>.</P>
<P>Needless to say, this program would be far less confusing if these three variables
were given unique names!
<H3 ALIGN="CENTER"><A NAME="Heading25"></A><FONT COLOR="#000077">Function Statements</FONT></H3>
<P>There is virtually no limit to the number or types of statements that can be in
a function body. Although you can't define another function from within a function,
you can call a function, and of course <TT>main()</TT> does just that in nearly every
C++ program. Functions can even call themselves, which is discussed soon, in the
section on recursion.</P>
<P>Although there is no limit to the size of a function in C++, well-designed functions
tend to be small. Many programmers advise keeping your functions short enough to
fit on a single screen so that you can see the entire function at one time. This
is a rule of thumb, often broken by very good programmers, but a smaller function
is easier to understand and maintain.</P>
<P>Each function should carry out a single, easily understood task. If your functions
start getting large, look for places where you can divide them into component tasks.
<H3 ALIGN="CENTER"><A NAME="Heading26"></A><FONT COLOR="#000077">Function Arguments</FONT></H3>
<P>Function arguments do not have to all be of the same type. It is perfectly reasonable
to write a function that takes an integer, two <TT>long</TT>s, and a character as
its arguments.</P>
<P>Any valid C++ expression can be a function argument, including constants, mathematical
and logical expressions, and other functions that return a value.
<H4 ALIGN="CENTER"><A NAME="Heading27"></A><FONT COLOR="#000077">Using Functions
as Parameters to Functions</FONT></H4>
<P>Although it is legal for one function to take as a parameter a second function
that returns a value, it can make for code that is hard to read and hard to debug.</P>
<P>As an example, say you have the functions <TT>double()</TT>, <TT>triple()</TT>,
<TT>square()</TT>, and <TT>cube()</TT>, each of which returns a value. You could
write</P>
<PRE><FONT COLOR="#0066FF">Answer = (double(triple(square(cube(myValue)))));
</FONT></PRE>
<P>This statement takes a variable, <TT>myValue</TT>, and passes it as an argument
to the function <TT>cube()</TT>, whose return value is passed as an argument to the
function <TT>square()</TT>, whose return value is in turn passed to <TT>triple()</TT>,
and that return value is passed to <TT>double()</TT>. The return value of this doubled,
tripled, squared, and cubed number is now passed to <TT>Answer</TT>.</P>
<P>It is difficult to be certain what this code does (was the value tripled before
or after it was squared?), and if the answer is wrong it will be hard to figure out
which function failed.</P>
<P>An alternative is to assign each step to its own intermediate variable:</P>
<PRE><FONT COLOR="#0066FF">unsigned long myValue = 2;
unsigned long cubed = cube(myValue); // cubed = 8
unsigned long squared = square(cubed); // squared = 64
unsigned long tripled = triple(squared); // tripled = 196
unsigned long Answer = double(tripled); // Answer = 392
</FONT></PRE>
<P>Now each intermediate result can be examined, and the order of execution is explicit.
<H3 ALIGN="CENTER"><A NAME="Heading28"></A><FONT COLOR="#000077">Parameters Are Local
Variables</FONT></H3>
<P>The arguments passed in to the function are local to the function. Changes made
to the arguments do not affect the values in the calling function. This is known
as passing by value, which means a local copy of each argument is made in the function.
These local copies are treated just like any other local variables. Listing 5.5 illustrates
this point.</P>
<P><A NAME="Heading29"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 5.5. A demonstration
of passing by value.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: // Listing 5.5 - demonstrates passing by value
2:
3: #include <iostream.h>
4:
5: void swap(int x, int y);
6:
7: int main()
8: {
9: int x = 5, y = 10;
10:
11: cout << "Main. Before swap, x: " << x << " y: " << y << "\n";
12: swap(x,y);
13: cout << "Main. After swap, x: " << x << " y: " << y << "\n";
14: return 0;
15: }
16:
17: void swap (int x, int y)
18: {
19: int temp;
20:
21: cout << "Swap. Before swap, x: " << x << " y: " << y << "\n";
22:
23: temp = x;
24: x = y;
25: y = temp;
26:
27: cout << "Swap. After swap, x: " << x << " y: " << y << "\n";
28:
<TT>29: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: Main. Before swap, x: 5 y: 10
Swap. Before swap, x: 5 y: 10
Swap. After swap, x: 10 y: 5
Main. After swap, x: 5 y: 10
</FONT></PRE>
<P><FONT COLOR="#0000AA"><B>Analysis: </B></FONT>This program initializes two variables
in <TT>main()</TT> and then passes them to the <TT>swap()</TT> function, which appears
to swap them. When they are examined again in <TT>main()</TT>, however, they are
unchanged!<BR>
The variables are initialized on line 9, and their values are displayed on line 11.
<TT>swap()</TT> is called, and the variables are passed in.</P>
<P>Execution of the program switches to the <TT>swap()</TT> function, where on line
21 the values are printed again. They are in the same order as they were in <TT>main()</TT>,
as expected. On lines 23 to 25 the values are swapped, and this action is confirmed
by the printout on line 27. Indeed, while in the <TT>swap()</TT> function, the values
are swapped.</P>
<P>Execution then returns to line 13, back in <TT>main()</TT>, where the values are
no longer swapped.</P>
<P>As you've figured out, the values passed in to the <TT>swap()</TT> function are
passed by value, meaning that copies of the values are made that are local to <TT>swap()</TT>.
These local variables are swapped in lines 23 to 25, but the variables back in <TT>main()</TT>
are unaffected.</P>
<P>On Days 8 and 10 you'll see alternatives to passing by value that will allow the
values in <TT>main()</TT> to be changed.
<H3 ALIGN="CENTER"><A NAME="Heading31"></A><FONT COLOR="#000077">Return Values</FONT></H3>
<P>Functions return a value or return <TT>void</TT>. <TT>Void</TT> is a signal to
the compiler that no value will be returned.</P>
<P>To return a value from a function, write the keyword <TT>return</TT> followed
by the value you want to return. The value might itself be an expression that returns
a value. For example:</P>
<PRE><FONT COLOR="#0066FF">return 5;
return (x > 5);
return (MyFunction());
</FONT></PRE>
<P>These are all legal <TT>return</TT> statements, assuming that the function <TT>MyFunction()</TT>
itself returns a value. The value in the second statement, <TT>return (x > 5)</TT>,
will be zero if <TT>x</TT> is not greater than 5, or it will be <TT>1</TT>. What
is returned is the value of the expression, <TT>0</TT> (<TT>false</TT>) or <TT>1</TT>
(<TT>true</TT>), not the value of <TT>x</TT>.</P>
<P>When the <TT>return</TT> keyword is encountered, the expression following <TT>return</TT>
is returned as the value of the function. Program execution returns immediately to
the calling function, and any statements following the return are not executed.</P>
<P>It is legal to have more than one <TT>return</TT> statement in a single function.
Listing 5.6 illustrates this idea.</P>
<P><A NAME="Heading32"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 5.6. A demonstration
of multiple return statements</B></FONT><FONT SIZE="2" COLOR="#000077"><B>.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: // Listing 5.6 - demonstrates multiple return
2: // statements
3:
4: #include <iostream.h>
5:
6: int Doubler(int AmountToDouble);
7:
8: int main()
9: {
10:
11: int result = 0;
12: int input;
13:
14: cout << "Enter a number between 0 and 10,000 to double: ";
15: cin >> input;
16:
17: cout << "\nBefore doubler is called... ";
18: cout << "\ninput: " << input << " doubled: " << result << "\n";
19:
20: result = Doubler(input);
21:
22: cout << "\nBack from Doubler...\n";
23: cout << "\ninput: " << input << " doubled: " << result << "\n";
24:
25:
26: return 0;
27: }
28:
29: int Doubler(int original)
30: {
31: if (original <= 10000)
32: return original * 2;
33: else
34: return -1;
35: cout << "You can't get here!\n";
<TT>36: }</TT>
Output: Enter a number between 0 and 10,000 to double: 9000
Before doubler is called...
input: 9000 doubled: 0
Back from doubler...
input: 9000 doubled: 18000
Enter a number between 0 and 10,000 to double: 11000
Before doubler is called...
input: 11000 doubled: 0
Back from doubler...
input: 11000 doubled: -1
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis: </B></FONT>A number is requested on lines 14
and 15, and printed on line 18, along with the local variable result. The function
<TT>Doubler()</TT> is called on line 20, and the input value is passed as a parameter.
The result will be assigned to the local variable <TT>result</TT>, and the values
will be reprinted on lines 22 and 23.<BR>
On line 31, in the function <TT>Doubler()</TT>, the parameter is tested to see whether
it is greater than 10,000. If it is not, the function returns twice the original
number. If it is greater than 10,000, the function returns <TT>-1</TT> as an error
value.</P>
<P>The statement on line 35 is never reached, because whether or not the value is
greater than 10,000, the function returns before it gets to line 35, on either line
32 or line 34. A good compiler will warn that this statement cannot be executed,
and a good programmer will take it out!
<H3 ALIGN="CENTER"><A NAME="Heading34"></A><FONT COLOR="#000077">Default Parameters</FONT></H3>
<P>For every parameter you declare in a function prototype and definition, the calling
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -