设为首页 加入收藏

TOP

9.9.9 通用类(1)
2013-10-07 12:44:17 来源: 作者: 【 】 浏览:64
Tags:9.9.9 通用

9.9.9  通用类(1)

C++(www.cppentry.com)/CLI给我们提供了定义通用类的功能,具体类将在运行时通过实例化通用类产生。我们可以定义通用数值类、通用引用类、通用接口类和通用委托。定义通用类的方法是使用一个或多个形参,这与第6章定义通用函数的方法相似。

例如,我们可以像下面这样,定义Ex9_14示例中Stack类的通用版本:

  1. // Stack.h for Ex9_21  
  2. // A generic pushdown stack  
  3.  
  4. generic<typename T> ref class Stack  
  5. {  
  6. private:  
  7. // Defines items to store in the stack  
  8. ref struct Item  
  9. {  
  10. T Obj;  // Handle for the object in this item  
  11. Item^ Next; // Handle for next item in the stack or nullptr  
  12.  
  13. // Constructor  
  14. Item(T obj, Item^ next): Obj(obj), Next(next){}  
  15. };  
  16.  
  17. Item^ Top; // Handle for item that is at the top  
  18.  
  19. public:  
  20. // Push an object on to the stack  
  21. void Push(T obj)  
  22. {  
  23. Top = gcnew Item(obj, Top);     // Create new item and make it the top  
  24. }  
  25.  
  26. // Pop an object off the stack  
  27. T Pop()  
  28. {  
  29. if(Top == nullptr) // If the stack is empty  
  30. return T();     // return null equivalent  
  31. obj = Top->Obj; // Get object from item  
  32. TopTop = Top->Next;    // Make next item the top  
  33. return obj;  
  34. }  
  35. }; 

该类的通用版本现在有个类型形参T。注意,我们在指定该形参时可以使用class关键字代替typename关键字,二者在此处的上下文中没有区别。当使用通用类类型时,类型实参将代替形参T,T是通过类定义由类型实参代替的,因此与原来版本相比通用类类型的主要优点是更加安全,但不会丧失任何灵活性。原来类的Push()成员可接受任何句柄,因此我们可以将MyClass^类型、String^类型或任何句柄类型的对象混合压入相同的堆栈,但通用类实例的Push()函数只能接受实参类型的对象以及以实参为基类的类型的对象。

我们看一下Pop()函数的实现。如果栈顶项为空,原来的版本将返回nullptr,但我们在返回类型为形参的情况下不能返回nullptr,因为类型实参可能是数值类型。解决方法是返回T(),以调用类型T中无参数的构造函数,这样做的结果等价于为数值类型返回0,为句柄类型返回nullptr。

注意:

我们可以用第6章为通用函数指定约束的相同方式,使用where关键字来指定对通用类类型形参的约束。

如下所示,我们可以用Stack<>通用类型创建一个存储Box对象句柄的堆栈:

  1. Stack<Box^>stack = gcnew Stack<Box^>

类型实参Box^处于尖括号之间,该语句将在CLR堆上创建一个Stack<Box^>对象。该对象允许将Box^类型以及任何以Box为直接或间接基类的类型的句柄压入堆栈。我们可以用Ex9_14的修订版来试一试。

试一试:使用通用类类型

创建一个新的名为Ex9_21的CLR控制台程序,然后将Container.h、Box.h和GlassBox.h这3个头文件从Ex9_14复制到本项目的目录中。在Solution Explorer选项卡中右击Header Files,从弹出的上下文菜单中选择Add | Existing Item,将这些头文件添加到项目中。然后,我们可以给该项目添加一个新的头文件Stack.h,并输入前面介绍的通用Stack类定义。不要忘记在该文件开始处添加#pragma once指令。

  1. // Ex9_21.cpp : main project file.  
  2.  
  3. // Using a nested class to define a stack  
  4.  
  5. #include "stdafx.h"  
  6. #include "Box.h" // For Box and Container  
  7. #include "GlassBox.h"   // For GlassBox (and Box and Container)  
  8. #include "Stack.h" // For the generic stack class  
  9.  
  10. using namespace System;  
  11.  
  12. int main(array<System::String ^> ^args)  
  13. {  
  14. array<Box^>boxes = { gcnew Box(2.0, 3.0, 4.0),  
  15.                               gcnew GlassBox(2.0, 3.0, 4.0),  
  16.                               gcnew Box(4.0, 5.0, 6.0),  
  17.                             gcnew GlassBox(4.0, 5.0, 6.0)  
  18.                            };  
  19. Console::WriteLine(L"The array of boxes have the following volumes:");  
  20. for each(Box^ box in boxes)  
  21. box->ShowVolume();  // Output the volume of a box  
  22. Console::WriteLine(L"\nNow pushing the boxes on the stack...");  
  23.  
  24. Stack<Box^>stack = gcnew Stack<Box^>;     // Create the stack  
  25. for each(Box^ box in boxes)  
  26. stack->Push(box);  
  27.  
  28. Console::WriteLine(  
  29.      L"Popping the boxes off the stack presents them in reverse order:");  
  30. Box^ item;  
  31. while((item = stack->Pop()) != nullptr)  
  32. safe_cast<Container^>(item)->ShowVolume();  
  33.  
  34. // Try the generic Stack type storing integers  
  35. Stack<int>numbers = gcnew Stack<int>;     // Create the stack  
  36. Console::WriteLine(L"\nNow pushing integers on to the stack:");  
  37. for(int i = 2 ; i<=12 ; i += 2)  
  38. {  
  39. Console::Write(L"{0,5}",i);  
  40. numbers->Push(i);  
  41. }  
  42. int number;  
  43. Console::WriteLine(L"\n\nPopping integers off the stack produces:");  
  44. while((number = numbers->Pop()) != 0)  
  45. Console::Write(L"{0,5}",number);  
  46.  
  47. Console::WriteLine();  
  48. return 0;  

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇9.9.9 通用类(2) 下一篇详细阐述JSON结构的格式说明特点

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: