ИСПОЛЬЗОВАНИЕ BDS2006:
Я пытаюсь преобразовать пример Graphics32 Resampler_ex в C ++, но я даже не могу понять, что происходит в некоторых кодах, или как переписать этот код в C ++.
В этом примере есть поле со списком, чтобы выбрать, какой ресамплер использовать:
Это код Депли в его событии OnChange:
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;
[...]
};
Я никогда не понимаю, как я могу назначить один из них «Ядро» ….
Код Delphi опирается на виртуальные конструкторы Delphi. Эта функциональность не существует в C ++.
Если вы хотите перевести код буквально, вам нужно найти способ создания экземпляра класса, вызвав виртуальный конструктор Delphi. Вы не можете сделать это в C ++, поэтому вам понадобится код Delphi, чтобы склеить все это вместе. Ответ Реми Вот показывает, как использовать __classid()
получить метакласс Delphi. Затем вам нужно передать этот метакласс в функцию Delphi, чтобы выполнить создание экземпляра.
Честно говоря, я бы посчитал это довольно запутанным решением проблемы. Вместо этого я думаю, что я бы заменил список классов на список функций. Функции в списке будут иметь задачу создания нового экземпляра ядра. Таким образом, вместо добавления класса в список, вы добавляете функцию, которая создает новый экземпляр класса. На самом деле вам может понадобиться карта между именем и функцией, все зависит от ваших потребностей.
Из того, что я помню из программирования на Delphi, это фактически создаст экземпляр того же типа класса, который в настоящее время хранится в KernelList[index]
а затем бросить его обратно TCustomKernelClass
, AFAIK, в C ++ такого механизма нет, но вы можете решить его, введя виртуальный метод CreateInstance:
class TCustomKernelClass
{
public:
virtual TCustomKernelClass * CreateInstance() = 0;
}
class TDerivedKernelClass
{
public:
TCustomKernelClass * CreateInstance()
{
return new TDerivedKernelClass();
}
}
Вы должны будете внести некоторые изменения в классах, хотя. Я сомневаюсь, что это может быть решено непосредственно в C ++.
редактировать: В ответ на комментарии
Хорошо, теперь я вижу, что в этом списке хранятся определения классов. Поскольку RTTI в C ++ не такой обширный, как в Delphi, я бы изменил код на (записанный из памяти, может не скомпилироваться):
std::vector<std::function<TBaseKernelClass(void)>> KernelList;
KernelList.push_back([]() { return new TDerivedKernelClass(); });
// (...)
Kernel = KernelList[index]();