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;
};
};
public: void TestEvery()
{
Stack<System::String^>^ sta = gcnew
Stack<System::String^>();
}
CLI
泛型机制:
第一轮编译时,编译器只为
Stack<T>
类型产生泛型版的
IL
代码与元数据
----
并进行泛型类型的实例化,
T
在中间只充当占位符。
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>
{
public: virtual 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
{
public: static void GetInt(int i)
{
Console::WriteLine("i is ");
}
public: void 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