![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
описание динамического массива в классе [D7, WinXP]
serj © (2004-11-13 19:50:00)описывается класс
TDTable = class(TObject)
public
Cells : array of array of integer;
...
end;>
var
XD : TDTable;
begin
XD.Create;
при создании объекта происходит ошибка с сообщением debugger'a
Project Project1.exe raised exception class EAccessViolation whith message 'Access violation at address 00404E80 in module 'Project1.exe'.Read of address 00000000C
может кто знает, в чём тут дело?
GuAV (2004-11-14 20:29:00) [1]Piter © (14.11.04 16:04) [21]
а разве неправильнее какие бы то не было флаги передавать в конструктор, чтобы он уже устанавливат что надо?
И так кстати тоже делают.
constructor TWinControl.CreateParented(ParentWindow: HWnd);
begin
FParentWindow := ParentWindow;
Create(nil);
end;
Defunct (2004-11-14 17:37:00) [2]GuAV © (14.11.04 16:12) [22]
>> Defunct © (14.11.04 15:50) [19]
>> он чудом работает.
> Не чудом, этот случай _специально_ рассматривается в RTL.
Говоря "чудом работает" я подразумевал специально сделанное исключение, сделанное для совместимости с более ранними версиями.
> _специально_
специально = исключительный случай.
GuAV (2004-11-14 16:12:00) [3]Defunct © (14.11.04 15:50) [19]
он чудом работает.
Не чудом, этот случай _специально_ рассматривается в RTL. Считаю уместным процитировать здесь jack128 © :
Как известно конструктор объекта можно использовать в двух контекстах
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;
Раз уже делают различия между вызовом конструктора через ссылку на объект из другого конструктора и в другом случае, то можно было бы запретить этот самый другой случай. В _очень_немногих_ случаях вроде TApplication.CreateForm пойти например по пути [20].
Defunct © (14.11.04 15:50) [19]
IMHO TApplication.CreateForm не годится
Согласен.
Piter (2004-11-14 16:04:00) [4]jack128 © (14.11.04 15:31) [16]
до вызова конструктора нужно выставить флаги
а разве неправильнее какие бы то не было флаги передавать в конструктор, чтобы он уже устанавливат что надо?
А конкретно в твоем примере я не понял - нафига эти флаги устанавливать?
Defunct © (14.11.04 15:50) [19]
он чудом работает
гы, ну тут я не согласен... какое же это чудо, если все автосоздаваемые формы в приложении так создаются...
GuAV (2004-11-14 15:59:00) [5]jack128 © (14.11.04 15:31) [16]
В данном случае - хз.
Чтобы в OnCreate переменная Form1 была валидной.
Как сказал тогда Роб, ты можешь оспаривать достоинаства этого требования, но VCL работает именно так.
Однако в обоих случаях можно избежать такой техники.
достакточно объявить такой конструктор
constructor TComponent.CreateAndInitInstVar(AOwner: TComponent; var Instance);
begin
TComponent(Instance):=Self;
Create(AOwner); // no classcreate call, just like calling inherited constructor
end;
Defunct (2004-11-14 15:50:00) [6]jack128 © (14.11.04 15:37) [18]
> а заглянуть в исходники CreateForm вы, конечно, не догадались? ;-)
Конечно - нет, вы насчет этого?
Instance.Create(Self);
Вероятно, этот код никто не менял начиная с Delphi 1, он чудом работает. И в качестве корректногопримера, IMHO TApplication.CreateForm не годится.
jack128 (2004-11-14 15:37:00) [7]Defunct © (14.11.04 15:34) [17]
а заглянуть в исходники CreateForm вы, конечно, не догадались? ;-)
Defunct (2004-11-14 15:34:00) [8]jack128 © (14.11.04 03:55) [12]
> Внимательно читаем [8] ;-)
А что там внимательно читать?
Piter прав, то что в [8] не есть пример вызова конструктора:
procedureTApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
> а можно корректный пример, когда это не так?
нет такого примера, кроме случая когда используется тип Object.
Type TLalala = Object
Constructor Create;
End;
var Lalala : TLalala;
begin
lalala.Create;
end.
jack128 (2004-11-14 15:31:00) [9]GuAV © (14.11.04 13:31) [13]
2 jack128 © а почему бы не поговорить об этом ещё раз ;-)
:-) Свою позицию я не изменил.
Piter © (14.11.04 14:48) [15]
ну да... А зачем так сделано?
В данном случае - хз. Могу привести случай, чде подобный алгоритм создания оправдан:
function TReader.ReadComponent(Component: TComponent): TComponent;
...
Result := TComponent(ComponentClass.NewInstance);
if ffInline in Flags then // до вызова конструктора нужно выставить флаги
begin
Include(Result.FComponentState, csLoading);
Include(Result.FComponentState, csInline);
end;
try
Result.Create(Owner);
except
Result := nil;
raise;
end;
Piter (2004-11-14 14:48:00) [10]jack128 © (14.11.04 3:55) [12]
Внимательно читаем [8] ;-)
А, ну да... А зачем так сделано?
GuAV (2004-11-14 13:33:00) [11]GuAV © (14.11.04 13:31) [13]
конструктор всё равно прибьёт недосозданный объект
под "недосозданым" объектом понимался вызов конструктора в котором произошло исключение.
GuAV (2004-11-14 13:31:00) [12]Германн © (14.11.04 3:23) [11]
А "Инициализация", иногда, нужна без создания.
Только эта... конструктор всё равно прибьёт недосозданный объект, даже при инициализации... в Borland специально постарались чтоб было именно так...
2 jack128 © а почему бы не поговорить об этом ещё раз ;-)
jack128 (2004-11-14 03:55:00) [13]Piter © (14.11.04 3:15) [10]
Внимательно читаем [8] ;-)
Германн (2004-11-14 03:23:00) [14]2 Piter © (14.11.04 03:15) [10]
Может я и не прав. Но, имхо, конструктор объекта выполняет две функции: Создание и Инициализация. А "Инициализация", иногда, нужна без создания.
Piter (2004-11-14 03:15:00) [15]GuAV © (13.11.04 20:31) [4]
Не всегда
а можно корректный пример, когда это не так?
Гаврила (2004-11-13 22:41:00) [16]
> [8] GuAV
Пусть в меня полетят камни... Но за это метод - можно и расстрелять
GuAV (2004-11-13 22:35:00) [17]2 Гаврила ©
Смотрите метод TApplication.CreateForm, который обычно вызывается из dpr. Вы хотите растрелять автора VCL ? :-)
Гаврила (2004-11-13 22:16:00) [18]
> [5] begin...end
> Конструктор можно вызвать и после создания экземпляра.
Можно конечно, и все сработает. Но я бы за такое расстреливал :-)))
serj (2004-11-13 21:41:00) [19]да, ребят, это я уже конкретно стормозил...
begin...end (2004-11-13 20:34:00) [20]Piter © (13.11.04 20:22) [3]
Конструктор можно вызвать и после создания экземпляра.