J'aimerais savoir comment puis-je déclarer un enregistrement, qui a des valeurs fixes. J'ai besoin d'envoyer des données à l'aide de ce modèle: octet ($ FF) -Byte (0..250) -Byte (0..250) code>. J'utilise enregistrement code> pour cela et j'aimerais avoir la première valeur de sa constante, de sorte qu'il ne peut pas être gâché.
Comme:
4 Réponses :
Les versions modernes de Delphi permettent des méthodes d'enregistrement. Bien que vous ne puissiez pas empêcher une personne de changer le champ, vous pouvez au moins l'initialiser correctement:
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;
Compte tenu du fait que les enregistrements peuvent désormais avoir des propriétés, vous pouvez définir un enregistrement comme: étant donné que les véritables variables sont strictes privées, vous ne devriez pas pouvoir les toucher sans que magie spéciale.
Vous devrez utiliser le constructeur pour init les valeurs «fixes». P> p>
Il n'empêche pas de déclarer une variable et de l'utiliser comme un enregistrement standard sans utiliser le constructeur. Vous aurez juste des ordures dans ffixed code> et aucun moyen de le changer ...
@ François, vous ne pouvez pas annuler le constructeur par défaut?
Pas que je sache de. Le constructeur par défaut est si important qu'il vous empêche même de déclarer un autre constructeur sans paramètre. Tout constructeur personnalisé que vous fournissez doit avoir des paramètres (s). Voir DOCWIKI : "Les enregistrements sont automatiquement construits, à l'aide d'un constructeur sans argument par défaut, mais Les classes doivent être explicitement construites. Parce que les enregistrements ont un constructeur no-argument par défaut, tout constructeur d'enregistrement défini par l'utilisateur doit avoir un ou plusieurs paramètres. "
Ceci est le moyen le plus simple:
Non, ce n'est pas le seul moyen, voir ma réponse. Et, BTW, vous ne pouvez pas initialiser les variables locales telles que votre variable de paquets (Erreur de compilateur E2195).
Vous ne pouvez pas compter sur un constructeur car, contrairement aux classes, les enregistrements ne sont pas obligés de les utiliser, le constructeur de paramètres par défaut étant utilisé implicitement.
Mais vous pouvez utiliser un champ constant: p> puis utilisez-le comme un enregistrement régulier, sauf que vous n'avez pas (et que vous ne pouvez pas) changer le initbyte code> champ.
FLIDCHAR CODE> Conserve le champ Constant et se comporte comme prévu. P> 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;
@Mike, presque est. François, il vous manque la gamme de conservation du firstval code> et secondval code>. Si je comprends bien, ils doivent figurer dans la plage de 0..250 code>. Mais vous pouvez ensuite répondre au problème avec FLIDCHAR CODE>, qui peut définir les valeurs de cette limite (avec la plage de la plage).
@Tlama, je m'appuyais sur la déclaration record de l'OP et j'ai manqué la gamme. Réponse mise à jour avec un sous-type ...
@Tlama, Fillcharne ne suit jamais la plage de valeurs car elle ne fait que écrire un octet dans la mémoire réservée. La déclaration de const rend le premier champ inaccessible à Fillchar; C'est à peu près tout ce que nous pouvons faire. Impossible d'empêcher d'aller et de piquer directement dans la mémoire ;-)
@Tlama, `valeur: = 251; R.firstval: = valeur; `vous donnera une erreur de contrôle de plage (à condition que vous l'utilisez dans les options de compilation), comme tout autre abus de gamme, vous essayerez de vous faufiler. :)
Oui, mais c'est une erreur d'exécution ce qui pourrait être indésirable, +1 cependant :)
Vous pourriez recourir à des types de subranges
Si tout ce que vous faites, c'est des valeurs d'octets dans un pavadère, je voudrais plutôt utiliser Rawbytestring et définir simplement les constantes nommées initbyte = 0, firstval = 1, etc. Et je vous assurerais que la valeur initiale était la valeur constante correcte en le faisant dans le code de ma fonction PacketBuild.
Quelle version Delphi utiliserez-vous?
Qu'entendez-vous par «envoyer des données à l'aide de ce modèle»? Avez-vous l'intention d'utiliser ttream.write (paquet, taille de (paquet)) ou similaire? Sinon, pourquoi doit-il être un disque?
Je vais tester une communication COM, elle sera envoyée par Writefile, une gamme d'octets pourrait également être une possibilité. Mais je voulais le faire "Néater" et le disque semblait être un meilleur choix