Constant object cannot be passed as var parameter

喜欢而已 提交于 2019-12-10 12:58:12

问题


This is the trouble code..

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

Full procedure

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;

mult function

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;

and conjugate

 function TForm2.conjugate( var quat:TQuaternion) :TQuaternion;
  begin
     quat.x := -quat.x;
     quat.y := -quat.y;
     quat.z := -quat.z;
     result := quat;
  end;

and if needed TQuaternion

type
  TQuaternion = class
    x: single;
    y: single;
    z: single;
    w: single;
  end;

any idea why i get this error and how to fix it?


回答1:


The answer to the question you asked is that the parameters to mult should be const. You don't modify them (and you should not), so make them const. Then your code compiles.

In a similar vein, it's bad form for Conjugate to modify its input parameter. That makes the function horrid to use. Don't do that.

Consider this line:

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

Since conjugate modifies temp, you'd better hope that the call to conjugate is made after the other use of temp. The language makes no such guarantee. So, cross your fingers!

One of the principles worth following with arithmetic code is that input parameters/operands should never be modified, and that functions always return new values. Follow this principle and you'll never fall into trap highlighted above. See the second part of my answer for an illustration.

However the code won't work even with these changes because you are not instantiating any instances of the TQuaternion class. Are you sure that it's not a record?


The real forward progress will come when you create a good quaternion type. This should be a value type since arithmetic operations are better suited to value types for a number of reasons.

In modern Delphi you want to use a record with operators. Here's a flavour of what you need, ready to extend as you need.

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;

With this type your multiplication call becomes:

 multresult := temp*quatview*temp.Conjugate;

You'll surely want to write more operators and helper functions for this type.

It's really important to move the arithmetic functions into this type and out of your form. Don't use your high level GUI form class to implement low level arithmetic.

One final piece of advice. Your code has repeated mis-use of var parameters. I suggest you treat var parameters as things to be avoided. Try to write code without them if possible.




回答2:


The mult method declares the A parameter as a var so you must pass a variable to the method in order to work, like so.

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


来源:https://stackoverflow.com/questions/18295482/constant-object-cannot-be-passed-as-var-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!