Страница 1 из 1
Обращение к типам по имению
Добавлено: 21 июл 2005, 08:34
UUU
Попробую объяснить на пальцах:
Есть переменные разной структуры (структура почти разная)
var
DSM : TDSM;
DtSM : TDtSM;
в теле:
DSM:=PDSM(Date)^;
Но иногда надо делать и
DtSM:=PDtSM(Date)^;
а дальше работаем уже с нужной переменной. Используются только одинаково названные поля любой из структур.
Вопрос такой - можно ли сделать, что-то наподобие:
var
Dt: pointer;
Dt:=что-требуется('PDSM')(Date)^;
Dt.Pole1;
Dt.Pole2.Pole1;
и т.д.
Добавлено: 21 июл 2005, 09:51
Naeel Maqsudov
Нет. Так делать нельзя.
Если типы "почти разные" то может лучше использовать case в оописании типа?
Тогда получится один тип, который предусматривает обращение к одной и той же физической области памяти, но используя разную логическую структуру.
Другое решение - объявить две переменных с этими "почти разными типами", но так, чтобы вторая занимала в памяти то же самое место что и первая. Это желается с помошью директивы Absolute при объявлении переменных.
-----------------
См. справку по применению case в описании типов данных и переменных, а также по ключевому слову absolute.
PS
Вообще, Паскаль - пожалуй, самый гибкий язык в отношении высокоуровневого представления структур данных.
Добавлено: 21 июл 2005, 10:26
UUU
Спасибо.
Абсолют не подходит, т.к. структуры разные внутри.
Пробую с кейс:
type
TRSM = record
case CommandId: Cardinal of
cmDS: (
RSM:TDSM;
);
cmDtS: (
RSM:TDtSM;
);
end;
Ругается на второе RSM:TDtSM;
А так действительно было бы прекрасно: объявил переменную этого типа, поставил нужный CommandId и дальше везде обращайся одинаково...
Может я туплю?
Добавлено: 21 июл 2005, 16:50
Игорь Акопян
а это никак не реализовать с помощью объектной технологии? Типа базовый класс, потомок с бОльшим количеством свойств... Обращение к свойствам через виртуальные методы...
Добавлено: 21 июл 2005, 17:00
UUU
В результате по сути так и сделал
Добавлено: 21 июл 2005, 19:46
Naeel Maqsudov
Ругается на второе RSM:TDtSM;
В разных кейсах нельзя использовать одинаковые имена полей.
А так действительно было бы прекрасно: объявил переменную этого типа, поставил нужный CommandId и дальше везде обращайся одинаково...
Не-е-е-ет. Логика другая (Это ж обрабатывается КОМПИЛЯТОРОМ, которому наплевать на значение CommandId!!!)
CommandID - это поле для Ваших алгоритмов. Они в зависимости от CommandID должны обрабатывать использовать одно поле или другое, причем физически в памяти они пересекаются!
T.е. в одном месте:
X.CommandID:=cmDS;
X.RSM1:=<value of TDSM>;
А в другом:
Case X.CommandID of .... и т.д.
Если без проверки дернуть X.RSM2, то там будет лажа. Или напротив, если сделать X.RSM2:=<value of TDtSM>;
то будет испорчено значение X.RSM1.
Наиболее яркий методический пример использования case это побайтный и пословный доступ к двойному слову
Код: Выделить всё
type
TDWord = record
case byte of
0: (D: DWORD;);
1: (W_Lo,W_Hi: Word;);
2: (B_LoLo,B_LoHi,B_HiLo,B_HiHi:Byte;);
end;
var
X:TDword;
Теперь пишем
X.D:=321321321;
Теперь X.W_Lo будет равен 63849, т.е. младшему слову этого двойного слова.
Я просто не понял, насколько различаются TDSM и TDtSM.
Если Вы разрабатываете какой-то протокол, то как раз кейсы - это то что надо. Очень удобно для разбора: Тип команды, а за ним лежат данные, которые должны быть проинтерпретированы в соответствии с типом команды.
Правда пакетики получатся фиксированного размера (равного размеру наидлиннейшего кейса). Так как переменная быдет съедать столько памяти, чтобы любой кейс поместился...
Добавлено: 27 июл 2005, 14:09
UUU
Эту задачу, что называется, решил в лоб: в коде кейс и необходимое присваивание.
Но появилась другая задача:
Есть тип. И есть пары строки(массив) "имя-значение".
Т.е. надо сделать присваивание (обращение)
тип.имя:=значение.
В перле для таких конструкций есть например eval. Как быть в дельфях?
Причем в какой-то момент может получиться, что у "тип"а нет такого свойства, как "имя". Но это можно и try except отловить...