今天在发现delphi里的接口是不能强制转化的, 比如如下代码:
ITestInterface
=
interface
(IUnknown)
[
'
{DE8E7E63-BD1B-4BD8-B59A-43F4B2B3A3DC}
'
]
procedure Chk;
end;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ITestInterface2
=
interface
(IUnknown)
[
'
{3B47B113-4664-4CCC-9A69-E378F2D2363E}
'
]
procedure Chk2;
end;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
var
mInt: ITestInterface;
mInt2: ITestInterface2;
begin
mInt :
=
TTestInterface2.Create;
mInt.Chk;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ITestInterface2(mInt).Chk2;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
mInt2 :
=
mInt
as
ITestInterface2;
mInt2.Chk2;
end;
从 运行情况可以看出,在第一种情况 ITestInterface2(mInt).Chk2; 下,实际运行的还是ITestInterface下的procedure Chk;而第二种情况 mInt2 := mInt as ITestInterface2; 就能正确的运行ITestInterface2下的procedure Chk2;了.这是为什么呢?
原来这都出自Delphi的编译之手,在进行强制转化 ITestInterface2(mInt).Chk2; 时, 代码是:
mov eax, [ebp
-
$
04
]
mov edx, [eax]
call dword ptr [edx
+
$0c]
而 进行 mInt.Chk; 调用时的代码也是这个,这说明强制转化时,编译器根本就没有把ITestInterface转化为ITestInterface2,而是理解为直接的对象 强制转化,然后希望能在方法表里找到对应的方法,而且在对接口进行方法的解析时,也只是以方法的声明顺序,而不是实际的方法名来进行解析.所以在Chk为 ITestInterface的第一个方法,而Chk2也为ITestInterface2的第一个方法时,就会直接的调用了 ITestInterface的Chk,而不是ITestInterface2的Chk2.这个结论也可能通过下面这个实验来表明.
ITestInterface
=
interface
(IUnknown)
[
'
{DE8E7E63-BD1B-4BD8-B59A-43F4B2B3A3DC}
'
]
procedure Chk;
end;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ITestInterface2
=
interface
(IUnknown)
[
'
{3B47B113-4664-4CCC-9A69-E378F2D2363E}
'
]
procedure Chk2;
procedure Chk22;
end;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
var
mInt: ITestInterface;
mInt2: ITestInterface2;
begin
mInt :
=
TTestInterface2.Create;
mInt.Chk;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ITestInterface2(mInt).Chk22;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
mInt2 :
=
mInt
as
ITestInterface2;
mInt2.Chk2;
end;
在这种情况下,就会报地址出错,那是因为ITestInterface根本就没有第二个方法.当然下面的代码也能说明问题
ITestInterface
=
interface
(IUnknown)
[
'
{DE8E7E63-BD1B-4BD8-B59A-43F4B2B3A3DC}
'
]
procedure Chk;
procedure Chk1;
end;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ITestInterface2
=
interface
(IUnknown)
[
'
{3B47B113-4664-4CCC-9A69-E378F2D2363E}
'
]
procedure Chk2;
procedure Chk22;
end;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
var
mInt: ITestInterface;
mInt2: ITestInterface2;
begin
mInt :
=
TTestInterface2.Create;
mInt.Chk;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ITestInterface2(mInt).Chk22;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
mInt2 :
=
mInt
as
ITestInterface2;
mInt2.Chk2;
end;
在这种情况下,程序会调用ITestInterface的Chk1方法.
好上面说了强制转化时发生的情况,下面说用as来转化时发生的情况.
当用as来转化时,代码就变为:
lea eax, [ebp
-
$
08
]
mov edx, [ebp
-
$
04
]
mov ecx, $00452bc4
call @IntfCast
mov eax, [ebp
-
$
08
]
mov edx, [eax]
call dword prt [edx
+
$0c]
发现,在用as标志转化后,就会使编译器知道要在类实例中查找实际的接口ITestInterface2而不是用mInt所声明的ITestInteface.
以上说明Delphi7的编译器对接口的支持还是不够好,造成在强制转化时,不能正确的识别出要求的接口类型来.
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
从 运行情况可以看出,在第一种情况 ITestInterface2(mInt).Chk2; 下,实际运行的还是ITestInterface下的procedure Chk;而第二种情况 mInt2 := mInt as ITestInterface2; 就能正确的运行ITestInterface2下的procedure Chk2;了.这是为什么呢?
原来这都出自Delphi的编译之手,在进行强制转化 ITestInterface2(mInt).Chk2; 时, 代码是:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
而 进行 mInt.Chk; 调用时的代码也是这个,这说明强制转化时,编译器根本就没有把ITestInterface转化为ITestInterface2,而是理解为直接的对象 强制转化,然后希望能在方法表里找到对应的方法,而且在对接口进行方法的解析时,也只是以方法的声明顺序,而不是实际的方法名来进行解析.所以在Chk为 ITestInterface的第一个方法,而Chk2也为ITestInterface2的第一个方法时,就会直接的调用了 ITestInterface的Chk,而不是ITestInterface2的Chk2.这个结论也可能通过下面这个实验来表明.
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
在这种情况下,就会报地址出错,那是因为ITestInterface根本就没有第二个方法.当然下面的代码也能说明问题
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
在这种情况下,程序会调用ITestInterface的Chk1方法.
好上面说了强制转化时发生的情况,下面说用as来转化时发生的情况.
当用as来转化时,代码就变为:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
发现,在用as标志转化后,就会使编译器知道要在类实例中查找实际的接口ITestInterface2而不是用mInt所声明的ITestInteface.
以上说明Delphi7的编译器对接口的支持还是不够好,造成在强制转化时,不能正确的识别出要求的接口类型来.