📄 ch05.htm
字号:
function must pass in a value. The value passed in must be of the declared type.
Thus, if you have a function declared as</P>
<PRE><FONT COLOR="#0066FF">long myFunction(int);
</FONT></PRE>
<P>the function must in fact take an integer variable. If the function definition
differs, or if you fail to pass in an integer, you will get a compiler error.</P>
<P>The one exception to this rule is if the function prototype declares a default
value for the parameter. A default value is a value to use if none is supplied. The
preceding declaration could be rewritten as</P>
<PRE><FONT COLOR="#0066FF">long myFunction (int x = 50);
</FONT></PRE>
<P>This prototype says, "<TT>myFunction()</TT> returns a <TT>long</TT> and takes
an integer parameter. If an argument is not supplied, use the default value of <TT>50</TT>."
Because parameter names are not required in function prototypes, this declaration
could have been written as</P>
<PRE><FONT COLOR="#0066FF">long myFunction (int = 50);
</FONT></PRE>
<P>The function definition is not changed by declaring a default parameter. The function
definition header for this function would be</P>
<PRE><FONT COLOR="#0066FF">long myFunction (int x)
</FONT></PRE>
<P>If the calling function did not include a parameter, the compiler would fill <TT>x</TT>
with the default value of <TT>50</TT>. The name of the default parameter in the prototype
need not be the same as the name in the function header; the default value is assigned
by position, not name.</P>
<P>Any or all of the function's parameters can be assigned default values. The one
restriction is this: If any of the parameters does not have a default value, no previous
parameter may have a default value.</P>
<P>If the function prototype looks like</P>
<PRE><FONT COLOR="#0066FF">long myFunction (int Param1, int Param2, int Param3);
</FONT></PRE>
<P>you can assign a default value to <TT>Param2</TT> only if you have assigned a
default value to <TT>Param3</TT>. You can assign a default value to <TT>Param1</TT>
only if you've assigned default values to both <TT>Param2</TT> and <TT>Param3</TT>.
Listing 5.7 demonstrates the use of default values.</P>
<P><A NAME="Heading35"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 5.7. A demonstration
of default parameter values.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: // Listing 5.7 - demonstrates use
2: // of default parameter values
3:
4: #include <iostream.h>
5:
6: int AreaCube(int length, int width = 25, int height = 1);
7:
8: int main()
9: {
10: int length = 100;
11: int width = 50;
12: int height = 2;
13: int area;
14:
15: area = AreaCube(length, width, height);
16: cout << "First area equals: " << area << "\n";
17:
18: area = AreaCube(length, width);
19: cout << "Second time area equals: " << area << "\n";
20:
21: area = AreaCube(length);
22: cout << "Third time area equals: " << area << "\n";
23: return 0;
24: }
25:
26: AreaCube(int length, int width, int height)
27: {
28:
29: return (length * width * height);
<TT>30: }</TT></FONT></PRE>
<PRE><FONT COLOR="#0066FF">
Output: First area equals: 10000
Second time area equals: 5000
Third time area equals: 2500
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis: </B></FONT>On line 6, the <TT>AreaCube()</TT>
prototype specifies that the <TT>AreaCube()</TT> function takes three integer parameters.
The last two have default values.<BR>
This function computes the area of the cube whose dimensions are passed in. If no
<TT>width</TT> is passed in, a <TT>width</TT> of 25 is used and a <TT>height</TT>
of 1 is used. If the <TT>width</TT> but not the <TT>height</TT> is passed in, a <TT>height</TT>
of 1 is used. It is not possible to pass in the <TT>height</TT> without passing in
a <TT>width</TT>.</P>
<P>On lines 10-12, the dimensions <TT>length</TT>, <TT>height</TT>, and <TT>width</TT>
are initialized, and they are passed to the <TT>AreaCube()</TT> function on line
15. The values are computed, and the result is printed on line 16.</P>
<P>Execution returns to line 18, where <TT>AreaCube()</TT> is called again, but with
no value for <TT>height</TT>. The default value is used, and again the dimensions
are computed and printed.</P>
<P>Execution returns to line 21, and this time neither the <TT>width</TT> nor the
<TT>height</TT> is passed in. Execution branches for a third time to line 27. The
default values are used. The area is computed and then printed.
<BLOCKQUOTE>
<P>
<HR>
<B>DO</B> remember that function parameters act as local variables within the function.
<B>DON'T</B> try to create a default value for a first parameter if there is no default
value for the second. <B>DON'T</B> forget that arguments passed by value can not
affect the variables in the calling function. <B>DON'T</B> forget that changes to
a global variable in one function change that variable for all functions.
<HR>
</BLOCKQUOTE>
<H3 ALIGN="CENTER"><A NAME="Heading36"></A><FONT COLOR="#000077">Overloading Functions</FONT></H3>
<P>C++ enables you to create more than one function with the same name. This is called
function overloading. The functions must differ in their parameter list, with a different
type of parameter, a different number of parameters, or both. Here's an example:</P>
<PRE><FONT COLOR="#0066FF">int myFunction (int, int);
int myFunction (long, long);
int myFunction (long);
</FONT></PRE>
<P><TT>myFunction()</TT> is overloaded with three different parameter lists. The
first and second versions differ in the types of the parameters, and the third differs
in the number of parameters.</P>
<P>The return types can be the same or different on overloaded functions. You should
note that two functions with the same name and parameter list, but different return
types, generate a compiler error.</P>
<DL>
<DD>
<HR>
<FONT COLOR="#000077"><B>New Term: </B></FONT>Function <I>overloading</I> i s also
called function <I>polymorphism</I>. Poly means many, and morph means form: a polymorphic
function is many-formed.
<HR>
</DL>
<P>Function polymorphism refers to the ability to "overload" a function
with more than one meaning. By changing the number or type of the parameters, you
can give two or more functions the same function name, and the right one will be
called by matching the parameters used. This allows you to create a function that
can average integers, doubles, and other values without having to create individual
names for each function, such as <TT>AverageInts()</TT>, <TT>AverageDoubles()</TT>,
and so on.</P>
<P>Suppose you write a function that doubles whatever input you give it. You would
like to be able to pass in an <TT>int</TT>, a <TT>long</TT>, a <TT>float</TT>, or
a <TT>double</TT>. Without function overloading, you would have to create four function
names:</P>
<PRE><FONT COLOR="#0066FF">int DoubleInt(int);
long DoubleLong(long);
float DoubleFloat(float);
double DoubleDouble(double);
</FONT></PRE>
<P>With function overloading, you make this declaration:</P>
<PRE><FONT COLOR="#0066FF">int Double(int);
long Double(long);
float Double(float);
double Double(double);
</FONT></PRE>
<P>This is easier to read and easier to use. You don't have to worry about which
one to call; you just pass in a variable, and the right function is called automatically.
Listing 5.8 illustrates the use of function overloading.</P>
<P><A NAME="Heading37"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 5.8. A demonstration
of function polymorphism</B></FONT><FONT SIZE="2" COLOR="#000077"><B>.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: // Listing 5.8 - demonstrates
2: // function polymorphism
3:
4: #include <iostream.h>
5:
6: int Double(int);
7: long Double(long);
8: float Double(float);
9: double Double(double);
10:
11: int main()
12: {
13: int myInt = 6500;
14: long myLong = 65000;
15: float myFloat = 6.5F;
16: double myDouble = 6.5e20;
17:
18: int doubledInt;
19: long doubledLong;
20: float doubledFloat;
21: double doubledDouble;
22:
23: cout << "myInt: " << myInt << "\n";
24: cout << "myLong: " << myLong << "\n";
25: cout << "myFloat: " << myFloat << "\n";
26: cout << "myDouble: " << myDouble << "\n";
27:
28: doubledInt = Double(myInt);
29: doubledLong = Double(myLong);
30: doubledFloat = Double(myFloat);
31: doubledDouble = Double(myDouble);
32:
33: cout << "doubledInt: " << doubledInt << "\n";
34: cout << "doubledLong: " << doubledLong << "\n";
35: cout << "doubledFloat: " << doubledFloat << "\n";
36: cout << "doubledDouble: " << doubledDouble << "\n";
37:
38: return 0;
39: }
40:
41: int Double(int original)
42: {
43: cout << "In Double(int)\n";
44: return 2 * original;
45: }
46:
47: long Double(long original)
48: {
49: cout << "In Double(long)\n";
50: return 2 * original;
51: }
52:
53: float Double(float original)
54: {
55: cout << "In Double(float)\n";
56: return 2 * original;
57: }
58:
59: double Double(double original)
60: {
61: cout << "In Double(double)\n";
62: return 2 * original;
<TT>63: }</TT></FONT></PRE>
<PRE><FONT COLOR="#0066FF">Output: myInt: 6500
myLong: 65000
myFloat: 6.5
myDouble: 6.5e+20
In Double(int)
In Double(long)
In Double(float)
In Double(double)
DoubledInt: 13000
DoubledLong: 130000
DoubledFloat: 13
DoubledDouble: 1.3e+21</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The <TT>Double()</TT>function
is overloaded with <TT>int</TT>, <TT>long</TT>, <TT>float</TT>, and <TT>double</TT>.
The prototypes are on lines 6-9, and the definitions are on lines 41-63.<BR>
In the body of the main program, eight local variables are declared. On lines 13-16,
four of the values are initialized, and on lines 28-31, the other four are assigned
the results of passing the first four to the <TT>Double()</TT> function. Note that
when <TT>Double()</TT> is called, the calling function does not distinguish which
one to call; it just passes in an argument, and the correct one is invoked.</P>
<P>The compiler examines the arguments and chooses which of the four <TT>Double()</TT>
functions to call. The output reveals that each of the four was called in turn, as
you would expect.
<H3 ALIGN="CENTER"><A NAME="Heading39"></A><FONT COLOR="#000077">Special Topics About
Functions</FONT></H3>
<P>Because functions are so central to programming, a few special topics arise which
might be of interest when you confront unusual problems. Used wisely, inline functions
can help you squeak out that last bit of performance. Function recursion is one of
those wonderful, esoteric bits of programming which, every once in a while, can cut
through a thorny problem otherwise not easily solved.
<H4 ALIGN="CENTER"><A NAME="Heading40"></A><FONT COLOR="#000077">Inline Functions</FONT></H4>
<P>When you define a function, normally the compiler creates just one set of instructions
in memory. When you call the function, execution of the program jumps to those instructions,
and when the function returns, execution jumps back to the next line in the calling
function. If you call the function 10 times, your program jumps to the same set of
instructions each time. This means there is only one copy of the function, not 10.</P>
<P>There is some performance overhead in jumping in and out of functions. It turns
out that some functions are very small, just a line or two of code, and some efficiency
can be gained if the program can avoid making these jumps just to execute one or
two instructions. When programmers speak of efficiency, they usually mean speed:
the program runs faster if the function call can be avoided.</P>
<P>If a function is declared with the keyword <TT>inline</TT>, the compiler does
not create a real function: it copies the code from the inline function directly
into the calling function. No jump is made; it is just as if you had written the
statements of the function right into the calling function.</P>
<P>Note that inline functions can bring a heavy cost. If the function is called 10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -