delphi - significado - palabra reservada const java
En Delphi 7, ¿por qué puedo asignar un valor a un const? (4)
Por qué: debido a que en las versiones anteriores de Delphi, las constantes tipadas se podían asignar de forma predeterminada para preservar la compatibilidad con versiones anteriores en las que siempre podían escribirse (Delphi 1 hasta principios de Pascal).
El valor predeterminado ahora se ha cambiado para hacer que las constantes sean realmente constantes ...Conmutador del compilador: {$ J +} o {$ J-} {$ WRITEABLECONST ON} o {$ WRITEABLECONST OFF}
O en las opciones de proyecto para el compilador: verificar Constantes tipeables asignables- Cómo funciona: si el compilador puede calcular el valor en tiempo de compilación, reemplaza la const por su valor en todas partes del código, de lo contrario, mantiene un puntero a un área de memoria que contiene el valor, que puede escribirse o no.
- ver 3.
Copié un código Delphi de un proyecto a otro y descubrí que no se compila en el nuevo proyecto, aunque sí en el anterior. El código se ve así:
procedure TForm1.CalculateGP(..)
const
Price : money = 0;
begin
...
Price := 1.0;
...
end;
Entonces, en el nuevo proyecto, Delphi se queja de que "el lado izquierdo no puede asignarse a", ¡comprensible! Pero este código se compila en el proyecto anterior. Entonces mi pregunta es, ¿por qué ? ¿Hay un cambio de compilador para permitir reasignar consts? ¿Cómo funciona eso? Pensé que las constelaciones fueron reemplazadas por sus valores en tiempo de compilación.
Como dijo Barry, la gente se aprovechó de las constelaciones; Una de las formas en que esto se usó fue para realizar un seguimiento de las instancias únicas. Si observas una implementación singleton clásica, verías 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;
Debe activar las constantes tipeadas asignables. Proyecto -> Opciones -> Compilador -> Constantes tipadas asignables
También puede agregar {$J+}
o {$WRITEABLECONST ON}
al archivo pas, que probablemente sea mejor, ya que funcionará incluso si mueve el archivo a otro proyecto.
Las constantes de tipo inferido solo pueden ser valores escalares, es decir, cosas como enteros, dobles, etc. Para este tipo de constantes, el compilador sí reemplaza el símbolo de la constante con el valor de la constante siempre que los encuentre en expresiones.
Las constantes tipadas, por otro lado, pueden ser valores estructurados: matrices y registros. Estos tipos necesitan almacenamiento real en el ejecutable, es decir, necesitan tener almacenamiento asignado para ellos de forma tal que, cuando el sistema operativo cargue el ejecutable, el valor de la constante tipeada esté físicamente contenido en alguna ubicación de la memoria.
Para explicar por qué, históricamente, las constantes tipadas en Delphi inicial y su predecesor, Turbo Pascal, son escribibles (y, por lo tanto, esencialmente variables globales inicializadas), tenemos que volver a los días de DOS.
DOS se ejecuta en modo real, en términos x86. Esto significa que los programas tienen acceso directo a la memoria física sin que ninguna MMU realice asignaciones virtuales-físicas. Cuando los programas tienen acceso directo a la memoria, no hay protección de memoria en efecto. En otras palabras, si hay memoria en cualquier dirección dada, es legible y escribible en modo real.
Entonces, en un programa Turbo Pascal para DOS con una constante tipada, cuyo valor se asigna a una dirección en la memoria en tiempo de ejecución, esa constante tipeada será escribible. No hay una MMU de hardware que se interponga y que impida que el programa escriba en ella. De manera similar, debido a que Pascal no tiene noción de ''const''ness'' que C ++ tiene, no hay nada en el sistema de tipos que lo detenga. Mucha gente se aprovechó de esto, ya que Turbo Pascal y Delphi en ese momento no habían inicializado las variables globales como una característica.
Pasando a Windows, hay una capa entre las direcciones de memoria y físicas: la unidad de gestión de memoria. Este chip toma el índice de página (una máscara desplazada) de la dirección de memoria a la que intenta acceder y busca los atributos de esta página en su tabla de páginas . Estos atributos incluyen legibles, editables, y para chips modernos x86, indicadores no ejecutables. Con este soporte, es posible marcar secciones de .EXE o .DLL con atributos tales que cuando el cargador de Windows carga la imagen ejecutable en la memoria, asigna atributos de página apropiados para las páginas de memoria que asignan páginas de disco dentro de estas secciones.
Cuando apareció la versión de Windows de 32 bits del compilador Delphi, tenía sentido hacer que las cosas parecidas a const fuesen realmente reales, ya que el sistema operativo también tiene esta característica.