Форум: "Потрепаться";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];
ВнизКто-нибудь сможет сходу определить причину ошибки? :) Найти похожие ветки
← →
Piter © (2004-10-04 23:10) [0]Вот такой я маленький тест придумал... Кто сможет без Дельфей объяснить следующую ситуацию:
Такой код работает:procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
with Edit do
begin
Edit := TEdit.Create(self);
Parent := self;
end;
end;
А вот такой код НЕ работает:procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
end;
Вопрос - почему? :)
P.S. На ум приходит очевидный ответ... но почему же первый пример работает?
← →
panov © (2004-10-04 23:13) [1]Всё просто...
← →
panov © (2004-10-04 23:14) [2]Edit: TEdit - обрабатывает компилятор.
← →
Ломброзо © (2004-10-04 23:20) [3]> Parent := self;
чей блин парент?
← →
Piter © (2004-10-04 23:24) [4]panov © (04.10.04 23:14) [2]
Edit: TEdit - обрабатывает компилятор
не понял твою идею :)
Что значит обрабатывает компилятор? Типа другие строки компилятор не обрабатывает? :)
← →
_silver © (2004-10-04 23:30) [5]
>var
> ArrayEdit: array of TEdit;
Может я и не прав, но это динамический массив.
Надо SetLength
← →
jack128 © (2004-10-04 23:33) [6]Тя разговор с GuAV навел на эти эксперементы?? Ну так у него(у GuAV) в анкете есть ответ на твой вопрос. Нужно лищь глянуть в окно CPU..
← →
_silver © (2004-10-04 23:35) [7]Извиняюсь.
ArrayEdit[0].Parent := self;
← →
_silver © (2004-10-04 23:39) [8]
>_silver © (04.10.04 23:30) [5][Ответить]
>
>>var
>> ArrayEdit: array of TEdit;
>
>Может я и не прав, но это динамический массив.
> Надо SetLength
Ещё раз прошу прошения.
← →
Cobalt © (2004-10-04 23:40) [9]Вообще-то код с логической точки зрения некорректный - если компилятор и может (в принципе), то с логической точки зрения надо сначала проинициализировать переменную, а потом уже делать
with AlreadyInitialisedClassVariable do
← →
Cobalt © (2004-10-04 23:42) [10]пардон, не закончил фразу - компилятор может, в принципе, разрулить такую ситуацию.
Но разработчики переложили это на плечи программистов.
← →
Ломброзо © (2004-10-04 23:47) [11]Cobalt © (04.10.04 23:40) [9]
ИМХО под локальные переменные просто выделяется кусок стека. А посему при вызове делать инициализацию этого куска нулём - это лишний такт. Вот пущай программист сам обнуляет, если ему нужно.
← →
jack128 © (2004-10-04 23:48) [12]Ломброзо © (04.10.04 23:47) [11]
ИМХО под локальные переменные просто выделяется кусок стека
не всегда. Пример с edit"ом(первый) тому подтверждение
← →
_silver © (2004-10-04 23:50) [13]Работает так:
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
ArrayEdit[0].Parent := self;
end;
и так:
ArrayEdit[0] := TEdit.Create(self);
with ArrayEdit[0] do
begin
Parent := self;
end;
← →
_silver © (2004-10-04 23:52) [14]Это я ктому, что компилятор может ещё не знать о ArrayEdit[0].Parent в первом варианте.
← →
_silver © (2004-10-04 23:57) [15]Т.е. конструкция width ArrayEdit[0] ещё не определена.
← →
Ломброзо © (2004-10-04 23:58) [16]jack128 © (04.10.04 23:48) [12]
А что там в первом примере? Указатель нулю равен? дык это просто повезло.
← →
jack128 © (2004-10-05 00:04) [17]Если с асм"ом не очень, то озвучу явно - в первом примере переменной Edit вообще не существует. И строка with Edit компилятором вообщ игнорируется. Для обращения к SetParent используется результат TEdit.Create(Self)
Во втором примере начало в регистры проца закачивается ArrayEdit[0] (мусор)(эквивалент with ArratEdit[0] do), потом в память записывается результат TEdit.Create(Self), а потом уже берется наша копия ArrayEdit[0] (которая мусор) и используется для SetParent
Ломброзо © (04.10.04 23:58) [16]
Указатель нулю равен? дык это просто повезло.
нету указателя как такового. Нету переменной Edit вообще. вот для такого кода
:
procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
with Edit do
begin
Edit := TEdit.Create(self);
Parent := self;
Top := 10;
end;
end;
то что храниться в esi можно назвать переменной Edit, но не для примера Piter"a
← →
Ломброзо © (2004-10-05 00:14) [18]Аспасиба. Я действительно в ассемблере мало, но на грабли с неинициализированным указателем на объект в теле функции в ++, как и всякому нормальному человеку, наступать приходилось )
← →
GuAV © (2004-10-05 00:31) [19]А теперь версия ответа на этот вопрос от GuAV :)
Откомпилируйте обе версии.
Слева вы видете то что попало в конечный ехе синими кружечками отмечено.
в случае с массивом with попало в ехе. это как бы создало локальную переменную.
в другом случае Edit и есть та переменная
регистры или память не важно ({$O-} - и будет оно в стеке), но Ctrl+Alt+ тут конечно проясняет.
← →
GuAV © (2004-10-05 00:33) [20]
> Ctrl+Alt+ тут конечно проясняет.
Ctrl+Alt+С естественно, не Del :)
← →
_silver © (2004-10-05 00:47) [21]О чём вы рассуждаете?
ArrayEdit: array of TEdit - дин масив.
На этапе
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
ещё не известно что будет находиться в ArrayEdit[0].
Вся конструкция
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
просто не коректна.
← →
jack128 © (2004-10-05 01:02) [22]_silver © (05.10.04 0:47) [21]
ну и что?? with Edit do - тоже не определен, а тем немение работает.
ГуАВ все правельно объяснил.
← →
Piter © (2004-10-05 01:10) [23]jack128 © (04.10.04 23:33) [6]
лищь глянуть в окно CPU..
ну дык. Только вот:
> Кто сможет без Дельфей объяснить следующую ситуацию
:)))
Я вот о чем подумал. Отстранимся от ассемблера.
С точки зрения разработчика, получается, что в первом случае под with подразумевается именно реальный текущий Edit.
То есть, можно написать:procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
with Edit do
begin
Edit := TEdit.Create(self);
Free;
Edit := TEdit.Create(self);
Parent := self;
end;
end;
И все будет ок. В последней строчкеParent := self;
имеется в виду именно реальный Edit. Не тот Edit который был на начале With (мусор). И не тот Edit, который был создан первично. А именно актуальный на текущий момент Edit. Вот то, что показывает Watch List [Pointer(Edit)] - к тому и будет обращение .
Получается аналог этого кода:procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
Edit := TEdit.Create(self);
Edit.Free;
Edit := TEdit.Create(self);
Edit.Parent := self;
end;
В случае втором же все обстоит иначе. Если следовать приведенной выше логике, то код:procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
end;
Должен быть эквивалентен:procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
ArrayEdit[0] := TEdit.Create(self);
ArrayEdit[0].Parent := self;
end;
Иначе говоря, если есть обращение:with SomeClass do
SomeMethod;
то если у SomeClass есть метод SomeMethod, то такая конструкция ничем не должна отличаться от простого:SomeClass.SomeMethod
Но во втором случае компилятор не так делает. Он не тупо обращается к экземпляру класса. Он обращается туда, куда указывал ArrayEdit[0] на начало with.
Ведь with не что иное как просто упрощения записи, чтобы было понятнее.
То есть, если мы пишем:with SomeClass do
begin
SomeMethod1;
SomeMethod2;
SomeMethod3;
SomeMethod4;
end;
То мы как бы можем рассчитывать, что это тоже самое, что и такой код:SomeClass.SomeMethod1;
SomeClass.SomeMethod2;
SomeClass.SomeMethod3;
SomeClass.SomeMethod4;
А получается, что не совсем так...
Во втором случае мне кажется компилятор ведет себя немного не так, как нужно. Кто как считает? :)
P.S. Сейчас мне кто-нибудь точно припомнит IS :)))
P.S.S. Сам сейчас прочитал, что написал... блин, надо учиться излагать мысли, как-то все коряво получилось.
← →
Piter © (2004-10-05 01:11) [24]_silver © (05.10.04 0:47) [21]
О чём вы рассуждаете?
ArrayEdit: array of TEdit - дин масив.
На этапе
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
ещё не известно что будет находиться в ArrayEdit[0].
Вся конструкция
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
просто не коректна.
Ладно, получается что:
"О чём вы рассуждаете?
Edit: TEdit - это экземпляр класса
На этапе
with Edit do
ещё не известно что будет находиться в Edit.
Вся конструкция
with Edit do
begin
Edit := TEdit.Create(self);
Parent := self;
end;
просто не коректна."
Только вопрос - почему работает то? :)
← →
_silver © (2004-10-05 01:17) [25]Дин масив ссылок на что-то типа TEdit допустим.
with ArrayParent[0] - ожидается использование объекта типа TEdit, но ещё не создан.
Поэтому в блоке begin .. end свойство Parent(класса TEdit) неизвестно.
З.Ы.
Это тоже что сказал GuAV тока с объяснением.
← →
Knight © (2004-10-05 01:19) [26]Не знаю как вы, а я всегда сначала делаю Create, а только после этого уже юзаю with...
procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
ArrayEdit[0] := TEdit.Create(self);
with ArrayEdit[0] do begin
Parent := self;
end;
end;
← →
GuAV © (2004-10-05 01:20) [27]Если with использованна с переменной, полем записи, то то что в with не требует вычислений и with вносит чисто синтаксические изменения.
Если with использованна с функцией, методом класса, и т.д. то то что в with требует вычислений, результат которых фактически заносится в новую переменную (которая в прочем может быть и в регистрах - но это уже следствие оптимиации).
> То мы как бы можем рассчитывать, что это тоже самое, что
> и такой код:
нет. но к записи это применимо.
← →
jack128 © (2004-10-05 01:22) [28]Piter © (05.10.04 1:10) [23]
Piter © (05.10.04 1:10) [23]
То есть, если мы пишем:
with SomeClass do
begin
SomeMethod1;
SomeMethod2;
SomeMethod3;
SomeMethod4;
end;
То мы как бы можем рассчитывать, что это тоже самое, что и такой код:
SomeClass.SomeMethod1;
SomeClass.SomeMethod2;
SomeClass.SomeMethod3;
SomeClass.SomeMethod4;
А получается, что не совсем так...
Как я понял из GuAV © (05.10.04 0:31) [19] из асм"а реально with SameVar do делает следующее
для кода
begin
with SameVar do
begin
DoSamething1;
DoSamething2;
DoSamething3;
end;
end;
компилятор генерит примерно следующее
для переменных в дин памяти:
var
LocalVar: TSameType;
begin
LocalVar := SameVar;
LocalVar.DoSamething1;
LocalVar.DoSamething2;
LocalVar.DoSamething3;
end;
а для любых других - ничего не делается!! Например, если ты заменишь дин массив - статическим, то все будет работать..
Piter © (05.10.04 1:10) [23]
> Кто сможет без Дельфей объяснить следующую ситуацию
Я бы ответил (я собственно так и ответил) не правельно, насчет оптимизации с выкидыванием ненужного Edit"a
← →
GuAV © (2004-10-05 01:29) [29]
> для переменных в дин памяти:
Не только в дин. памяти, см. [27] .
Хороший пример
with MyArray[Random(5)] do
begin
A:=5; B:=7;
end;
не то же что
MyArray[Random(5)].A:=5;
MyArray[Random(5)].B:=7;
но если заменить Random(5) на 5, то with не делает разницы.
← →
_silver © (2004-10-05 01:35) [30]GuAV © (05.10.04 1:29) [29]
Если MyArray : array of recor a : Integer; b : Integer; end;
..
with MyArray[Random(5)] do
begin
A:=5; B:=7;
end;
то еррор, как раз о то о чём говорил я.
← →
GuAV © (2004-10-05 02:10) [31]я имел ввиду стат массив.
← →
Ihor Osov'yak © (2004-10-05 02:43) [32]> Кто-нибудь сможет сходу определить причину ошибки? :)
Корень ошибки - в упорном нежелании обращать внимание на хинты и варнинги компилятора.
Зы. странно, что борланды вообще такую конструкцию считают синтастически допустимой...
← →
1008 © (2004-10-05 09:14) [33]Объявить массив глобально - должно работать, во всяком случае у меня подобные конструкции работают. Правда никогда не пробовал в качестве предка задавать сам компонент.
← →
Fay © (2004-10-05 09:18) [34]2 1008 © (05.10.04 09:14) [33]
> Правда никогда не пробовал в качестве предка задавать сам
> компонент.
Это Вы о чём?
← →
1008 © (2004-10-05 09:28) [35]Fay © (05.10.04 09:18) [34]
я делаю так:
var
RichEditArray:array of TRichEdit;
...
Procedure ...
var
i,n:integer;
begin
...
SetLehgth(RichEditArray,n);
for i:=0 to n-1 do begin
RichEditArray[i]:=TRichEdit.Create(Self);
RichEditArray[i].Parent:=Panel;//к примеру
end;
← →
Fay © (2004-10-05 09:31) [36]Как Вы делаете я понял. Но в пику чему этот пример?
← →
SergP. (2004-10-05 09:35) [37]Могу конечно ошибиться, так как сейчас не могу запустить Delphi и поэкспериментировать с обоими примерами, а также попробовать статический массив.
with ArrayEdit[0]
Но имхо здесь автор сабжа вместо элемента массива получает указатель на сам массив.
← →
1008 © (2004-10-05 09:40) [38]Fay © (05.10.04 09:31) [36]
Никому ни в чью пику я ничего не делаю. Я просто сказал как я делаю, чтоб не было ошибок.
Piter © (04.10.04 23:10)
А вот такой код НЕ работает:
procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
ArrayEdit[0].Parent := self;
end;
end;
вот так работает, хотя это уже указали
← →
Fay © (2004-10-05 09:45) [39]Вы, видимо, думаете, что в качестве
Self
выступаетArrayEdit[0]
? Уверен, что это не так, чтоSelf
в данном случае - экземплярTForm1
.
← →
SergP. (2004-10-05 09:46) [40]
> [37] SergP. (05.10.04 09:35)
Все-таки я ошибся.
Такой код:
ArrayEdit[0] := TEdit.Create(self);
with ArrayEdit[0] do Parent := self;
Работает.
Значит причина ошибки та что была уже неоднократно высказана.
Страницы: 1 2 3 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.038 c