Вопрос

I am translating some C++ code to ObjectPascal (first time), and C++ is still fairly new to me.

The C++ header file looks like this:

class RenumFd {
public:
    RenumFd(int length);
    ~RenumFd();
    void CompFd(double *buff);

//...other public functions cut for space

private:
    void rmfd(int n, int isgn, double *a, int *ap, double *kw);

//...other private functions cut for space

    int _length;
    int *_ap;
    double *_kw;
}

I have translated them this way:

Type
 TRenumFD = class
 private
   _length: integer;
   _ap: Pinteger;
   _kw: Pdouble;
   procedure rmfd(n:integer; isgn:integer; var a:double; var ap:integer; var kw:double);

//... other procedures cut for space   

public
  constructor Create(const length:integer);
  destructor  Destroy(); override;
  procedure CompFd(var buff:double);
end;

I read that pointers used as parameters in C++ should be set as var parameters in Object Pascal. Is that correct, or should I stick to a more literal translation (worried about being bitten later).

Also in the C++ constructor there is the following code, which I am unsure about in one line.

RenumFd::RenumFd(int length) {
    _length = length;
    _ap = new int[2 + (1 << ((int)(log(2.0 + length) + 0.5) / 2))];
    _ap[0] = 0;  <-- is this setting the pointer to nil, or assigning 0?

    //...

}

I am unsure if I should translate that line in Object Pascal to filling the first element with zero or assigning to nil:

_ap := AllocMem(2 + (1 shl (trunc(ln(2.0 + length) + 0.5) / 2))) * sizeOf(integer));
_ap := nil;

Maybe I am trying too hard to guess the intent?

Это было полезно?

Решение

The decision to use a var or a pointer really depends on how it is going to be used, and whether it can be set to nil or not. Typically var is better, but pointer has its uses. You did not provide enough code to show which decision is best.

As for the array allocation, a dynamic array would be a better choice than AllocMem():

type
  RenumFd = class
  public
    constructor Create(length: Integer);
    //...    
  private
    _ap: array of Integer;
    //...
  end;

constructor RenumFd.Create(length: Integer);
begin
  SetLength(_ap, 2 + (1 shl (Trunc(log(2.0) + 0.5) div 2)));
  _ap[0] := 0; // <-- assigns 0 to the first integer in the array
  //...
end;

Другие советы

In general, your translation is of good quality.

I read that pointers used as parameters in C++ should be set as var parameters in Object Pascal. Is that correct, or should I stick to a more literal translation (worried about being bitten later).

I'd say it is partially correct. Using typed pointer as parameter is lower-level way to implement passing parameters by reference. It adds a flexibility to pass NULL pointer (nil) instead of real variable reference, effectively making parameter optional. You should examine your code for such checks (if (kw) { *kw = ...; } /* writes to kw only if requested */). If there is no intent to make pointer parameter(s) optional, then you should stick to higher-level by reference declarations (var or out).

_ap[0] = 0;  <-- is this setting the pointer to nil, or assigning 0?

I am unsure if I should translate that line in Object Pascal to filling the first element with zero or assigning to nil:

_ap := AllocMem(2 + (1 shl (trunc(log(2.0) + 0.5) / 2))) * sizeOf(integer));
_ap := nil;

Maybe I am trying too hard to guess the intent?

You clearly got implicit dereferencing in the questionable line, so it writes 0 to the very first element of _ap. It is illogical to overwrite pointer to the recent memory allocation, isn't it? Your literal Pascal translation should be: _ap^ := 0;

But note what new operator allocates more than 1 int, so your PInteger type is not enough, you need PIntegerArray. That is:

type TIntegerArray = array[0..MaxInt div SizeOf(Integer)] of Integer;
type PIntegerArray = ^TIntegerArray;

Declaring _ap to this type will save you a lot of typecasting and still remains as close to the C++ original as possible. I do not agree what you need a dynamic array is absolute good choice here.

One last word (minor):

constructor Create(const length:integer);

I see no purpose of passing this integer by constant reference and it does not match original C++ code literally. There will be no effect at all, but I'd remove const.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top