C++/CLI的泛型

C++/CLI新增的泛型机制类似于本地C++中的模板,但是又区别于模板,主要表现在新的泛型机制是运行时泛型,可以避免编译时泛型的代码膨胀。

以下内容摘自:http://blog.youkuaiyun.com/luqinghua/article/details/1551418

C++/CLI 支持两大泛型机制,三种泛型应用
1 )编译时机制  ---- ISO-C++ 模版
                   ----  编译时实例化
                   ----  基于签名的隐式约束
2 )运行时泛型  ---- CLI 泛型
                   ----  运行时实例化
                   ----  基于“基类  +  接口”的显式约束。
应用:
(1)          ISO-C++ 本地类型上应用模板(编译时泛型)
(2)          CLI 托管类型上应用模板(编译时泛型)
(3)          CLI 托管类型上应用 CLI 泛型。
(4)         C++/CLI 所支持的泛型程序库
(1)          标准模板库  STL
(2)          CLI 标准模板库  STL.NET
(3)          CLI 泛型库  System::Collections::Generic
eg:
         generic <typename T>
         public ref class Stack
         {
         public: T tem;
                            T Pop()
                            {
                                     return tem;
                            }
                             String^ GetStr()
                            {
                                     // 用追踪句柄来调用函数成员
                                     return tem->ToString();
                            }
                            void Push(T t)
                            {}
                            int Size()
                            {
                                     return 0;
                            };
         };
         publicvoid TestEvery()
                   {
                            Stack<System::String^>^ sta = gcnew                                                   Stack<System::String^>();
         }
CLI  泛型机制:
第一轮编译时,编译器只为 Stack<T> 类型产生泛型版的 IL 代码与元数据 ---- 并进行泛型类型的实例化, 在中间只充当占位符。
JIT 编译时,当 JIT 编译器第一次遇到 Stack<System::String^> 时,将 String^ 替换“泛型版” IL 代码与元数据中的 T---- 进行泛型类型的实例化。
CLI 为所有类型参数为 ref class  的泛型类型产生同一份代码,但是如果参数类型为 value class  ,针对每一个不同的 value class  CLI 将产生一份独立的代码。
CLI  泛型机制特点
(1)          由于 CLI 泛型的实例化会推迟到 JIT 编译阶段进行,因此未经实例化的泛型类型会存在于编译生成的程序集中,成为一个类型实体。
(2)          如果实例化泛型类型的参数相同,那么 JIT 编译器会重复使用该类型,因此 CLI 泛型可以避免 C++  模板可能导致的代码膨胀问题。
(3)          CLI 泛型类型携带有丰富的元数据,因此可以通过反射来获取程序集中的泛型类型的相关信息。
CLI 泛型适用于四种对象:
(1)          CLI 托管类型 (包括引用类型和值类型)
(2)          CLI 接口类型
(3)          CLI 委托类型
(4)          函数 (成员函数,全局函数)
CLI 不适用于:
(1)          ISO-C++  本地类型  ----  本地类型没有 CLI 泛型的条件 :元数据的信息
(2)          CLI 属性,事件,索引器,操作符
A.                  CLI 泛型接口
         generic <typename Item>
         public interface class IList
         {
                   void ListCount();
         };
         generic <typename Item>
         ref class MyList : public IList<Item>
         {
         publicvirtual void ListCount()
                  {
                            Console::WriteLine("Call interface method !");
                   }
};
B.                  CLI 泛型委托
         //delegate
         generic <typename type>
         public delegate void MyDelegate(type ty);
 
         public ref struct MyDeleClass
         {
         public ref class DeleClass
         {
         publicstatic void GetInt(int i)
                   {
                            Console::WriteLine("i is ");
                   }
         publicvoid UserDele()
                   {
                            MyDelegate<int>^ dele = gcnew MyDelegate<int>(&DeleClass::GetInt);
                            dele(200);
                   }
};                           
C.                  CLI 泛型函数
               ref  class Megedata
         {              
                 generic  <typename T>
                void ControType(T t)
                {
                }
         };
         调用泛型函数:
               Megedata^ mana = gcnew Megedata();
         mana->ControType<int>(2);
泛型约束
(1)          类型参数约束:
         A CLI  泛型采用“基类  +  接口”的方式来实现对类型参数的“显式约束”。
         B CLI  泛型不支持 ISO-C++ 模板所使用的基于“签名”的“隐式约束”。
         C .虽然获得了编译时类型安全和相关代码清晰,但却丧失了很多灵活性(无法使用静态函数,操          作符、字符、内嵌类型等)
2 ) 结束代码示例
          generic  <typename T>
          ref  class MyCollect
          {
                    T t;
                    public  void Add()
                    {};
          };
         T  实现  IComparable  接口
 CLI 泛型与 C++ 模板:
          两个根本性的区别:
(1)          C++ 模板为编译时实例化, CLI 泛型为运行时实例化
(2)          C++ 模板为基于“签名”的隐式约束, CLI 泛型为基于“基类  +  接口”的显式约束。
CLI 泛型不支持如下 C++ 模板中的机制:
(1)          非参数类型
(2)          缺省参数值
(3)          模板的模板参数
(4)          模板特化及部分特化。
A 非参数类型
                   template  <class type,int size>
                   public  ref class StackInfor
                   {
                             array <type>^ m_stack;
                             int  top;
                   public : StackInfor() : top(0)
                              {
                                       m_stack = gcnew array<type>(size);
                              }
                   };
                  // 调用 StackInfor
                   StackInfor<int,100>^ stack = gcnew StackInfor<int,100>();
                   B .缺省参数值
                   template  <class type,int size  = 256 >
                    public  ref class StackInfor
                    {
                              array <type>^ m_stack;
                              int  top;
                    public : StackInfor() : top(0)
                              {
                                       m_stack = gcnew array<type>(size);
                             }
                   };
                   // 调用 StackInfor
                    StackInfor<int>^ stack = gcnew StackInfor<int>();
                    StackInfor<int 100 >^ stack = gcnew StackInfor<int 100 >();
                   C .模板的模板参数
                    template <template<class T>class TT,class t>
                    ref  class MyClass
                    {
                              TT<t> m_data;
                    };
 
                    template  <class t>
                    public  ref class Apple
                    {};
 
                    ref  class Use
                    {
                    public void Test()
                              {
                                       MyClass<Apple,int> ^m_clas = gcnew MyClass<Apple,int>();
                              }
                    };
                   D .模板的局部特化
                    //-----------
                    template  <long B,long E>
                    ref  struct Power
                    {
                              literal  long value = B * Power<B,E-1>::value;
                    };
                    template  <long B>
                    ref  struct Power<B,0>
                    {
                              literal  long value = 1;
                    };
                   // 调用
                    Console::Write(Power<2,10>::value);
另一篇参考: http://blog.youkuaiyun.com/anenyang/article/details/7035507

官方知识库:http://technet.microsoft.com/zh-cn/interopmigration/8z2kbc1y

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值