1

使用 BDS2006:我正在尝试在 C++ 中转换 Graphics32 Resampler_ex 示例,但我什至无法理解某些代码中发生了什么,或者如何在 C++ 中重写该代码。

在该示例中,有一个组合框可以选择要使用的重采样器:这是他的 OnChange 事件中的 Deplhi 代码:

procedure TfmResamplersExample.KernelClassNamesListClick(Sender: TObject);
var
  Index: Integer;
begin
  Index := KernelClassNamesList.ItemIndex;
  if Src.Resampler is TKernelResampler then
    with TKernelResampler(Src.Resampler) do
    begin
      Kernel := TCustomKernelClass(KernelList[Index]).Create;
      LbParameter.Visible := (Kernel is TAlbrechtKernel) or
{$IFDEF Ex}
        (Kernel is TGaussianKernel) or
        (Kernel is TKaiserBesselKernel) or
        (Kernel is TNutallKernel) or
        (Kernel is TBurgessKernel) or
        (Kernel is TBlackmanHarrisKernel) or
        (Kernel is TLawreyKernel) or
{$ENDIF}
        (Kernel is TSinshKernel);
      gbParameter.Visible := LbParameter.Visible;
      SetKernelParameter(Kernel);
      CurveImage.Repaint;
    end;
end;

在哪里:

{ TClassList }
{ This is a class that maintains a list of classes. }
TClassList = class(TList)
protected
  function GetItems(Index: Integer): TClass;
  procedure SetItems(Index: Integer; AClass: TClass);
public
  function Add(AClass: TClass): Integer;
  function Extract(Item: TClass): TClass;
  function Remove(AClass: TClass): Integer;
  function IndexOf(AClass: TClass): Integer;
  function First: TClass;
  function Last: TClass;
  function Find(AClassName: string): TClass;
  procedure GetClassNames(Strings: TStrings);
  procedure Insert(Index: Integer; AClass: TClass);
  property Items[Index: Integer]: TClass read GetItems write SetItems; default;
end;
ResamplerList: TClassList;

我的问题在这条线上

      Kernel := TCustomKernelClass(KernelList[Index]).Create;

我如何在 C++ 中转换这一行?

在评论和答案之后编辑:

好吧,似乎超出了我的理解。就我的目的而言,无需太多麻烦即可复制此代码的功能就足够了。

是否可以仅使用基于 itemindex 的开关来实例化正确的类?

这些是我应该实例化的 4 个类:

class DELPHICLASS TNearestResampler;
class PASCALIMPLEMENTATION TNearestResampler : public Gr32::TCustomResampler 
{
    typedef Gr32::TCustomResampler inherited;
    [...]
}

class DELPHICLASS TLinearResampler;
class PASCALIMPLEMENTATION TLinearResampler : public Gr32::TCustomResampler 
{
    typedef Gr32::TCustomResampler inherited;
    [...]
};


class DELPHICLASS TDraftResampler;
class PASCALIMPLEMENTATION TDraftResampler : public TLinearResampler 
{
    typedef TLinearResampler inherited;
    [...]   
};


class DELPHICLASS TKernelResampler;
class PASCALIMPLEMENTATION TKernelResampler : public Gr32::TCustomResampler 
{
    typedef Gr32::TCustomResampler inherited;
    [...]
};

我不明白我怎么能将其中一个分配给“内核”....

4

2 回答 2

1

Delphi 代码依赖于 Delphi 虚拟构造函数。C++ 中不存在此功能。

如果您想逐字翻译代码,那么您需要找到一种方法来通过调用虚拟 Delphi 构造函数来实例化该类。你不能在 C++ 中做到这一点,所以你需要一些 Delphi 代码将它们粘合在一起。Remy's answer here展示了如何使用__classid()来获取 Delphi 元类。然后,您需要将该元类传递给 Delphi 函数以执行实例化。

坦率地说,我认为这是一个相当复杂的问题解决方案。相反,我想我会用函数列表替换类列表。列表中的函数将具有实例化内核的新实例的任务。因此,不是向列表中添加一个类,而是添加一个创建该类的新实例的函数。实际上,您可能需要名称和功能之间的映射,这完全取决于您的需要。

于 2014-06-18T11:24:15.463 回答
0

根据我对 Delphi 编程的记忆,这实际上将实例化相同类型的类,该类当前保存在KernelList[index]然后将其转换回TCustomKernelClass. AFAIK 在 C++ 中没有这样的机制,但是您可以通过引入虚拟 CreateInstance 方法来解决它:

class TCustomKernelClass
{
public:
    virtual TCustomKernelClass * CreateInstance() = 0;
}

class TDerivedKernelClass
{
public:
    TCustomKernelClass * CreateInstance()
    {
        return new TDerivedKernelClass();
    }
}

但是,您必须在类中引入一些更改。我怀疑它可以直接用 C++ 解决。


编辑:回应评论

好的,我现在看到了,该列表中保留了类定义。由于 C++ 中的 RTTI 不像 Delphi 那样广泛,我将代码更改为(从内存编写,可能无法编译):

std::vector<std::function<TBaseKernelClass(void)>> KernelList;

KernelList.push_back([]() { return new TDerivedKernelClass(); });

// (...)

Kernel = KernelList[index]();
于 2014-06-18T10:54:17.587 回答