我已经创建了几个简单的列表(以及整数列表和颜色列表),但是当我尝试创建“扩展”列表时,即使我对前两个列表使用了类似的类型转换,它也会显示无效的类型转换(无论我在哪里,都会抛出错误使用Extended()类型转换)。

Type
  TAExtList = Class(TObject)
  Private
    FList: TList;
    Procedure SetExt(Index: Integer; Value: Extended);
    Function GetCnt: Integer;
    Function GetExt(Index: Integer): Extended;
  Public
    Constructor Create;
    Destructor Destroy; Override;
    Function Add(Value: Extended): Integer;
    Function Insert(Index: Integer; Value: Extended): Integer;
    Procedure Delete(Index: Integer);
    Procedure Clear;
    Function IndexOf(Value: Extended): Integer;
    Property Count: Integer Read GetCnt;
    Property Extendeds[Index: Integer]: Extended Read GetExt Write SetExt; Default;
  End;

Function TAExtList.Add(Value: Extended): Integer;
Begin
  Result := FList.Add(Pointer(Value));
End;

最佳答案

有几个原因。首先,正如MBo在他的答案中所写的那样,Extended的大小为10个字节,因此它不适合Pointer的32位(4个字节)。

另一个原因是,在Delphi中,不允许将硬转换直接转换为浮点类型,因为太多的C程序员期望转换进行转换,而不仅仅是重新解释Extended(或其他浮点类型)的字节。尽管大小会匹配,但也不强制转换为Single。如果我没记错的话,很早的Delphi版本确实允许进行这些强制转换(或者说是Turbo Pascal?)。

但是,如果使用指向TExtendedList的指针,您仍然可以创建Extended(毕竟,TList存储指针):

type
  PExtended = ^Extended;

function TExtendedList.Add(const E: Extended): Integer;
var
  P: PExtended;
begin
  New(P);       // allocate an Extended on the heap and "return" a pointer to it
  P^ := E;      // store the parameter on the heap
  inherited Add(P); // add the pointer to the list
end;


但这意味着您的TList现在包含指向在堆上分配的Extended的指针。因此,删除或更改要求您使用

Dispose(P);


在适当的位置(例如Delete()Remove()Extract()Clear等以及析构函数中)。每个分配的Extended必须在正确的时间处理。

检索类似:

function TExtendedList.GetExt(Index: Integer): Extended;
var
  P: PExtended;
begin
  P := inherited Items[Index];
  Result := P^;
  // or short form: Result := PExtended(inherited Items[Index])^;
end;

procedure TExtendedList.SetExt(Index: Integer; Value: Extended);
var
  P: PExtended;
begin
  P := inherited Items[Index];
  P^ := Value;
  // or short form: PExtended(inherited Items[Index])^ := Value;
end;

procedure TExtendedList.Delete(Index: Integer);
begin
  Dispose(PExtended(inherited Items[Index]));
  inherited Delete(Index);
end;

procedure TExtendedList.Clear;
var
  I: Integer;
begin
  for I := 0 to Count - 1 do
    Dispose(PExtended(inherited Items[I]));
  inherited Clear;
end;


等等...

更新资料

正如@kobik所说,您可以使用虚拟的Notify函数来删除已删除的项目,而不是在每种方法中:

procedure TExtendedList.Notify(Ptr: Pointer; Action: TListNotification); // declare as override;
begin
  inherited;
  if Action = lnDeleted then
    Dispose(PExtended(Ptr));
end;

关于delphi - 为什么Delphi 7不允许扩展类型的TList,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44683319/

10-10 08:01