e股脑电脑教程网
  • 首 页
  • 操作系统
  • 应用软件
  • 下载工具
  • 影音视频
  • 办公软件
  • 媒体制作
  • 网站建设
  • 平面设计
  • 数据库
  • 程序开发
  • 视频教程
编辑推荐: | 文章搜索:
您现在的位置: e股脑 >> 程序开发 >> ASP.net教程 >> C++/CLI基本数据类型探索 >> 教程正文
 
教程搜索
 
 
相关教程
  • 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++/CLI基本数据类型探索
  • 来源:e股脑
  • 点击次数:
  • 更新时间:2007-8-9

导读 :本文向大家揭示了在将CLI类型系统和ISO-C++语义框架集成在一起的时候,微软做了哪些调整工作,以及如何在必要的时候调整在集成过程中所出现的各个情况的优先级。同时,这也提醒大家在将一个本地类型重新构造为一个CLI类的过程中需要注意的问题。

C++/CLI所支持的基本类型,例如int、double、bool等,在某些方面可以说是沿袭了ISO-C++中的类型——同样的用法会在C++/CLI中得到同样的结果,例如加法或者赋值操作。但是C++/CLI也为这些基本类型引入了一些新的东西。

在通用类型系统(CTS)中,每一个基本类型都在System命名空间中存在一个对应的类(见表1)。例如int实际上完全等价于System::Int32。我们可以使用二者中的任何一个来声明一个整数:

int ival = 0;

Int32 ival2 = 0;

出于移植性的考虑,在使用这些基本类型时,我们推荐大家使用内建的关键词,而非System命名空间中的类名。

基本类型 System命名空间中对应的类 注释/用法 bool System::Boolean bool dirty = false; char System::SByte char sp = ' '; signed char System::SByte signed char ch = -1; unsigned char System::Byte unsigned char ch = '\0'; wchar_t System::Char wchar_t wch = ch; short System::Int16 short s = ch; unsigned short System::UInt16 unsigned short s = 0xffff; int System::Int32 int ival = s; unsigned int System::UInt32 unsigned int ui = 0xffffffff; long System::Int32 long lval = ival; unsigned long System::UInt32 unsigned long ul = ui; long long System::Int64 long long etime = ui; unsigned long long System::UInt64 unsigned long long mtime = etime; float System::Single float f = 3.14f; double System::Double double d = 3.14159; long double System::Double long double d = 3.14159L; 表1 基本类型和它们在System命名空间中对应的类

对于System命名空间中类的公有静态成员,我们既可以通过内建的关键字,也可以通过System命名空间中的类名来访问。例如,为了获取一个数值类型的取值范围,我们可以直接使用内建的关键字来访问其静态属性MaxValue和MinValue。

int imaxval = int::MaxValue;

int iminval = Int32::MinValue;

每个数值类型都支持一个名为Parse的成员函数,用以将一个字符串转化为其所表示的数值。例如,给定下面的字符串:


String^ bonus = "$ 12,000.79";

调用Parse会将myBonus初始化为12000.79:

double myBonus = double::Parse( bonus, ns );

其中ns表示对一些NumberStyles枚举类型取位或(bitwise or)运算的结果。NumberStyles是位于System::Globalization命名空间中的一个枚举类型,用于表征对空白、货币符号、小数点或者逗号等的处理。看下面的代码:

using namespace System;

using namespace System::Globalization;

double bonusString( String^ bonus )

{

NumberStyles ns = NumberStyles::AllowLeadingWhite;

ns |= NumberStyles::AllowCurrencySymbol;

ns |= NumberStyles::AllowThousands;

ns |= NumberStyles::AllowDecimalPoint;

return double::Parse( bonus, ns );

}

我们也可以使用转型符号来在类型间进行显式的转换。

int ival = ( int ) myBonus;

或者使用System::Convert类的一些转换方法,例如ToDouble(), ToInt32(), ToDateTime()等:

int ival2 = Convert::ToInt32( myBonus );

两种转换方法采用的策略有所不同:显式转型会直接对小数部分进行截断,而Convert的成员函数则采用的是舍入算法。例如上面的例子中ival赋值后的结果为12000,而ival2赋值后的结果为12001。

我们还可以直接使用字面常量(literal)来调用其对应类型的成员函数,虽然这乍看起来有些怪异。例如,我们可以编写如下代码:

