【精华帖】托管C++/CLI编程:第2部分

目录

摘要

1、控制语句

2、循环构造

3、数组

4、静态成员

5、接口

6、继承

7、抽象类

8、异常处理

9、委托

10、泛型函数

11、资源管理

12、本机代码和托管代码混合

总结


摘要

本文概述了C++/CLI面向对象编程的其余特性,如继承、接口和多态性。我们将通过在 CLR 执行模型下应用 C++/CLI 语义,详细了解各种控制语句,例如 if、while 和 do-while 构造以及其他不同的循环构造,例如 for 循环和开关构造。除此之外,我们还将面临其他重要概念,例如异常处理、内存管理、委托和泛型。最后,本文演示如何在 CLR 上下文中将本机 C++ 代码的实现与托管 C++/CLI 代码混合使用。

1、控制语句

控制语句定义应从给定语句执行哪些代码。C++/CLI 建议 if/else、条件运算符和 Switch 构造作为控制语句。if/else 构造语法与 C# 编码非常相似,如下所示。

  1. #include "stdafx.h"  
  2. using namespace System;  
  3.   
  4. int main(array<System::String ^> ^args)  
  5. {  
  6.     wchar_t ltr;  
  7.     Console::WriteLine("Enter the Letter");  
  8.     ltr= Console::Read();  
  9.     if (ltr >='a')  
  10.         if(ltr<='z')  
  11.         {  
  12.             Console::WriteLine("you have entered small Letter");  
  13.         }  
  14.     if (ltr >='A')  
  15.         if(ltr<='Z')  
  16.         {  
  17.             Console::WriteLine("you have entered capital Letter");  
  18.         }  
  19.     return 0;  
  20. }  

C++/CLI 中的条件运算符称为三元运算符。第一个参数必须是布尔值结果;如果结果为 true,则计算第一个表达式;否则,第二个是,如下所示:

  1. String^ str= i>5 ? "India" : "USA";  

开关构造与 C# 非常相似,但不同之处在于 C++/CLI 不支持大小写选择中的字符串。相反,我们需要使用 if/else 结构。以下是此构造的简单示例:

  1. wchar_t days;  
  2.     Console::WriteLine("1 = Sunday");  
  3.     Console::WriteLine("2 = Monday");  
  4.     Console::WriteLine("3 = Tuesday");  
  5.   
  6.     Console::WriteLine("Enter your choice");  
  7.     days= Console::Read();  
  8.     switch(days)  
  9.     {  
  10.     case '1': Console::WriteLine("Sunday");  
  11.         break;  
  12.        case '2': Console::WriteLine("Monday");  
  13.         break;  
  14.     case '3': Console::WriteLine("Tuesday");  
  15.         break;  
  16.     default: Console::WriteLine("Out of Reach");  
  17.         break;  
  18.     }  

2、循环构造

C++/CLI 为每个循环构造定义 while 和 do-while 循环构造。使用循环时,代码会重复执行,直到满足条件。for、while 和 do-while 构造在语法上类似于 C#,如下所示:

  1. //for loop  
  2.       for(int i=0;i<5;i++)  
  3.     {  
  4.         //statements  
  5.     }  
  6. //while loop  
  7.     int x=0;  
  8.     while(x<3)  
  9.     {  
  10.         //statements  
  11.     }  
  12. //do-while loop  
  13.     do  
  14.     {  
  15.         //statements  
  16.     }while(i<3);  
for 每个循环都在 C++/CLI 中。它不存在于 ANSI C++ 中,因为它需要 IEnumerable 接口。
  1. array<int>^ arry= {1,2,3,4,5};  
  2.   
  3. foreach(int x in arry)  
  4. {  
  5.   Console::WriteLine(x);  
  6. }  

3、数组

C++/CLI 引入了一个数组关键字来实现数组。此关键字使用带有尖括号的通用语法。尖括号用于定义元素的类型。C++/CLI 支持与 C# 语法相同的数组初始值设定项。

  1. #include "stdafx.h"  
  2. using namespace System;  
  3.   
  4. int main(array<System::String ^> ^args)  
  5. {  
  6.     //Array Declaration  
  7.     array<int>^ a1={ 10,20,30,40,50 };  
  8.   
  9.     for each(int i in a1)  
  10.     {  
  11.          Console::WriteLine(i);  
  12.     }  
  13.     Console::ReadLine();  
  14.     return 0;  
  15. }  

4、静态成员

