Форум: "Потрепаться";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
ВнизОсобенности вызовов конструкторов Найти похожие ветки
← →
jack128 © (2004-07-06 17:50) [0]Как известно конструктор объекта можно использовать в двух контекстах
1) как классовый метод
Instance := TMyCoolObject.Create();
2) как обычный метод
Instance.Create();
а вот код который компилятор ренерит при вызове коструктора можно разделить на три группы
1)
Instance := TMyCoolObject.Create();
в этом случае происходит вызов _ClassCreate(это влечет за собой вызов NewInstance а потом вызов собственно тела конструктора. если в конструкторе возникло исключение, то вызывается FreeInstance
2) Instance.Create();
последовательность вызовов таже, что и в первом случае, но в _ClassCreate передается флаг, указывающий на то что конструктор вызывается как обычный метод и вызова NewInstance не поисходит. Однако если в конструкторе возникло исключение, то теста на этот флаг не делается и соответственно объект уничтожается.
Instance.Create(); //если здесь возникло исключение, то Instance - уничтожается
3)
constructor TChildMyCoolObject.Create;
begin
inherited Create(); // тут происходит просто передача управления в унаследованный конструктор. Безо всяких дополнительных вызовов.
end;
Собственно все эти исследования меня заставила провести особенность второго варианта. Если во время вызова Instance.Create() возникло исключение, то объект уничтожается. Чем вызвано такое (ИМХО нелогичное) решение??
← →
Reindeer Moss Eater © (2004-07-06 18:02) [1]Если во время вызова Instance.Create() возникло исключение, то объект уничтожается.
А он вообще создается?
← →
jack128 © (2004-07-06 18:03) [2]
> А он вообще создается?
предпологается, что объект уже создан..
← →
Reindeer Moss Eater © (2004-07-06 18:05) [3]Создается ли объект в результате вызова конструктора с несозданным экземпляром?
nonexistingone.Create(nil)
← →
jack128 © (2004-07-06 18:05) [4]в том смысле, что код в конструктор можно разный повесить, для работы в режиме классового метода он будет работать без исключений, а для обычного метода генерить исключения..
← →
jack128 © (2004-07-06 18:07) [5]
> nonexistingone.Create(nil)
нет, конечно.
> в _ClassCreate передается флаг, указывающий на то что конструктор
> вызывается как обычный метод и вызова NewInstance не поисходит
procedure _ClassCreate;
asm
{ -> EAX = pointer to VMT }
{ <- EAX = pointer to instance }
PUSH EDX
PUSH ECX
PUSH EBX
TEST DL,DL
JL @@noAlloc
CALL dword ptr [EAX].vmtNewInstance
← →
Reindeer Moss Eater © (2004-07-06 18:07) [6]Если во время вызова Instance.Create() возникло исключение, то объект уничтожается.
А он вообще создается?
← →
jack128 © (2004-07-06 18:12) [7]блин, пример
type
TTest = class(TObject)
public
constructor Create;
end;
var
IsClassMethod: boolean = True;
procedure TForm1.Button1Click(Sender: TObject);
var
t: TTest;
begin
IsClassMethod := True;
t := TTest.Create(); // объект создан
try
IsClassMethod := False;
t.Create(); // так как поднялось исключение, то объект уничтожается
finally
t.Free; // t - битый указатель
end ;
end;
{ TTest }
constructor TTest.Create;
begin
if not IsClassMethod then
raise Exception.Create("");
end;
← →
Reindeer Moss Eater © (2004-07-06 18:22) [8]Ах вот ты о чем.
Я же думал что ты вызываешь конструктор у не инициализированного t и удивляешься тому, что создаваемый (якобы) конструктором объект сразу уничтожается.
Ну а по твоему примеру что можно сказать:
Используя замысловатым способом простые и очевидные вещи, надо быть готовым к неожиданностям.
Зачем вызывать конструктор используя конкретный экземпляр?
Ну хоть одна причина для этого есть?
← →
Digitman © (2004-07-06 18:27) [9]тот кто пытается клонировать себя через пятую причинную точку, должен быть готов к любым неприятным неожиданностям
← →
jack128 © (2004-07-06 18:29) [10]
> Зачем вызывать конструктор используя конкретный экземпляр?
> Ну хоть одна причина для этого есть?
но синтаксически же такое разрешено. вот том же С++ конструктор для созданного объекта нельзя вызвать и никаких вопросов не возникает..
А уж если в паскале такое разрешили, то должна же быть какая то причина.
← →
Юрий Зотов © (2004-07-06 18:29) [11]> Reindeer Moss Eater © (06.07.04 18:22) [8]
> Ну хоть одна причина для этого есть?
Inherited Create внутри конструктора - это какой вызов, как Вы думаете?
← →
jack128 © (2004-07-06 18:31) [12]
> Юрий Зотов © (06.07.04 18:29)
> > Reindeer Moss Eater © (06.07.04 18:22) [8]
>
> > Ну хоть одна причина для этого есть?
>
> Inherited Create внутри конструктора - это какой вызов,
> как Вы думаете?
но вызов то реализовать по разному для inherited Create() и Instance.Create(). по сути - это разные вещи ..
← →
Юрий Зотов © (2004-07-06 18:31) [13]> jack128
Кстати, [11] - это и ответ на Ваш вопрос тоже. Исключение в цепочке унаследованных конструкторов тоже должно уничтожать свежесозданный объект.
← →
jack128 © (2004-07-06 18:32) [14]
> но вызов то реализовать
но вызовы то реализованы по разному
← →
Reindeer Moss Eater © (2004-07-06 18:38) [15]но синтаксически же такое разрешено.
синтаксически и такое вот разрешено:
procedure TForm1.Btn1Click(Sender : TObject);
var mycomp : tcomponent;
begin
caption := mycomp.name;
end
← →
Гаврила © (2004-07-06 18:45) [16]
> Чем вызвано такое (ИМХО нелогичное) решение??
Думаю, это недоработка Борланда.
А все остальные участники ветки похоже не поняли, о чем речь вообще идет
← →
jack128 © (2004-07-06 18:53) [17]
> Исключение в цепочке унаследованных конструкторов тоже должно
> уничтожать свежесозданный объект.
да не должно. вызов унаследованного конструктора - это вызов унаследованного конструктора и нечего более. Вызова _ClassCreate не происходит и соответственно объект не уничтожается.
сравните
constructor TTest.Create();
begin
raise Exception.Create();
end;
constructor TChildTest.Create()
begin
try
inherited Create; // исключение в унаследованном конструкторе, но объект жив
except
end;
end;
try
TTest.Create() // исключение в конструкторе и объект помер
except
end;
> синтаксически и такое вот разрешено:
>
> procedure TForm1.Btn1Click(Sender : TObject);
> var mycomp : tcomponent;
> begin
> caption := mycomp.name;
> end
конечно - это же логическая ошибка, а не синтаксическая. Использовать битый указатель безнаказанно нигде нельзя.
но тут то другой случай. Я вообще не говорил про ошибку, мне интересно почему сделано именно так, а не иначе. Почему вдруг объект должен уничтоваться во случае 2) ?
> Думаю, это недоработка Борланда.
А я так верил в его святость :-))
> А все остальные участники ветки похоже не поняли, о чем
> речь вообще идет
еще не вечер ;-)
← →
GuAV © (2004-07-06 22:30) [18]Мда. Когда я вернусь сюда, я обязательно поищу эту вету в архиве. Если ситуация не прояснится - напишу письмо Борланд.
> еще не вечер ;-)
уже темнеет ;-)
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.043 c