在.NET平台下开发,unsafe代码依然很重要,因为现有的很多代码都是iso-c++的,涉及到很多指针操作和运算。如果将其都转化为托管代码,工作量非常大。因此在托管代码中使用unsafe类型是非常重要的手段。本文在《Pro Visual C++ CLI and the dot.NET 2.0 Platform》的基础上,针对非托管类、值类和引用类的相互调用问题进行了总结。
class Class {};
ref class RefClass {};
value class ValueClass {};
下表显示的是class、Value class、Ref class的类成员中是否可以有左侧不同类型的对象。
包含关系
|
Class
|
Value class
|
Ref class
|
Class c;
|
√
|
|
|
Class* pc;
|
√
|
√
|
√
|
ValueClass vc;
|
√
|
√
|
√
|
ValueClass *pvc;
|
√
|
√
|
√
|
ValueClass ^hvc;
|
|
√
|
√
|
RefClass rc;
|
|
|
√
|
RefClass ^hrc;
|
?
|
√
|
√
|
1 值类型不能包含引用类型对象,但是可以有引用类型句柄。因为如果值类型可以包含引用类型对象,建立值类型对象时,就决定了在托管堆中建立值类型对象,这是不符合值类型定义的。
2 引用类型和值类型可以包含非托管类的指针:
class
ClassUnsafe
... {
int m_int;
public:
ClassUnsafe():m_int(4)
...{}
int GetValue()
...{
return m_int;
}
} ;
ref class ClassRef
... {
ClassUnsafe* pUnsafe;
public:
ClassRef()
...{
pUnsafe = new ClassUnsafe;
}
int GetValue()
...{
return pUnsafe->GetValue();
}
} ;
... {
int m_int;
public:
ClassUnsafe():m_int(4)
...{}
int GetValue()
...{
return m_int;
}
} ;
ref class ClassRef
... {
ClassUnsafe* pUnsafe;
public:
ClassRef()
...{
pUnsafe = new ClassUnsafe;
}
int GetValue()
...{
return pUnsafe->GetValue();
}
} ;
这意味着可以在托管代码中可以使用现有的非托管类。
3 “?”表示在非托管类中虽然不能包含托管类句柄,但是可以包含
gcroot<
RefClass ^> mclass;
如下面代码:
ref
class
MClass
... {
public:
int x;
~MClass() ...{ Console::WriteLine("MClass disposed"); }
protected:
!MClass() ...{ Console::WriteLine("MClass finalized"); }
} ;
#pragma unmanaged // works with or without this line
class UMClass
... {
public:
gcroot<MClass^> mclass;
~UMClass() ...{ printf("UMClass deleted "); }
} ;
#pragma managed
void main()
... {
UMClass *umc = new UMClass();
umc->mclass = gcnew MClass();
umc->mclass->x = 4;
Console::WriteLine("Managed Print {0}", umc->mclass->x);
printf("Unmanaged Print %d ", umc->mclass->x);
delete umc;
}
... {
public:
int x;
~MClass() ...{ Console::WriteLine("MClass disposed"); }
protected:
!MClass() ...{ Console::WriteLine("MClass finalized"); }
} ;
#pragma unmanaged // works with or without this line
class UMClass
... {
public:
gcroot<MClass^> mclass;
~UMClass() ...{ printf("UMClass deleted "); }
} ;
#pragma managed
void main()
... {
UMClass *umc = new UMClass();
umc->mclass = gcnew MClass();
umc->mclass->x = 4;
Console::WriteLine("Managed Print {0}", umc->mclass->x);
printf("Unmanaged Print %d ", umc->mclass->x);
delete umc;
}
下表显示的是class、Value class、Ref class是否可以继承自左侧不同类型。
继承关系
|
Class
|
Value class
|
Ref class
|
Class
|
√
|
|
|
ValueClass
|
|
|
|
RefClass
|
|
|
√
|
值类型不能继承自其他类型,只能继承自接口。
引用类型也不能继承自值类型,因为继承是Is-A关系。引用类型和值类型只有通过装箱/拆箱操作进行相互转换。
非托管类只能继承自非托管类。
总结自《Pro Visual C++ CLI and the dot.NET 2.0 Platform》p812