Console::Write( "{0} : ", ( 5 ).ToString() );

其中( 5 ).ToString()返回的是字面常量整数5的字符串表示。注意5外面的圆括号是必须的,因为它会使得编译器将后面的成员选择操作符点号绑定到整数5上,而不是将'5.'解析为一个double类型的字面常量——那样的话,后面的ToString()将变得不合法。为什么我们有时候需要这样做呢?一种可能的情况是将一个字符串传递给Console的成员函数要比传递实际的数值来的更加高效。

对于字符以及字符串这样的字面常量,我们也可以像上面的整数一样调用它们的成员函数,但是它们的行为有一点点晦涩。例如,下面的代码:

Console::WriteLine(( 'a' ).ToString() );

将在控制台上打印出97,而非'a'这个字符。要将字符'a'打印出来,我们需要将其首先转型为System::Char:

Console::WriteLine(((wchar_t)'a').ToString() );


C++/CLI对字符串字面常量采取了特殊的处理策略。从某种程度上来讲,字符串字面常量在C++/CLI中的类型更接近System::String,而非C风格的字符串指针。显然,这将对重载函数的辨析产生影响。例如:

public ref class R {

public:

void foo( System::String^ ); // (1)

void foo( std::string ); // (2)

void foo( const char* ); // (3)

};

void bar( R^ r )

{

// 调用哪一个foo呢?

r->foo( "Pooh" );

}

在ISO-C++中,这将被辨析为第3个foo(),因为字符串字面常量更接近const char*,而非ISO-C++标准库中的string类型。但是,在C++/CLI中,上面的调用将被辨析为第1个foo(),因为现在字符串字面常量被认为更接近System::String,而非字符指针。要理解其中的缘由,让我们往后退两步,先来看看ISO-C++和C++/CLI如何辨析一个重载函数,然后再来看ISO-C++和C++/CLI如何辨析一个字符串字面常量。

一个重载函数的辨析过程通常包含以下三个步骤:

1.选择候选函数集合。候选函数是指那些从词法范畴来看与所调用函数名相匹配的函数。例如,由于我们上面是在R的一个实例上调用foo(),所以所有名称为foo但却不是R或者其基类的成员的那些函数将不被认为是候选函数。这样看来,我们现在有三个候选函数,即R中三个名称为foo的成员函数。如果这个阶段得到的候选函数集合为空,那么调用将告失败。

2.从候选函数集合中选择可用函数集合。可用函数是指函数声明时的参数个数和它们的类型与调用时所指定的相匹配的那些函数。在我们上面的例子中,三个候选函数都是可用函数。如果这个阶段得到的可用函数集合为空,那么调用也将失败。

3.从可用函数集合中选择最匹配的函数。这个阶段将会对实际传递的参数和可用函数所声明的参数之间的转换进行一个排名。对于只含一个参数的函数来说,这个过程比较简单。但是对于含有多个参数的函数来说,这个过程就变得相对有些复杂。如果没有一个最佳的匹配函数胜出,那么调用将告失败。也就是说各个可用函数的参数类型到实际参数类型之间的转换被认为一样的好,换言之多个调用之间产生了混淆。

那么现在摆在我们面前有两个问题:(1)我们实际传递的参数"Pooh"到底是什么类型?(2)在判定类型转换的优劣时采用的是什么算法?

在ISO-C++中,字符串字面常量"Pooh"的类型为const char[5]——注意,在字符串字面常量后面有一个隐含的截断字符null。在上面的例子中显然不存在这样的精确匹配,因此必须应用某种形式的类型转换。这样,两个ISO-C++候选函数(2)和(3)将进行竞争:

void foo( std::string ); // (2)

void foo( const char* ); // (3)

那么编译器如何从中判断可用函数呢?C++语言对类型转换按照优先顺序定义有一个层级结构,在这个结构中,如果一种转换优于另一种转换,那么它将被排在前面。在C++/CLI中,我们将CLI类型的行为也集成到了ISO-C++的标准类型转换层级结构中。下面是对集成之后的层级结构的一个描述:


1 2 下一页
  • 上一篇教程: 用托管C++编写Windows服务
  • 下一篇教程: Visual Studio 2005体验泛型编程
  •  

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

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