e股脑电脑教程网
  • 首 页
  • 操作系统
  • 应用软件
  • 下载工具
  • 影音视频
  • 办公软件
  • 媒体制作
  • 网站建设
  • 平面设计
  • 数据库
  • 程序开发
  • 视频教程
编辑推荐: | 文章搜索:
您现在的位置: e股脑 >> 程序开发 >> ASP.net教程 >> C++/CLR泛型与C++模板之间的对比 >> 教程正文
 
教程搜索
 
 
相关教程
  • C++/CLI实战——HELLO
  • VC编写简单的序列号(SN)填写器
  • Visual Studio 2005体验泛型编程
  • C++/CLI基本数据类型探索
  • 用托管C++编写Windows服务
  • Visual C++ 2005图像编程之属性设置栏
  • Visual C++ 2005图像编程之工具栏
  • Visual C++ 2005图像编程之预备知识
  • 把其他C/C++编译器集成到VC2005中
  • VC.NET实现清爽便利的Windows游戏窗口
  • C++:最强大的.NET语言之可访问性
  • C++:最强大的.NET语言之装箱
  • C++:最强大的.NET语言之内存与资源
  • C++:最强大的.NET语言之对象构造
  • Visual C++2005中开发自定义绘图控件
  • C++/CLI程序进程之间的通讯
 
 

图文教程


  • Windows抢了谁的饭碗 非主流操作系统To

  • 地球还是火星 平常心看“非主流”

  • 综合运用Office 2007批量制作奖状

  • 没有系统盘如何才能修复受损系统?

  • 巧妙运用Excel中边界的附加功能!
 
 
赞 助 商
 
 
C++/CLR泛型与C++模板之间的对比
  • 来源:e股脑
  • 点击次数:
  • 更新时间:2007-8-9

Visual Studio 2005把泛型编程的类型参数模型引入了微软.NET框架组件。C++/CLI支持两种类型参数机制--通用语言运行时(CLR)泛型和C++模板。本文将介绍两者之间的一些区别--特别是参数列表和类型约束模型之间的区别。

参数列表又回来了

参数列表与函数的信号(signature)类似:它标明了参数的数量和每个参数的类型,并把给每个参数关联一个唯一的标识符,这样在模板定义的内部,每个参数就可以被唯一地引用。

参数在模板或泛型的定义中起占位符(placeholder)的作用。用户通过提供绑定到参数的实际值来建立对象实例。参数化类型的实例化并非简单的文本替代(宏扩展机制就是使用文本替代的)。相反地,它把实际的用户值绑定到定义中的相关的形式参数上。

在泛型中,每个参数都表现为Object类型或衍生自Object的类型。在本文后面你可以看到,这约束了你可能执行的操作类型或通过类型参数声明的对象。你可以通过提供更加明确的约束来调整这些约束关系。这些明确的约束引用那些衍生出实际类型参数的基类或接口集合。

模板除了支持类型参数之外,还支持表达式和模板参数。此外,模板还支持默认的参数值。这些都是按照位置而不是名称来分解的。在两种机制之下,类型参数都是与类或类型名称关键字一起引入的。

参数列表的额外的模板功能

模板作为类型参数的补充,允许两种类型的参数:非类型(non-type)参数和模板参数。我们将分别简短地介绍一下。

非类型参数受常数表达式的约束。我们应该立即想到它是数值型或字符串常量。例如,如果选择提供固定大小的堆栈,你就可能同时指定一个非类型的大小参数和元素类型参数,这样就可以同时按照元素类别和大小来划分堆栈实例的类别。例如,你可以在代码1中看到带有非类型参数的固定大小的堆栈。

代码1:带有非类型固定大小的堆栈

template <class elemType, int size>

public ref class tStack

{

array<elemType> ^m_stack;

int top;

public:

tStack() : top( 0 )

{ m_stack = gcnew array<elemType>( size ); }

};

此外,如果模板类设计者可以为每个参数指定默认值,使用起来就可能方便多了。例如,把缓冲区的默认大小设置为1KB就是很好的。在模板机制下,可以给参数提供默认值,如下所示:

// 带有默认值的模板声明

template <class elemType, int size = 1024>

public ref class FixedSizeStack {};

