【精华帖】托管C++/CLI编程:第2部分
目录
摘要
本文概述了C++/CLI面向对象编程的其余特性,如继承、接口和多态性。我们将通过在 CLR 执行模型下应用 C++/CLI 语义,详细了解各种控制语句,例如 if、while 和 do-while 构造以及其他不同的循环构造,例如 for 循环和开关构造。除此之外,我们还将面临其他重要概念,例如异常处理、内存管理、委托和泛型。最后,本文演示如何在 CLR 上下文中将本机 C++ 代码的实现与托管 C++/CLI 代码混合使用。
1、控制语句
控制语句定义应从给定语句执行哪些代码。C++/CLI 建议 if/else、条件运算符和 Switch 构造作为控制语句。if/else 构造语法与 C# 编码非常相似,如下所示。
- #include?"stdafx.h"??
- using?namespace?System;??
- ??
- int?main(array<System::String?^>?^args)??
- {??
- ????wchar_t?ltr;??
- ????Console::WriteLine("Enter?the?Letter");??
- ????ltr=?Console::Read();??
- ????if?(ltr?>='a')??
- ????????if(ltr<='z')??
- ????????{??
- ????????????Console::WriteLine("you?have?entered?small?Letter");??
- ????????}??
- ????if?(ltr?>='A')??
- ????????if(ltr<='Z')??
- ????????{??
- ????????????Console::WriteLine("you?have?entered?capital?Letter");??
- ????????}??
- ????return?0;??
- } ?
C++/CLI 中的条件运算符称为三元运算符。第一个参数必须是布尔值结果;如果结果为 true,则计算第一个表达式;否则,第二个是,如下所示:
- String^?str=?i>5???"India"?:?"USA";??
开关构造与 C# 非常相似,但不同之处在于 C++/CLI 不支持大小写选择中的字符串。相反,我们需要使用 if/else 结构。以下是此构造的简单示例:
- wchar_t?days;??
- ????Console::WriteLine("1?=?Sunday");??
- ????Console::WriteLine("2?=?Monday");??
- ????Console::WriteLine("3?=?Tuesday");??
- ??
- ????Console::WriteLine("Enter?your?choice");??
- ????days=?Console::Read();??
- ????switch(days)??
- ????{??
- ????case?'1':?Console::WriteLine("Sunday");??
- ????????break;??
- ???????case?'2':?Console::WriteLine("Monday");??
- ????????break;??
- ????case?'3':?Console::WriteLine("Tuesday");??
- ????????break;??
- ????default:?Console::WriteLine("Out?of?Reach");??
- ????????break;??
- ????} ?
2、循环构造
C++/CLI 为每个循环构造定义 while 和 do-while 循环构造。使用循环时,代码会重复执行,直到满足条件。for、while 和 do-while 构造在语法上类似于 C#,如下所示:
- //for?loop??
- ??????for(int?i=0;i<5;i++)??
- ????{??
- ????????//statements??
- ????}??
- //while?loop??
- ????int?x=0;??
- ????while(x<3)??
- ????{??
- ????????//statements??
- ????}??
- //do-while?loop??
- ????do??
- ????{??
- ????????//statements??
- ????}while(i<3); ?
- array<int>^?arry=?{1,2,3,4,5};??
- ??
- foreach(int?x?in?arry)??
- {??
- ??Console::WriteLine(x);??
- } ?
3、数组
C++/CLI 引入了一个数组关键字来实现数组。此关键字使用带有尖括号的通用语法。尖括号用于定义元素的类型。C++/CLI 支持与 C# 语法相同的数组初始值设定项。
- #include?"stdafx.h"??
- using?namespace?System;??
- ??
- int?main(array<System::String?^>?^args)??
- {??
- ????//Array?Declaration??
- ????array<int>^?a1={?10,20,30,40,50?};??
- ??
- ????for?each(int?i?in?a1)??
- ????{??
- ?????????Console::WriteLine(i);??
- ????}??
- ????Console::ReadLine();??
- ????return?0;??
- }??
4、静态成员
可以通过 static 关键字定义,这与 C# 非常相似。对于该类型的所有对象,静态字段仅实例化一次。我们不需要实例化类来访问静态成员。相反,我们可以使用类类型名称后跟 “::” 运算符 as 直接访问它们(就像在 C# 中使用 “.” 运算符一样)。
- #include?"stdafx.h"??
- using?namespace?System;??
- ??
- public?ref?class?test??
- {??
- public:??
- ????static?int?i;??
- ????test()??
- ????{??
- ????????i++;??
- ????????Console::WriteLine("Constructor?Called?:{0}",i);??
- ????}??
- };??
- ??
- int?main(array<System::String?^>?^args)??
- {??
- ????test^?obj=gcnew?test();??
- ????test^?obj1=gcnew?test();??
- ????//directly?access?of?static?member??
- ????Console::WriteLine(test::i);??
- ????Console::Read();??
- ???return?0;??
- }??
5、接口
interface 关键字用于定义接口。在 C++/CLI 中定义接口类似于 C# 语言,但实现略有不同。接口中定义的方法必须在子类中使用 virtual 关键字实现,如下所示:
- public?interface?class?IDisplay??
- {??
- ????void?hello();??
- };??
- ??
- public?ref?class?test:?IDisplay??
- {??
- public:??
- ????virtual?void?hello()??
- ????{??
- ????????Console::WriteLine("Hello?test");??
- ????}??
- };??
6、继承
继承是一种机制,在该机制中,可以在其相应的派生类中访问基类成员。默认情况下,所有 C++/CLI 类都是派生类。这是因为 value 类和引用类都具有标准基类 System::Object。在派生类中,基类应后跟冒号 (:)如下所示:
- public?ref?class?baseClass???
- {??
- public:??
- ????virtual?void?showBase()???
- ????{??
- ????????Console::WriteLine("base?class");??
- ????}??
- };??
- public?ref?class?test?:?baseClass??
- {??
- public:??
- ?????void?showDerived()???
- ?????{??
- ????????Console::WriteLine("derieved?class");??
- ?????}??
- };??
- int?main(array<System::String?^>?^args)??
- {??
- ????test^?t=gcnew?test();??
- ????t->showBase();??
- ????t->showDerived();??
- ????return?0;??
- } ?
访问修饰符描绘了继承中的重要角色,以防止程序集内部或外部的成员进行访问。
?
7、抽象类
用于实现 C++ 等效的纯虚函数。抽象类由 abstract 关键字定义,该关键字阻止您创建该类类型的对象。与接口不同,我们可以在抽象类中定义函数的实现(主体)。多态方法实现必须在派生类中使用 override 关键字进行标记,如下所示:
- #include?"stdafx.h"??
- using?namespace?System;??
- ??
- public?ref?class?absClass?abstract??
- {??
- public:??
- ????virtual?double?square(int?x)?abstract;??
- ????virtual?void?show()???
- ????{??
- ????????Console::WriteLine("showing?you?in?abstract?class");??
- ????}??
- };??
- public?ref?class?test?:?absClass??
- {??
- public:??
- ????virtual?double?square(int?x)?override??
- ?????{??
- ?????????return?x*x;??
- ?????}??
- ?????virtual?void?show()?override??
- ?????{??
- ????????Console::WriteLine("showing?you?in?derived?class");??
- ?????}??
- };??
- int?main(array<System::String?^>?^args)??
- {??
- ????test^?t=gcnew?test();??
- ????Console::WriteLine("square?is=?{0}",t->square(20));??
- ????t->show();??
- ????Console::Read();??
- ????return?0;??
- }??
8、异常处理
C++/CLI 定义了 try、catch、throw 和 finally 关键字来处理代码段中的所有运行时错误。异常处理实现与其他 CLR 支持的语言非常相似。下面的示例通过使用异常处理来处理数组越界错误。
- int?main(array<System::String?^>?^args)??
- {??
- ????array<int>^?arry=?{1,2,3};??
- ??
- ????try??
- ????{??
- ??????for(int?i=0;i<=arry->Length;i++)??
- ??????{??
- ????????Console::WriteLine(arry[i]);??
- ??????}??
- ????}??
- ????catch(Exception^?ex)??
- ?????{??
- ?????????Console::WriteLine(ex);??
- ?????}??
- ?????finally??
- ?????{??
- ??????Console::WriteLine("Exection?Done");??
- ?????}??
- ????Console::Read();??
- ????return?0;??
- }??
前面的示例引发由 try/catch 块处理的运行时异常,如下所示:
?
9、委托
委托是指向方法的特殊类型安全指针。它们由 C++/CLI 语言中的?delegate?关键字定义,如下所示:
- #include?"stdafx.h"??
- using?namespace?System;??
- ??
- //delegate?definition???
- public?delegate?void?testDel(int?z);??
- ??
- public?ref?class?test??
- {??
- public:??
- ????void?square(int?x)??
- ????{??
- ????????Console::WriteLine("Square?is=",x*x);??
- ????}??
- };????
- ??
- int?main(array<System::String?^>?^args)??
- {??
- ????test^?t=gcnew?test();??
- ????testDel^?td=gcnew?testDel(t,&test::square);??
- ????td(2);??
- ????Console::Read();??
- ????return?0;??
- }??
10、泛型函数
似乎执行与 C++ 函数模板相同的操作。泛型函数规范本身是编译的,当您调用与泛型函数规范匹配的函数时,实际类型将在执行时替换类型参数。编译时不会生成额外的代码。
为了定义委托,C++/CLI 使用类似 C++ 的尖括号,使用类型参数,在调用函数时替换为实际类型,如下所示。
- #include?"stdafx.h"??
- using?namespace?System;??
- ??
- generic<typename?T>?where?T:IComparable??
- ????T?MaxElement(array<T>^?x)??
- {??
- ????T?max=x[0];??
- ????for(int?i=1;?i<?x->Length;?i++)??
- ????{??
- ????????if(max->?CompareTo(x[i])?<?0)??
- ????????{??
- ?????????max=x[i];??
- ????????}??
- ????}??
- ??????
- return?max;???
- }??
- ??
- int?main(array<System::String?^>?^args)??
- {??
- ????array<int>^?iData=?{3,?20,?4,?12,?7,?9};??
- ????int?maxI=?MaxElement(iData);??
- ????Console::WriteLine("Max?Integer?is={0}",maxI);??
- ??
- ????array<double>^?dData=?{4.2,?2.12,?25.7,1.1};??
- ????double?maxD=?MaxElement(dData);??
- ????Console::WriteLine("Max?Double?is={0}",maxD);??
- ??????
- ????Console::Read();??
- ????return?0;??
- }??
前面的示例使用未定义类型的泛型函数从数组中生成最大数字。相反,类型(如整数或双精度)在执行期间定义,如下所示。
?
11、资源管理
C++/CLI 代码通过定义隐式调用 IDisposable 接口的析构函数来清理内存资源。
- public?ref?class?test??
- {??
- public:??
- ????~test()??
- ????{??
- ????????//?release?resources?code??
- ????}??
- }; ?
C# using 语句在不再使用资源后立即释放资源。编译隐式创建一个 try/finally 语句,并在 finally 块中调用 Dispose() 方法。C++/CLI 也提供了这种方法,但以更优雅的方式处理它,如下所示:
- public?ref?class?test??
- {??
- public:??
- ????void?hello()??
- ????{??
- ????????Console::WriteLine("Hello?test");??
- ????}??
- };??
- int?main(array<System::String?^>?^args)??
- {??
- ????//Releasing?resources??
- ????{??
- ????????test?t;??
- ????????t.hello();??
- ????}??
- ????Console::Read();??
- ????return?0;??
- }??
12、本机代码和托管代码混合
C++/CLI 允许将本机 C++ 代码与 CLR 托管代码混合使用,从而提供了很大的优势。这个术语在 C++/CLI 中被称为“它只是工作”。以下示例通过调用本机 C++ iostream 命名空间的 cout 方法演示混合代码,如下所示:
- #include?"stdafx.h"??
- #include?<iostream>??
- using?namespace?System;??
- ??
- public?ref?class?test??
- {??
- public:??
- ?????void?managedCode()??
- ?????{??
- ????????Console::WriteLine("Hello?test");??
- ?????}??
- ?????//Native?code?funtion?calling??
- ?????void?nativeCode()??
- ?????{??
- ?????????std::cout?<<?"native?code?sample";??
- ?????}??
- };??
- int?main(array<System::String?^>?^args)??
- {??
- ????//Releasing?resources??
- ????{??
- ????????test?t;??
- ????????t.managedCode();??
- ????????t.nativeCode();??
- ????}??
- ????return?0;??
- }??
总结
本文通过定义数组、控制语句、泛型、委托和条件语句的语义,详细概述了其他重要主题。我们还通过一些示例来理解 C++/CLI OOP 概念,例如接口、多态性和继承。完成本系列文章后,人们能够有效地用 C++/CLI 编写代码。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!