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