科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Visual C++ .NET编程:托管C++概述

Visual C++ .NET编程:托管C++概述

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

托管是.NET的一个专门概念,它是融于通用语言运行时(CLR)中的一种新的编程理念,因此我们完全可以把“托管”视为“.NET”

作者:Adding 来源:YESKY 2007年11月16日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
(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用来将对象描述成一个字符串。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章