编辑“︁
C++/CLI
”︁
跳转到导航
跳转到搜索
Template:Editnotice load/content
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{noteTA |G1=IT }} {{Infobox programming language | name = C++/CLI | logo = | paradigm = [[结构化编程|结构化]], [[指令式编程|指令式]], [[面向对象编程|面向对象]] | family = [[C语言|C]] | year = {{Start date and age|2005}} | designer = [[Microsoft]] | developer = Microsoft | latest release version = | latest release date = | typing = | implementations = | dialects = | influenced_by = [[C++]], [[C++托管扩展]], [[C♯|C#]] | influenced = | platform = [[通用语言架构]] | license = | file_ext = | website = {{URL|https://docs.microsoft.com/en-us/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp}} | wikibooks = | versions = }} '''C++/CLI'''(CLI: '''C'''ommon '''L'''anguage '''I'''nfrastructure)在计算机语言中是一门由[[微软]]设计,用来代替[[C++托管扩展]](Managed C++,下文使用MC++指代)的语言。这门语言在兼容原有的[[C++]]标准的同时,重新简化了托管代码扩展的语法,提供了更好的代码可读性。和[[微软.NET]]的其他语言一样,[[微软]]向[[Ecma International|ECMA]]提交了C++/CLI的标准化请求,并且被ECMA通过成为正式的标准<ref>{{Cite web |url=http://www.ecma-international.org/publications/standards/Ecma-372.htm |title=ECMA 372 |access-date=2006-08-27 |archive-url=https://web.archive.org/web/20080810165757/http://www.ecma-international.org/publications/standards/Ecma-372.htm |archive-date=2008-08-10 |dead-url=yes }}</ref>。C++/CLI现在可以被[[Visual C++]] 2005和更高版本的编译器支持。C++/CLI的部分特性已经申请了专利。 == 语法改变 == C++/CLI是一门独立的语言(比如新的关键字),而不是像[[C++托管扩展]]一样是C++的超集<ref name="转换指南">{{Cite web |url=http://msdn.microsoft.com/zh-cn/library/ms379603(vs.80).aspx |title=转换指南: 将程序从托管扩展 C++ 迁移到 C++/CLI |accessdate=2008-08-29 |archive-date=2009-01-22 |archive-url=https://web.archive.org/web/20090122124407/http://msdn.microsoft.com/zh-cn/library/ms379603(VS.80).aspx |dead-url=no }}</ref>。([[C++托管扩展]]有一些不标准的关键字如__gc和__value)。所以,C++/CLI对于这些语法有较大的改变,尤其是去除了一些意义不明确的关键字,增加了一些对.NET的特性的语言级别的支持<ref name="转换指南"/>。 === 关键字 === 有歧义的语法,像MC++的不同版本用新的操作符gcnew区分:在C++/CLI,.NET引用类型的创建需要要使用新的关键字gcnew,以和本地类型区分开<ref name="转换指南"/>。 C++/CLI增加了新的泛型概念(书写方式与C++的模板相似,但行为有很大的測試区别)。 == 数据类型 == ===基本数据类型=== {| class="wikitable" |- ! C++/CLI基本类型!! System命名空间中对应的类!! C#类型 !! 注释/用法 |- | bool|| System::Boolean|| bool || bool dirty = false; |- | char或signed char || System::SByte|| sbyte || char sp = ' '; |- | unsigned char || System::Byte|| byte || unsigned char ch = '\0'; |- | wchar_t || System::Char|| char || wchar_t wch = ch; |- | short|| System::Int16|| short || short s = ch; |- | unsigned short|| System::UInt16|| ushort || unsigned short s = 0xffff; |- | int或long|| System::Int32|| int || int ival = s; |- | unsigned int或unsigned long|| System::UInt32|| uint || unsigned int ui = 0xffffffff; |- | long long || System::Int64|| long || long long etime = ui; |- | unsigned long long|| System::UInt64|| ulong || unsigned long long mtime = etime; |- | float || System::Single|| float || float f = 3.14f; |- | double或long double|| System::Double|| double || double d = 3.14159; |} === 句柄(Handle)代替了指针 === 回到MC++,有两类指针:用__nogc标识的指针是传统意义上的C++指针,而用__gc标识的指针为.NET中的引用。但在C++/CLI里,唯一的指针就是传统意义上的C++指针,而.NET引用类型使用一个“句柄”来获取,使用新的语法“类名^”代替了MC++的“类名*”。新的句法使得托管和非托管代码混合开发更加方便;它指明了对象将会被[[垃圾回收器]]自动销毁还是手动销毁。 范例代码: <syntaxhighlight lang="cpp"> // C++托管扩展 #using <mscorlib.dll> using namespace System::Collections; __gc class referencetype { protected: String* stringVar; int intArr __gc[]; ArrayList* doubleList; public: referencetype(String* str,int* pointer,int number) // 哪个是托管的? { doubleList = new ArrayList(); System::Console::WriteLine(str->Trim() + number.ToString()); } }; </syntaxhighlight> <syntaxhighlight lang="cpp"> // C++/CLI #using <mscorlib.dll> using namespace System::Collections::Generic; ref class referencetype { protected: String^ stringVar; array<int> intArr; List<double>^ doubleList; public: referencetype(String^ str,int* pointer,int number) // 不会再分不清了吧? { doubleList = gcnew List<double>(); System::Console::WriteLine(str->Trim() + number); } }; </syntaxhighlight> ===托管类型的定义=== 在CLR中,托管类型是分为引用类型(class)和值类型(struct)的,在C++/CLI中的分别定义方式如下: 引用类型: public ref class MyClass { }; 值类型: public value class MyClass { }; ===数组=== 数组现在需要用cli名字空间内的array类声明,语法和STL的vector类似<ref name="转换指南"/>。 C++/CLI中新增了array<T> ^的方式定义数组。 array<int> ^a = gcnew array<int>(100) { 1, 2, 3 }; 或者使用它的完整版: cli::array<int> ^a = gcnew cli::array<int> {1, 2, 3}; ===System::String=== <syntaxhighlight lang="cpp"> #include <string> using namespace std; using namespace System; using namespace System::Runtime::InteropServices; string cast_to_string(String^ str) { IntPtr ip = Marshal::StringToHGlobalAnsi(str); const char* ch = static_cast<const char*>(ip.ToPointer()); string stdStr = ch; Marshal::FreeHGlobal(ip); return stdStr; } </syntaxhighlight> ===不定参数=== 对于C#中的不定参数的语法: void foo(params string[] args) 在C++/CLI中对应的版本为: void foo(... array<String^>^ args) === 跟踪引用(Tracking reference) === C++/CLI里的一个“跟踪引用”也是一个控制代碼,但它是传地址而不是传值。等同于在[[C♯|C#]]中加了“ref”关键字,或[[Visual Basic .NET]]的“ByRef”。C++/CLI使用“^%”语法来定义一个跟踪引用。与传统C++中的“*&”语法相似。 下面的示例了“跟踪引用”的使用。如果把“^%”改成“^”(也就是使用普通的句柄),10个字符串将不会被修改,而只会生成那些字符串的副本,这些都是因为那些引用已经不是传地址而是传值。 <syntaxhighlight lang="cpp"> int main() { array<String^>^ arr = gcnew array<String^>(10); int i = 0; for each(String^% s in arr) s = gcnew String(i++.ToString()); return 0; } </syntaxhighlight> 上面的代码示例了用户如何用C++/CLI做一些其他.NET语言不能做的事情,比如C#就不允许在foreach循环中这样做。例如<code>foreach(ref string s in arr)</code>在C#中是非法的。 === 析构(Finalizer/Destructor) === C++/CLI的另一个变化就是使用“!类名()”来声明一个托管类型的“析构方法”(在[[垃圾回收器]]回收对象之前的不确定的时间由CLR调用),而原来的“~类名()”是用来定义“传统的析构函数”(能被用户自己调用)。另外,下面的例子说明了如何在C++/CLI中托管对象如何自动调用“传统析构函数”。 在一个典型的.NET程序中(例如直接使用[[公共中间语言|CLI]])编程,可以由用户自己调用的“解构方法”是用实现IDisposable接口,通过编写Dispose方法来实现显式释放资源;而不确定的“解构方法”是通过重载Finalize函数来实现的。 <syntaxhighlight lang="cpp"> // C++/CLI ref class MyClass // :IDisposable (编译器自动实现IDisposable接口) { public: MyClass(); // 建构函数 ~MyClass(); // (确定的) 析构函数 (编译器使用IDisposable.Dispose来实现) protected: !MyClass(); // 解构方法 (不确定的) (编译器通过重载virtual void Finalize来实现) public: static void Test() { MyClass _auto; // 这不是个控制代碼,它将调用MyClass的默认建構函数 // 使用_auto对象 // 函数返回前自动调用_auto的析构函数(IDisposable.Dispose,由~MyClass()定义)来释放资源 // 以上代码等效于: MyClass^ user = gcnew MyClass(); try { /* 使用_auto对象 */ } finally { delete user; /* 由编译器调用_auto.Dispose() */ } } }; </syntaxhighlight> <syntaxhighlight lang="csharp"> // C# class MyClass : IDisposable { public MyClass() {} // 构造函数 ~MyClass() {} // 析构方法 (不确定的) (编译器通过重载virtual void Finalize来实现),与C++/CLI的!MyClass()等效 public void Dispose() {} // Dispose方法 public static void Test() { using(MyClass auto = new MyClass()) { /* 使用auto对象 */ } // 因为使用了using句法,编译器自动调用auto.Dispose() // 以上代码等效于: MyClass user = new MyClass(); try { /* 使用user对象 */ } finally { user.Dispose(); } } } </syntaxhighlight> == 引用和参考 == {{reflist}} == 外部链接 == *[https://web.archive.org/web/20080810165757/http://www.ecma-international.org/publications/standards/Ecma-372.htm ECMA C++/CLI标准] {{程序设计语言|C++/CLI}} {{DotNET}} {{C语言}} [[Category:程序设计语言]] [[Category:.NET编程语言]]
摘要:
请注意,所有对Local Chinese Wikipedia的贡献均可能会被其他贡献者编辑、修改或删除。如果您不希望您的文字作品被随意编辑,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源(详情请见
Project:著作权
)。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
导航菜单
个人工具
未登录
讨论
贡献
创建账号
登录
命名空间
页面
讨论
大陆简体
不转换
简体
繁體
大陆简体
香港繁體
澳門繁體
大马简体
新加坡简体
臺灣正體
查看
阅读
编辑
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息