我正在尝试为复合控件构建一个泛型祖先。最初的想法是这样的:
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;正如你可能已经知道的,这将触发编译器错误E2568:如果类型参数声明中没有构造函数约束,则无法创建新实例。然而,添加constructor约束并没有什么帮助,因为它暗示了一个无参数的构造函数。
将模板转换为TControl使代码可编译:
...
FControl1 := TControl(TControl1).Create(Self);
......but它会在运行时导致访问冲突。
一个可能可行的方法是通过RTTI调用构造函数,但我认为这是一个相当糟糕的解决方案。
另一个本质上有效的技巧是使用类类型变量作为中间层:
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;有没有更干净的解决方案?另外,有人能给我解释一下为什么classtype约束不足以直接调用type参数上的虚拟构造函数吗?
发布于 2012-03-06 23:51:35
你的类型转换不好:TControl(TControl1).Create(Self)。这告诉编译器TControl1是TControl的一个实例,但我们知道它不是一个实例。它是一个类引用。type -将其转换为类引用类型:
FControl1 := TControlClass(TControl1).Create(Self);发布于 2015-12-11 06:34:26
另一种语法是
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中使用的,我只是不能决定哪个选项是最不丑陋的!
发布于 2016-02-15 01:07:11
这似乎是最新的delphi版本(西雅图),这个编译器错误不再发出。我在我们的应用程序中遇到了同样的问题,但只有在使用DelphiXe8而不是delphi Seattle编译时才会遇到这个问题
https://stackoverflow.com/questions/9586626
复制相似问题