可以通过 static 关键字定义,这与 C# 非常相似。对于该类型的所有对象,静态字段仅实例化一次。我们不需要实例化类来访问静态成员。相反,我们可以使用类类型名称后跟 “::” 运算符 as 直接访问它们(就像在 C# 中使用 “.” 运算符一样)。

  1. #include "stdafx.h"  
  2. using namespace System;  
  3.   
  4. public ref class test  
  5. {  
  6. public:  
  7.     static int i;  
  8.     test()  
  9.     {  
  10.         i++;  
  11.         Console::WriteLine("Constructor Called :{0}",i);  
  12.     }  
  13. };  
  14.   
  15. int main(array<System::String ^> ^args)  
  16. {  
  17.     test^ obj=gcnew test();  
  18.     test^ obj1=gcnew test();  
  19.     //directly access of static member  
  20.     Console::WriteLine(test::i);  
  21.     Console::Read();  
  22.    return 0;  
  23. }  

5、接口

interface 关键字用于定义接口。在 C++/CLI 中定义接口类似于 C# 语言,但实现略有不同。接口中定义的方法必须在子类中使用 virtual 关键字实现,如下所示:

  1. public interface class IDisplay  
  2. {  
  3.     void hello();  
  4. };  
  5.   
  6. public ref class test: IDisplay  
  7. {  
  8. public:  
  9.     virtual void hello()  
  10.     {  
  11.         Console::WriteLine("Hello test");  
  12.     }  
  13. };  

6、继承

继承是一种机制,在该机制中,可以在其相应的派生类中访问基类成员。默认情况下,所有 C++/CLI 类都是派生类。这是因为 value 类和引用类都具有标准基类 System::Object。在派生类中,基类应后跟冒号 (:)如下所示:

  1. public ref class baseClass   
  2. {  
  3. public:  
  4.     virtual void showBase()   
  5.     {  
  6.         Console::WriteLine("base class");  
  7.     }  
  8. };  
  9. public ref class test : baseClass  
  10. {  
  11. public:  
  12.      void showDerived()   
  13.      {  
  14.         Console::WriteLine("derieved class");  
  15.      }  
  16. };  
  17. int main(array<System::String ^> ^args)  
  18. {  
  19.     test^ t=gcnew test();  
  20.     t->showBase();  
  21.     t->showDerived();  
  22.     return 0;  
  23. }  

访问修饰符描绘了继承中的重要角色,以防止程序集内部或外部的成员进行访问。
 

kewore%20and%20description.jpg

7、抽象类

用于实现 C++ 等效的纯虚函数。抽象类由 abstract 关键字定义,该关键字阻止您创建该类类型的对象。与接口不同,我们可以在抽象类中定义函数的实现(主体)。多态方法实现必须在派生类中使用 override 关键字进行标记,如下所示:

  1. #include "stdafx.h"  
  2. using namespace System;  
  3.   
  4. public ref class absClass abstract  
  5. {  
  6. public:  
  7.     virtual double square(int x) abstract;  
  8.     virtual void show()   
  9.     {  
  10.         Console::WriteLine("showing you in abstract class");  
  11.     }  
  12. };  
  13. public ref class test : absClass  
  14. {  
  15. public:  
  16.     virtual double square(int x) override  
  17.      {  
  18.          return x*x;  
  19.      }  
  20.      virtual void show() override  
  21.      {  
  22.         Console::WriteLine("showing you in derived class");  
  23.      }  
  24. };  
  25. int main(array<System::String ^> ^args)  
  26. {  
  27.     test^ t=gcnew test();  
  28.     Console::WriteLine("square is= {0}",t->square(20));  
  29.     t->show();  
  30.     Console::Read();  
  31.     return 0;  
  32. }  

8、异常处理

C++/CLI 定义了 try、catch、throw 和 finally 关键字来处理代码段中的所有运行时错误。异常处理实现与其他 CLR 支持的语言非常相似。下面的示例通过使用异常处理来处理数组越界错误。

  1. int main(array<System::String ^> ^args)  
  2. {  
  3.     array<int>^ arry= {1,2,3};  
  4.   
  5.     try  
  6.     {  
  7.       for(int i=0;i<=arry->Length;i++)  
  8.       {  
  9.         Console::WriteLine(arry[i]);  
  10.       }  
  11.     }  
  12.     catch(Exception^ ex)  
  13.      {  
  14.          Console::WriteLine(ex);  
  15.      }  
  16.      finally  
  17.      {  
  18.       Console::WriteLine("Exection Done");  
  19.      }  
  20.     Console::Read();  
  21.     return 0;  
  22. }  

前面的示例引发由 try/catch 块处理的运行时异常,如下所示:
 

cli.jpg

9、委托

