使用DrawText重载分辨率错误

时间:2014-07-31 07:37:37

标签: delphi delphi-xe2 overload-resolution

在将一些代码从D2007移植到XE2时,我遇到了编译错误,我无法理解。请参阅以下示例:

procedure TForm1.FormPaint(Sender: TObject);
var
  c: Char;
  pc: PChar;
  r: TRect;
begin
  c := '1';
  pc := @c;
  r := Bounds(100, 100, 100, 100);
  DrawText(Canvas.Handle, pc, 1, r, DT_SINGLELINE or DT_NOCLIP); //1
{$TYPEDADDRESS OFF}
  DrawText(Canvas.Handle, @c, 1, r, DT_SINGLELINE or DT_NOCLIP); //2
{$TYPEDADDRESS ON}
  DrawText(Canvas.Handle, @c, 1, r, DT_SINGLELINE or DT_NOCLIP); //3
  DrawText(Canvas.Handle, PChar(@c), 1, r, DT_SINGLELINE or DT_NOCLIP); //4
end;

D2007编译没有问题。 XE2编译器拒绝标记为//3的行

  

[DCC Fehler] Unit1.pas(38):E2010 Inkompatible Typen:' string' '指针'

我想这是因为新添加的DrawText重载接受了Delphi字符串。

你能解释一下这个错误吗?由于我有一个解决方法(明确的演员),这不是什么大问题,但我很好奇。该错误是否仍存在于以后的Delphi版本中?

编辑:我问是否编译器中有错误,而不是解释为什么。很可能我忽略了编译器拒绝我的代码的正当理由。

1 个答案:

答案 0 :(得分:7)

这似乎不是正常的重载解决情况。 DrawText定义为:

function DrawText(hDC: HDC; 
                  lpString: PWideChar; 
                  nCount: Integer;
                  var lpRect: TRect; 
                  uFormat: UINT): Integer; external user32 name 'DrawTextW';

function DrawText(hDC: HDC; 
                  const lpString: UnicodeString; 
                  nCount: Integer;
                  var lpRect: TRect; uFormat: UINT): Integer;
begin
  Result := Winapi.Windows.DrawText(hDC, 
                                    PWideChar(lpString), 
                                    nCount, 
                                    lpRect, 
                                    uFormat);
end;

{$TYPEDADDRESS OFF}似乎编译器将^Char解释为无类型pointer,与PChar的声明类型永远不兼容@c似乎解决了PChar确定。这似乎与{$TYPEDADDRESS OFF}旨在使所有指针类型无关的概念不一致。似乎PChar^Char在编译器中的处理方式与其他指针不同。

使用{$TYPEDADDRESS ON} @c^Char都会变得相同,但只要没有重载解决方案可以接受,就会被奇怪地接受为参数。

在这两种情况下,似乎重载决策在完全建立类型兼容性之前完成。我不确定我会把它称为一个错误,但是......似乎行为在不引起问题的情况下变得很棘手。

SSCCE

program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

{$DEFINE OVLD}

{$IFDEF OVLD}
procedure Test(s:string); overload;
begin
end;
{$ENDIF}
procedure Test(x:PChar); {$IFDEF OVLD}overload; {$ENDIF}
begin
end;

var
  c : Char;
  pc : ^Char;
begin
  {$TYPEDADDRESS OFF}
  Test(@c);
  Test(pc);    //OVLD - Incompatible types : 'string'-'pointer'
               //No OVLD - Incompat. types : 'PWideChar'-'pointer'
  {$TYPEDADDRESS ON}
  Test(@c);    //OVLD - Incompatible types : 'string'-'pointer'
               //No OVLD - OK
  Test(pc);    //OVLD - Incompatible types : 'string'-'pointer'
               //No OVLD - OK
end.