Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2002.10.14;
Скачать: [xml.tar.bz2];

Вниз

Странное поведение конструкции with ... do   Найти похожие ветки 

 
Толик   (2002-10-02 15:33) [0]

Столкнулся с такой проблемой:
Есть некая структура: не важно какая, например:

TMyStruct = record
Field1: longint;
Field2: byte;
end;

Далее, я хочу как-то инициализировать переменную, типа TMyStruct с использованием конструкции with. Эта переменная передаётся в ф-ю как var-параметр:

procedure Init(var MyStruct: TMyStruct);
begin
with(MyStruct)do begin
Field1 := 1;
Field2 := 2;
end;
end;

вылезает ошибка "Left side cannot be assigned to" хотя если убрать скобки, то всё работает.

procedure Init(var MyStruct: TMyStruct);
begin
with MyStruct do begin
Field1 := 1;
Field2 := 2;
end;
end;

А вот если объявить TMyStruct не как record, а как class, то работают оба примера. Если передавать MyStruct не по ссылке, а через указатель - тоже всё работает. Если обращатся к MyStruct как к глобальной переменно - тоже работает. А вот с var проблема. На это можно было бы и забить, если бы не ф-я TWinControl.CreateParams(var Params: TCreateParams). Как сие понимать? Это что баг Делфей???


 
Digitman   (2002-10-02 16:01) [1]

Может, и баг.

Ясно одно - компилятор ожидает явное приведение типа:

with TSomeOtherStruc(MyStruct)do begin
Field1 := 1;
Field2 := 2;
end;


 
McSimm   (2002-10-02 16:04) [2]

На первый взгляд такое поведение действительно кажется странным.

Однако объяснить это можно.

Дело в том, что для компилятора
MyStruct
и
(MyStruct)
разные вещи. Первое это переменная, второе - выражение, результатом которого является значение типа TMyStruct.


 
AlexT1000   (2002-10-02 16:05) [3]

with(MyStruct)do begin - а зачем это в скобки брать? смысл?





 
Best Before 2024   (2002-10-02 16:09) [4]

Вот более явный пример:

procedure MyXProc(var X : Integer);
begin
X := X + 1;
end;

procedure MyYProc;
var Y : Integer;
begin
Y := 0;
MyXProc(Y); //Ok
MyXProc((Y)); //[Error]: Constant object cannot be passed
// as var parameter
end;


 
Толик   (2002-10-02 16:36) [5]

Насчёт того, есть ли смысл подобное выражение брать в скобки - это просто привычка.

По логике вещей, если (MyStruct) действительно выражение (константное), то почему всё то же самое работает для классов?
Если объявить TMyStruct не record, а class, то оба примера компилируются без ошибок.


 
qube   (2002-10-02 16:39) [6]

Для классов работает, потому что экземпляры классов по указателю передаются


 
McSimm   (2002-10-02 16:53) [7]

>почему всё то же самое работает для классов?
Если результатом некоторого выражения является ссылка на экземпляр класса, мы вполне можем обращаться к членам этого класса:

(SomeClassVar).SomeField :=

Однако, обсуждаемая проблема может быть продемонстрирована таким примером:
SomeClassVar := TSomeClassVar.Create - нормально
(SomeClassVar) := TSomeClassVar.Create - ошибка


 
Толик   (2002-10-02 17:09) [8]

to qube © (02.10.02 16:39)
Допустим, если TMyStruct объявлен как класс, то в ф-ю
Init(var MyStruct: TMyStruct) по ссылке передаётся указатель на экземпляр. Если TMyStruct объявлен как record, то по ссылке передаётся сам экземпляр. Но как тогда объяснить такой факт: есть куча WinAPI"шных ф-й, параметрами которых являются указатели на структуру (так написано в хелпе и так работает в C++) Почему же тогда в Делфях надо передавать туда не Адрес объекта типа record, а сам этот объект??? Например:

function CreateProcess(... lpStartupInfo: TStartupInfo; ...);

но не

function CreateProcess(... lpStartupInfo: PStartupInfo; ...);
где
PStartupInfo = :TStartupInfo;

хотя на самлм деле передаётся туда адрес переменной а не переменная
Получается, что и record передаётся по указателю!


 
Игорь Шевченко   (2002-10-02 17:21) [9]

>Получается, что и record передаётся по указателю!

Все, что описано как var, гарантировано передается по указателю.
Все, что больше 8-х байт, гарантировано передается по указателю.


 
qube   (2002-10-02 17:23) [10]

Init(var MyStruct: TMyStruct) -- неявно передается адрес, где расположены поля структуры

Init(MyObj: TMyClass) -- неявно передается адрес, где расположен экземпляр объекта.

Init(var MyObj: TMyClass) -- неявно передается адрес, где расположен указатель на экземпляр объекта.


 
Digitman   (2002-10-02 17:38) [11]

>Толик

Смутившие тебя конструкции

function CreateProcess(... const lpStartupInfo: TStartupInfo; ...); stdcall;
и
function CreateProcess(... lpStartupInfo: PStartupInfo; ...); stdcall

будут скомпилированы одинаково, и фактический параметр передан по ссылке в обоих случаях. Обрати внимание на префикс const и соглашение о вызове stdcall.

Вот если бы вызов был декларирован так
function CreateProcess(... lpStartupInfo: TStartupInfo; ...);
компилятор поступил бы иначе : передал бы факт.параметр по значению, "натолкав" значения полей структуры в стек непосредственно перед вызовом.


 
Digitman   (2002-10-02 17:42) [12]

Скажу более - и в случае

function CreateProcess(... const lpStartupInfo: TStartupInfo; ...);

параметр будет передан по ссылке (но результат - сам понимаешь, какой будет)


 
Толик   (2002-10-02 18:03) [13]

Огромное спасибо всем принявшим участие в обсуждении!
Если не возражаете, то продолжим завтра. У меня есть ещё пара вопросов по поводу обсуждаемой темы, а сейчас уже домой пора :)



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2002.10.14;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.007 c
3-45181
Солер
2002-09-22 08:32
2002.10.14
Фильтр в базе данных


1-45345
raiks
2002-10-05 17:29
2002.10.14
Как при компиляции изменить свойство компонента?


3-45186
Bsl
2002-09-23 08:08
2002.10.14
Где достать Provider при работе с SQL Server через ADO?


1-45365
Свой, но не чужой
2002-10-05 22:57
2002.10.14
Передвигание Shape при помощи ScrollBar


14-45504
Darts
2002-09-16 19:14
2002.10.14
Стоимость Delphi





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский