2014-01-08 4 views
2

Ребята, к моему удивлению, я вижу, что «двойной вызов» конструктору объекта приемлемо для компилятора. Любая идея, какая цель это служит, и что будет результатом такой функции?«Двойной вызов» конструктору объекта допустим

procedure TForm1.Button1Click(Sender: TObject); 
var 
    vLabel : Tlabel; 
begin 
    vLabel := Tlabel.Create(self).Create(self); 
end; 
+0

Я не уверен, почему вы удивлены. 'TLabel.Create (Self)' возвращает экземпляр 'TLabel', а' TLabel' имеет метод с именем 'Create', поэтому вы можете его вызвать. :-) Вы также можете использовать что-то вроде 'TLabel.Create (Self) .Free', а не то, что в этом случае это будет иметь смысл. –

+0

Честно говоря, я был также очень удивлен, когда узнал, что «Constructor chaining» полностью легальна в Delphi. В учебниках часто не упоминается об этом. –

+0

Это странно, потому что Create - это метод класса, вы, конечно, теряете память – Qsebas

ответ

5

Второй вызов Create работ, как обычный вызов процедуры: она отсутствует какая-либо из специального строительного кодекса и только выполняет код пользователя в конструкторе. На практике это очень полезно, чтобы иметь возможность вызывать другие конструкторы от реализации конструктора:

constructor TLabel.CreateHello(AOwner: TComponent); 
begin 
    // Perform default construction. 
    Create(AOwner); 
    // Set default text. 
    Caption := 'Hello'; 
end; 

Сравните это с C++, где вы должны переместить общую логику для нескольких конструкторов в отдельную функцию, потому что вы не можете вызовите конструктор после создания объекта. Решение Delphi элегантно и поощряет повторное использование кода.

Для реализации этого существует скрытый дополнительный логический параметр для конструкторов, который указывает, выполнять ли полную логику построения (например, распределение памяти) или нет.

+1

Также обратите внимание, что 'Create (AOwner)' также не должно быть первой операцией в этом конструкторе, а не только перегруженным конструктором, который вызывается. Java, например, имеет этот предел. –

+1

FYI, C++ 11 вводит делегирующие конструкторы, так что конструктор может вызывать другой конструктор того же класса, и поэтому разделяемая логика больше не должна отделяться. –

+0

@Frederik Я не настолько уверен, что это самое элегантное решение. Разделение объекта-объекта в объектной модели Delphi на процедуры создания и инициализации было бы проще и понятнее. Здесь мы видим магическое/скрытое/удивительное поведение. – alcalde

Смежные вопросы