Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.144.154.208] |
|
Сообщ.
#1
,
|
|
|
При создании объекта нужно предусмотреть ситуацию ошибки (конструктор проверяет некоторые системные настройки и принимает решение - создавать объект или нет), т.е. чтобы Create вернул nil или сгенерировал исключение. Как это сделать?
|
Сообщ.
#2
,
|
|
|
Ну и кидай исключение, в чем проблема-то?
|
Сообщ.
#3
,
|
|
|
Цитата If an exception is raised during execution of a constructor that was invoked on a class reference, the Destroy destructor is automatically called to destroy the unfinished object. constructor TBase.Create; begin raise Exception.Create('Missing envirement') at @TBase.Create; end; ... var tmp:TBase; procedure TForm1.Button1Click(Sender: TObject); begin try tmp:=TBase.Create; except on E: Exception do tmp:=nil; end; end; |
Сообщ.
#4
,
|
|
|
Ok, а как просто nil вернуть без генерации исключения?
|
Сообщ.
#5
,
|
|
|
Jin X
Просто никак. Всякая конструкция вида self:=nil; приведёт к ошибке в автоконструкторе и последний вызывает исключение. Можно попробовать хаком изменить адрес возврата на свою функцию, тем самым обойти автоконструктор. |
Сообщ.
#6
,
|
|
|
Разве что фабрикой
function CreateObj(aClass: TClass): TObject; begin try Result := aClass.Create; except Result := nil; end; end; Но с параметрами конструктора придется что-то придумывать. Ну или через asm регистры зачистить. Но это жестко |
Сообщ.
#7
,
|
|
|
Fr0sT, не факт, что это прокатит, т.к.
class function TMyObject1.NewInstance: TObject; begin Result := nil; end; |
Сообщ.
#8
,
|
|
|
Цитата Jin X @ не факт, что это прокатит То, что ты привел, никак не связано с моим предположением |
Сообщ.
#9
,
|
|
|
Ну ок.
Вот такая конструкция работает: {$APPTYPE CONSOLE} type TObj = class constructor Create; end; constructor TObj.Create; asm // int 3 xor eax,eax db 0EBh,9 // jmp $+2+9 end; var Obj: TObj; begin Obj := TObj.Create; WriteLn(Integer(Obj)) end. Но! Есть 2 нюанса: 1. Create после выполнения основного кода делает: test dl,dl je @@ret call Call_AfterDestruction // вот здесь как раз и возникало исключение в варианте с NewInstance pop dword fs:[0] add esp,0Ch @@ret: ret Может, где-то оно и нужно и там будет креш. 2. dcc64 (и XE2, и Tokyo) не компилируют конструктор, написанный на ассемблере, выдают Fatal: F2084 Internal Error: AV00511A6C-R00000001-0. Так что такой вариант не будет работать в 64 битах... обидно |
Сообщ.
#10
,
|
|
|
Цитата Jin X @ Зачем проверяется dl и что там должно быть - х/з. Кто-нибудь знает? См. справку. Конструкторы и деструкторы имеют дополнительный булевский параметр (флаг), передаваемый через регистр dl (при register convention). Значение true=1 означает вызов конструктора через ссылку на класс для создания нового экземпляра класса. Значение false=0 передается при вызове конструктора через экземпляр класса как обычного метода инициализации (например при вызове inherited Create). |
Сообщ.
#11
,
|
|
|
Спасибо за инфу. Так что, приведённый мной пример вообще неуниверсален. При разном содержимом Create будет работать по-разному, нужно подгонять под каждый случай.
В целом, я так подумал, что возвращать nil вообще нехорошо, лучше генерить исключение |
Сообщ.
#12
,
|
|
|
Цитата Jin X @ В целом, я так подумал, что возвращать nil вообще нехорошо, лучше генерить исключение Возвращение блудного сына к разумному решению)) |