2010-10-08 1 views
1

Еще одна в моей серии вопросов относительно конструкторов в Delphi.Delphi: переопределенный потомок потомков конструктора, не вызываемый перегрузкой

у меня есть базовый класс, который имеет имеет виртуальный конструктор:

TComputer = class(TObject) 
public 
    constructor Create(Teapot: Integer); virtual; 
end; 

Конструктор является виртуальным для времени, что кто-то должен позвонить

var 
    computerClass: class of TComputer; 
    computer: TComputer; 
begin  
    computer := computerClass.Create(nTeapot); 

Конструктор в потомках overridden:

TCellPhone = class(TComputer) 
public 
    constructor Create(Teapot: Integer); override; 
end; 

TiPhone = class(TCellPhone) 
public 
    constructor Create(Teapot: Integer); override; 
end; 

Где TCellPhone и TiPhone Каждый из потомков имеет возможность выполнить свою инициализацию (членов, не включенных для удобочитаемости).

Но теперь я добавить перегруженный конструктор некоторому предку:

TCellPhone = class(TComputer) 
public 
    constructor Create(Teapot: Integer); override; overload; 
    constructor Create(Teapot: Integer; Handle: string); overload; 
end; 

Альтернативный конструктор в TCellPhone вызывает другой виртуального конструктора, поэтому он всегда получает надлежащее перекрытое поведение:

constructor TCellPhone.Create(Teapot: Integer; Handle: string); 
begin 
    TCellPhone.Create(Teapot); //call sibling virtual constructor 

    FHandle := Handle; 
end; 

Проблема заключается в том, что потомок, переопределенный конструктор никогда не вызывается. Действительное трассировки стека цепочка вызовов:

phone := TiPhone.Create(37, 'spout') 
    constructor TCellPhone.Create(Teapot: Integer; Handle: string) 
     constructor TCellPhone.Create(Teapot: Integer) 
     constructor TComputer.Create(Teapot: Integer) 
      TObject.Create 

родственный вызов TCellPhone.Create(int), который является виртуальным, следовало назвать потомком, переопределить метод в TiPhone:

phone := TiPhone.Create(37, 'spout') 
    constructor TCellPhone.Create(Teapot: Integer; Handle: string) 
     constructor TiPhone.Create(Teapot: Integer) 
     constructor TCellPhone.Create(Teapot: Integer) 
      constructor TComputer.Create(Teapot: Integer) 
       TObject.Create 

Таким образом, кажется, что попытки для использования виртуального конструктора sibling Delphi не работает должным образом.

Неужели это плохая идея для одного конструктора использовать другой? Является ли намерение дизайна, что код в перегруженных конструкторах является версиями для копирования-вставки друг друга?

я замечаю в .NET, что некоторые Конструкторы цепи друг с другом:

public Bitmap(int width, int height) : this(width, height, PixelFormat.Format32bppArgb) {} 

public Bitmap(int width, int height, PixelFormat format) {...} 

Это только кажется, быть проблемой, если:

  • конструктор является виртуальным
  • вы перегружать конструкторы

Правило ли, что один конструктор не может перегружать другой?

ответ

8

Errr ..

constructor TCellPhone.Create(Teapot: Integer; Handle: string); 
begin 
    TCellPhone.Create(Teapot); //call sibling virtual constructor 

    FHandle := Handle; 
end; 

Это должно быть:

constructor TCellPhone.Create(Teapot: Integer; Handle: string); 
begin 
    Create(Teapot); //call sibling virtual constructor 

    FHandle := Handle; 
end; 

Вы просто создать новый экземпляр TCellphone и не вызывая другой метод Create.

+0

+1. Я был прав, чтобы ответить на это, но ты избил меня до этого. –

+1

+1, утечка сотового телефона! –

+0

Хорошо, спасибо. я просто подумал, что 'унаследованный Create' вызывает предок - i * must * должен иметь что-то, указывающее * me *. : \ –