常量对象不能作为var参数传递

Gle*_*rse 7 delphi delphi-xe2

这是故障代码..

multresult := mult(mult(temp, quatview), conjugate(temp));
Run Code Online (Sandbox Code Playgroud)

完整程序

procedure TForm2.RotateCamera(var angle: Single; x: Single; y: Single; z: Single);
var
    temp, QuatView, multResult : TQuaternion;
begin
    temp.x := x * sin(Angle/2);
    temp.y := y * sin(Angle/2);
    temp.z := z * sin(Angle/2);
    temp.w := cos(Angle/2);

    quatview.x := camera1.Position.x;
    quatview.y := camera1.Position.y;
    quatview.z := camera1.Position.z;
    quatview.w := 0;

    multresult := mult(mult(temp, quatview), conjugate(temp));

    camera1.Position.x := multresult.x;
    camera1.Position.y := multresult.y;
    camera1.Position.z := multresult.z;
end;
Run Code Online (Sandbox Code Playgroud)

多功能

function TForm2.mult(var A: TQuaternion; B: TQuaternion) :TQuaternion;
 var
   c : TQuaternion;
begin
  C.x := A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
  C.y := A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
  C.z := A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
  C.w := A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
result := C;
End;
Run Code Online (Sandbox Code Playgroud)

和共轭

 function TForm2.conjugate( var quat:TQuaternion) :TQuaternion;
  begin
     quat.x := -quat.x;
     quat.y := -quat.y;
     quat.z := -quat.z;
     result := quat;
  end;
Run Code Online (Sandbox Code Playgroud)

如果需要TQuaternion

type
  TQuaternion = class
    x: single;
    y: single;
    z: single;
    w: single;
  end;
Run Code Online (Sandbox Code Playgroud)

任何想法为什么我得到这个错误以及如何解决它?

Dav*_*nan 13

你问的问题的答案是mult的参数应该是const.你不修改它们(你不应该),所以把它们变成const.然后你的代码编译.

类似地,Conjugate修改其输入参数是不好的形式.这使得功能可怕使用.不要那样做.

考虑这一行:

multresult := mult(mult(temp, quatview), conjugate(temp) );
Run Code Online (Sandbox Code Playgroud)

由于共轭修改了temp,你最好希望在使用temp之后调用共轭.语言没有这样的保证.所以,交叉你的手指!

算术代码值得遵循的原则之一是不应修改输入参数/操作数,并且该函数始终返回值.遵循这个原则,你永远不会陷入上面强调的陷阱.请参阅我的答案的第二部分以获得说明.

但是,即使使用这些更改,代码也无法工作,因为您没有实例化TQuaternion类的任何实例.你确定它不是一张唱片吗?


当您创建良好的四元数类型时,将会出现真正的前进进展.这应该是值类型,因为算术运算由于多种原因更适合于值类型.

在现代Delphi中,您希望使用带有运算符的记录.这是您需要的风格,随时可以根据需要进行扩展.

type
  TQuaternion = record
    x: single;
    y: single;
    z: single;
    w: single;
    function Conjugate: TQuaternion;
    class operator Multiply(const A, B: TQuaternion): TQuaternion;
  end;

function TQuaternion.Conjugate: TQuaternion;
begin
  Result.x := -x;
  Result.y := -y;
  Result.z := -z;
  Result.w := w;
end;

class operator TQuaternion.Multiply(const A, B: TQuaternion): TQuaternion;
begin
  Result.x := A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
  Result.y := A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
  Result.z := A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
  Result.w := A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
end;
Run Code Online (Sandbox Code Playgroud)

使用此类型,您的乘法调用将变为:

 multresult := temp*quatview*temp.Conjugate;
Run Code Online (Sandbox Code Playgroud)

您肯定希望为此类型编写更多运算符和辅助函数.

将算术函数移入此类型并从表单中移除是非常重要的.不要使用高级GUI表单类来实现低级算术.

最后一条建议.您的代码重复使用了var参数.我建议你将var参数视为要避免的事情.如果可能的话,尽量不用编写代码.


RRU*_*RUZ 5

mult方法将A参数声明为a,var因此您必须将变量传递给方法才能工作,就像这样.

 multresult := mult(temp, quatview);
 multresult := mult(multresult, conjugate(temp));
Run Code Online (Sandbox Code Playgroud)

  • 我认为这个答案对问题的分析有点浅薄.是的,此更改将使代码编译.但是,你会遇到许多其他问题.即使这样,这里提出的解决方案也很差,因为要克服的第一个错误是错误使用var参数.这似乎是一个反复出现的主题. (5认同)