| | | Visual C++ .NET编程:托管C++概述 | | 2002-04-02·
·Adding··yesky
| 上一页 1 2 3 4 下一页 (3) 新增三个托管C++类型:__gc class、__value class和__gc interface
一个__gc类或结构意味着该类或结构的生命周期是由.NET开发平台自动管理及垃圾自动收集,用户不必自已去调用delete来删除。定义一个__gc类或结构和标准C++基本相似,所不同的是在class或struct前加上__gc,例如下面的代码:
__gc class G { public: int k; int sum(int); };
G::sum(int i) {return i*(i + 1)/2;} int main() { G * g = new G; Console::WriteLine(g->sum(4)); // 结果输出10 return 0; } | 但要注意:
A. 一个__gc类不能从一个非托管类中继承,且不能包含从它派生的非托管类。但一个__gc类最多可以从一个托管类中继承。
B. 一个__gc类不能定义成一个友元类或包含一个友元成员函数。所谓友元函数,是用来让外部函数访问类中的私有和保护类型成员。
C. 一个__gc类不能声明或定义以及重载new或delete操作以及不能包含using等声明。
__value类是用来使用具有短生命期的小型数据项,它不同于__gc类。__gc类数据分配在CLR堆中,而__value类对象是在运行栈或称为NDP(.NET Developer Platform,.NET开发者平台)堆中创建的,从而避免了垃圾回收器不断分配和释放空间而带来的开销。一个__value类可以声明成为一个局部变量、参数和返回值,也可嵌入到一个__gc类中或是作为一个静态变量或在C++堆中分配的变量。例如下面的代码:
#using using namespace System; __value struct V { int i; }; __gc struct G { V v; }; // 嵌入到__gc类中 V f(V v) { // 定义一个全局函数,其值存储在运行栈中 v.i += 1; // 不影响原来形参v的值 return v; // 返回V结构类型的值 } int main(void) { V v1 = {10}; // 在运行栈中声明并初始化 V v2 = f(v1); // 调用f函数,此时v1中的i为10,而v2中的i为11 G *pG = new G; // 为G实例分配堆空间 pG->v = v1; // pG的v中的i为10 pG->v.i += v2.i; // pG的v中的i为10+11=21 Console::WriteLine(v1.i); // 输出结果为10 Console::WriteLine(v2.i); // 输出结果为11 Console::WriteLine(pG->v.i); // 输出结果为21 return 0; } | 除此之外,所有的__gc对象都是从类System::Object派生而来,因而能够很容易使用作用在__gc类中的集合和映射功能。然而__value类型并没有与这个基类所共享,因而不能直接将__value作为函数中的Object*实参。为了解决这个问题,.NET允许我们使用__box关键字将一个__value类型视为一个__gc对象。此时__value类型被封装成一个__gc类桩子(Stub),并被复制到NDP堆中。由于在托管C++中,box不具备隐式转换的功能,因此在转换时必须指明转换的类型。
托管C++中的__gc接口最能体现COM接口的思想,它的定义和声明是非常简单的,它除了关键字不同外,与一个__gc类的声明极为相似。例如下面的代码定义了一个接口IMyBase,其中包含了一个f的方法:
__gc __interface Ibase { void f(); }; | 需要说明的是,接口中所有的方法默认时都是纯虚的且都是公有的,我们不需要在方法之前使用virtual关键字或在方法之后加上“= 0”。其次,在一个__gc接口中不能包含数据成员以及静态成员,也不能包含任何类的声明。下面举一个示例来说明__gc接口的使用:
#using using namespace System;
__gc __interface Ibase1 { int f(int); }; __gc __interface Ibase2 { int f(int); }; __gc struct C: Ibase1, Ibase2 { int f(int i) { // 接口方法的实现 return 2*i-1; }; };
int main(void){ C* c = new C; Console::WriteLine((c -> f(1)).ToString()); // 输出结果为1 Console::WriteLine((__try_cast (c)->f(2)).ToString()); // 输出结果为3
Console::WriteLine((__try_cast (c)->f(3)).ToString()); // 输出结果为5
return 0; } | 代码中,__try_cast用来将某个对象转换成一个指定类型,并当类型转换失败时自动处理由此产生的异常。ToString用来将对象描述成一个字符串。
上一页 1 2 3 4 下一页 | | | 感谢
访问天极网,如果您觉得该文章涉及版权问题,请看这里!
|
|