有人在使用QueryInterface在Delphi中注意到这种行为吗?

时间:2010-08-11 12:21:07

标签: delphi queryinterface

以下是我的类型......

unit unitTestInterfaces;

interface
type
  IFoo = interface
    ['{169AF568-4568-429A-A8F6-C69F4BBCC6F0}']
    function TestFoo1:string;
    function TestFoo:string;
  end;

  IBah = interface
    ['{C03E4E20-2D13-45E5-BBC6-9FDE12116F95}']
    function TestBah:string;
    function TestBah1:string;
  end;

  TFooBah = class(TInterfacedObject, IFoo, IBah)
    //IFoo
    function TestFoo1:string;
    function TestFoo:string;

    //IBah
    function TestBah1:string;
    function TestBah:string;
  end;

implementation

{ TFooBah }

function TFooBah.TestBah: string;
begin
  Result := 'TestBah';
end;

function TFooBah.TestBah1: string;
begin
  Result := 'TestBah1';
end;

function TFooBah.TestFoo: string;
begin
  Result := 'TestFoo';
end;

function TFooBah.TestFoo1: string;
begin
  Result := 'TestFoo1';
end;

end.

这是我运行示例的代码......

var
  fb:TFooBah;
  f:IFoo;
  b:IBah;
begin
  try
    fb := TFooBah.Create;

    /// Notice we've used IBah here instead of IFoo, our writeln() still outputs the
    /// result from the TestBah() function, presumably because it's the "first" method
    /// in the IBah interface, just as TestFoo1() is the "first" method in the IFoo
    /// interface.
    (fb as IUnknown).QueryInterface(IBah,f); //So why bother with this way at all??
    //f := fb as IBah; //causes compile error
    //f := fb; //works as expected
    if Assigned(f)then
    begin
      writeln(f.TestFoo1); //wouldn't expect this to work since "f" holds reference to IBah, which doesn't have TestFoo1()
    end;

    (fb as IUnknown).QueryInterface(IBah,b);
    if Assigned(f) then
    begin
      writeln(b.TestBah1);
    end;

  except on E:Exception do
    writeln(E.Message);
  end;
end.

似乎在第一次调用QueryInterface时,即使我们将错误类型的接口分配给“f”变量,它仍然会尝试执行它所指向的任何“第一”方法,而不是名为“TestFoo1”的方法。使用f:= fb按预期工作,所以有理由我们使用QueryInterface而不是语法f:= fb?

3 个答案:

答案 0 :(得分:7)

我猜你违反了规则:

QueryInterface会将接口放入您请求的f中。你有责任f是适当的类型。由于第二个参数是无类型的,编译器无法警告您有关您的错误。

答案 1 :(得分:3)

我认为更好的语法既不是QueryInterface也不是f := fb。这是你评论过的那个:

f := fb as IBah; //causes compile error

这正是因为它有类型检查,它覆盖了QueryInterface的问题,它不检查它的参数。

答案 2 :(得分:2)

请注意f:= Fb作为IFoo,调用Supports(Fb,IFoo)等tec都在后台调用QueryInterface。所以使用了QueryInterface方法,但是你可以通过autocasting,is,as和方法来获得很好的语法。