📄 ch14.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"><HTML><HEAD><!-- This document was created from RTF source by rtftohtml version 3.0.1 --> <META NAME="GENERATOR" Content="Symantec Visual Page 1.0"> <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1"> <TITLE>Teach Yourself C++ in 21 Days</TITLE></HEAD><BODY TEXT="#000000" BGCOLOR="#FFFFFF"><H1 ALIGN="CENTER"><A HREF="ch13.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/htm/ch13.htm"><IMG SRC="BLANPREV.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANPREV.GIF"WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="tppmsgs/msgs0.htm#1" tppabs="http://www.mcp.com/sams"><IMGSRC="BLANHOME.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANHOME.GIF" WIDTH="37" HEIGHT="37" ALIGN="BOTTOM"BORDER="0"></A><A HREF="index.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/index.htm"><IMG SRC="BLANTOC.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANTOC.GIF"WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="ch14rv2.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/htm/ch14rv2.htm"><IMG SRC="BLANNEXT.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANNEXT.GIF"WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A></H1><H1></H1><UL> <LI><A HREF="#Heading1">Day 14</A> <UL> <LI><A HREF="#Heading2">Special Classes and Functions</A> <UL> <LI><A HREF="#Heading3">Static Member Data</A> <LI><A HREF="#Heading4">Listing 14.1. Static member data.</A> <LI><A HREF="#Heading5">Listing 14.2. Accessing static members without an object</A><A HREF="#Heading6">.</A> <LI><A HREF="#Heading7">Listing 14.3. Accessing static members using non-static member functions</A><A HREF="#Heading8">.</A> <LI><A HREF="#Heading9">Static Member Functions</A> <LI><A HREF="#Heading10">Listing 14.4. Static member functions</A><A HREF="#Heading11">.</A> <LI><A HREF="#Heading12">Static Member Functions</A> <LI><A HREF="#Heading13">Pointers to Functions</A> <LI><A HREF="#Heading14">Listing 14.5. Pointers to functions</A><A HREF="#Heading15">.</A> <LI><A HREF="#Heading16">Pointer to Function</A> <UL> <LI><A HREF="#Heading17">Why Use Function Pointers?</A> </UL> <LI><A HREF="#Heading18">Listing 14.6. Rewriting Listing 14.5 without the pointer to function</A><A HREF="#Heading19">.</A> <LI><A HREF="#Heading20">Shorthand Invocation</A> <UL> <LI><A HREF="#Heading21">Arrays of Pointers to Functions</A> </UL> <LI><A HREF="#Heading22">Listing 14.7. Demonstrates use of an array of pointers to functions</A><A HREF="#Heading23">.</A> <UL> <LI><A HREF="#Heading24">Passing Pointers to Functions to Other Functions</A> </UL> <LI><A HREF="#Heading25">Listing 14.8. Passing pointers to functions</A> <LI><A HREF="#Heading26">as function arguments.</A> <UL> <LI><A HREF="#Heading27">Using typedef with Pointers to Functions</A> </UL> <LI><A HREF="#Heading28">Listing 14.9. Using typedef to make pointers to functions more readable</A><A HREF="#Heading29">.</A> <LI><A HREF="#Heading30">Pointers to Member Functions</A> <LI><A HREF="#Heading31">Listing 14.10. Pointers to member functions</A><A HREF="#Heading32">.</A> <UL> <LI><A HREF="#Heading33">Arrays of Pointers to Member Functions</A> </UL> <LI><A HREF="#Heading34">Listing 14.11. Array of pointers to member functions</A><A HREF="#Heading35">.</A> <LI><A HREF="#Heading36">Summary</A> <LI><A HREF="#Heading37">Q&A</A> <LI><A HREF="#Heading38">Workshop</A> <UL> <LI><A HREF="#Heading39">Quiz</A> <LI><A HREF="#Heading40">Exercises</A> </UL> </UL> </UL></UL><P><HR SIZE="4"><H2 ALIGN="CENTER"><BR><A NAME="Heading1"></A><FONT COLOR="#000077">Day 14</FONT></H2><H2 ALIGN="CENTER"><A NAME="Heading2"></A><FONT COLOR="#000077">Special Classes andFunctions</FONT></H2><P>C++ offers a number of ways to limit the scope and impact of variables and pointers.So far you've seen how to create global variables, local function variables, pointersto variables, and class member variables. Today you learn<UL> <LI>What static member variables and static member functions are. <P> <LI>How to use static member variables and static member functions. <P> <LI>How to create and manipulate pointers to functions and pointers to member functions. <P> <LI>How to work with arrays of pointers to functions.</UL><H3 ALIGN="CENTER"><A NAME="Heading3"></A><FONT COLOR="#000077">Static Member Data</FONT></H3><P>Until now, you have probably thought of the data in each object as unique to thatobject and not shared among objects in a class. For example, if you have five <TT>Cat</TT>objects, each has its own age, weight, and other data. The age of one does not affectthe age of another.</P><P>There are times, however, when you'll want to keep track of a pool of data. Forexample, you might want to know how many objects for a specific class have been createdin your program, and how many are still in existence. Static member variables areshared among all instances of a class. They are a compromise between global data,which is available to all parts of your program, and member data, which is usuallyavailable only to each object.</P><P>You can think of a static member as belonging to the class rather than to theobject. Normal member data is one per object, but static members are one per class.Listing 14.1 declares a <TT>Cat</TT> object with a static data member, <TT>HowManyCats</TT>.This variable keeps track of how many <TT>Cat</TT> objects have been created. Thisis done by incrementing the static variable, <TT>HowManyCats</TT>, with each constructionand decrementing it with each destruction.</P><P><A NAME="Heading4"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.1. Staticmember data.</B></FONT><PRE><FONT COLOR="#0066FF">1: //Listing 14.1 static data members2:3: #include <iostream.h>4:5: class Cat6: {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 HowManyCats;13:14: private:15: int itsAge;16:17: };18:19: int Cat::HowManyCats = 0;20:21: int main()22: {23: const int MaxCats = 5; int i;24: Cat *CatHouse[MaxCats];25: for (i = 0; i<MaxCats; i++)26: CatHouse[i] = new Cat(i);27:28: for (i = 0; i<MaxCats; i++)29: {30: cout << "There are ";31: cout << Cat::HowManyCats;32: cout << " cats left!\n";33: cout << "Deleting the one which is ";34: cout << CatHouse[i]->GetAge();35: cout << " years old\n";36: delete CatHouse[i];37: CatHouse[i] = 0;38: }39: return 0;<TT>40: }</TT></FONT><FONT COLOR="#0066FF">Output: There are 5 cats left!Deleting the one which is 0 years oldThere are 4 cats left!Deleting the one which is 1 years oldThere are 3 cats left!Deleting the one which is 2 years oldThere are 2 cats left!Deleting the one which is 3 years oldThere are 1 cats left!Deleting the one which is 4 years old</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>On lines 5 to 17 the simplifiedclass <TT>Cat</TT> is declared. On line 12, <TT>HowManyCats</TT> is declared to bea static member variable of type <TT>int</TT>.</P><P>The declaration of <TT>HowManyCats</TT> does not define an integer; no storagespace is set aside. Unlike the non-static member variables, no storage space is setaside by instantiating a <TT>Cat</TT> object, because the <TT>HowManyCats</TT> membervariable is not in the object. Thus, on line 19 the variable is defined and initialized.</P><P>It is a common mistake to forget to define the static member variables of classes.Don't let this happen to you! Of course, if it does, the linker will catch it witha pithy error message such as the following:</P><PRE><FONT COLOR="#0066FF">undefined symbol Cat::HowManyCats</FONT></PRE><P>You don't need to do this for <TT>itsAge</TT>, because it is a non-static membervariable and is defined each time you make a <TT>Cat</TT> object, which you do hereon line 26.</P><P>The constructor for <TT>Cat</TT> increments the static member variable on line8. The destructor decrements it on line 9. Thus, at any moment, <TT>HowManyCats</TT>has an accurate measure of how many <TT>Cat</TT> objects were created but not yetdestroyed.</P><P>The driver program on lines 21-40 instantiates five <TT>Cat</TT>s and puts themin an array. This calls five <TT>Cat</TT> constructors, and thus <TT>HowManyCats</TT>is incremented five times from its initial value of <TT>0</TT>.</P><P>The program then loops through each of the five positions in the array and printsout the value of <TT>HowManyCats</TT> before deleting the current <TT>Cat</TT> pointer.The printout reflects that the starting value is <TT>5</TT> (after all, 5 are constructed),and that each time the loop is run, one fewer <TT>Cat</TT> remains.</P><P>Note that <TT>HowManyCats</TT> is public and is accessed directly by <TT>main()</TT>.There is no reason to expose this member variable in this way. It is preferable tomake it private along with the other member variables and provide a public accessormethod, as long as you will always access the data through an instance of <TT>Cat</TT>.On the other hand, if you'd like to access this data directly without necessarilyhaving a <TT>Cat</TT> object available, you have two options: keep it public, asshown in Listing 14.2, or provide a static member function, as discussed later inthis chapter.</P><P><A NAME="Heading5"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.2. Accessingstatic members without an object.</B></FONT><PRE><FONT COLOR="#0066FF">1: //Listing 14.2 static data members2:3: #include <iostream.h>4:5: class Cat6: {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 HowManyCats;13:14: private:15: int itsAge;16:17: };18:19: int Cat::HowManyCats = 0;20:21: void TelepathicFunction();22:23: int main()24: {25: const int MaxCats = 5; int i;26: Cat *CatHouse[MaxCats];27: for (i = 0; i<MaxCats; i++)28: {29: CatHouse[i] = new Cat(i);30: TelepathicFunction();31: }32:33: for ( i = 0; i<MaxCats; i++)34: {35: delete CatHouse[i];36: TelepathicFunction();37: }38: return 0;39: }40:41: void TelepathicFunction()42: {43: cout << "There are ";44: cout << Cat::HowManyCats << " cats alive!\n";<TT>45: }</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>Listing 14.2 is much likeListing 14.1 except for the addition of a new function, <TT>TelepathicFunction()</TT>.This function does not create a <TT>Cat</TT> object, nor does it take a <TT>Cat</TT>object as a parameter, yet it can access the <TT>HowManyCats</TT> member variable.Again, it is worth reemphasizing that this member variable is not in any particularobject; it is in the class as a whole, and, if public, can be accessed by any functionin the program.</P><P>The alternative to making this member variable public is to make it private. Ifyou do, you can access it through a member function, but then you must have an objectof that class available. Listing 14.3 shows this approach. The alternative, staticmember functions, is discussed immediately after the analysis of Listing 14.3.</P><P><A NAME="Heading7"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 14.3. Accessingstatic members using non-static member functions.</B></FONT><PRE><FONT COLOR="#0066FF">1: //Listing 14.3 private static data members2:3: #include <iostream.h>4:5: class Cat6: {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: virtual int GetHowMany() { return HowManyCats; }13:14:15: private:16: int itsAge;17: static int HowManyCats;18: };19:20: int Cat::HowManyCats = 0;21:22: int main()23: {24: const int MaxCats = 5; int i;25: Cat *CatHouse[MaxCats];26: for (i = 0; i<MaxCats; i++)27: CatHouse[i] = new Cat(i);28:29: for (i = 0; i<MaxCats; i++)30: {31: cout << "There are ";32: cout << CatHouse[i]->GetHowMany();33: cout << " cats left!\n";34: cout << "Deleting the one which is ";35: cout << CatHouse[i]->GetAge()+2;36: cout << " years old\n";37: delete CatHouse[i];38: CatHouse[i] = 0;39: }40: return 0;<TT>41: }</TT></FONT><FONT COLOR="#0066FF">Output: There are 5 cats left!Deleting the one which is 2 years oldThere are 4 cats left!Deleting the one which is 3 years oldThere are 3 cats left!Deleting the one which is 4 years oldThere are 2 cats left!Deleting the one which is 5 years oldThere are 1 cats left!Deleting the one which is 6 years old</FONT></PRE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -