1 / 137

第二部分 托管类程序设计

第二部分 托管类程序设计. 第十四章 托管类 C++ 程序设计基础. 所谓托管类 C++ 程序是通过 Visual C++ 的 C++/CLI 扩展使用 .NET 框架提供的框架库 FCL 和其他功能设计和编写,并由公共 语言运行时 CLR 进行运行管理的 C++ 程序。 托管类 C++ 程序与非托管类 C++ 程序在形式上十分相似,程 序的书写语法上也基本一致,但由于程序中对 FCL 和 CLR 的使 用是通过 C++/CLI 扩展实现的,这是非托管类 C++ 程序没有的。

Download Presentation

第二部分 托管类程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第二部分 托管类程序设计

  2. 第十四章 托管类C++程序设计基础

  3. 所谓托管类 C++程序是通过 Visual C++ 的C++/CLI 扩展使用 .NET 框架提供的框架库FCL和其他功能设计和编写,并由公共 语言运行时 CLR 进行运行管理的 C++程序。 托管类 C++ 程序与非托管类 C++ 程序在形式上十分相似,程 序的书写语法上也基本一致,但由于程序中对 FCL 和 CLR 的使 用是通过 C++/CLI 扩展实现的,这是非托管类 C++ 程序没有的。 本章将通过比较两类程序在实现相同或可以类比的功能时, 在实现方法上的相同和不同之处,介绍设计和编写托管类 C++ 程序必须要掌握的基本知识。为了便于叙述,以下称非托管类 C++ 程序为 C++ 程序;称托管类 C++ 程序为 C++/CLI 程序。

  4. 14.1 程序中常用的预编译命令 1 包含命令行 #include C++程序中用于包含系统的(.h)头文件,程序项目中的 (.h)头文件或(.cpp )源文件。例如: #include <iostream> 和 #include “stdafx.h”等 C++/CLI程序中一般只用于包含程序项目中的(.h)头文件或 (.cpp )源文件。例如: #include “stdafx.h” 2 引用命令行 #using C++程序中一般较少使用该命令行 。

  5. C++/CLI程序中经常用于引用预包装单元(如 .dll),例如: #using <mscorlib.dll> 3 名域使用命令行 using namespace C++程序和 C++/CLI程序中都用于声明程序中要使用的在某个 指定命名空间中定义的各种成员。例如: C++程序中的: using namespace std; C++/CLI程序中的: using namespace System; C++/CLI程序设计需要使用的 FCL 提供的类型和功能都定义在 树型层次的命名空间中。其中根命名空间为 System。

  6. 在System命名空间中,包含如下子命名空间: CodeDom, Collections, ComponentModel, Configuration, Data, Deployment, Diagnostics, DirectoryServices, Drawing, EnterpriseServices, Globalization, IdentityModel, Internal, IO, Linq, Management, Media, Messaging, Net, Printing, Reflection, Resource, Runtime, Security, ServiceModel, ServiceProcess, Speech, Text, Threading, Timers, Transaction, Transactions, Web, Windows, Workflow 和Xml。 第二层子命名空间中,多数包含了第三层子命名空间。 System::CodeDom中包含了子命名空间: compiler。

  7. System::Collections中包含了子命名空间: Generic, IList, ObjectModel 和 Specialized。 System::ComponentModel中包含了子命名空间: Design, IBindingList和 IEditableObject。 System::Configuration中包含了子命名空间: Assemblies, Install, Internal 和 Provider。 System::Data中包含了子命名空间: Common, Design, Linq, Odbc, OleDb, OracelClient, Sql, SqlClient 和 SqlTypes。 System::Deployment中包含了子命名空间: Application和 Internal。

  8. System::Diagnostics中包含了子命名空间: CodeAnalysis, Design, Eventing, PerformanceData 和 SymbolStore。 System::DirectoryServices中包含了子命名空间: AccountManagement, ActiveDirectory和 Protocols。 System::Drawing中包含了子命名空间: Design, Drawing2D, Imaging, Printing 和 Text。 System::EnterpriseServices中包含了子命名空间: CompensatingResourceManager。 System::IdentiyModel中包含了子命名空间: Claims, Policy, Selectors和 Tokens。

  9. System::IO中包含了子命名空间: Compression, IsolatedStorage, Log, Packaging, Pipes 和 Ports。 System::Linq中包含了子命名空间: Expressions。 System::Management中包含了子命名空间: Instrumentation。 System::Messaging中包含了子命名空间: Design。 System::Net中包含了子命名空间: Cache, Configuration, Mail, Mime, NegotiateStream, NetworkInformation, PeerToPeer, Collaboration, Security, Sockets 和 SslStream。

  10. System::Printing中包含了子命名空间: IndexedProperties 和 Interop。 System::Reflection中包含了子命名空间: Emit。 System::Resources中包含了子命名空间: Tools。 System::Runtime中包含了子命名空间: CompilerServices, ConstrainedExecution, Hosting, InteropServices, Remoting, Serialization 和 Versioning。 System::Security中包含了子命名空间: AccessControl, Authentication, Cryptography, Permissions, Policy, Principal 和 RightsManagement。

  11. System::ServiceModel中包含了子命名空间: Activation, Channels, ComIntegration, Configuration, Description, Diagnostics, Dispatcher, Internal, MsmqIntegration, PeerResolvers, Persistence, Security, Syndication 和Web。 System::ServiceProcess中包含了子命名空间: Design。 System::Speech中包含了子命名空间: AudioFormat, Recognition 和Synthesis。 System::Text中包含了子命名空间: RegularExceptions。

  12. System::Trasactions中包含了子命名空间: Configuration。 System::Web中包含了子命名空间: Caching, ClientServices, Compilation, Configuration, Handlers, Hosting, Mail, Management, Mobile, Profile, Query, RegularExpressions, Script, Security, Services, SessionState, UI 和Util。 System::Windows中包含了子命名空间: Annotation, Automation, Controls, Converters, Data, Documents, Forms, Ink, Input, Interop, Markup, Media, Navigation, Resources, Shapes, Threading和Xps。

  13. System::Workflow中包含了子命名空间: Activities, ComponentModel 和 Runtime。 System::Xml中包含了子命名空间: Linq, Schema, Serialization, XPath 和 Xsl。 第三层子命名空间中,有些又包含有第四层子命名空间。 System::ComponentModel::Design 中包含了子命名空间: Data。 System::Data::Linq 中包含了子命名空间: Mapping和 SqlClient。 System::Diagnostics::Eventing 中包含了子命名空间: Reader。

  14. System::Runtime::InteropServerces中包含了子命名空间:System::Runtime::InteropServerces中包含了子命名空间: ComTypes, CustomMarshalers和 Expando。 System::Runtime::Remoting中包含了子命名空间: Activation, Channels, Contexts, Lifetime, Messaging, Metadata, MetadataServices, Proxies 和 Services。 System::Runtime::Serialization中包含了子命名空间: Configuration, Formatters 和 Json。 System::Security::Cryptography中包含了子命名空间: Pkcs, X509Certificates 和 Xml。 System::ServiceModel::Activation 中包含了子命名空间: Configuration。

  15. System::ServiceModel::Security中包含了子命名空间: Tokens。 System::Speech::Recognition中包含了子命名空间: SrgsGrammar。 System::Speech::Synthesis中包含了子命名空间: TtsEngine。 System::Web::ClientServices 中包含了子命名空间: Providers。 System::Web::Configuration 中包含了子命名空间: Internal。 System::Web::Query 中包含了子命名空间: Dynamic。

  16. System::Web::Script 中包含了子命名空间: Serialization和 Services。 System::Web::Services 中包含了子命名空间: Configuration, Description, Discovery和 Protocols。 System::Web::UI 中包含了子命名空间: Adapters, Design, HtmlControls, MobileControls和 WebControls。 System::Windows::Annotation 中包含了子命名空间: Storage。 System::Windows::Automation 中包含了子命名空间: Peers, Providers和 Text。

  17. System::Windows::Controls 中包含了子命名空间: Primitives。 System::Windows::Documents 中包含了子命名空间: DocumentStructures和 Serialization。 System::Windows::Forms中包含了子命名空间: ComponentModel, Design, Integration, Layout, PropertyGridInternal和VisualStyles。 System::Windows::Ink中包含了子命名空间: AnalysisCore。 System::Windows::Markup中包含了子命名空间: Localizer和 Primitives。

  18. System::Windows::Media中包含了子命名空间: Animation, Converters, Effects, Imaging, Media3D和 TextFormtting。 System::Windows::Xps中包含了子命名空间: Packaging和 Serialization。 System::Workflow::ComponentModel 中包含了子命名空间: Compiler和 Design。 System::Workflow::Runtime 中包含了子命名空间: Configuration, DebugEngine, Hosting和 Tracking。 System::Xml::Serialization中包含了子命名空间: Advanced 和Configuration。

  19. System::Xml::Xsl中包含了子命名空间: Runtime。 第四层子命名空间中,有些又包含有第五层子命名空间。 System::Runtime::Remoting::Channels 中包含了子命名空间: Http, Ipc和 Tcp。 System::Runtime::Remoting::Metadata中包含了子命名空间: W3cXsd2001。 System::Workflow::Activities::Rules 中包含了子命名空间: Design。 System::Runtime::Serialization::Formatters中包含了子命名空间: Binary和 Saop。

  20. System::Web::UI::Design 中包含了子命名空间: WebControls。 System::Web::UI::MobileControls 中包含了子命名空间: Adapters。 System::Web::UI::WebControls 中包含了子命名空间: Adapters和 WebParts。 System::Windows::Forms::ComponentModel中包含了子命名空间: Com2Interop。 System::Windows::Forms::Design 中包含了子命名空间: Behavior。 System::Windows::Media::Media3D 中包含了子命名空间: Converters。

  21. 第五层子命名空间中,只有 WebControls中包含第六层子命名 空间。 System::Web::UI::Design::WebControls 中包含了子命名空间: WebParts。

  22. 4 #pragma once命令行 在 Visual Studio.NET 开发环境中,该命令行在 C++ 程序项目和 C++/CLI 程序项目创建时都被缺省添加。该命令行指示编译器 只对一个头文件处理一次,即使该头文件在项目的多个文件 中被包含,避免了一个类被多次定义的错误。

  23. 14.2 输入与输出语句 在 C++ 程序中,控制台程序的输入与输出功能是通过 I/O 流 类库提供的输入流类和输出流类对象实现的,而MFC 窗口程序 中输入输出功能是通过设备上下文类 CDC和图形设备接口类 GDI的对象实现的。 而在 C++/CLI 程序中,控制台程序的输入与输出功能是通过在 命名空间 System中定义的控制台类 Console提供的静态方法实 现的。典型的输入方法有 Read、ReadKey和 ReadLine,典型的 输出方法有 Write和 WriteLine。下面的简单代码描述了这类输入 输出方法的典型使用方法:

  24. String ^number; … Console::WriteLine( L”Welcom to Visual C++ .NET Programming!” ); Console::Write( L”Please Enter a Number: “ ); number = Console::ReadLine(); 而C++/CLI 窗口程序中的输入输出功能是通过在 System::Drawing 名域空间中定义的图形上下文类 Graphics和扩展图形设备接口 类 GDI+的对象实现的。

  25. 14.3 类对象的创建和回收 C++ 程序中,所有类型的创建、使用和回收是一致的。所有 的类型包括自定义类型都可以与 C++ 预定义的数据类型一样既 能使用堆栈语义在堆栈内存中直接创建类型对象;也能通过对 类型指针 * (本地指针)使用运算符 new 在堆内存中动态创建 类型对象。在堆栈内存中直接创建的类型对象会在其生存期结 束时由系统调用类型的析构函数回收类型对象占用的内存资 源;而在堆内存中动态创建的类型对象必须对指向类型对象的 类型指针 * 使用运算符 delete以便调用类型的析构函数回收类型 对象占用的内存资源。

  26. C++/CLI 程序中,类型分为两种:值类型(value type)和引用 类型(ref type)。两种类型的创建、使用和回收是有区别的。 系统 FCL的内建数据类型均为值类型,同时还提供大量的引 用类型,以便使用 .NET框架功能。用户自定义的类型既可以是 值类型,也可以引用类型。 其中引用类型对象的创建方式有两种:一种是通过类型的句 柄^(类对象的“跟踪指针”,^ 发音为“hat”)用 gcnew 运算符在 托管堆内存创建类型的托管对象,也可以将句柄 ^ 指向一个已 经存在的该类型的托管对象;另一种是使用堆栈语义在堆栈内 存中隐含创建句柄 ^ ,而在托管堆内存中隐含创建托管对象。

  27. 而值类型既可以像 C++ 程序中那样使用堆栈语义在堆栈内存 直接创建或通过类型指针 * 使用 new 在堆内存中动态创建值类 型对象;也允许通过定义值类型的句柄 ^,使用 gcnew在托管堆 内存中创建值类型托管对象。 下面的简单代码描述了如何定义类型的句柄 ^,并且通过句 柄 ^ 使用 gcnew 创建类型的托管对象的方法:

  28. Stirng ^firstPrompt = gcnew String( L”Please the first integer: “ ); Stirng ^secondPrompt = gcnew String( L”Please the second integer: “ ); String ^firstNumber, ^secondNumber; … Console::WriteLine( firstPrompt ); firstNumber = Console::ReadLine(); Console::WriteLine( secondPrompt ); secondNumber = Console::ReadLine(); …

  29. 几点说明: 1 类型指针 *,必须用 new 在堆内存中动态创建 *指针指向的类 型对象,并必须用 delete 对类型对象进行手动撤消和回收。 注意,类型 *指针虽然可以指向在堆栈内存中的类型对象, 但绝对不能用 delete 对该类型对象进行手动撤消和回收。 2 类型句柄 ^,必须用 gcnew 在托管堆内存中动态创建类型的 托管对象或指向一个在托管堆内存中已经存在的托管对象。 系统的垃圾收集器通过句柄 ^,自动地跟踪托管对象的使用 状态,并且在托管对象不再被使用时,自动撤消和回收托管 对象所占用的托管内存的空间,程序员可以无须自己管理。

  30. 这里需要特别指出的是:C++/CLI 扩展也支持使用 delete 对 gcnew 动态创建类型的托管对象执行撤消的用法,这个概念 称为确定性销毁。这使我们可以在托管代码中通过一种与本 地 C++ 相似的语法执行手工内存管理。该语法还包括使用 delete[] 销毁一个托管数组所占用的内存。注意,delete 实际上 并没有直接销毁托管对象的内存,它只是调用类型的析构函 数对句柄 ^ 执行结束性的清理工作,而垃圾收集器将负责最 终销毁和回收托管对象的内存。C++/CLI 扩展使用垃圾收集 器,为我们自动管理内存。这意味着没有用 delete 运算符手 工销毁的托管对象都将会在垃圾收集器运行时被自动销毁。

  31. 它保证了忘记销毁的托管对象不会导致内存泄漏。事实上,它保证了忘记销毁的托管对象不会导致内存泄漏。事实上, 如果我们愿意,可以完全避免对托管类型的对象使用 delete, 垃圾收集器将会负责销毁这些对象的内存。垃圾收集器的工 作方式称为非确定性最后化。这意味着我们无法准确地预测 垃圾收集器什么时候将会运行。而且,当垃圾收集器运行 时,无法保证哪些对象将被销毁。在被销毁的对象中,无法 保证它们的销毁顺序。而在处理表示某种资源(例如文件和 网络连接)的对象时销毁顺序显然特别重要。因此,对于表 示这种资源的对象,最好采用手工删除的方法,以便确保内 存何时被销毁。

  32. 总之,垃圾收集器只在性能上付出一点代价,却避免了程序总之,垃圾收集器只在性能上付出一点代价,却避免了程序 员必须手工释放内存的责任,从而极大地提高了程序的可靠 性。C++/CLI 扩展同时提供了确定性和非确定性销毁托管对象 内存的功能,使我们在需要速度和确定性时可以手工删除对 象,在其他时候由垃圾收集器根据需要释放内存。 切记,垃圾收集器永远不会回收非托管对象的内存,这一点 非常重要。因为垃圾收集器并不知道那些并不是在托管堆中 分配的对象。所以我们必须仔细调用 delete 释放它们所占用 的内存,否则将会导致内存泄漏。

  33. 3 如果需要将类型的句柄^ 初始化为 “空”,则应该按照 如下方法为类型的句柄^ 赋值: Stirng ^firstPrompt = nullptr; // nullptr 是系统内建的 而不能按照如下方法赋值: Stirng ^firstPrompt = null; // 在旧版本的 MC++ 中合法 或 Stirng ^firstPrompt = 0; // 在旧版本的 MC++ 中合法 和本地 C++ 的指针一样,在使用 delete 运算符删除托管对象 内存之后,应该养成将句柄设置为 nullptr 的好习惯。

  34. 4 注意,在旧版本的 MC++ 中,类型的句柄^ 是用 * 说明的, 并使用 new 创建类型的托管对象。因此,不能从形式上区分 两种不同指针,降低了可读性。例如: String *string = String( L”Welcome to Visual C++ .NET Programming!” ); 5 使用堆栈语义创建的托管类对象在其生存期结束时,系统会自动调用类型的析构函数对堆栈内存中的句柄 ^ (在托管对象创建时,自动隐含创建的)执行结束性的清理工作,而垃 圾收集器将负责最终销毁和回收该托管对象的内存。显然, 这实际上是由系统借助堆栈语义实现的托管对象的隐含动态 创建和托管对象的隐含确定性销毁。

  35. 14.4 字符数据类型和字符串 在 C++ 程序中, 字符数据是用 ASCII码表示的,因此在内存 中是以 8位字节为单位存储的。字符数据变量是多用 char 类型 定义的,每个字符数据占一个字节,表示一个 ASCII码字符,一 个汉字字符需要用两个字符数据来表示。字符常量数据是用一 对单引号中字符表示的,例如:‘x’,‘$’,‘7’,‘*’,‘\n’ 等等。 定义一个字符类型数组可以存放一个字符串。使用在 std名 域空间中定义的 string可以更为方便、安全地存放、管理和操 作字符串。字符串常量数据是用一对双引号中字符串表示的, 例如:

  36. char str[] = “Welcome to Visual C++ .NET Programming!”; 在 C++/CLI 程序中,虽然也可以使用 char 类型定义字符数据 变量,但在大多数情况下则必须使用 Unicode码表示字符数据, 所以不提倡使用 char 类型定义字符数据变量。 Unicode码是国 际通用字符集,可以表示不同语言文字、数学符号等。 Unicode字符在内存中是以 16位字节为单位存储的。字符数 据变量是用 __wchar_t或 wchar_t 类型定义的,每个字符数据占 两个字节,表示一个 Unicode字符。字符常量数据也是用一对单 引号中字符表示的,例如: ‘x’,‘$’,‘7’,‘*’,‘\n’ 等等。

  37. 定义字符类型数组可以存放一个字符串(使用 System::Array 定义各种类型,包括字符串类型托管数组的方法将后面关于托 管数组的一节中叙述)。使用在 System名域中定义的 String类 型可以像在 C++ 程序中使用 string 那样,方便、安全地存放、管 理和操作字符串。 字符串常量数据是用以大写的字符 ‘L’ 为前缀的一对双引号中 字符串表示的,例如: wchar_t str[] = L“Welcome to Visual C++ .NET Programming!”; 注意,在 C++ 程序中也提倡使用 __wchar_t或 wchar_t 类型定 义 Unicode字符变量和字符数组。

  38. 14.5 FCL 的基元数据类型 FCL提供一系列用结构 struct定义的基元数据类型,这是在 .NET 框架上能够实现多语言混合编程的重要基础之一。 为了符合标准 C++ 程序员的编程习惯,在 C++/CLI 扩展中提 供了这些基元数据类型的别名,这些别名与 C++ 中提供的内建 数据类型名相同。换句话说,在 C++/CLI 程序中,使用内建数据 类型定义的变量实际上是定义了 FCL提供基元数据类型对象。 例如,基元数据类型 Int32的别名是 int。 基元数据类型不仅提供了相应类型数据的结构,还提供了一 系列操作数据的方法。下面的程序代码典型地描述了基元数据 类型与相应别名的关系和使用方法。

  39. #include “stdafx.h” #using <mscorlib.dll> using namespace System; int main() { String ^firstNumber, ^secondNumber; int number1, number2, sum; Console::Write( L”Please Enter the first integer: “ ); firstNumber = Console::ReadLine(); Console::Write( L”Please Enter the second integer: “ ); secondNumber = Console::ReadLine();

  40. number1 = Int32::Parse( firstNumber ); number2 = Int32::Parse( secondNumber ); sum = number1 + number2; Console::WriteLine( L”\nThe sum is {0}.”, sum.ToString() ); return 0; } 其中 int是基元数据类型 Int32的别名,Parse 和 ToString 都是 Int32 提供的数据操作方法。

  41. FCL提供的主要基元数据类型与(C++/CLI 类型)别名如下: 基元数据类型 C++/CLI 类型 说明 Boolean bool布尔类型 Byte char8位无符号整数 SByte signed char8位有符号整数 Char __wchar_t16位Unicode 字符类型 Int16 short16位有符号整数 UInt16 unsigned short16位无符号整数 Int32 int 或 long32位有符号整数 UInt32 unsigned int / long32位有符号整数

  42. 基元数据类型 C++/CLI 类型 说明 Int64 __int6464位有符号整数 UInt64 unsigned __int6464位有符号整数 Single float32位单精度浮点数 Double double64位双精度浮点数 Decimal Decimal96位有符号整数 Object Object^类对象引用 String String^Unicode 字符串引用

  43. 14.6 数学函数 虽然在 C++/CLI 程序中仍然可以使用 C++ 的系统库函数。例 如,通过包含math.h使用数学函数。但在托管程序中更应该使 用由 FCL提供的大量的类型和类型方法来取代使用 C++ 的系统 库函数。程序最频繁使用的数学函数在 FCL 中是由 Math类型的 方法提供的。 Math类型是定义在 System 命名空间中的,该类型 的静态属性 E 和 PI 为用户提供了常用的数学常量 e 和π;该类 型的静态成员函数为用户提供了常用的数学函数如下: 绝对值函数: Abs 指数函数: Exp 三角函数: Sin Cos Tan

  44. 双曲三角函数: Sinh Cosh Tanh 反三角函数: Asin Acos Atan Atan2 对数函数: Log Log10 平方函数: Pow 开方函数: Sqrt 求较大数函数: Max 求较小数函数: Min 四舍五入函数: Round 取整函数: Floor 注意使用这些静态属性和方法时必须冠以类名 Math和名域运算 符 ::,例如 Math::PI, Math::Sqrt( 25.0 ) 等。

  45. 调用一个函数时,如果实参与形参的类型不符,就会发生实调用一个函数时,如果实参与形参的类型不符,就会发生实 参类型的隐式转换或需要用户进行显式(强制)转换。隐式转 换的原则是数据长度提升。根据这一原则, FCL内建的基元数 据类型可以进行如下隐式转换: 类型 可以安全转换成的类型 Byte UInt16, Int16, UInt32, Int32, Uint64, Int64, Single, Double 或 Decimal SByte Int16, Int32, Int64, Single, Double 或 Decimal Int16 Int32, Int64, Single, Double 或 Decimal UInt16 UInt32, Int32, UInt64, Int64, Single, Double 或 Decimal

  46. Char UInt16, UInt32, Int32, UInt64, Int64, Single, Double 或 Decimal Int32 Int64, Single, Double 或 Decimal UInt32 Int64, Single, Double 或 Decimal Int64 Decimal UInt64 Decimal Single Double 强制转换可以通过在 System命名空间中定义的 Convert类型提 供的方法实现。例如,将一个 Int32类型的变量值强制转换为 Int64类型的方法如下:

  47. int number; __int64 longNumber = Convert::ToInt64( number ); 注意,强制转换允许不遵守数据长度提升的原则。

  48. 14.7 托管数组 在 C++/CLI 程序中,提倡定义 “托管数组” (Managed Array)。 托管数组实际是 System::Array类型的对象,因此在 C++/CLI 程序 中创建的托管数组能使用该类提供的各种方法和属性。 1 托管数组的定义和创建 托管数组定义的一般表达式: [qualifiers] [cli::]array<[qualifiers]type[, dimension]> ^var; qualifiers 存储方式说明(可选项)。可选择的存储方式包 括:mutable, volatile, const, extern 和 statc。 array 托管数组定义的关键字,该关键字是定义在 cli名 域中的。托管程序项目中 using namespace cli;是隐 含的,所以 array 的名域说明 cli:: 可省略。

  49. type 托管数组元素的类型名。可选择的类型包括类型type 托管数组元素的类型名。可选择的类型包括类型 的句柄 ^ 名,值类型名或本地指针名(例如值类 型的 *指针名)。 dimension 托管数组的维数。缺省维数为 1,最大维数为 32。 var托管数组名。 例如: array<int> ^intArray;// 一维整型托管数组 array<String^> ^strArray1;// 一维 String^托管数组 array<String^, 2> ^strArray2;// 二维 String^托管数组 array<double, 2> ^doubleArray;// 二维 double托管数组

  50. 托管数组创建的一般表达式: var = gcnew [cli::]array<[qualifiers]type[, dimension]>(val [, val…]); gcnew托管对象创建运算符。 val 托管数组指定维的尺寸。 例如: intArray = gcnewarray<int>(100); strArray1 = gcnewarray<String^>(50); strArray2 = gcnewarray<String^, 2>(5, 10); doubleArray = gcnewarray<double, 2>(10, 10);

More Related