用户可以通过提供明确的第二个值来重载默认大小值:

// 最多128个字符串实例的堆栈

FixedSizeState<String^, 128> ^tbs = gcnew FixedSizeStack<String^, 128>;


否则,由于没有提供第二个参数,它使用了相关的默认值,如下所示:

// 最多1024个字符串实例的堆栈

FixedSizeStack<String^> ^tbs = gcnew FixedSizeStack<String^>;

使用默认的参数值是标准模板库(STL)的一个基本的设计特征。例如,下面的声明就来自ISO-C++标准:

// ISO-C++名字空间std中的默认类型参数值示例

{

template <class T, class Container = deque<T> >

class queue;

template <class T, class Allocator = allocator<T> >

class vector;

// ...

}

你可以提供默认的元素类型,如下所示:

// 带有默认的元素类型的模板声明

template <class elemType=String^, int size=1024>

public ref class tStack {};

从设计的角度来说很难证明它的正确性,因为一般来说容器不会集中在在单个默认类型上。

指针也可以作为非类型参数,因为对象或函数的地址在编译时就已知了,因此是一个常量表达式。例如,你可能希望为堆栈类提供第三个参数,这个参数指明遇到特定条件的时候使用的回调处理程序。明智地使用typedef可以大幅度简化那些表面上看起来很复杂的声明,如下所示:

typedef void (*handler)( ... array<Object^>^ );

template <class elemType, int size, handler cback >

public ref class tStack {};

当然,你可以为处理程序提供默认值--在这个例子中,是一个已有的方法的地址。例如,下面的缓冲区声明就提供了大小和处理程序:

void defaultHandler( ... array<Object^>^ ){ ... }

template < class elemType,

int size = 1024,

handler cback = &defaultHandler >

public ref class tStack {};

由于默认值的位置次序优先于命名次序,因此如果不提供明确的大小值(即使这个大小与默认值是重复的),就无法提供重载的处理程序的。下面就是可能用到的修改堆栈的方法:

void demonstration()

{

// 默认的大小和处理程序

tStack<String^> ^ts1 = nullptr;

// 默认的处理程序

tStack<String^, 128> ^ts2 = gcnew tStack<String^, 128>;


// 重载所有的三个参数

tStack<String^, 512, &yourHandler> ^ts3;

}

模板支持的第二种额外的参数就是template模板参数--也就是这个模板参数本身表现为一个模板。例如:

// template模板参数

template <template <class T> class arena, class arenaType>

class Editor {

arena<arenaType> m_arena;

// ...

};

Editor模板类列出了两个模板参数arena和arenaType。ArenaType是一个模板类型参数;你可以传递整型、字符串型、自定义类型等等。Arena是一个template模板参数。带有单个模板类型参数的任何模板类都可以绑定到arena。m_arena是一个绑定到arenaType模板类型参数的模板类实例。例如:

// 模板缓冲区类

template <class elemType>

public ref class tBuffer {};

void f()

{

Editor<tBuffer,String^> ^textEditor;

Editor<tBuffer,char> ^blitEditor;

// ...

} 类型参数约束

如果你把参数化类型简单地作为存储和检索元素的容器,那么你可以略过这一部分了。当你需要调用某个类型参数(例如在比较两个对象,查看它们相等或者其中一个小于另一个的时候,或者通过类型参数调用方法名称或嵌套类型的时候)上的操作的时候,才会考虑约束的问题。例如:

template <class T>

ref class Demonstration {

int method() {

typename T::A *aObj;

// ...

}

};

这段代码成功地声明了aObj,它同时还约束了能够成功地绑定到你的类模板的类型参数。例如,如果你编写下面的代码,aObj的声明就是非法的(在这种特定的情况下),编译器会报错误信息:

int demoMethod()

{

Demonstration<int> ^demi = gcnew Demonstration<int>( 1024 );

return dm->method();

}

当然,其特定的约束是,这个类型参数必

1 2 3 下一页
  • 上一篇教程: VC2005下利用OpenGL实现三维绘图
  • 下一篇教程: 用Visual C++.NET简单实现GIF动画
  •  

    关于本站 | 广告联系 | 版权声明 | 使用帮助

    Copyright © 2004-2008 www.egunao.com All rights reserved.