使用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;
[...]
};
我从来没有得到如何将其中一个分配给“内核”....
答案 0 :(得分:1)
Delphi代码依赖于Delphi虚拟构造函数。 C ++中不存在此功能。
如果你想从字面上翻译代码,那么你需要找到一种通过调用虚拟Delphi构造函数来实例化类的方法。你不能用C ++做到这一点,所以你需要一些Delphi代码将它们粘合在一起。 Remy的回答here显示了如何使用__classid()
来获得Delphi元类。然后,您需要将该元类传递给Delphi函数以执行实例化。
坦率地说,我认为这是解决问题的一个相当复杂的解决方案。相反,我想我会用函数列表替换类列表。列表中的函数将具有实例化内核的新实例的任务。因此,不添加类到列表,而是添加一个创建类的新实例的函数。实际上,您可能需要名称和功能之间的地图,这一切都取决于您的需求。
答案 1 :(得分: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]();