delphi — проверка перевода с C ++ на ObjectPascal, что лучше

Я перевожу некоторый код C ++ в ObjectPascal (впервые), и C ++ все еще довольно нов для меня.

Заголовочный файл C ++ выглядит так:

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;
}

Я перевёл их так:

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;

Я читал, что указатели, используемые в качестве параметров в C ++, должны быть установлены как параметры var в Object Pascal. Это правильно, или я должен придерживаться более буквального перевода (беспокоюсь о том, чтобы быть укушенным позже).

Также в конструкторе C ++ есть следующий код, в котором я не уверен в одной строке.

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?

//...

}

Я не уверен, стоит ли переводить эту строку в Object Pascal, чтобы заполнить первый элемент нулем или присвоить nil:

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

Может быть, я слишком стараюсь угадать намерение?

3

Решение

Решение использовать var или указатель действительно зависит от того, как он будет использоваться, и может ли он быть установлен на nil или нет. типично var лучше, но указатель имеет свое применение. Вы не предоставили достаточно кода, чтобы показать, какое решение лучше.

Что касается выделения массива, динамический массив будет лучшим выбором, чем 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;
1

Другие решения

В целом, ваш перевод хорошего качества.

Я читал, что указатели, используемые в качестве параметров в C ++, должны быть установлены как var
параметры в Object Pascal. Это правильно, или я должен придерживаться
более буквальный перевод (беспокоюсь о том, чтобы быть укушенным позже).

Я бы сказал, что это частично правильно. Использование типизированного указателя в качестве параметра является способом реализации более низкого уровня. передача параметров по ссылке. Это добавляет гибкость для передачи указателя NULL (nil) вместо ссылки на реальную переменную, что делает параметр необязательным. Вы должны проверить свой код для таких проверок (if (kw) { *kw = ...; } /* writes to kw only if requested */). Если нет намерения сделать параметры указателя необязательными, вам следует придерживаться более высокого уровня по ссылке декларации (var или же out).

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

Я не уверен, стоит ли переводить эту строку в Object Pascal в
заполнение первого элемента нулем или присвоение нулю:

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

Может быть, я слишком стараюсь угадать намерение?

Вы явно получили неявную разыменование в сомнительной строке, поэтому она записывает 0 в самый первый элемент _ap, Нелогично перезаписывать указатель на недавнее выделение памяти, не так ли? Ваш буквальный перевод на Паскаль должен быть: _ap^ := 0;

Но обратите внимание, что new оператор выделяет более 1 int, Так что ваши PInteger типа не хватает, нужно PIntegerArray, То есть:

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

декларирование _ap этот тип сэкономит вам много типов и по-прежнему будет максимально приближен к оригиналу C ++. Я не согласен, что вам нужен динамический массив, это абсолютно хороший выбор здесь.

Последнее слово (минор):

constructor Create(const length:integer);

Я не вижу цели передачи этого целого числа по константной ссылке, и оно не соответствует буквальному коду оригинального C ++. Там не будет никакого эффекта, но я бы удалить const,

1

По вопросам рекламы [email protected]