?? 014.htm
字號:
29: case 2:
30: PrintVals(valOne, valTwo);
31: Square(valOne,valTwo);
32: PrintVals(valOne, valTwo);
33: break;
34:
35: case 3:
36: PrintVals(valOne, valTwo);
37: Cube(valOne, valTwo);
38: PrintVals(valOne, valTwo);
39: break;
40:
41: case 4:
42: PrintVals(valOne, valTwo);
43: Swap(valOne, valTwo);
44: PrintVals(valOne, valTwo);
45: break;
46:
47: default :
48: fQuit = TRUE;
49: break;
50: }
51:
52: if (fQuit)
53: break;
54: }
55: return 0;
<TT>56: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: (0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 1
x: 1 y: 2
New value for ValOne: 2
New value for ValTwo: 3
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 3
x: 2 y: 3
x: 8 y: 27
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 2
x: 8 y: 27
x: 64 y: 729
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 4
x: 64 y: 729
x: 729 y: 64
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 0
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The implementation of the
functions has been left out, because it is identical to that provided in Listing
14.5. As you can see, the output is unchanged, but the body of the program has expanded
from 27 lines to 38. The calls to <TT>PrintVals()</TT> must be repeated for each
case.</P>
<P>It was tempting to put <TT>PrintVals()</TT> at the top of the <TT>while</TT> loop
and again at the bottom, rather than in each case statement. This would have called
<TT>PrintVals()</TT> even for the exit case, however, and that was not part of the
specification.</P>
<P>Setting aside the increased size of the code and the repeated calls to do the
same thing, the overall clarity is somewhat diminished. This is an artificial case,
however, created to show how pointers to functions work. In real-world conditions
the advantages are even clearer: pointers to functions can eliminate duplicate code,
clarify your program, and allow you to make tables of functions to call based on
runtime conditions.
<H3 ALIGN="CENTER"><A NAME="Heading20"></A><FONT COLOR="#000077">Shorthand Invocation</FONT></H3>
<P>The pointer to function does not need to be dereferenced, though you are free
to do so. Therefore, if <TT>pFunc</TT> is a pointer to a function taking an integer
and returning a variable of type <TT>long</TT>, and you assign <TT>pFunc</TT> to
a matching function, you can invoke that function with either</P>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">pFunc(x);
</FONT></PRE>
<P>or</P>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">(*pFunc)(x);
</FONT></PRE>
<P>The two forms are identical. The former is just a shorthand version of the latter.
<H4 ALIGN="CENTER"><A NAME="Heading21"></A><FONT COLOR="#000077">Arrays of Pointers
to Functions</FONT></H4>
<P>Just as you can declare an array of pointers to integers, you can declare an array
of pointers to functions returning a specific value type and with a specific signature.
Listing 14.7 again rewrites Listing 14.5, this time using an array to invoke all
the choices at once.
<BR>
<BR>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>To compile this program, place lines
41-80 of Listing 14.5 immediately after line 39.
<HR>
<BR>
<BR>
</BLOCKQUOTE>
<BR>
<P><A NAME="Heading22"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.7. Demonstrates
use of an array of pointers to functions.</B></FONT>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">1: // Listing 14.7 demonstrates use of an array of pointers to functions
2:
3: #include <iostream.h>
4:
5: void Square (int&,int&);
6: void Cube (int&, int&);
7: void Swap (int&, int &);
8: void GetVals(int&, int&);
9: void PrintVals(int, int);
10: enum BOOL { FALSE, TRUE };
11:
12: int main()
13: {
14: int valOne=1, valTwo=2;
15: int choice, i;
16: const MaxArray = 5;
17: void (*pFuncArray[MaxArray])(int&, int&);
18:
19: for (i=0;i<MaxArray;i++)
20: {
21: cout << "(1)Change Values (2)Square (3)Cube (4)Swap: ";
22: cin >> choice;
23: switch (choice)
24: {
25: case 1:pFuncArray[i] = GetVals; break;
26: case 2:pFuncArray[i] = Square; break;
27: case 3:pFuncArray[i] = Cube; break;
28: case 4:pFuncArray[i] = Swap; break;
29: default:pFuncArray[i] = 0;
30: }
31: }
32:
33: for (i=0;i<MaxArray; i++)
34: {
35: pFuncArray[i](valOne,valTwo);
36: PrintVals(valOne,valTwo);
37: }
38: return 0;
<TT>39: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: (1)Change Values (2)Square (3)Cube (4)Swap: 1
(1)Change Values (2)Square (3)Cube (4)Swap: 2
(1)Change Values (2)Square (3)Cube (4)Swap: 3
(1)Change Values (2)Square (3)Cube (4)Swap: 4
(1)Change Values (2)Square (3)Cube (4)Swap: 2
New Value for ValOne: 2
New Value for ValTwo: 3
x: 2 y: 3
x: 4 y: 9
x: 64 y: 729
x: 729 y: 64
x: 7153 y:4096
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Once again the implementation
of the functions has been left out to save space, but it is the same as in Listing
14.5. On line 17, the array <TT>pFuncArray</TT> is de- clared to be an array of 5
pointers to functions that return <TT>void</TT> and that take two integer references.</P>
<P>On lines 19-31, the user is asked to pick the functions to invoke, and each member
of the array is assigned the address of the appropriate function. On lines 33-37,
each function is invoked in turn. The result is printed after each invocation.
<H4 ALIGN="CENTER"><A NAME="Heading24"></A><FONT COLOR="#000077">Passing Pointers
to Functions to Other Functions</FONT></H4>
<P>The pointers to functions (and arrays of pointers to functions, for that matter)
can be passed to other functions, which may take action and then call the right function
using the pointer.</P>
<P>For example, you might improve Listing 14.5 by passing the chosen function pointer
to another function (outside of <TT>main()</TT>), which prints the values, invokes
the function, and then prints the values again. Listing 14.8 illustrates this variation.
<BR>
<BR>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>WARNING:</B></FONT><B> </B>To compile this program, place
lines 46-80 of Listing 14.5 immediately after line 45.
<HR>
<BR>
<BR>
</BLOCKQUOTE>
<BR>
<P><A NAME="Heading25"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.8. Passing
pointers to functions as function arguments.</B></FONT>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">1: // Listing 14.8 Without function pointers
2:
3: #include <iostream.h>
4:
5: void Square (int&,int&);
6: void Cube (int&, int&);
7: void Swap (int&, int &);
8: void GetVals(int&, int&);
9: void PrintVals(void (*)(int&, int&),int&, int&);
10: enum BOOL { FALSE, TRUE };
11:
12: int main()
13: {
14: int valOne=1, valTwo=2;
15: int choice;
16: BOOL fQuit = FALSE;
17:
18: void (*pFunc)(int&, int&);
19:
20: while (fQuit == FALSE)
21: {
22: cout << "(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: ";
23: cin >> choice;
24: switch (choice)
25: {
26: case 1:pFunc = GetVals; break;
27: case 2:pFunc = Square; break;
28: case 3:pFunc = Cube; break;
29: case 4:pFunc = Swap; break;
30: default:fQuit = TRUE; break;
31: }
32: if (fQuit == TRUE)
33: break;
34: PrintVals ( pFunc, valOne, valTwo);
35: }
36:
37: return 0;
38: }
39:
40: void PrintVals( void (*pFunc)(int&, int&),int& x, int& y)
41: {
42: cout << "x: " << x << " y: " << y << endl;
43: pFunc(x,y);
44: cout << "x: " << x << " y: " << y << endl;
<TT>45: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: (0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 1
x: 1 y: 2
New value for ValOne: 2
New value for ValTwo: 3
x: 2 y: 3
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 3
x: 2 y: 3
x: 8 y: 27
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 2
x: 8 y: 27
x: 64 y: 729
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 4
x: 64 y: 729
x: 729 y:64
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 0
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On line 18, <TT>pFunc</TT>
is declared to be a pointer to a function returning <TT>void</TT> and taking two
parameters, both integer references. On line 9, <TT>PrintVals</TT> is declared to
be a function taking three parameters. The first is a pointer to a function that
returns <TT>void</TT> but takes two integer reference parameters, and the second
and third arguments to <TT>PrintVals</TT> are integer references. The user is again
prompted for which functions to call, and then on line 34 <TT>PrintVals</TT> is called.</P>
<P>Go find a C++ programmer and ask him what this declaration means:</P>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">void PrintVals(void (*)(int&, int&),int&, int&);
</FONT></PRE>
<P>This is the kind of declaration that you use infrequently and probably look up
in the book each time you need it, but it will save your program on those rare occasions
when it is exactly the required construct.
<H4 ALIGN="CENTER"><A NAME="Heading27"></A><FONT COLOR="#000077">Using typedef with
Pointers to Functions</FONT></H4>
<P>The construct <TT>void (*)(int&, int&)</TT> is cumbersome, at best. You
can use <TT>typedef</TT> to simplify this, by declaring a type <TT>VPF</TT> as a
pointer to a function returning void and taking two integer references. Listing 14.9
rewrites Listing 14.8 using this <TT>typedef</TT> statement.
<BR>
<BR>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE: </B></FONT>To compile this program, place lines 46-80
of Listing 14.5 immediately after line 45.
<HR>
<BR>
<BR>
</BLOCKQUOTE>
<BR>
<P><A NAME="Heading28"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.9. Using
typedef to make pointers to functions more readable.</B></FONT>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">1: // Listing 14.9. Using typedef to make pointers to functions more _readable
2:
3: #include <iostream.h>
4:
5: void Square (int&,int&);
6: void Cube (int&, int&);
7: void Swap (int&, int &);
8: void GetVals(int&, int&);
9: typedef void (*VPF) (int&, int&) ;
10: void PrintVals(VPF,int&, int&);
11: enum BOOL { FALSE, TRUE };
12:
13: int main()
14: {
15: int valOne=1, valTwo=2;
16: int choice;
17: BOOL fQuit = FALSE;
18:
19: VPF pFunc;
20:
21: while (fQuit == FALSE)
22: {
23: cout << "(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: ";
24: cin >> choice;
25: switch (choice)
26: {
27: case 1:pFunc = GetVals; break;
28: case 2:pFunc = Square; break;
29: case 3:pFunc = Cube; break;
30: case 4:pFunc = Swap; break;
31: default:fQuit = TRUE; break;
32: }
33: if (fQuit == TRUE)
34: break;
35: PrintVals ( pFunc, valOne, valTwo);
36: }
37: return 0;
38: }
39:
40: void PrintVals( VPF pFunc,int& x, int& y)
41: {
42: cout << "x: " << x << " y: " << y << endl;
43: pFunc(x,y);
44: cout << "x: " << x << " y: " << y << endl;
<TT>45: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: (0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 1
x: 1 y: 2
New value for ValOne: 2
New value for ValTwo: 3
x: 2 y: 3
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 3
x: 2 y: 3
x: 8 y: 27
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 2
x: 8 y: 27
x: 64 y: 729
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 4
x: 64 y: 729
x: 729 y: 64
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 0
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On line 9, <TT>typedef</TT>
is used to declare <TT>VPF</TT> to be of the type "function that returns <TT>void</TT>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -