Question

J'ai copié du code Delphi d'un projet à un autre et j'ai constaté qu'il ne se compile pas dans le nouveau projet, alors qu'il le faisait dans l'ancien.Le code ressemble à ceci :

procedure TForm1.CalculateGP(..)
const
   Price : money = 0;
begin
   ...
   Price := 1.0;
   ...
end;

Ainsi, dans le nouveau projet, Delphi se plaint que "le côté gauche ne peut pas être attribué" - c'est compréhensible !Mais ce code est compilé dans l'ancien projet.Donc ma question est, pourquoi?Existe-t-il un commutateur de compilateur permettant de réaffecter les consts ?Comment ça marche ?Je pensais que les consts étaient remplacés par leurs valeurs au moment de la compilation ?

Était-ce utile?

La solution

Vous devez activer les constantes typées assignables.Projet -> Options -> Compilateur -> Constantes typées assignables

Vous pouvez également ajouter {$J+} ou {$WRITEABLECONST ON} au fichier pas, ce qui est probablement mieux, car cela fonctionnera même si vous déplacez le fichier vers un autre projet.

Autres conseils

Les constantes déduites de type ne peuvent être que des valeurs scalaires - c'est-à-diredes choses comme les entiers, les doubles, etc.Pour ce type de constantes, le compilateur remplace en effet le symbole de la constante par la valeur de la constante chaque fois qu'il les rencontre dans des expressions.

Les constantes typées, en revanche, peuvent être des valeurs structurées – des tableaux et des enregistrements.Ces gars-là ont besoin d'un stockage réel dans l'exécutable - c'est-à-direils doivent disposer d'un stockage qui leur est alloué de telle sorte que, lorsque le système d'exploitation charge l'exécutable, la valeur de la constante saisie soit physiquement contenue à un emplacement de la mémoire.

Pour expliquer pourquoi, historiquement, les constantes typées des premiers Delphi et de son prédécesseur, Turbo Pascal, sont accessibles en écriture (et donc essentiellement des variables globales initialisées), nous devons revenir à l'époque du DOS.

DOS fonctionne en mode réel, en termes x86.Cela signifie que les programmes ont un accès direct à la mémoire physique sans aucune UMM faire des mappages virtuels-physiques.Lorsque les programmes ont un accès direct à la mémoire, aucune protection de la mémoire n'est effective.En d’autres termes, s’il y a de la mémoire à une adresse donnée, elle est à la fois lisible et inscriptible en mode réel.

Ainsi, dans un programme Turbo Pascal pour DOS avec une constante typée, dont la valeur est allouée à une adresse en mémoire au moment de l'exécution, cette constante typée sera accessible en écriture.Aucune MMU matérielle ne gêne et empêche le programme d'y écrire.De même, comme Pascal n'a aucune notion de « constance » comme le C++, il n'y a rien dans le système de types pour vous arrêter.Beaucoup de gens en ont profité, car Turbo Pascal et Delphi n'avaient pas encore de fonctionnalités d'initialisation de variables globales.

Passant à Windows, il existe une couche entre les adresses mémoire et les adresses physiques :l'unité de gestion de la mémoire.Cette puce prend l'index de la page (un masque décalé) de l'adresse mémoire à laquelle vous essayez d'accéder et recherche les attributs de cette page dans son tableau des pages.Ces attributs incluent des indicateurs lisibles, inscriptibles et, pour les puces x86 modernes, des indicateurs non exécutables.Avec cette prise en charge, il est possible de marquer des sections du .EXE ou du .DLL avec des attributs tels que lorsque le chargeur Windows charge l'image exécutable en mémoire, il attribue des attributs de page appropriés pour les pages mémoire qui sont mappées aux pages disque dans ces sections.

Lorsque la version Windows 32 bits du compilateur Delphi est apparue, il était donc logique de créer des éléments de type const. vraiment const, car le système d'exploitation possède également cette fonctionnalité.

  1. Pourquoi:Parce que dans les versions précédentes de Delphi, les constantes saisies étaient assignables par défaut pour préserver la compatibilité avec les anciennes versions où elles étaient toujours accessibles en écriture (Delphi 1 jusqu'au début de Pascal).
    La valeur par défaut a maintenant été modifiée pour rendre les constantes vraiment constantes…

  2. Commutateur du compilateur :{$J+} ou {$J-} {$WRITEABLECONST ON} ou {$WRITEABLECONST OFF}
    Ou dans les options du projet pour le compilateur :vérifier les constantes typées assignables

  3. Comment ça fonctionne:Si le compilateur peut calculer la valeur au moment de la compilation, il remplace le const par sa valeur partout dans le code, sinon il détient un pointeur vers une zone mémoire contenant la valeur, qui peut être rendue accessible en écriture ou non.
  4. voir 3.

Comme Barry l'a dit, les gens ont profité des consts ;L'une des façons dont cela a été utilisé était de garder une trace des instances singleton.Si vous regardez une implémentation singleton classique, vous verrez ceci :

  // Example implementation of the Singleton pattern.
  TSingleton = class(TObject)
  protected
    constructor CreateInstance; virtual;
    class function AccessInstance(Request: Integer): TSingleton;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    class function Instance: TSingleton;
    class procedure ReleaseInstance;
  end;

constructor TSingleton.Create;
begin
  inherited Create;

  raise Exception.CreateFmt('Access class %s through Instance only', [ClassName]);
end;

constructor TSingleton.CreateInstance;
begin
  inherited Create;

  // Do whatever you would normally place in Create, here.
end;

destructor TSingleton.Destroy;
begin
  // Do normal destruction here

  if AccessInstance(0) = Self then
    AccessInstance(2);

  inherited Destroy;
end;

{$WRITEABLECONST ON}
class function TSingleton.AccessInstance(Request: Integer): TSingleton;
const
  FInstance: TSingleton = nil;
begin
  case Request of
    0 : ;
    1 : if not Assigned(FInstance) then
          FInstance := CreateInstance;
    2 : FInstance := nil;
  else
    raise Exception.CreateFmt('Illegal request %d in AccessInstance', [Request]);
  end;
  Result := FInstance;
end;
{$IFNDEF WRITEABLECONST_ON}
  {$WRITEABLECONST OFF}
{$ENDIF}

class function TSingleton.Instance: TSingleton;
begin
  Result := AccessInstance(1);
end;

class procedure TSingleton.ReleaseInstance;
begin
  AccessInstance(0).Free;
end;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top