委托是指向方法的特殊类型安全指针。它们由 C++/CLI 语言中的 delegate 关键字定义,如下所示:

  1. #include "stdafx.h"  
  2. using namespace System;  
  3.   
  4. //delegate definition   
  5. public delegate void testDel(int z);  
  6.   
  7. public ref class test  
  8. {  
  9. public:  
  10.     void square(int x)  
  11.     {  
  12.         Console::WriteLine("Square is=",x*x);  
  13.     }  
  14. };    
  15.   
  16. int main(array<System::String ^> ^args)  
  17. {  
  18.     test^ t=gcnew test();  
  19.     testDel^ td=gcnew testDel(t,&test::square);  
  20.     td(2);  
  21.     Console::Read();  
  22.     return 0;  
  23. }  

10、泛型函数

似乎执行与 C++ 函数模板相同的操作。泛型函数规范本身是编译的,当您调用与泛型函数规范匹配的函数时,实际类型将在执行时替换类型参数。编译时不会生成额外的代码。

为了定义委托,C++/CLI 使用类似 C++ 的尖括号,使用类型参数,在调用函数时替换为实际类型,如下所示。

  1. #include "stdafx.h"  
  2. using namespace System;  
  3.   
  4. generic<typename T> where T:IComparable  
  5.     T MaxElement(array<T>^ x)  
  6. {  
  7.     T max=x[0];  
  8.     for(int i=1; i< x->Length; i++)  
  9.     {  
  10.         if(max-> CompareTo(x[i]) < 0)  
  11.         {  
  12.          max=x[i];  
  13.         }  
  14.     }  
  15.       
  16. return max;   
  17. }  
  18.   
  19. int main(array<System::String ^> ^args)  
  20. {  
  21.     array<int>^ iData= {3, 20, 4, 12, 7, 9};  
  22.     int maxI= MaxElement(iData);  
  23.     Console::WriteLine("Max Integer is={0}",maxI);  
  24.   
  25.     array<double>^ dData= {4.2, 2.12, 25.7,1.1};  
  26.     double maxD= MaxElement(dData);  
  27.     Console::WriteLine("Max Double is={0}",maxD);  
  28.       
  29.     Console::Read();  
  30.     return 0;  
  31. }  

前面的示例使用未定义类型的泛型函数从数组中生成最大数字。相反,类型(如整数或双精度)在执行期间定义,如下所示。
 

console%20output.jpg

11、资源管理

C++/CLI 代码通过定义隐式调用 IDisposable 接口的析构函数来清理内存资源。

  1. public ref class test  
  2. {  
  3. public:  
  4.     ~test()  
  5.     {  
  6.         // release resources code  
  7.     }  
  8. };  

C# using 语句在不再使用资源后立即释放资源。编译隐式创建一个 try/finally 语句,并在 finally 块中调用 Dispose() 方法。C++/CLI 也提供了这种方法,但以更优雅的方式处理它,如下所示:

  1. public ref class test  
  2. {  
  3. public:  
  4.     void hello()  
  5.     {  
  6.         Console::WriteLine("Hello test");  
  7.     }  
  8. };  
  9. int main(array<System::String ^> ^args)  
  10. {  
  11.     //Releasing resources  
  12.     {  
  13.         test t;  
  14.         t.hello();  
  15.     }  
  16.     Console::Read();  
  17.     return 0;  
  18. }  

12、本机代码和托管代码混合

C++/CLI 允许将本机 C++ 代码与 CLR 托管代码混合使用,从而提供了很大的优势。这个术语在 C++/CLI 中被称为“它只是工作”。以下示例通过调用本机 C++ iostream 命名空间的 cout 方法演示混合代码,如下所示:

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace System;  
  4.   
  5. public ref class test  
  6. {  
  7. public:  
  8.      void managedCode()  
  9.      {  
  10.         Console::WriteLine("Hello test");  
  11.      }  
  12.      //Native code funtion calling  
  13.      void nativeCode()  
  14.      {  
  15.          std::cout << "native code sample";  
  16.      }  
  17. };  
  18. int main(array<System::String ^> ^args)  
  19. {  
  20.     //Releasing resources  
  21.     {  
  22.         test t;  
  23.         t.managedCode();  
  24.         t.nativeCode();  
  25.     }  
  26.     return 0;  
  27. }  

总结

本文通过定义数组、控制语句、泛型、委托和条件语句的语义,详细概述了其他重要主题。我们还通过一些示例来理解 C++/CLI OOP 概念,例如接口、多态性和继承。完成本系列文章后,人们能够有效地用 C++/CLI 编写代码。

  • 16
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉特思米(gitusme)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值