在将一些代码从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版本中?
编辑:我问是否编译器中有错误,而不是解释为什么。很可能我忽略了编译器拒绝我的代码的正当理由。
答案 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.