Модератор: Модераторы
Хм, это работае только для WRITELN с ее безразличием к типу. В прочих случаях для работы со значениями придется проверять на тип :зато плюсы ООП налицо:
- Код: Выделить всё
for i:= high(arr1) downto low(arr1) do
arr1[i].WriteDataWithType;
if arr1[i] is INTObj then
else if arr1[i] is TEXTObj then
debi12345 писал(а):Значит, какая-то опция копилятора ? Но какая ?
{$mode objfpc}{$h+}
chmorec = packed record
int_val: integer;
str_val: pchar;
end;
pchmorec = ^chmorec;
ANYTYPE = (INT_T,TEXT_T,REAL_T,CHMO_T);
anydatarecty = packed record
case data_type:ANYTYPE of
INT_T: (ival: integer);
TEXT_T: (tval: pchar);
REAL_T: (rval: double);
CHMO_T: (chmoval: chmorec);
end;
anydatarecarty = array of anydatarecty;
procedure addelem(var arr: anydatarecarty; atype:ANYTYPE; adataptr: pointer);
begin
setlength(arr,length(arr)+1);
arr[high(arr)].data_type:= atype;
// case integer(atype) of
// integer(INT_T): arr[high(arr)].ival:= integer(adataptr^);
// integer(TEXT_T): arr[high(arr)].tval:= strnew(pchar(adataptr));
// integer(REAL_T): arr[high(arr)].rval:= double(adataptr^);
// integer(CHMO_T): begin
// with arr[high(arr)].chmoval do begin
// int_val:= (chmorec(adataptr^)).int_val;
// str_val:= strnew((chmorec(adataptr^)).str_val);
// end;
// end;
// end;
case atype of
INT_T: arr[high(arr)].ival:= integer(adataptr^);
TEXT_T: arr[high(arr)].tval:= strnew(pchar(adataptr));
REAL_T: arr[high(arr)].rval:= double(adataptr^);
CHMO_T: begin
with arr[high(arr)].chmoval do begin
int_val:= (chmorec(adataptr^)).int_val;
str_val:= strnew((chmorec(adataptr^)).str_val);
end;
end;
end;
end;
Error: Constant and CASE types do not match
program test;
{$mode objfpc}{$h+}
uses
sysutils,strings;
const
TEST_CNT = 300000;
type
chmorec = packed record
int_val: integer;
str_val: pchar;
end;
pchmorec = ^chmorec;
ANYTYPE = (INT_T,TEXT_T,REAL_T,CHMO_T);
anydatarecty = packed record
case data_type:ANYTYPE of
INT_T: (ival: integer);
TEXT_T: (tval: pchar);
REAL_T: (rval: double);
CHMO_T: (chmoval: chmorec);
end;
anydatarecarty = array of anydatarecty;
procedure addelem(var arr: anydatarecarty; atype:ANYTYPE; adataptr: pointer);
begin
setlength(arr,length(arr)+1);
arr[high(arr)].data_type:= atype;
// case integer(atype) of
// integer(INT_T): arr[high(arr)].ival:= integer(adataptr^);
// integer(TEXT_T): arr[high(arr)].tval:= strnew(pchar(adataptr));
// integer(REAL_T): arr[high(arr)].rval:= double(adataptr^);
// integer(CHMO_T): begin
// with arr[high(arr)].chmoval do begin
// int_val:= (chmorec(adataptr^)).int_val;
// str_val:= strnew((chmorec(adataptr^)).str_val);
// end;
// end;
// end;
case atype of
INT_T: arr[high(arr)].ival:= integer(adataptr^);
TEXT_T: arr[high(arr)].tval:= strnew(pchar(adataptr));
REAL_T: arr[high(arr)].rval:= double(adataptr^);
CHMO_T: begin
with arr[high(arr)].chmoval do begin
int_val:= (chmorec(adataptr^)).int_val;
str_val:= strnew((chmorec(adataptr^)).str_val);
end;
end;
end;
end;
var
arr1: anydatarecarty;
i1: integer;
pch1: pchar;
r1: double;
chmo1: chmorec;
i: integer;
begin
for i:= 0 to TEST_CNT do begin
i1:= i;
addelem(arr1,INT_T,@i1);
r1:= double(i);
addelem(arr1,REAL_T,@r1);
pch1:= pchar(inttostr(i) + ' as text');
addelem(arr1,TEXT_T,pch1);
chmo1.int_val:= i;
chmo1.str_val:= pchar(inttostr(i) +' as text in CHMOREC');
addelem(arr1,CHMO_T,@chmo1);
end;
for i:= high(arr1) downto low(arr1) do begin
case integer(arr1[i].data_type) of
// integer(INT_T): writeln('int val = ', arr1[i].ival);
integer(TEXT_T): begin
// writeln('text val = ', arr1[i].tval);
dispose(arr1[i].tval);
end;
// integer(REAL_T): writeln('real val = ', arr1[i].rval);
integer(CHMO_T): begin
// writeln('chmo rec = {', arr1[i].chmoval.int_val,',',arr1[i].chmoval.str_val, '}');
dispose(arr1[i].chmoval.str_val);
end;
end;
end;
end.
program project1;
{$mode objfpc}{$h+}
uses
sysutils,strings;
const
TEST_CNT = 300000;
type
chmorec = packed record
int_val: integer;
str_val: pchar;
end;
pchmorec = ^chmorec;
tdatasized=packed array [1..sizeof(chmorec)] of byte;
baseObj = packed object
data:tdatasized{pointer};
procedure WriteDataWithType;virtual;abstract;
destructor done;virtual;
end;
INTObj = packed object(baseObj)
procedure WriteDataWithType;virtual;
constructor init(adataptr: pointer);
end;
TEXTObj = packed object(baseObj)
procedure WriteDataWithType;virtual;
constructor init(adataptr: pointer);
destructor done;virtual;
end;
REALObj = packed object(baseObj)
procedure WriteDataWithType;virtual;
constructor init(adataptr: pointer);
destructor done;virtual;
end;
CHMOObj = packed object(baseObj)
procedure WriteDataWithType;virtual;
constructor init(adataptr: pointer);
destructor done;virtual;
end;
anyObjarty = array of baseObj;
ANYTYPE = (INT_T,TEXT_T,REAL_T,CHMO_T);
destructor baseObj.done;
begin
end;
procedure INTObj.WriteDataWithType;
begin
writeln('int val = ', pinteger(@data)^);
end;
constructor INTObj.init(adataptr: pointer);
begin
pinteger(@data)^:=pinteger(adataptr)^;
end;
procedure TEXTObj.WriteDataWithType;
begin
writeln('text val = ', ppchar(@data)^);
end;
constructor TEXTObj.init(adataptr: pointer);
begin
ppchar(@data)^:=strnew(pchar(adataptr));
end;
destructor TEXTObj.done;
begin
strdispose(ppchar(@data)^);
end;
procedure REALObj.WriteDataWithType;
begin
writeln('real val = ', pdouble(@data)^);
end;
constructor REALObj.init(adataptr: pointer);
begin
//new(pdouble(data));
pdouble(@data)^:=pdouble(adataptr)^;
end;
destructor REALObj.done;
begin
//dispose(pdouble(data));
end;
procedure CHMOObj.WriteDataWithType;
begin
writeln('chmo rec = {', inttostr(pchmorec(@data)^.int_val)+',',pchmorec(@data)^.str_val,'}');
end;
constructor CHMOObj.init(adataptr: pointer);
begin
//new(pchmorec(data));
pchmorec(@data)^.int_val:=pchmorec(adataptr)^.int_val;
pchmorec(@data)^.str_val:=strnew(pchmorec(adataptr)^.str_val);
end;
destructor CHMOObj.done;
begin
strdispose(pchmorec(@data)^.str_val);
//dispose(pchmorec(@data));
end;
procedure addelem(var arr: anyObjarty; atype:ANYTYPE; adataptr: pointer);
begin
setlength(arr,length(arr)+1);
case atype of
INT_T: INTObj(arr[high(arr)]).init(adataptr);
TEXT_T:TEXTObj(arr[high(arr)]).init(adataptr);
REAL_T:REALObj(arr[high(arr)]).init(adataptr);
CHMO_T:CHMOObj(arr[high(arr)]).init(adataptr);
end;
end;
var
arr1: anyObjarty;
i1: integer;
pch1: pchar;
r1: double;
chmo1: chmorec;
i: integer;
begin
for i:= 0 to TEST_CNT do begin
i1:= 1;
addelem(arr1,INT_T,@i1);
r1:= 1.234;
addelem(arr1,REAL_T,@r1);
pch1:= 'one';
addelem(arr1,TEXT_T,pch1);
chmo1.int_val:= 100;
chmo1.str_val:= 'hundred';
addelem(arr1,CHMO_T,@chmo1);
end;
for i:= high(arr1) downto low(arr1) do
begin
arr1[i].WriteDataWithType;
arr1[i].done;
end;
end.
проверка типа производится автоматом при вызове виртуального метода - т.е. для разных типов будут вызваны методы разных обжектов.
убрана куча мелких выделений памяти но размер массива увеличен -
setlength(arr,length(arr)+1);
zamtmn@zamtmn-desktop:/mnt/wind/array$ time ./v1
real 0m0.201s
user 0m0.196s
sys 0m0.004s
zamtmn@zamtmn-desktop:/mnt/wind/array$ time ./v2
real 0m0.127s
user 0m0.096s
sys 0m0.028s
zamtmn@zamtmn-desktop:/mnt/wind/array$ time ./v3
real 0m0.095s
user 0m0.080s
sys 0m0.016s
всяко не попадает под вылизанное решение
с уходом от setlength
мы мереем скорость setlength,
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 23