Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 为什么可以';德尔福变体不能容纳对象吗?_Delphi_Oop_Variant - Fatal编程技术网

Delphi 为什么可以';德尔福变体不能容纳对象吗?

Delphi 为什么可以';德尔福变体不能容纳对象吗?,delphi,oop,variant,Delphi,Oop,Variant,为什么Delphi变体不能保存对象?更重要的是,这一限制背后的原因是什么 根据我的经验,这只是一个观点,即变体可以做什么,不能做什么 如果将COM对象放入其中,它将被存储为IDispatch引用,因此在此对象上访问的任何方法调用或属性都将转换为查找方法/属性的内部DISPID的代码,并将构造一个带有方法参数的数组,该方法将通过IDispatch接口调用 换句话说,IDispatch是为您处理的,您通常必须以这种方式处理,但它是由编译器自动完成的 然而,对于普通的Delphi对象,事情变得更加困难

为什么Delphi变体不能保存对象?更重要的是,这一限制背后的原因是什么

根据我的经验,这只是一个观点,即变体可以做什么,不能做什么

如果将COM对象放入其中,它将被存储为IDispatch引用,因此在此对象上访问的任何方法调用或属性都将转换为查找方法/属性的内部DISPID的代码,并将构造一个带有方法参数的数组,该方法将通过IDispatch接口调用

换句话说,IDispatch是为您处理的,您通常必须以这种方式处理,但它是由编译器自动完成的

然而,对于普通的Delphi对象,事情变得更加困难。您可以使用RTTI查找并调用已发布的方法和属性,但仅此而已。如果您有一个未发布的非虚拟方法的名称,Delphi将无法在您的方法上找到它的正确地址

换句话说,你所能做的就是拿着这个物体,你不能使用它。也许他们可以增加对仅仅释放它的支持,但再一次,可能就是这样

我知道,如果正确实现IDispatch,就可以通过变量安全地存储和使用该对象。我有一个类,可以用作您希望在其上执行此操作的Delphi对象的基类。它将自动公开已发布的方法/属性,如果需要,可以通过一些受保护的方法调用添加更多。如果有人对这门课感兴趣,我可以把它放在某个地方

但同样,这是通过IDispatch实现的,它使用已发布的方法,其余的是手动代码,因此对变体的支持必须由您构建到您的对象中

这就是为什么我认为他们只是说:这只会引起抱怨,我们可以拿着一个物体,但它毫无用处

但那只是我的想法。也许某位官员有一个更好的答案。

您完全可以将对象存储在变量中,只需将其转换为NativeUInt即可。无论如何,对象只是一个指针

obj := TObject.Create;
v := NativeUInt(obj);
obj := TSomeObject(NativeUInt(v));

我过去曾使用变体来保存对象,使用变体内部结构,代码如下所示:

var
  MyObject: TMyObject;
  Value: Variant;
begin
  MyObject:= TMyObject.Create;
  TVarData(Value).VType:= VarByRef or VarUnknown;
  TVarData(Value).VPointer:= MyObject;

注意你在作弊。VarByRef是一个用于修改基础类型字段的标志。你的代码说变量是空的,但是引用是空的;从逻辑上讲,对位置的非类型化引用相当于非类型化指针,即C中的void*或Delphi中的指针。它应该是
varByRef或varVariant
,才能在Delphi中正常工作。varByRef是类型的前四位中的标志。由于VarByRef标志是在类型上自行设置的,因此保存实际类型的较低12位将为零,这对于变量意味着类型整数。一个更好的方法是将类型设置为varByRef | varUnknown-实际上就是这样,一个指向变量未知类型的指针。你说得很对。您还应该提到TCustomVariantType和TInvokeableVariantType类。这些类显示了一个类在变量中使用(而不仅仅是存储)所必须做的所有事情,而不必实现IDispatch.+1 to Rob:TCustomVariantType和TInvokeableVariantType功能非常强大。一些性能惩罚,但其中。