我复制了一些特尔斐码从一个项目到另一个项目,并发现它没有编制中的新的项目,虽然它没有在旧的。代码看起来是这样的:

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

因此,在新的项目,德尔福抱怨说,"左侧不能分配给"-可以理解的!但是,这代码汇编在旧项目。所以我的问题是, 为什么?是否有一个编译器切换到允许consts被重新分配?如何,即使工作?我想consts被替换他们的价值在编制时间?

有帮助吗?

解决方案

您需要转分配的类型的常数。项目>的选择->编译>可转让的类型的常量

你也可以加入 {$J+}{$WRITEABLECONST ON} 以考绩制度文件,这可能是更好的,因为它会工作,甚至如果你将文件移到另一个项目。

其他提示

类型推断出常只能标值--即事情就像整数加倍,等等。对于这些种类的常量,编译器的确代替恒的象征,与恒的价值,只要它满足他们的表情。

类型的常量,另一方面,可以结构化的价值观阵和记录。这些家伙需要实际存在的可执行--即他们需要有储存分配给他们这样的,在操作系统的载荷的可执行,值的类型不变的是身体包含在某个位置存储器。

解释为什么从历史上看,类型的常量在早期Delphi及其前身,涡轮增压Pascal,可写的(并因此而基本上是初始化的全球变量),我们需要回到天DOS。

DOS运行在实模式,在x86条款。这意味着计划有直接的物理存储器没有任何 MMU 做虚拟实物的映射。当程序具有直接进入存储器中,没有记忆的保护是有效的。换句话说,如果有存在任何特定地址,这是这两种可读写在实模式。

因此,在一个涡轮增压Pascal程序DOS用类型不变,其价值是分配给在某个地址在内存在运行时,这一类型的常会可写的。没有硬件MMU的方式获得和防止该程序编写。同样,因为帕斯卡有没有概念'const'ness C++已,没有什么类型的系统以阻止你。很多人利用了这一点,由于涡轮增压帕斯卡和德尔斐没有在那个时候有初始化的全球变量为特征。

移到Windows,有一个层之间存地址和身体的地址:存储管理单元。这个芯片取页指标(a转移掩)的存储地址你在试图访问,并且看起来的属性,这在其页面 页表.这些特性包括可读、写,并为现代x86芯片,不可执行的标志。有了这一支持,它可能标志部分。EXE或.DLL属性使得当的窗户装载负荷的可执行图像进入存储器,它分配适当的网页属性存页地图盘页内的这些部分。

当32位的视窗版本的德尔菲编译器,来到身边,它因此是有道理的,使const-喜欢的东西 真的 const,作为操作系统也具有这个特点。

  1. 为什么:因为在以前版本的德尔菲的类型的常数分配的默认保留的相容性与旧版本在哪里他们总是可写的(德尔斐1到早期的帕斯卡).
    默认的现已改变,以使常真的恒定...

  2. 编译器开关:{$J+}或者{$J-}{$WRITEABLECONST在}或者{$WRITEABLECONST关}
    或在项目选编译器:检查可转让的类型的常量

  3. 它是如何工作:如果编译器可以计算的价值在编制时间,它取代了const通过它的价值无处不在的代码,否则它拥有一个指向一个存储器区保持的价值,它可以写入或者没有。
  4. 见3.

像巴里说,人们利用了consts;一方面,这是使用,用于跟踪单独的实例。如果你看一个经典的单独执行,你会看到这样的:

  // 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;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top