这实际上是一个很古老的话题了,但许多朋友还并不知道之所以不能传递的原因。所以在本文就试图为大家简单的说明一下。
首先,对象是类的一个具体的实例。而这就存在以下问题:
- 不同的语言对于类的实现方式也不一样,所以,同样名为 TMyClass 的 Delphi 实例 A 并不可能转换为同名的 C++ 实例 B,就算是强转了,那么后果也是难以预料的。
- 既然不同语言编译的不行,那么相同语言编译的是不是就行呢?很遗憾,依然不行。一个简单的例子就是 C++,规范并没有约定类的实现方式,所以不同的编译器厂商有自己的实现,显示 VC++ 和 BC++ 实现的同名的类型也是无法转换的。
- 好了,那我同一个开发工具编译的是不是能行呢?报歉,这依然是一个很令人觉得难过的任务。这里存在几个问题:
- 同一开发工具,不同的版本之间的实现之间可能存在差异;
- 同一版本的开发工具,由于无法预期主程序和 DLL/BPL 之间是否是同一个 IDE 编译,所以实现上,他们是各自独立记录了自己的类型信息。而这些类型信息由于各自独立,所以,当你传递一个对象的实例给 DLL/BPL 时,如果这个对象内部的某个方法进行了类型转换( Delphi 中的 as,C++ 中的 xxx_cast )或判定(Delphi 中的 is ),而这是很常见的操作。由于 DLL/BPL 按照自己的类型信息去判断对象的类型信息,由于在对象的类型信息表中无法找到目标类型信息,所以转换也只能以失败告终。
- 至此,你是不是死心了。好吧,我也觉得你应该死心用别的方式来实现。但实际上还是有一个微小的缝隙留下来,那就是在同时符合以下条件下,你传递对象可以被认为是安全的:
- 同一开发工具编译的主程序和 DLL /BPL;
- 对象类型是基类或者对象不会调用任何赋值给父类型或其它类型转换的操作;
好了,说到这里,我觉得这个条件有点太苛刻了,所以,我们还是放弃这一努力吧。真要需要传递对象时,采用接口对对象进行一个简单的封装来代替直接传递对象是一个不错的选择。只所以接口是可行的,是因为接口这个东西是有统一的规范的,各个语言都实现了相同的规则,所以大家的类型信息是可以相互交互的。
如果有什么补充,欢迎大家提供说明或在群中讨论。