Pregunta

He copiado algunas código de Delphi de un proyecto a otro, y se encontró que no se compila en el nuevo proyecto, aunque lo hizo en el anterior.El código se ve algo como esto:

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

Así, en el nuevo proyecto de Delphi se queja de que "la izquierda no puede ser asignado a" - comprensible!Pero este código se compila en el antiguo proyecto.Así que mi pregunta es, por qué?Hay un modificador de compilador para permitir consts para ser reasignado?¿Cómo que aún funciona?Pensé consts fueron sustituidas por sus valores en tiempo de compilación?

¿Fue útil?

Solución

Necesita activar asignables escribió constantes en.Proyecto -> Opciones -> Compiler -> Asignables escribió Constantes

También puede agregar {$J+} o {$WRITEABLECONST ON} para el pas de archivo, que es probablemente la mejor, ya que va a trabajar incluso si mueve el archivo a otro proyecto.

Otros consejos

Tipo deduce constantes sólo se puede escalar de valores - es decir,cosas como enteros, dobles, etc.Para estos tipos de constantes, el compilador de hecho reemplazar la constante del símbolo con el de la constante de valor cada vez que se reúna con ellos en las expresiones.

Escrito constantes, por otro lado, pueden ser estructuradas en los valores de las matrices y registros.Estos chicos necesidad real de almacenamiento en el archivo ejecutable - es decir,que necesitan para tener almacenamiento asignado para ellas, de tal forma que, cuando el sistema operativo se carga el ejecutable, el valor del tipo constante es físicamente contenido en algún lugar en la memoria.

Para explicar por qué, históricamente, escribió constantes a principios de Delphi y su predecesor, Turbo Pascal, son modificables (y, por tanto, esencialmente inicializan las variables globales), necesitamos volver a los días de los DOS.

DOS se ejecuta en modo real, en x86 términos.Esto significa que los programas tienen acceso directo a memoria física sin ningún tipo de MMU virtual-física de las asignaciones.Cuando los programas tienen acceso directo a la memoria, sin la protección de la memoria es, en efecto.En otras palabras, si no hay memoria en cualquier dirección, tanto de lectura y escritura en modo real.

Así, en un programa de Turbo Pascal para DOS con un tipo constante, cuyo valor es asignado a una dirección en memoria en tiempo de ejecución, que escribió constante se puede escribir.No hay ningún hardware MMU en el medio del camino y evitando que el programa de escritura.Asimismo, debido a que Pascal no tiene noción de 'const'ness que C++ tiene, no hay nada en el tipo de sistema que lo detenga.Un montón de gente tomó ventaja de esto, desde Turbo Pascal y Delphi no se en que tiempo se han inicializado las variables globales como una característica.

De pasar a Windows, hay una capa entre las direcciones de memoria física y direcciones:la unidad de administración de memoria.Este chip se lleva a la página de índice (un desplazado de la máscara) de la dirección de memoria que estás intentando acceder, y busca los atributos de esta página en su de la tabla de páginas.Estos atributos incluyen lectura, escritura, y para los modernos chips x86, no ejecutables banderas.Con este apoyo, es posible marcar las secciones de la .EXE o .DLL con atributos tales que cuando el cargador de Windows carga el ejecutable de la imagen en la memoria, se asigna apropiado atributos de página para las páginas de memoria que se asignan a disco las páginas dentro de estas secciones.

Cuando el Windows de 32 bits versión de Delphi compilador llegó a su alrededor, así que tenía sentido hacer const cosas como realmente const, como el sistema operativo también tiene esta característica.

  1. Por qué:Porque en versiones anteriores de Delphi el escrito eran constantes asignable por defecto para mantener la compatibilidad con versiones anteriores donde siempre estaban de escritura (Delphi 1 hasta principios de Pascal).
    El valor predeterminado ha cambiado a hacer constantes muy constante...

  2. Modificador de compilador:{$J+} o {$J-} {$WRITEABLECONST EN} o {$WRITEABLECONST OFF}
    O en las opciones de proyecto para el compilador:compruebe asignables escribió Constantes

  3. Cómo funciona:Si el compilador puede calcular el valor en tiempo de compilación, se reemplaza la const por su valor en todas partes en el código, de lo contrario, contiene un puntero a un área de memoria de retención el valor, que pueden ser modificables o no.
  4. ver 3.

Como Barry dijo, la gente se aprovechó de consts;Una de las maneras en que esto se utilizó, fue para mantener un seguimiento de singleton instancias.Si nos fijamos en un clásico de la implementación de singleton, tendría que ver esto :

  // 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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top