Delphi XE:我可以从类类型约束的泛型类型中调用带有参数的虚拟构造函数而不接受黑客攻击吗? | 珊瑚贝

Delphi XE: Can I call virtual constructors with parameters from a classtype-constrained generic type without resigning to hacks?


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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: Can\\’t create new instance without CONSTRUCTOR constraint in type parameter declaration。然而,添加 constructor 约束并没有帮助,因为它意味着一个无参数的构造函数。

将模板转换为 TControl 使代码可编译:

1
2
3

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

…但它会在运行时导致访问冲突。

一个可能可行的技巧是通过 RTTI 调用构造函数,但我认为这是一个相当肮脏的解决方案。

另一个基本有效的技巧是使用类类型变量作为中间体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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-constraint 不足以直接在类型参数上调用虚拟构造函数吗?


你的类型转换不好:TControl(TControl1).Create(Self)。这告诉编译器 TControl1 是 TControl 的一个实例,但我们知道它不是一个实例。这是一个类参考。将其类型转换为类引用类型:

1
FControl1 := TControlClass(TControl1).Create(Self);
  • 啊,是的。接得好。说得通。
  • 顺便说一句,您是否也知道为什么我不能将 FControl1 和 FControl2 分别声明为 TControl1 和 TControl2 ?如果我这样做了,我会在单元末尾收到编译器错误 E2010 Incompatible types: ‘TLabel’ and ‘TControl’。
  • 不知道。我没有要测试的 Delphi 版本。如果这里还没有关于它的问题,请从这个问题中削减代码并将其作为一个新问题发布。
  • 肯定会的。奇怪的是,到目前为止,我无法用比 TComponent-descendants 更简单的方法重现问题……无论如何,再次感谢原始答案!


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


另一种语法是

1
2
3
4
5
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 中使用
我只是无法决定哪个选项最不丑!


如果你的类使用没有参数的构造函数(如 TObject),我建议按照编译器所说的去做:

“在类型参数声明中添加构造函数约束”

它应该看起来像这样:

TCompositeControl < Control1:TControl,构造函数; TControl2:TControl,构造函数 > = Class(TWinControl)

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

Howether,我不知道,如果它与需要参数的构造函数一起使用。


如果可行,请告诉我们。

  • 请重新阅读问题。这特别是关于带有参数的构造函数,并且 constructor 约束不能与这些一起使用。


来源:https://www.codenong.com/9586626/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_9186.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?