Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 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
1-1089125866
DDDeN
2004-07-06 18:57
2004.07.25
TrackBar как в регуляторе громкости


9-1080408372
AbLaZe
2004-03-27 20:26
2004.07.25
Прорисовка карты


3-1088573748
Ratiborr
2004-06-30 09:35
2004.07.25
На сколько облегчает DLL


1-1089650210
maverick
2004-07-12 20:36
2004.07.25
FastReport


14-1088405291
Dmitriy O.
2004-06-28 10:48
2004.07.25
Кто появился ранше ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский