gpt4 book ai didi

delphi - 将 self 作为函数结果返回时出现问题

转载 作者:行者123 更新时间:2023-12-03 14:55:45 25 4
gpt4 key购买 nike

我有一个非常简单的 3D 矢量类定义,TVector3D,以及一些用于实现 TVector3D.Normalise 函数的方法。如果我向 Normalise 函数传递一个已经标准化的向量,我希望它返回我传递给它的向量。在这里我使用了 Result := Self 但我得到了一些疯狂的返回。

控制台应用程序:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

type
TVector3D = Class
public
x : Single;
y : Single;
z : Single;
constructor Create(x : Single;
y : Single;
z : Single);
function GetMagnitude() : Single;
function IsUnitVector() : Boolean;
function Normalise() : TVector3D;
end;

constructor TVector3D.Create(x : Single;
y : Single;
z : Single);
begin
Self.x := x;
Self.y := y;
Self.z := z;
end;

function TVector3D.GetMagnitude;
begin
Result := Sqrt(Sqr(Self.x) + Sqr(Self.y) + Sqr(Self.z));
end;

function TVector3D.IsUnitVector;
begin
if Self.GetMagnitude = 1 then
Result := True
else
Result := False;
end;

function TVector3D.Normalise;
var
x : Single;
y : Single;
z : Single;
MagnitudeFactor : Single;
begin
if IsUnitVector then
Result := Self
else
MagnitudeFactor := 1/(Self.GetMagnitude);
x := Self.x*MagnitudeFactor;
y := Self.y*MagnitudeFactor;
z := Self.z*MagnitudeFactor;
Result := TVector3D.Create(x,
y,
z);
end;

procedure TestNormalise;
var
nonUnitVector : TVector3D;
unitVector : TVector3D;
nUVNormed : TVector3D;
uVNormed : TVector3D;
begin
//Setup Vectors for Test
nonUnitVector := TVector3D.Create(1,
1,
1);
unitVector := TVector3D.Create(1,
0,
0);
//Normalise Vectors & Free Memory
nUVNormed := nonUnitVector.Normalise;
nonUnitVector.Free;
uVNormed := unitVector.Normalise;
unitVector.Free;
//Print Output & Free Memory
WriteLn('nUVNormed = (' + FloatToStr(nUVNormed.x) + ', ' + FloatToStr(nUVNormed.y) + ', ' + FloatToStr(nUVNormed.z) + ')');
nUVNormed.Free;
WriteLn('uVNormed = (' + FloatToStr(uVNormed.x) + ', ' + FloatToStr(uVNormed.y) + ', ' + FloatToStr(uVNormed.z) + ')');
uVNormed.Free;
end;

begin
try
TestNormalise;
Sleep(10000);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

Normalise 对于非单位向量效果很好,即 IsUnitVector 返回 false。但对于单位向量,例如 (1,0,0),我不会返回自身,而是会得到一个具有非常低的非零数字的结果,无论以前有一个非零值,例如 (8.47122. ..E-38,0,0).

如果我通过调试器运行此代码,并在 Result := Self 行上设置一个断点来评估 Self,则 Self 为 (1,0,0) 但结果变为(非常低的数字,0,0)。每次运行程序时,非常低的数字都会发生变化,但似乎总是在E-38/E-39左右。

我不明白为什么会发生这种情况。为什么会发生这种情况以及如何最好地改变我的 Normalise 函数来避免它。

最佳答案

您当前的 TVector3D.Normalise 实现存在一些问题:

  • 最后 4 行总是执行,因为您没有在 else 之后使用 begin-end block ,
  • 因此例程永远不会返回Self,但始终返回一个新实例,
  • 返回实例的内存可能会泄漏,因为您在函数调用后失去了它的所有权,
  • IsUnitVector返回True时,MagnitudeFactor的赋值将被跳过,并且它将是一个随机值(当前存在于该值)内存的地址),这解释了为什么你会得到垃圾。编译器还会对此发出警告:变量 MagnitudeFactor 可能尚未初始化。

相反,我会重写例程如下:

function TVector3D.Normalise: TVector3D;
begin
if not IsUnitVector then
begin
x := x / GetMagnitude;
y := y / GetMagnitude;
z := z / GetMagnitude;
end;
Result := Self;
end;

关于delphi - 将 self 作为函数结果返回时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14547935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com