![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с указателями [D7]
aka © (2012-12-28 11:35:00)Привет, чтобы лучше донести суть вопроса набросал примерчик
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
PA = ^TA;
TA = record
recType: string[20];
field_1: Integer;
field_2: Integer;
end;
PB = ^TB;
TB = record
recType: string[20];
field_3: Integer;
field_4: Integer;
name: String[30];
end;
PC = ^TC;
TC = record
recType: string[20];
field_5: Integer;
end;
var
PtrData: array of Pointer;
PtrCount: Integer;
A: PA;
B: PB;
C: PC;
i: Integer;
begin
PtrCount := 3;
SetLength(PtrData, PtrCount);
New(A); //index in PtrData array = 0
A.recType := 'AType';
A.field_1 := 1;
A.field_2 := 2;
PtrData[0] := A;
New(B); //index in PtrData array = 1
B.recType := 'BType';
B.field_3 := 1;
B.field_4 := 2;
B.name := 'ivan';
PtrData[1] := B;
New(C); //index in PtrData array = 2
C.recType := 'CType';
C.field_5 := 1;
PtrData[2] := C;
writeln(PA(PtrData[0])^.recType); //out = AType
writeln(PB(PtrData[1])^.recType); //out = BType
writeln(PC(PtrData[2])^.recType); //out = CType
for i := 0 to Length(PtrData) - 1 do
writeln(i,' - ',PA(PtrData[i])^.recType);
for i := 0 to Length(PtrData) - 1 do
Dispose(PtrData[i]);
readln;
end.
Теперь, если мне нужно вывести значения, я могу поступить так:
writeln(PA(PtrData[0])^.recType); //out = AType
writeln(PB(PtrData[1])^.recType); //out = BType
writeln(PC(PtrData[2])^.recType); //out = CType
Здесь мы явно "показываем" тип PA или PB или PC перед PtrData[I], потому что знаем что там "лежит". Вопрос: как быть если мы не знаем что там, но нам нужно узнать какой там находится тип записи (у каждой и трех структур {A,B,C} имеется общее поле recType).
Можно и так, но бутет ли так корректно, применил один из типов, хотя там может быть и другой:
for i := 0 to Length(PtrData) - 1 do
writeln(i,' - ', PA(PtrData[i])^.recType);
Rouse_ (2012-12-28 23:30:00) [1]
> aka (28.12.12 17:46) [23]
> Короче закрывайте тему.
Эт можно...
Сергей М. (2012-12-28 21:55:00) [2]
> Мне на ДельфиКиндом написали
Мало ли кто на кого написал после того как ты тему закрыл)
знайка (2012-12-28 18:29:00) [3]не верим, и смотреть даже не будем. :)
aka (2012-12-28 17:51:00) [4]Мне на ДельфиКиндом написали что вариант первый с записями шикарный по реализации ). Так что так. Не верите? - посмотрите сами.
aka (2012-12-28 17:46:00) [5]Короче закрывайте тему.
Сергей М. (2012-12-28 17:33:00) [6]
> один класс может иметь разный ObjType
Упарил ты своими ObjType и rectype)
Если ты уж развернул оглобли в сторону классов и объектов, то не нужныони вообще - информацию о типах компилятор сам создаст и поместит в RTTI.
Вот так это будет выглядеть:
if ObjArray[i] is TClass1 then
TClass1(ObjArray[i]).Property1 ...
else if SomeObject is TClass2 then
TClass2(ObjArray[i]).Property3 ...
else if SomeObject is TClass3 then
TClass3(ObjArray[i]).Property3 ...
aka (2012-12-28 17:20:00) [7]Закрывайте тему.
мне нужно так if (TCustomObject(PtrObjArray[i]).ObjType="???
> Она вот чего сделает:
>
> if SomeObject is TClass1 then
> //.. в SomeObject - объект класса TClass1
> else if SomeObject is TClass2 then
> .. в SomeObject - объект класса TClass3
> else if SomeObject is TClass3 then
> .. в SomeObject - объект класса TClass3
")
это не подходит по причине того, что один класс может иметь разный ObjType - ну так уж получилось)
Сергей М. (2012-12-28 17:03:00) [8]
> Задача такая - это свойство должно быть и все.
Ты сам себе поставил эту задачу или на этот счет было конкретное постановление партии и правительства ?
> RTTI, а что она сделает?
Она вот чего сделает:
if SomeObject is TClass1 then
//.. в SomeObject - объект класса TClass1
else if SomeObject is TClass2 then
.. в SomeObject - объект класса TClass3
else if SomeObject is TClass3 then
.. в SomeObject - объект класса TClass3
RWolf (2012-12-28 16:48:00) [9]ООП же, ну.
полиморфизм, виртуальные функции — зачем изобретать кривые велосипеды?
aka (2012-12-28 16:42:00) [10]
> Сергей М. © (28.12.12 16:28) [17]
Задача такая - это свойство должно быть и все.
RTTI, а что она сделает?
Если нужно работать с массивом указателей на массу объектов. Нужно в начале узнать на что указывает конкретный елемент PtrObjArray[I], для этого и используется это поле.
Чтобы разыменовать указатель - нужно знать какой тип он имеет и как это узнать заранее, ведь массив имеет ссылки на не однотипные объекты
Сергей М. (2012-12-28 16:28:00) [11]Зачем ты добавляешь в свои классы это свойство ?
RTTI сама все сделает.
И вообще - перейти от записей к классам кавалерийским наскоком не получится, нужно сначала проштудировать учебные и справочные материалы.
aka (2012-12-28 16:22:00) [12]оп ошибка
PtrObjArray[1] := BObj;
PtrObjArray[2] := CObj;
aka (2012-12-28 16:18:00) [13]А как правильно описать свойства в классах?
raised exception class EPropertyError with message 'Property ObjType does not exist'
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, TypInfo;
type
TCustomObject = class(TObject)
private
FObjType: String;
public
property ObjType:String read FObjType write FObjType;
end;
A = class(TCustomObject)
public
property ObjType;
end;
B = class(TCustomObject)
public
property ObjType;
end;
C = class(TCustomObject)
public
property ObjType;
end;
var
PtrObjArray: array of Pointer;
i,ObjCount: Integer;
AObj: A;
BObj: B;
CObj: C;
ObjType: String;
begin
SetLength(PtrObjArray,3);
AObj := A.Create;
AObj.ObjType := 'AClass';
PtrObjArray[0] := AObj;
BObj := B.Create;
BObj.ObjType := 'BClass';
PtrObjArray[1] := AObj;
CObj := C.Create;
CObj.ObjType := 'CClass';
PtrObjArray[2] := AObj;
for i := 0 to Length(PtrObjArray) - 1 do
begin
ObjType := GetStrProp(TCustomObject(PtrObjArray[i]), 'ObjType');
if(ObjType = 'AClass') then
begin
end;
if(ObjType = 'BClass') then
begin
end;
if(ObjType = 'CClass') then
begin
end;
end;
readln;
end.
Сергей М. (2012-12-28 13:13:00) [14]
> в чем же хлипкость?
чем выше конструкция - тем она ненадежнее
aka (2012-12-28 12:52:00) [15]
> Сергей М. © (28.12.12 12:39) [10]
Что высокая - согласен. Воспользуюсь RTTI.
Ну а в чем же хлипкость?
Сергей М. (2012-12-28 12:44:00) [16]Ну нравится и нравится)
На вкус и цвет, как говорится, товарищей нет)
aka (2012-12-28 12:43:00) [17]
> TAccess - лишняя табуретка, конструкция твоя и без нее достаточно
> высокая и хлипкая)
Ну не знаю, а мне нравится...
Сергей М. (2012-12-28 12:39:00) [18]TAccess - лишняя табуретка, конструкция твоя и без нее достаточно высокая и хлипкая)
aka (2012-12-28 12:29:00) [19]
> Ну в качестве самодельного велосипеда вполне подойдет.
ну тогда для красоты и стройности введем дополнительную запись TAccess )))
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
PAccess = ^ TAccess;
TAccess = record
recType: String[20];
end;
PA = ^TA;
TA = record
recType: string[20];
field_1: Integer;
field_2: Integer;
end;
PB = ^TB;
TB = record
recType: string[20];
field_3: Integer;
field_4: Integer;
name: String[30];
end;
PC = ^TC;
TC = record
recType: string[20];
field_5: Integer;
end;
var
PtrData: array of Pointer;
PtrCount: Integer;
A: PA;
B: PB;
C: PC;
i: Integer;
begin
PtrCount := 3;
SetLength(PtrData, PtrCount);
New(A); //index in PtrData array = 0
A.recType := 'AType';
A.field_1 := 1;
A.field_2 := 45;
PtrData[0] := A;
New(B); //index in PtrData array = 1
B.recType := 'BType';
B.field_3 := 1;
B.field_4 := 20;
B.name := 'Ivan Ivanovich';
PtrData[1] := B;
New(C); //index in PtrData array = 2
C.recType := 'CType';
C.field_5 := 909045;
PtrData[2] := C;
for i := 0 to Length(PtrData) - 1 do
begin
if(PAccess(PtrData[i])^.recType = 'AType') then
writeln(PA(PtrData[i])^.field_2);
if(PAccess(PtrData[i])^.recType = 'BType') then
writeln(PB(PtrData[i])^.name);
if(PAccess(PtrData[i])^.recType = 'CType') then
writeln(PC(PtrData[i])^.field_5);
end;
for i := 0 to Length(PtrData) - 1 do
Dispose(PtrData[i]);
readln;
end.
aka (2012-12-28 12:15:00) [20]
> Только непонятно зачем в поле recType держать именно строку,
> в то время как достаточно одного байта.
просто для примера.