En Delphi 7, ¿por qué no puedo asignar un valor a una constante?
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?
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.
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...Modificador de compilador:{$J+} o {$J-} {$WRITEABLECONST EN} o {$WRITEABLECONST OFF}
O en las opciones de proyecto para el compilador:compruebe asignables escribió Constantes- 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.
- 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;