Delphi XE:我可以使用类类型约束泛型类型中的参数调用虚拟构造函数,而不必接受黑客攻击吗?

Delphi XE:我可以使用类类型约束泛型类型中的参数调用虚拟构造函数,而不必接受黑客攻击吗?,delphi,generics,constructor,polymorphism,generic-constraints,Delphi,Generics,Constructor,Polymorphism,Generic Constraints,我正在尝试为复合控件构建一个通用祖先。最初的想法是这样的: type TCompositeControl<TControl1: TControl; TControl2: TControl> = class(TWinControl) private FControl1, FControl2: TControl; public constructor Create(AOwner: TComponent); override; end; TL

我正在尝试为复合控件构建一个通用祖先。最初的想法是这样的:

type
  TCompositeControl<TControl1: TControl; TControl2: TControl> = class(TWinControl)
  private
    FControl1,
    FControl2: TControl;
  public
    constructor Create(AOwner: TComponent); override; 
  end;

  TLabelAndEdit = TCompositeControl<TLabel, TEdit>; // simple example for illustration only

constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FControl1 := TControl1.Create(Self);
  FControl2 := TControl2.Create(Self);
end;
…但它会在运行时导致访问冲突

一个可能工作的黑客通过RTTI调用构造函数,但我认为这是一个相当肮脏的解决方案。< /P> 另一种基本有效的方法是使用类类型变量作为中间变量:

type
  TControlClass = class of TControl;

constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
var
  lCtrlClass1,
  lCtrlClass2: TControlClass;
begin
  inherited Create(AOwner);
  lCtrlClass1 := TControl1;
  FControl1 := lCtrlClass1.Create(Self);
  lCtrlClass2 := TControl2;
  FControl2 := lCtrlClass2.Create(Self);
end;
类型
TControlClass=TControl的类别;
构造函数TCompositeControl.Create(所有者:TComponent);
变量
立法会一题,,
lCtrlClass2:TControlClass;
开始
继承的创建(AOOwner);
lCtrlClass1:=TControl1;
FControl1:=lCtrlClass1.Create(Self);
lCtrlClass2:=TControl2;
FControl2:=lCtrlClass2.Create(Self);
结束;

有更清洁的解决方案吗?另外,有人能给我解释一下为什么classtype约束不足以直接调用类型参数上的虚拟构造函数吗?

您的类型转换不好:
TControl(TControl1)。Create(Self)
。这告诉编译器
TControl1
TControl
的实例,但我们知道它不是实例。这是课堂参考资料。类型将其强制转换为类引用类型:

FControl1 := TControlClass(TControl1).Create(Self);

如果您的类使用没有参数的构造函数(如TObject),我建议您按照编译器的说明进行操作:

“将构造函数约束添加到类型参数声明”

它应该是这样的:

type
  TCompositeControl<TControl1: TControl; TControl2: TControl> = class(TWinControl)
  private
    FControl1,
    FControl2: TControl;
  public
    constructor Create(AOwner: TComponent); override; 
  end;

  TLabelAndEdit = TCompositeControl<TLabel, TEdit>; // simple example for illustration only

constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FControl1 := TControl1.Create(Self);
  FControl2 := TControl2.Create(Self);
end;
TCompositeControl=类(TWinControl)

如果这样做,您应该能够对泛型类型的构造函数进行必要的调用

但是,我不知道,如果它与构造函数一起工作,谁需要一个参数


如果有效,请告诉我们。

另一种语法是

FControl1 := TControl1(TControl1.NewInstance); // get memory for object
FControl1.Create(self); // call type-specific constructor

FControl2 := TControl2(TControl2.NewInstance); // get memory for object
FControl2.Create(self); // call type-specific constructor
这在Delphi的Classes.pas::CreateComponent中使用
我只是无法决定哪种选择最不丑陋

似乎是最新的delphi版本(西雅图)不再发出此编译器错误。我遇到了与应用程序相同的问题,但只有在使用DelphiXe8编译时,而不是使用delphi Seattle

Arghl,是的。抢手货有道理。顺便问一下,您是否也知道为什么我不能将
FControl1
FControl2
分别声明为
TControl1
TControl2
?如果我这样做,我会得到一个编译器错误E2010不兼容的类型:“TLabel”和“TControl”在单元的末尾。不知道。我没有要测试的Delphi版本。从这个问题中删减代码,并将其作为一个新问题发布,如果这里还没有关于它的问题。当然可以。奇怪的是,到目前为止,我还不能用比
TComponent
-子体更简单的方法重现这个问题。。。无论如何,再次感谢你的原始答案!请重读这个问题。这特别是关于带参数的构造函数,而
构造函数
约束不能与这些参数一起使用。