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

2023-12-13 11:55:19

目录

摘要

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 编写代码。

文章来源:https://blog.csdn.net/m0_51887793/article/details/134892758
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。