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

📄 ch21rv3.htm

📁 vc的电子书
💻 HTM
📖 第 1 页 / 共 2 页
字号:
221:   T *  List<T>::operator[](int offSet) const
222:   {
223:    Node<T>* pNode = pHead;
224:
225:    if (!pHead)
226:       throw EmptyList();
227:
228:    if (offSet > itsCount)
229:       throw BoundsError();
230:
231:    for (int i=0;i<offSet; i++)
232:       pNode = pNode->itsNext;
233:
234:   return   pNode->itsObject;
235:   }
236:
237:   // find a given object in list based on its unique number (id)
238:   template <class T>
239:   T*   List<T>::Find(int & position, int ObjectNumber)  const
240:   {
241:    Node<T> * pNode = 0;
242:    for (pNode = pHead, position = 0;
243:          pNode!=NULL;
244:          pNode = pNode->itsNext, position++)
245:    {
246:       if (pNode->itsObject->GetObjectNumber() == ObjectNumber)
247:          break;
248:    }
249:    if (pNode == NULL)
250:       return NULL;
251:    else
252:       return pNode->itsObject;
253:   }
254:
255:   // insert if the number of the object is unique
256:   template <class T>
257:   void List<T>::Insert(T* pObject)
258:   {
259:    Node<T> * pNode = new Node<T>(pObject);
260:    Node<T> * pCurrent = pHead;
261:    Node<T> * pNext = 0;
262:
263:    int New =  pObject->GetObjectNumber();
264:    int Next = 0;
265:    itsCount++;
266:
267:    if (!pHead)
268:    {
269:       pHead = pNode;
270:       return;
271:    }
272:
273:    // if this one is smaller than head
274:    // this one is the new head
275:    if (pHead->itsObject->GetObjectNumber() > New)
276:    {
277:       pNode->itsNext = pHead;
278:       pHead = pNode;
279:       return;
280:    }
281:
282:    for (;;)
283:    {
284:       // if there is no next, append this new one
285:       if (!pCurrent->itsNext)
286:       {
287:          pCurrent->itsNext = pNode;
288:          return;
289:       }
290:
291:       // if this goes after this one and before the next
292:       // then insert it here, otherwise get the next
293:       pNext = pCurrent->itsNext;
294:       Next = pNext->itsObject->GetObjectNumber();
295:       if (Next > New)
296:       {
297:          pCurrent->itsNext = pNode;
298:          pNode->itsNext = pNext;
299:          return;
300:       }
301:       pCurrent = pNext;
302:    }
303:   }
304:
305:
306:   int main()
307:   {
308:    List<Part> theList;
309:    int choice;
310:    int ObjectNumber;
311:    int value;
312:    Part * pPart;
313:    while (1)
314:    {
315:       cout << "(0)Quit (1)Car (2)Plane: ";
316:       cin >> choice;
317:
318:       if (!choice)
319:          break;
320:
321:       cout << "New PartNumber?: ";
322:       cin >>  ObjectNumber;
323:
324:       if (choice == 1)
325:       {
326:          cout << "Model Year?: ";
327:          cin >> value;
328:          try
329:          {
330:             pPart = new CarPart(value,ObjectNumber);
331:          }
332:          catch (OutOfMemory)
333:          {
334:             cout << "Not enough memory; Exiting..." << endl;
335:             return 1;
336:          }
337:       }
338:       else
339:       {
340:          cout << "Engine Number?: ";
341:          cin >> value;
342:          try
343:          {
344:             pPart = new AirPlanePart(value,ObjectNumber);
345:          }
346:          catch (OutOfMemory)
347:          {
348:             cout << "Not enough memory; Exiting..." << endl;
349:             return 1;
350:          }
351:       }
352:       try
353:       {
354:          theList.Insert(pPart);
355:       }
356:       catch (NullNode)
357:       {
358:          cout << "The list is broken, and the node is null!" << endl;
359:          return 1;
360:       }
361:       catch (EmptyList)
362:       {
363:          cout << "The list is empty!" << endl;
364:          return 1;
365:       }
366:    }
367:    try
368:    {
369:       for (int i = 0; i < theList.GetCount(); i++ )
370:          cout << *(theList[i]);
371:    }
372:       catch (NullNode)
373:       {
374:          cout << "The list is broken, and the node is null!" << endl;
375:          return 1;
376:       }
377:       catch (EmptyList)
378:       {
379:          cout << "The list is empty!" << endl;
380:          return 1;
381:       }
382:       catch (BoundsError)
383:       {
384:          cout << "Tried to read beyond the end of the list!" << endl;
385:          return 1;
386:       }
387:   return 0;
<TT>388: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: (0)Quit (1)Car (2)Plane: 1
New PartNumber?: 2837
Model Year? 90

 (0)Quit (1)Car (2)Plane: 2
New PartNumber?: 378
Engine Number?: 4938

 (0)Quit (1)Car (2)Plane: 1
New PartNumber?: 4499
Model Year? 94

 (0)Quit (1)Car (2)Plane: 1
New PartNumber?: 3000
Model Year? 93

 (0)Quit (1)Car (2)Plane: 0

Part Number: 378
Engine No. 4938

Part Number: 2837
Model Year: 90

Part Number: 3000
Model Year: 93

Part Number 4499
Model Year: 94
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The Week 3 in Review listing
modifies the program provided in Week 2 to add templates, <TT>ostream</TT> processing,
and exception handling. The output is identical.<BR>
On lines 35-39, a number of exception classes are declared. In the somewhat primitive
exception handling provided by this program, no data or methods are required of these
exceptions; they serve as flags to the <TT>catch</TT> statements, which print out
a very simple warning and then exit. A more robust program might pass these exceptions
by reference and then extract context or other data from the exception objects in
an attempt to recover from the problem.</P>

<P>On line 44, the abstract base class <TT>Part</TT> is declared exactly as it was
in Week 2. The only interesting change here is in the non-class member <TT>operator&lt;&lt;()</TT>,
which is declared on lines 69-73. Note that this is neither a member of <TT>Part</TT>
nor a friend of part, it simply takes a <TT>Part</TT> reference as one of its arguments.</P>
<P>You might want to have <TT>operator&lt;&lt;</TT> take a <TT>CarPart</TT> and an
<TT>AirPlanePart</TT> in the hopes that the correct <TT>operator&lt;&lt;</TT> would
be called, based on whether a car part or an airplane part is passed. Since the program
passes a pointer to a part, however, and not a pointer to a car part or an airplane
part, C++ would have to call the right function based on the real type of one of
the arguments to the function. This is called contravariance and is not supported
in C++.</P>
<P>There are only two ways to achieve polymorphism in C++: function polymorphism
and virtual functions. Function polymorphism won't work here because in every case
you are matching the same signature: the one taking a reference to a <TT>Part</TT>.</P>
<P>Virtual functions won't work here because <TT>operator&lt;&lt;</TT> is not a member
function of <TT>Part</TT>. You can't make <TT>operator&lt;&lt;</TT> a member function
of <TT>Part</TT> because you want to invoke</P>
<PRE><FONT COLOR="#0066FF">cout &lt;&lt; thePart</FONT></PRE>
<P>and that means that the actual call would be to <TT>cout.operator&lt;&lt;(Part&amp;)</TT>,
and <TT>cout</TT> does not have a version of <TT>operator&lt;&lt;</TT> that takes
a <TT>Part</TT> reference!</P>
<P>To get around this limitation, the Week 3 program uses just one <TT>operator&lt;&lt;</TT>,
taking a reference to a <TT>Part</TT>. This then calls <TT>Display()</TT>, which
is a virtual member function, and thus the right version is called.</P>
<P>On lines 129-142, <TT>Node</TT> is defined as a template. It serves the same function
as <TT>Node</TT> did in the Week 2 Review program, but this version of <TT>Node</TT>
is not tied to a <TT>Part</TT> object. It can, in fact, be the node for any type
of object.</P>
<P>Note that if you try to get the object from <TT>Node</TT>, and there is no object,
this is considered an exception, and the exception is thrown on line 174.</P>
<P>On lines 181-197, a generic <TT>List</TT> class template is defined. This <TT>List</TT>
class can hold nodes of any objects that have unique identification numbers, and
it keeps them sorted in ascending order. Each of the list functions checks for exceptional
circumstances and throws the appropriate exceptions as required.</P>
<P>On lines 306-388, the driver program creates a list of two types of <TT>Part</TT>
objects and then prints out the values of the objects in the list by using the standard
streams mechanism.

<DL>
	<P>
</DL>

<P ALIGN="CENTER"><A HREF="ch20.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/htm/ch20.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"><IMG
SRC="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="#heading1"><IMG SRC="BLANTOP.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANTOP.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A>


</BODY>

</HTML>

⌨️ 快捷键说明

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