风过无痕,生命如烟

每个人生下来都是天使,不过这个世界上也存在着恶魔。恶魔是天使变的,因为这个世界充满了诱惑。

导航

托管C++笔记(二)原创

.NET并不是平地而起的,它也是基于Win32构建的。所以不可避免的.NET会调用Win32来实现一些功能。因为标准代码的运行不受.NET运行库控制,所以在调用标准代码时,必须考虑到指针是没有被跟踪的,内存也没有垃圾回收,没有.NET上下文环境。因此不能向标准代码传递对象引用,相反,它们必须被封装为适合标准代码的形式。这个过程称为Interop.

  • 非托管类不能包含托管类的数据成员

因为非托管类是直接在堆栈上创建的,所以对于托管对象是不安全的,托管对象必须处在托管堆上。

但是非托管类可以包含value类型的成员或者指向value类型的非托管指针成员,因为值类型通常是生存周期很短的小对象,它们通常在堆栈上创建。

要注意的是,值类型和C++里面的结构类似,每个成员有对齐要求,可以用StructLayout来修改对齐方式。

非托管类的方法可以使用托管类型的参数和返回值

  • GCHandle可以让非托管类中包含托管指针

不要误解,这并不是说在非托管类中直接声明一个托管类型的指针,而是通过GCHandle和IntPtr的转换间接保存一个指向托管类型的指针

GCHandle是一个值类型,所以是在堆栈上构建的,同时它没有提供可用构造函数。使用方法如下:

调用GCHandle::Alloc生成一个实例用来引用一个托管对象,然后可以强制转换成IntPtr,并变换成int类型保存。

解引用则是反过来,int -> IntPtr -> GCHandle,然后便可以把GCHandle.Target转换成托管对象的指针了。

 

// Create instance
TestInterface^ instance = gcnew Derived();
// Create handle
GCHandle handle = GCHandle::Alloc(instance);
// Convert to pointer
IntPtr pointer = (IntPtr)handle;
// Convert back to handle from pointer
GCHandle newHandle = (GCHandle)pointer;
// Get the real pointer to nstance
if ( TestInterface::typeid->IsAssignableFrom(newHandle.Target->GetType() )
{
    TestInterface
^ orginInstance = (TestInterface^)newHandle.Target;
    orginInstance
->Name = "New Name";
}

 

 

  • 托管类型不支持STL

主要是托管类型必须在托管堆上创建。但是可以新建一个托管的模板类。

范例如下:

 

template <class T>
ref class ArrayClass
{
public:
    ArrayClass()
    {
        mData 
= gcnew array<T>(1);
    }
protected:
    array
<T>^ mData;
};

 

 补充:.NET2005 增加了范型的支持,参考我另外一篇随笔:托管C++中的范型和模板的区别

注意这里的array,在.NET 2005之前的版本,数组是可以用[]表示的,但是从.NET 2005开始就被替换成了cli::array了

老版本的范例:

// Old array syntax
String^ stringArray[] = __gc new String^[3];

 

 

  • 全局函数

托管C++允许全局函数的存在。而其他.NET语言则要求所有函数都是类的成员函数。这个目前没有测试过,不知道是否有更新

posted on 2010-10-22 10:25  hyamw  阅读(514)  评论(0编辑  收藏  举报