从C++到ObjectPascal的翻译比较,哪个更好?

3

我正在将一些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++中作为参数使用的指针应该设置为Object Pascal中的var参数。这是否正确?还是应该坚持更直接的翻译(担心以后出现问题)。

此外,在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;

也许我在过度猜测意图?

你应该关注析构函数和异常处理(相比之下,其他都是微不足道的)! - user2249683
此外,在Pascal中应该使用Ln表示自然对数。 - Free Consulting
1
我的错。我担心放太多代码(你能相信吗?)。但是针对你的观点,我认为这最初是C翻译成C ++的。这是一些DSP工作的工程代码。我更喜欢删除旧式写作,并使其更像OP。它需要被翻译以便与我们使用的所有OP代码更加灵活,但除了使其功能正常外,如果我们能理解每个部分,那就更好了。这就是我遇到麻烦的地方。我更倾向于使用OP而不是C或C ++。在我提出更多问题之前,我将尝试使用Dyn数组。我明白了。 - Michelle
@Michelle,你不需要一个动态数组,在事实上。看看表达式,它会导致new将要分配的元素数量。这是一个常数。如果你愿意牺牲那个漂亮的表达式(因为Borland编译器不喜欢常数表达式中的实数),那么普通数组就适用。 - Free Consulting
免费咨询,因此错误的揭示继续。是的,我确实需要一个动态数组。我忘记在公式中包括长度参数了。也为Pascal添加了Ln。谁是Borland? - Michelle
显示剩余2条评论
2个回答

1
决定使用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;

好的,我明白了。我肯定没有提供足够的代码。然而,现在看完其余的代码后,我认为如果我只将变量声明为普通数组(这是关键-将它们视为数组),并通过var传递它们,那么它会很好地工作。我陷入了试图保持所有指针的状态中。 - Michelle

1

总的来说,您的翻译质量很好。

我读过在C++中用作参数的指针应该设置为Object Pascal中的var参数。这是正确的吗,还是我应该坚持更字面的翻译(担心以后会出问题)。

我想说这部分是正确的。使用类型化指针作为参数是一种较低级别的实现通过引用传递参数的方式。它增加了灵活性,可以传递空指针(nil)而不是真正的变量引用,有效地使参数变为可选项。您应该检查代码是否有这样的检查(if (kw) { *kw = ...; } /* 仅在请求时写入kw */)。如果没有意图使指针参数成为可选项,则应坚持使用更高级别的按引用声明(varout)。

_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?

您在可疑行中明显使用了隐式解引用,因此它会将0写入_ap的第一个元素。覆盖指向最近内存分配的指针是不合逻辑的,对吗?您的字面Pascal翻译应该是:_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

谢谢。这些是非常好的观点,现在看来有点尴尬。我需要更好地解密实际内存使用情况。为了记录,我的第一个 _ap := ? 尝试是 _ap^ := 0,但然后 ap^[0] :=,然后... 可怕!再次感谢! - Michelle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接