Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
ВнизПроблема с описанием метода в потомке класса Найти похожие ветки
← →
lipskiy (2003-11-01 00:19) [0]Существует два экземпляра Some1 и Some2 класса TSome.
Каждый экземпляр содержит данные, формат которых я описываю отдельно для каждого экземпляра так:
type
PData1 = ^TData1;
TData1 = record
Caption : string;
Level : integer;
end;
PData2 = ^TData2;
TData1 = record
Position : real;
Level : integer;
end;
Класс TSome имеет событие OnInit. В обработчике этого события для каждого экземпляра класса я должен проинициализировать поле данных Level.
Хочу создать потомок класса - TMySome, куда включить обработчик события OnInit, поскольку для каждого экзепляра код обработчика события одинаков, отличие только в формате данных.
Сейчас обработчики события OnInit для каждого экземпляра класса выглядят так:
procedure TForm1.Some1Init(Sender: TSome);
var Data : PData1;
begin
Data:= Sender.GetData;
Data.Level:= SomeFunction;
end;
procedure TForm1.Some2Init(Sender: TSome);
var Data : PData2;
begin
Data:= Sender.GetData;
Data.Level:= SomeFunction;
end;
Как видно, код обработчиков одинаков, но описатели Data разные, хотя и имеют идентичное поле Level.
Вопрос: можно ли как-то описать в потомке класса TSome (в TMySome) обработчик события OnInit так, чтобы он мог использовать идентичные поля описателей Data при различиях в остальных полях? DataSize у данных каждого экземпляра разный.
← →
Ломброзо (2003-11-01 00:55) [1]Сделай так: интеджер вынеси первым полем,
type
PInt = ^TInt;
TInt = record
Level: integer;
end;
PData1 = ^TData1;
TData1 = record
Level : integer;
Position : real;
end;
Далее,
PInt(Data)^.Level := SomeFunction;
Попахивает хакерстом, 7-ка наверняка ругаться будет.
← →
Ломброзо (2003-11-01 00:57) [2]или как-нибудь в рантайм смещение адреса Level отсчитывай.
← →
lipskiy (2003-11-02 20:05) [3]Все получилось! Спасибо!
D7 не ругается, первый вариант работает.
То есть, насколько я понял, в этом случае происходит обращение к данным, которые объявлены дважды (в потомке класса и в головной программе), но занимают одну общую область памяти. Из головной программы инициализируется DataSize, включающий в себя все поля данных, а из потомка класса DataSize вообще не инициализируется но обращение к полю Level делается, и это поле физически расположено в том же самом месте, что и поле Level, объявленное в головной программе.
Верно я понял физику явления?
А не опасен ли такой метод? А если опасен, то чем?
← →
Ломброзо (2003-11-02 20:34) [4]В принципе ничем не опасен, если ты вынес поле Integer вперед, тогда смещение адреса относительно начала структуры равно 0. Если же у тебя в структурах винегрет из разных типов данных и ты хочешь проинициализировать вторую или там третью, то это уже опасно из-за разного sizeof этих типов и выравнивания, производимого компилятором. С трудом представляю, где вообще такой прием может понадобиться. В С++ проще, там смещение можно высчитать макросами при компиляции. См. также аттрибут Packed.
Есть еще одно рацпредложение - используй структуры вариантов, будет немного потормознее, но удобнее.
type
TMyRecord = record
a, b, c, d: Variant; // OleVariant
end;
← →
lipskiy (2003-11-03 00:39) [5]Не, мне надо быстро, у меня дерево большое (Tree).
Меня первый вариант вполне устраивает, тем более что я его понимаю и он не опасен, а с вариантами я не умею обращаться.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.033 c