当我尝试制作一个"扩展的"时,我已经创建了几个简单的列表(以及整数列表和颜色列表)。列出它表示无效的类型转换,即使我对前两个列表使用了类似的类型转换(无论我在何处使用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;
答案 0 :(得分:8)
Delphi 7中Integer
和TColor
的大小(4个字节)都与Pointer
相同,这就是显式转换的可能原因。
变量Typecasts
您可以将任何变量转换为任何类型,只要它们的大小相同即可 不要将整数与实数混在一起。
但是Extended
是真实的,它的大小是10个字节,你不能把它强制转换为Pointer
。而且,没有足够的地方。
P.S。请注意,新的Delphi版本包含相当方便的工具 - 泛型 - 只需定义和创建TList<Extended>
。
答案 1 :(得分:3)
有几个原因。首先,正如MBo在他的回答中所写,Extended
的大小为10个字节,因此它不适合Pointer
的32位(4个字节)。
另一个原因是在Delphi中,不允许直接硬转换为浮点类型,因为太多的C程序员期望转换器进行转换,而不仅仅是重新解释扩展的字节(或者其他浮点类型)。虽然大小匹配,但也不允许转换为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所说,您可以使用虚拟通知功能删除已删除的项目,而不是每种方法:
procedure TExtendedList.Notify(Ptr: Pointer; Action: TListNotification); // declare as override;
begin
inherited;
if Action = lnDeleted then
Dispose(PExtended(Ptr));
end;