⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch14.htm

📁 vc的电子书
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On line 17, the static member
variable <TT>HowManyCats</TT> is declared to have private access. Now you cannot
access this variable from non-member functions, such as <TT>TelepathicFunction</TT>
from the previous listing.</P>
<P>Even though <TT>HowManyCats</TT> is static, it is still within the scope of the
class. Any class function, such as <TT>GetHowMany()</TT>, can access it, just as
member functions can access any member data. However, for a function to call <TT>GetHowMany()</TT>,
it must have an object on which to call the function.


<BLOCKQUOTE>
	<P>
<HR>
<B>DO</B> use static member variables to share data among all instances of a class.
	<B>DO</B> make static member variables protected or private if you wish to restrict
	access to them. <B>DON'T </B>use static member variables to store data for one object.
	Static member data is shared among all objects of its class. 
<HR>


</BLOCKQUOTE>

<H3 ALIGN="CENTER"><A NAME="Heading9"></A><FONT COLOR="#000077">Static Member Functions</FONT></H3>
<P>Static member functions are like static member variables: they exist not in an
object but in the scope of the class. Thus, they can be called without having an
object of that class, as illustrated in Listing 14.4.</P>

<P><A NAME="Heading10"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.4. Static
member functions.</B></FONT>
<PRE><FONT COLOR="#0066FF">1:     //Listing 14.4 static data members
2:
3:     #include &lt;iostream.h&gt;
4:
5:     class Cat
6:     {
7:     public:
8:        Cat(int age):itsAge(age){HowManyCats++; }
9:        virtual ~Cat() { HowManyCats--; }
10:       virtual int GetAge() { return itsAge; }
11:       virtual void SetAge(int age) { itsAge = age; }
12:       static int GetHowMany() { return HowManyCats; }
13:    private:
14:       int itsAge;
15:       static int HowManyCats;
16:    };
17:
18:    int Cat::HowManyCats = 0;
19:
20:    void TelepathicFunction();
21:
22:    int main()
23:    {
24:       const int MaxCats = 5;
25:       Cat *CatHouse[MaxCats]; int i;
26:       for (i = 0; i&lt;MaxCats; i++)
27:       {
28:          CatHouse[i] = new Cat(i);
29:          TelepathicFunction();
30:       }
31:
32:       for ( i = 0; i&lt;MaxCats; i++)
33:       {
34:          delete CatHouse[i];
35:          TelepathicFunction();
36:       }
37:       return 0;
38:    }
39:
40:    void TelepathicFunction()
41:    {
42:       cout &lt;&lt; &quot;There are &quot; &lt;&lt; Cat::GetHowMany() &lt;&lt; &quot; cats alive!\n&quot;;
<TT>43: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: There are 1 cats alive!
There are 2 cats alive!
There are 3 cats alive!
There are 4 cats alive!
There are 5 cats alive!
There are 4 cats alive!
There are 3 cats alive!
There are 2 cats alive!
There are 1 cats alive!
There are 0 cats alive! 
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The static member variable
<TT>HowManyCats</TT> is declared to have private access on line 15 of the <TT>Cat</TT>
declaration. The public accessor function, <TT>GetHowMany()</TT>, is declared to
be both public and static on line 12.</P>
<P>Since <TT>GetHowMany()</TT> is public, it can be accessed by any function, and
since it is static there is no need to have an object of type <TT>Cat</TT> on which
to call it. Thus, on line 42, the function <TT>TelepathicFunction()</TT> is able
to access the public static accessor, even though it has no access to a <TT>Cat</TT>
object. Of course, you could have called <TT>GetHowMany()</TT> on the <TT>Cat</TT>
objects available in <TT>main()</TT>, just as with any other accessor functions.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Static member functions do not have
	a <TT>this</TT> pointer. Therefore, they cannot be declared <TT>const</TT>. Also,
	because member data variables are accessed in member functions using the <TT>this</TT>
	pointer, static member functions cannot access any non-static member variables! 
<HR>


</BLOCKQUOTE>

<H3 ALIGN="CENTER"><A NAME="Heading12"></A><FONT COLOR="#000077">Static Member Functions</FONT></H3>
<P>You can access static member functions by calling them on an object of the class
just as you do any other member function, or you can call them without an object
by fully qualifying the class and object name. Example</P>
<PRE><FONT COLOR="#0066FF">class Cat
{
public:
static int GetHowMany() { return HowManyCats; }
private:
static int HowManyCats;
};
int Cat::HowManyCats = 0;
int main()
{
int howMany;
Cat theCat;                       // define a cat
howMany = theCat.GetHowMany();   // access through an object
howMany = Cat::GetHowMany();     // access without an object
}
</FONT></PRE>
<H3 ALIGN="CENTER"><A NAME="Heading13"></A><FONT COLOR="#000077">Pointers to Functions</FONT></H3>
<P>Just as an array name is a constant pointer to the first element of the array,
a function name is a constant pointer to the function. It is possible to declare
a pointer variable that points to a function, and to invoke the function by using
that pointer. This can be very useful; it allows you to create programs that decide
which functions to invoke based on user input.</P>
<P>The only tricky part about function pointers is understanding the type of the
object being pointed to. A pointer to <TT>int</TT> points to an integer variable,
and a pointer to a function must point to a function of the appropriate return type
and signature.</P>
<P>In the declaration</P>
<PRE><FONT COLOR="#0066FF">long (* funcPtr) (int);
</FONT></PRE>
<P><TT>funcPtr</TT> is declared to be a pointer (note the <TT>*</TT> in front of
the name) that points to a function that takes an integer parameter and returns a
<TT>long</TT>. The parentheses around <TT>* funcPtr</TT> are necessary because the
parentheses around <TT>int</TT> bind more tightly, that is they have higher precedence
than the indirection operator (<TT>*</TT>). Without the first parentheses this would
declare a function that takes an integer and returns a pointer to a <TT>long</TT>.
(Remember that spaces are meaningless here.)</P>
<P>Examine these two declarations:</P>
<PRE><FONT COLOR="#0066FF">long * Function (int);
long (* funcPtr) (int);
</FONT></PRE>
<P>The first, <TT>Function</TT> <TT>()</TT>, is a function taking an integer and
returning a pointer to a variable of type <TT>long</TT>. The second, <TT>funcPtr</TT>,
is a pointer to a function taking an integer and returning a variable of type <TT>long</TT>.</P>
<P>The declaration of a function pointer will always include the return type and
the parentheses indicating the type of the parameters, if any. Listing 14.5 illustrates
the declaration and use of function pointers.</P>

<P><A NAME="Heading14"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.5. Pointers
to functions.</B></FONT>
<PRE><FONT COLOR="#0066FF">1:     // Listing 14.5 Using function pointers
2:
3:     #include &lt;iostream.h&gt;
4:
5:     void Square (int&amp;,int&amp;);
6:     void Cube (int&amp;, int&amp;);
7:     void Swap (int&amp;, int &amp;);
8:     void GetVals(int&amp;, int&amp;);
9:     void PrintVals(int, int);
10:    enum BOOL { FALSE, TRUE };
11:
12:    int main()
13:    {
14:       void (* pFunc) (int &amp;, int &amp;);
15:       BOOL fQuit = FALSE;
16:
17:       int valOne=1, valTwo=2;
18:       int choice;
19:       while (fQuit == FALSE)
20:       {
21:          cout &lt;&lt; &quot;(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: &quot;;
22:          cin &gt;&gt; choice;
23:          switch (choice)
24:          {
25:             case 1: pFunc = GetVals; break;
26:             case 2: pFunc = Square; break;
27:             case 3: pFunc = Cube; break;
28:             case 4: pFunc = Swap; break;
29:             default : fQuit = TRUE; break;
30:          }
31:
32:          if (fQuit)
33:             break;
34:
35:          PrintVals(valOne, valTwo);
36:          pFunc(valOne, valTwo);
37:          PrintVals(valOne, valTwo);
38:       }
39:     return 0;
40:    }
41:
42:    void PrintVals(int x, int y)
43:    {
44:       cout &lt;&lt; &quot;x: &quot; &lt;&lt; x &lt;&lt; &quot; y: &quot; &lt;&lt; y &lt;&lt; endl;
45:    }
46:
47:    void Square (int &amp; rX, int &amp; rY)
48:    {
49:       rX *= rX;
50:       rY *= rY;
51:    }
52: 
53:    void Cube (int &amp; rX, int &amp; rY)
54:    {
55:       int tmp;
56: 
57:       tmp = rX;
58:       rX *= rX;
59:       rX = rX * tmp;
60:
61:       tmp = rY;
62:       rY *= rY;
63:       rY = rY * tmp;
64:    }
65:
66:    void Swap(int &amp; rX, int &amp; rY)
67:    {
68:       int temp;
69:       temp = rX;
70:       rX = rY;
71:       rY = temp;
72:    }
73:
74:    void GetVals (int &amp; rValOne, int &amp; rValTwo)
75:    {
76:       cout &lt;&lt; &quot;New value for ValOne: &quot;;
77:       cin &gt;&gt; rValOne;
78:       cout &lt;&lt; &quot;New value for ValTwo: &quot;;
79:       cin &gt;&gt; rValTwo;
<TT>80: }</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 lines 5-8, four functions
are declared, each with the same return type and signature, returning <TT>void</TT>
and taking two references to integers.</P>
<P>On line 14, <TT>pFunc</TT> is declared to be a pointer to a function that returns
<TT>void</TT> and takes two integer reference parameters. Any of the previous functions
can be pointed to by <TT>pFunc</TT>. The user is repeatedly offered the choice of
which functions to invoke, and <TT>pFunc</TT> is assigned accordingly. On lines 35-36,
the current value of the two integers is printed, the currently assigned function
is invoked, and then the values are printed again.
<H3 ALIGN="CENTER"><A NAME="Heading16"></A><FONT COLOR="#000077">Pointer to Function</FONT></H3>
<P>A pointer to function is invoked exactly like the functions it points to, except
that the function pointer name is used instead of the function name. Assign a pointer
to function to a specific function by assigning to the function name without the
parentheses. The function name is a constant pointer to the function itself. Use
the pointer to function just as you would the function name. The pointer to function
must agree in return value and signature with the function to which you assign it.
Example</P>
<PRE><FONT COLOR="#0066FF">long (*pFuncOne) (int, int);
long SomeFunction (int, int);
pFuncOne = SomeFunction;
pFuncOne(5,7); 
</FONT></PRE>
<H4 ALIGN="CENTER"><A NAME="Heading17"></A><FONT COLOR="#000077">Why Use Function
Pointers?</FONT></H4>
<P>You certainly could write the program in Listing 14.5 without function pointers,
but the use of these pointers makes the intent and use of the program explicit: pick
a function from a list, and then invoke it.</P>
<P>Listing 14.6 uses the function prototypes and definitions from Listing 14.5, but
the body of the program does not use a function pointer. Examine the differences
between these two listings.


<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>To compile this program, place lines
	41-80 from Listing 14.5 immediately after line 56. 
<HR>


</BLOCKQUOTE>

<P><A NAME="Heading18"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.6. Rewriting
Listing 14.5 without the pointer to function.</B></FONT>
<PRE><FONT COLOR="#0066FF">1:     // Listing 14.6 Without function pointers
2:
3:     #include &lt;iostream.h&gt;
4:
5:     void Square (int&amp;,int&amp;);
6:     void Cube (int&amp;, int&amp;);
7:     void Swap (int&amp;, int &amp;);
8:     void GetVals(int&amp;, int&amp;);
9:     void PrintVals(int, int);
10:    enum BOOL { FALSE, TRUE };
11:
12:    int main()
13:    {
14:       BOOL fQuit = FALSE;
15:       int valOne=1, valTwo=2;
16:       int choice;
17:       while (fQuit == FALSE)
18:       {
19:          cout &lt;&lt; &quot;(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: &quot;;
20:          cin &gt;&gt; choice;
21:          switch (choice)
22:          {
23:             case 1:
24:                PrintVals(valOne, valTwo);
25:                GetVals(valOne, valTwo);
26:                PrintVals(valOne, valTwo);
27:                break;
28:
29:             case 2:
30:                PrintVals(valOne, valTwo);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -