TVector3D.AddVector3D不起作用(对我来说)

时间:2013-07-24 20:25:03

标签: delphi firemonkey delphi-xe4

使用 Delphi XE4 (update1)和 FMX ,我希望移动相机使用此代码(在wheel-mouse事件中):

AVector := Vector3D(0, 0, 3);
Camera.Position.Vector.AddVector3D(AVector);

代码编译,什么都不做。使用de调试器时,Camera.Position.Vector不会更改

使用

更改行时
AVector := Vector3D(0, 0, 3);
Camera.Position.Vector := Camera.Position.Vector + AVector;

......它有效!!!奇怪的是,AddVector3D()函数正好执行此代码!!!

procedure TVector3D.AddVector3D(const AVector3D: TVector3D);
begin
  Self := Self + AVector3D;
end;

我的代码有什么问题???

1 个答案:

答案 0 :(得分:4)

Camera.Position的类型为TPosition3DTPosition3D.VectorTVector3D类型的属性,带有getter和setter。请注意,TVector3D是一个记录,它是值类型而不是引用类型。这个细节至关重要。

所以,当你写Camera.Position.Vector时,你指的是矢量的副本。它是一个副本,因为TVector3D是值类型。

因此,非工作代码相当于:

var
  TempVec: TVector3D;
....
TempVec := Camera.Position.Vector;
TempVec.AddVector3D(...);

显然,对AddVector3D的调用不会修改Camera.Position,因为对AddVector3D的调用只会改变临时本地。

在您的代码中,该临时局部变量仍然存在,但您没有给它命名。这是一个隐藏的隐含变量。

为了修改位置,您必须对Vector属性进行赋值,这正是工作代码所做的。

作为一般规则,支持就地变异的价值类型通常表示设计不佳。因此,在我看来,Embarcadero工程师绝不应该添加变异实例方法,如AddVector3DNormalizeScale等。这些方法导致了这种混乱。相反,使用返回新值的函数可以更好地实现该功能,就像重载运算符一样。