Domanda

Ho copiato del codice Delphi da un progetto all'altro e ho scoperto che non viene compilato nel nuovo progetto, sebbene lo fosse in quello vecchio.Il codice è simile al seguente:

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

Quindi nel nuovo progetto Delphi lamenta che "non è possibile assegnare il lato sinistro" - comprensibile!Ma questo codice viene compilato nel vecchio progetto.Quindi la mia domanda è: Perché?Esiste un'opzione del compilatore per consentire la riassegnazione dei const?Come funziona?Pensavo che i const fossero sostituiti dai loro valori in fase di compilazione?

È stato utile?

Soluzione

È necessario attivare le costanti digitate assegnabili.Progetto -> Opzioni -> Compilatore -> Costanti tipizzate assegnabili

Inoltre puoi aggiungere {$J+} O {$WRITEABLECONST ON} al file pas, che probabilmente è meglio, poiché funzionerà anche se sposti il ​​file in un altro progetto.

Altri suggerimenti

Le costanti dedotte dal tipo possono essere solo valori scalari, ad es.cose come numeri interi, doppi, ecc.Per questi tipi di costanti, il compilatore sostituisce effettivamente il simbolo della costante con il valore della costante ogni volta che li incontra nelle espressioni.

Le costanti digitate, d'altro canto, possono essere valori strutturati: matrici e record.Questi ragazzi hanno bisogno di spazio di archiviazione effettivo nell'eseguibile, ad es.devono avere spazio di archiviazione allocato in modo tale che, quando il sistema operativo carica l'eseguibile, il valore della costante tipizzata sia fisicamente contenuto in una posizione della memoria.

Per spiegare perché, storicamente, le costanti digitate nel primo Delphi e nel suo predecessore, Turbo Pascal, sono scrivibili (e quindi variabili globali essenzialmente inizializzate), dobbiamo tornare ai tempi del DOS.

DOS funziona in modalità reale, in termini x86.Ciò significa che i programmi hanno accesso diretto alla memoria fisica senza alcuno MMU facendo mappature virtuale-fisiche.Quando i programmi hanno accesso diretto alla memoria, non è attiva alcuna protezione della memoria.In altre parole, se c'è memoria in un dato indirizzo, è sia leggibile che scrivibile in modalità reale.

Quindi, in un programma Turbo Pascal per DOS con una costante digitata, il cui valore è allocato in un indirizzo in memoria in fase di esecuzione, quella costante digitata sarà scrivibile.Non c'è nessuna MMU hardware che interferisca e impedisca al programma di scrivervi.Allo stesso modo, poiché Pascal non ha la nozione di "costanza" che ha C++, non c'è nulla nel sistema dei tipi che ti fermi.Molte persone ne approfittarono, dal momento che Turbo Pascal e Delphi a quel tempo non avevano inizializzato le variabili globali come funzionalità.

Passando a Windows, esiste uno strato tra indirizzi di memoria e indirizzi fisici:l'unità di gestione della memoria.Questo chip prende l'indice della pagina (una maschera spostata) dell'indirizzo di memoria a cui stai tentando di accedere e cerca gli attributi di questa pagina nel suo tabella delle pagine.Questi attributi includono flag leggibili, scrivibili e, per i moderni chip x86, non eseguibili.Con questo supporto, è possibile contrassegnare sezioni di .EXE o .DLL con attributi tali che quando il caricatore di Windows carica l'immagine eseguibile in memoria, assegni attributi di pagina appropriati per le pagine di memoria che mappano alle pagine del disco all'interno di queste sezioni.

Quando è arrivata la versione Windows a 32 bit del compilatore Delphi, aveva senso creare cose simili a const Veramente const, poiché anche il sistema operativo ha questa funzionalità.

  1. Perché:Perché nelle versioni precedenti di Delphi le costanti digitate erano assegnabili per impostazione predefinita per preservare la compatibilità con le versioni precedenti dove erano sempre scrivibili (Delphi 1 fino al primo Pascal).
    L'impostazione predefinita è stata ora modificata per rendere le costanti davvero costanti...

  2. Interruttore del compilatore:{$J+} o {$J-} {$WRITEABLECONST ON} o {$WRITEABLECONST OFF}
    Oppure nelle opzioni del progetto per il compilatore:controllare le costanti tipizzate assegnabili

  3. Come funziona:Se il compilatore può calcolare il valore in fase di compilazione, sostituisce const con il suo valore ovunque nel codice, altrimenti contiene un puntatore a un'area di memoria che contiene il valore, che può essere resa scrivibile o meno.
  4. vedi 3.

Come ha detto Barry, le persone hanno approfittato dei costi;Uno dei modi in cui è stato utilizzato è stato per tenere traccia delle istanze singleton.Se guardi un'implementazione singleton classica, vedresti questo:

  // 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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top