2012-03-15 16 views
6

Chciałbym wiedzieć, jak zadeklarować rekord, który ma pewne ustalone wartości. Muszę przesłać dane przy użyciu tego wzoru: Byte($FF)-Byte(0..250)-Byte(0..250). Używam do tego celu record i chciałbym, aby pierwsza wartość była stała, tak aby nie można go było zepsuć. Takich jak:Jak zadeklarować stałą wartość w rekordzie?

TPacket = record 
    InitByte: byte; // =255, constant 
    FirstVal, 
    SecondVal: byte; 
end; 
+3

mógł odwołać się do podzakresu Rodzaje – OnTheFly

+0

Jeśli wszystko robisz jest bajt o wartości TPacket, chciałbym zamiast używać RawByteString i po prostu zdefiniować stałe nazwanych InitByte = 0, FIrstVal = 1 i tak dalej. AND Zapewniam, że wartość początkowa była poprawną wartością stałą, wykonując ją w CODE w mojej funkcji PacketBuild. –

+1

Jakiej wersji Delphi użyjesz? – kobik

Odpowiedz

12

Nie można powoływać się na konstruktora, ponieważ, w przeciwieństwie do klas, płyty nie są wymagane do korzystania z nich, konstruktor domyślny bez parametrów wykorzystywane w sposób dorozumiany.

Ale można użyć stałego pola:

type 
    TPacket = record 
    type 
    TBytish = 0..250; 
    const 
    InitByte : Byte = 255; 
    var 
    FirstVal, 
    SecondVal: TBytish; 
    end; 

Wtedy to wykorzystać jako zwykły Record, oprócz tego, że nie ma (i nie może) zmienić pole InitByte.
FillChar zachowuje stałe pole i zachowuje się zgodnie z oczekiwaniami.

procedure TForm2.FormCreate(Sender: TObject); 
var 
    r: TPacket; 
begin 
    FillChar(r, SizeOf(r), #0); 
    ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal])); 
    // r.InitByte := 42; // not allowed by compiler 
    // r.FirstVal := 251; // not allowed by compiler 
    r.FirstVal := 1; 
    r.SecondVal := 2; 
    ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal])); 
end; 

Updated zawierać zagnieżdżony zakres typu 0..250

+1

Awesome. Pierwsza prawdziwa odpowiedź. –

+0

@Mike, prawie jest. François, brakuje ci utrzymywania zasięgu "FirstVal" i "SecondVal". Jeśli dobrze to zrobię, powinny znajdować się w przedziale '0..250'. Ale wtedy możesz napotkać problem z 'FillChar', który może ustawić wartości poza tymi granicami (z pewnością sprawdzanie zasięgu). – TLama

+1

@TLama, polegałem na deklaracji rekordu OP i nie trafiłem w zasięg. Zaktualizowana odpowiedź podtypem ... –

2

Nowoczesne wersje Delphi umożliwiają zapisywanie metod. Chociaż nie można uniemożliwić zmianę pola można przynajmniej zainicjować go prawidłowo:

type 
    TPacket = record 
    InitByte: byte; // =255, constant 
    FirstVal, 
    SecondVal: byte; 
    constructor Create(val1, val2 : byte); 
    end; 


constructor TPacket.Create(val1, val2: byte); 
begin 
    InitByte := 255; 
    FirstVal := val1; 
    SecondVal := val2; 
end; 
+1

Niestety, nie można wymusić użycia konstruktora ... –

0

Biorąc pod uwagę fakt, że rekordy mogą mieć właściwości, można zdefiniować jako rekord:

TMixedFixed = record 
strict private 
    FFixed: byte; 
    FVariable1: byte; 
    FVariable2: byte; 
public 
    property Fixed read FFixed; 
    property Variable read FVariable write FVariable; 
    constructor Create(Var1, Var2: byte); 
end; 

constructor TMixedFixed.create(Var1, Var2: byte); 
begin 
    FFixed:= 255; 
    FVariable1:= Var1; 
    FVariable2:= Var2; 
end; 

Biorąc pod uwagę, że rzeczywiste zmienne są ściśle prywatne, nie powinno się ich dotykać bez specjalnej magii. Będziesz musiał użyć konstruktora, aby zainicjować wartości "ustalone".

+0

Nie zapobiega zadeklarowaniu zmiennej i używa jej jako standardowego rekordu bez użycia Konstruktor. Będziesz mieć śmieci w 'FFixed' i nie da się tego zmienić ... –

+0

@ François, czy nie możesz uchylić domyślnego konstruktora? – Johan

+0

o czym nie wiem. Domyślny konstruktor jest tak ważny, że uniemożliwia nawet zadeklarowanie innego konstruktora bez parametrów. Dowolny niestandardowy konstruktor musi mieć parametry. Zobacz [docwiki] (http://docwiki.embarcadero.com/RADStudio/en/Structured_Types): "Rekordy są konstruowane automatycznie, przy użyciu domyślnego konstruktora bezargumentowego, ale klasy muszą być jawnie skonstruowane. konstruktor argumentów, każdy zdefiniowany przez użytkownika konstruktor rekordów musi mieć jeden lub więcej parametrów. " –

0

Jest to najbardziej prosty sposób:

type 
    TPacket = record 
    InitByte: byte; // =255, constant 
    FirstVal, 
    SecondVal: byte; 
    end; 

var 
    Packet : TPacket = (InitByte: 255); 

const 
    Packet1 : TPacket = (InitByte: 255); 
+1

Nie, to nie jedyny sposób, zobacz moją odpowiedź.A, BTW, nie można zainicjować zmiennych lokalnych, takich jak zmienna Packet (błąd kompilatora E2195). –

Powiązane problemy