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

📄 apf.htm

📁 VC 21天 学习VC 的好东西
💻 HTM
📖 第 1 页 / 共 5 页
字号:
	<TR ALIGN="LEFT" VALIGN="TOP">		<TD ALIGN="LEFT">CPtrList</TD>		<TD ALIGN="LEFT">void*--Pointers to memory addresses holding any type of data.</TD>	</TR>	<TR ALIGN="LEFT" VALIGN="TOP">		<TD ALIGN="LEFT">CStringList</TD>		<TD ALIGN="LEFT">CString--Text strings.</TD>	</TR></TABLE></P><P>Linked lists are several objects linked to each other in a sequential fashionlike carriages on a train. There is a definite head and tail position, but everyother element knows only its immediate neighbor. A POSITION variable keeps trackof a current position in a list. You can declare multiple POSITION variables to trackdifferent places in the same list. Each list's member functions then use a POSITIONvariable to find the head, tail, or next and previous elements in the list.</P><P>You can add elements to a list by calling the AddHead() or AddTail() functionsor by inserting items into a specific position using the InsertBefore() or InsertAfter()functions. Each function then returns a POSITION value to indicate the position ofthe new added item.</P><P>For example, you can construct a four-element list of CString items like this:</P><P><PRE>CStringList listMyStrings;POSITION pos;pos = listMyStrings.AddHead(&quot;Hand&quot;);listMyStrings.AddTail(&quot;Forearm&quot;);listMyStrings.InsertBefore(pos,&quot;Fingers&quot;);listMyStrings.AddTail(&quot;Elbow&quot;);</PRE><P>These lines will produce a linked list of CString strings from head to tail likethis:</P><P><PRE>Fingers-Hand-Forearm-Elbow</PRE><P>You can also pass other similar list objects to the AddHead() and AddTail() functionsto add another list to the head or tail of the current list.</P><P>When you've constructed a list, you can iterate through its members using a POSITIONvariable. The head or tail positions can be found by calling GetHeadPosition() orGetTailPosition(), respectively. These functions both return a POSITION value indicatingthe current position in the list. You can then pass the POSITION variable as a referenceto GetNext() or GetPrev() to find the next or previous element in the list. Thesefunctions then return the specific object and adjust the current position. When theend of the list is reached, the POSITION variable will be set to NULL.</P><P>For example, the following lines will iterate through the previous listMyStrings,displaying each element in turn:</P><P><PRE>POSITION posCurrent = listMyStrings.GetHeadPosition();while(posCurrent) TRACE(&quot;%s\n&quot;, listMyStrings.GetNext(posCurrent);</PRE><P>You can find specific list elements by using the Find() function, which returnsa POSITION value if the search parameter you pass is found. You can also optionallypass a position value, from which you can start the search.</P><P>For example, you can search for the string Fingers in the previous list by callingthe Find() function like this:</P><P><PRE>POSITION posFingers = Find(&quot;Fingers&quot;);</PRE><P>If the searched-for element isn't found, a NULL value will be returned.</P><P>There is also a FindIndex() function that will find the nth element from the headof the list (where n is the passed parameter).</P><P>You can find out how many elements are in the list by calling the GetCount() memberfunction, which returns the number of elements and doesn't need any parameters.</P><P>The value of elements at a specific position can be retrieved or reset by usingthe GetAt() and SetAt() functions, which are used in a similar way to their arrayequivalents, but by passing a POSITION value rather than an array index.</P><P>You can remove elements from the list by using the RemoveAt() function and passingthe POSITION value to identify the element to be removed. For example, to removethe Fingers item from the previous example, you might code the following:</P><P><PRE>RemoveAt(posFingers);</PRE><H3><A NAME="Heading4"></A>Using the Map Classes</H3><P>The map classes work by associating a type value (or element) with a key valuethat can be used to look up the element. The various map classes, and their key valuesand associated element types, are shown in Table F.3.</P><P><H4>TABLE F.3.&nbsp;THE MAP-BASED COLLECTION CLASSES.</H4><P><TABLE BORDER="1" WIDTH="100%">	<TR>		<TD WIDTH="33%"><I>Class Name</I></TD>		<TD WIDTH="33%"><I>Key Type</I></TD>		<TD WIDTH="34%"><I>Element Type</I></TD>	</TR>	<TR>		<TD WIDTH="33%">CMapWordToOb</TD>		<TD WIDTH="33%">WORD--16-bit</TD>		<TD WIDTH="34%">CObject--</TD>	</TR>	<TR>		<TD WIDTH="33%">&nbsp;</TD>		<TD WIDTH="33%">unsigned value</TD>		<TD WIDTH="34%">CObject-derived objects</TD>	</TR>	<TR>		<TD WIDTH="33%">CMapWordToPtr</TD>		<TD WIDTH="33%">WORD--16-bit</TD>		<TD WIDTH="34%">void*--</TD>	</TR>	<TR>		<TD WIDTH="33%">&nbsp;</TD>		<TD WIDTH="33%">unsigned value</TD>		<TD WIDTH="34%">Pointers to memory</TD>	</TR>	<TR>		<TD WIDTH="33%">CMapPtrToPtr</TD>		<TD WIDTH="33%">void*--</TD>		<TD WIDTH="34%">void*--</TD>	</TR>	<TR>		<TD WIDTH="33%">&nbsp;</TD>		<TD WIDTH="33%">Pointers to memory</TD>		<TD WIDTH="34%">Pointers to memory</TD>	</TR>	<TR>		<TD WIDTH="33%">CMapPtrToWord</TD>		<TD WIDTH="33%">void*--</TD>		<TD WIDTH="34%">WORD--16-bit</TD>	</TR>	<TR>		<TD WIDTH="33%">&nbsp;</TD>		<TD WIDTH="33%">Pointers to memory</TD>		<TD WIDTH="34%">unsigned value</TD>	</TR>	<TR>		<TD WIDTH="33%">CMapStringToOb</TD>		<TD WIDTH="33%">CString--</TD>		<TD WIDTH="34%">CObject--</TD>	</TR>	<TR>		<TD WIDTH="33%">&nbsp;</TD>		<TD WIDTH="33%">Text strings</TD>		<TD WIDTH="34%">CObject-derived objects</TD>	</TR>	<TR>		<TD WIDTH="33%">CMapStringToPtr</TD>		<TD WIDTH="33%">CString--</TD>		<TD WIDTH="34%">void*--</TD>	</TR>	<TR>		<TD WIDTH="33%">&nbsp;</TD>		<TD WIDTH="33%">Text strings</TD>		<TD WIDTH="34%">Pointers to memory</TD>	</TR>	<TR>		<TD WIDTH="33%">CMapStringToString</TD>		<TD WIDTH="33%">CString--</TD>		<TD WIDTH="34%">CString--</TD>	</TR>	<TR>		<TD WIDTH="33%">&nbsp;</TD>		<TD WIDTH="33%">Text strings</TD>		<TD WIDTH="34%">Text strings</TD>	</TR></TABLE></P><P>You can insert elements into a map by using the SetAt() function and passing akey value as the first parameter and your element value as the second. For example,if you must store your own CObject-derived objects indexed by a string value, youcan use the CMapStringToOb class and add elements like this:</P><P><PRE>CMapStringToOb mapPlanetDetails;mapPlanetDetails.SetAt(&quot;Mercury&quot;,new CPlanetDets  &Acirc;(4878, 0.054, 57.91, 87.969));mapPlanetDetails.SetAt(&quot;Venus&quot;,new CPlanetDets  &Acirc;(12100, 0.815, 108.21, 224.701));mapPlanetDetails.SetAt(&quot;Earth&quot;,new CPlanetDets  &Acirc;(12756, 1.000, 149.60, 365.256));</PRE><P>In the previous example, CPlanetDets is a CObject-derived class with a constructorthat takes four planetary detail parameters. The new objects are then associatedwith the planet names as keys.</P><P>You can also use the [ ] operator overload instead of SetAt() by enclosing thekey value inside the square brackets like this:</P><P><PRE>mapPlanetDetails[&quot;Mars&quot;] = new CPlanetDets  &Acirc;(6762, 0.107, 227.94, 686.98);</PRE><P>After you have set data to a map, you can retrieve it by calling the Lookup()member function by passing the key value and a reference to a variable to hold theassociated element value if found. If the element isn't found, a FALSE value is returnedfrom Lookup(). For example, to retrieve details about a planet from the previousexample, you can use these lines:</P><P><PRE>CPlanetDets* pMyPlanet = NULL;if (mapPlanetDetails.Lookup(&quot;Earth&quot;,(CObject*&amp;)pMyPlanet))    TRACE(&quot;Sidereal Period = %d days\n&quot;, pMyPlanet-&gt;m_dSidereal);</PRE><P>The (CObject*&amp;) cast is used to cast the pMyPlanet object pointer to a genericCObject pointer reference.</P><P>The GetCount() function will return the number of elements current in the map.These elements can be removed by calling the RemoveKey() function and passing thekey of the element to be removed like this:</P><P><PRE>mapPlanetDetails.RemoveKey(&quot;Jupiter&quot;);</PRE><P>Remember to delete the allocated objects. RemoveKey() just removes the pointerto the object--not the object itself--so it won't free up the used memory. You canalso remove all the elements by calling RemoveAll().</P><P>You can iterate through the list of associations using the GetNextAssoc() function,which needs parameters that reference a current POSITION holding variable, a keyvariable, and an element variable. You can find the position of the first elementby calling GetFirstPosition(), which returns the POSITION value for the first element.To iterate through the associations, you might code the following:</P><P><PRE>POSITION pos = mapPlanetDetails.GetStartPosition();while(pos!=NULL){CString strPlanet;CPlanet* pMyPlanet;mapPlanetDetails.GetNextAssoc(pos,strPlanet, (CObject*&amp;)pMyPlanet);TRACE(&quot;%s has a diameter of %d km\n&quot;,strPlanet, pMyPlanet-&gt;m_dDiameter);}</PRE><P>When GetNextAssoc() returns, pos will hold the position for the next associationor NULL if there are no more. The key and element values (strPlanet and pMyPlanetin the previous example) will be set to each key-element pair in turn.</P><P>Because of a map's capability to retrieve sparse data quickly and efficiently,it is often advantageous to use a map as a memory cache for a slow database lookup.</P><P>For example, in the following lines, the planet details associated with strPlanetNameare required. When first called, this code won't have a mapped version of the requiredplanet, so it will have to call GetPlanetFromSlowDB() to find it. Because it thenstores the retrieved planet in the mapPlanetDetails map, when it is next called withthe same strPlanetName, the details can be quickly returned from the cached versionin memory:</P><P><PRE>CPlanetDets* pMyPlanet = NULL;if (mapPlanetDetails.Lookup(strPlanetName,   &Acirc;(CObject*&amp;)pMyPlanet) == FALSE){pMyPlanet = GetPlanetFromSlowDB(strPlanetName);mapPlanetDetails.SetAt(strPlanetName,pMyPlanet);}return pMyPlanet;</PRE><P>This technique is easy to implement and can transform your application's speedwhen you are using slow retrieval devices such as databases or files.</P><P><H3><B>Creating Custom Collection Classes</B></H3><P>You might want to customize the collection classes to use your own objects ratherthan the generic CObject-derived classes. Customization offers several benefits becauseyou can make an array, list, or map that will accept and return only your specifictype of object. If you accidentally try to add the wrong sort of object to a customizedarray, list, or map, the compiler will issue an error message to notify you. Theother advantage is that you don't have to cast generic CObject* pointers (that is,from a CObArray) back to your specific object to use it.</P><P>This sort of customization is known as <I>type-safety</I>; in large programs itcan be invaluable for stopping accidental assignments of the wrong class. A set oftemplates, CArray, Clist, and CMap, lets you easily create an array, list, or mapto store, use, and return objects of your specified type only. Templates are a complexsubject, but you don't have to worry about writing templates; the MFC-provided templatesdefined in the afxtempl.h header file will do for these type-safe collection classes.For the scope of this section, it is best to think of templates as large macros thatgenerate lots of code based on your parameters when compiled.</P><P>The templates will give you access to all the normal functions in the array, list,or map classes discussed in the previous sections. However, instead of using genericCObject-based parameters and returned values, you can define your own types as parametersand return values.</P><P>To use the templates in your program, you'll need to include the following headerline in each module (.cpp/.h file) that uses the template definitions:</P><P><PRE>#include &quot;afxtempl.h&quot;</PRE><P>You can then define your own custom type-safe class using the template syntaxlike this for an array of custom objects:</P><P><PRE>CArray&lt;CMyCustomClass*, CMyCustomClass *&gt; myCustomClassArray;</PRE><P>The &lt; and &gt; symbols used in the definition should be thought of as anglebrackets (not greater-than or less-than conditional operators). The previous lineuses the CArray template to create an instance of myCustomClassArray. The first CMyCustomClass*parameter specifies types of object pointers you want the array to return when youuse GetAt() and other access functions. The second CMyCustomClass* specifies thetype that should be used for the input parameter definitions. Then all the functionsthat store objects, such as SetAt() and Add(), will accept only pointers to objectsof your specific CMyCustomClass.</P><P>For example, you can create an array that takes and returns only pointers to thespecific CPlanetDets class, defined (and implemented) like this:</P><P><PRE>class CPlanetDets : public CObject{public:CPlanetDets(double dDiameter,double dGravity,&Acirc;double dDistFromSun,double dSidereal):    m_dDiameter(dDiameter), m_dGravity(dGravity),    m_dDistFromSun(dDistFromSun), m_dSidereal(dSidereal) {}  double m_dDiameter,m_dGravity,m_dDistFromSun,m_dSidereal;};</PRE><P>To declare a type-safe CArray-based array called myPlanetArray, you can then codethe following line:</P><P><PRE>CArray&lt;CPlanetDets*,CPlanetDets*&gt; myPlanetArray;</PRE><P>This declares that myPlanetArray can only accept pointers to a CPlanetDets objectand return pointers to a CPlanetDets object. You might then use the new array likethis:</P><P><PRE>myPlanetArray.Add(new CPlanetDets  &Acirc;(4878, 0.054, 57.91, 87.969));myPlanetArray.Add(new CPlanetDets  &Acirc;(12100, 0.815, 108.21, 224.701));myPlanetArray.Add(new CPlanetDets  &Acirc;(12756, 1.000, 149.60, 365.256));for(int i=0;i&lt;myPlanetArray.GetSize();i++)   TRACE(&quot;Diameter = %f\n&quot;, myPlanetArray[i]-&gt;m_dDiameter);</PRE>

⌨️ 快捷键说明

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