如何避免通用容器中的非参数构造函数出现不兼容的类型错误?

时间:2012-11-12 11:04:56

标签: delphi delphi-xe2

我在以下代码中获得E2010 Incompatible types: 'TDerivedFrame' and 'TBaseFrame'

type
  TBaseFrame = class(TFrame)
  end;

  TDerivedFrame = class(TBaseFrame)
  end;

  TContainer<T: TBaseFrame> = class
  private
    FFrame: T;
  public
    property Frame: T read FFrame;
    constructor Create;
  end;

constructor TContainer<T>.Create;
begin
  inherited;
  FFrame := TBaseFrame(T).Create(nil);
end;

var
  FTab: TContainer<TDerivedFrame>;

仅使用T.Create(nil)会导致E2568 Can't create new instance without CONSTRUCTOR constraint in type parameter declaration

据我所知,你只能使用无参数构造函数创建一个构造函数约束。

这样做的正确方法是什么?

PS:代码在我删除变量时编译,这让我觉得这是编译器错误?!

编辑:我理解E2010错误,但即使使用T(TBaseFrame(T).Create(nil))它也无效。这会编译,但会在运行时导致访问冲突:

type
  TBaseFrame = class(TFrame)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TDerivedFrame = class(TBaseFrame)
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TContainer<T: TBaseFrame> = class
  private
    FFrame: T;
  public
    property Frame: T read FFrame;
    constructor Create;
  end;


constructor TBaseFrame.Create(AOwner: TComponent);
begin
  inherited;

end;

constructor TDerivedFrame.Create(AOwner: TComponent);
begin
  inherited;

end;

constructor TContainer<T>.Create;
begin
  inherited;
  FFrame := T(TBaseFrame(T).Create(nil));
end;

var
  FTab: TContainer<TDerivedFrame>;
begin
  FTab := TContainer<TDerivedFrame>.Create;
end.

2 个答案:

答案 0 :(得分:4)

FFrame := T(TBaseFrameClass(T).Create(nil));

是执行此操作的正确方法。

你需要

type 
  TBaseFrameClass = class of TBaseFrame;

您的编译器错误是因为您实例化类型TContainer<TDerivedFrame>。当您实例化该类型时,您要求编译器处理

FFrame := TBaseFrame(...);

其中FFrameTDerivedFrame。如果您在没有泛型的情况下编写该代码,您就会理解编译器错误。

所以,编译器在这里表现正常,但是实例化的问题正在抓住你。只有在实例化时,编译器错误才会变得明显。没有实例化,如果你实例化了TContainer<TBaseFrame>,那么就没有编译器错误。

AV是因为您将T转换为实例而不是类。

答案 1 :(得分:0)

尝试使用这个:    TContainer<T:constructor, TBaseFrame> = class