Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

описание динамического массива в классе [D7, WinXP]


Страницы:   1 2

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]

Конструктор можно вызвать и после создания экземпляра.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо