문제

한 프로젝트에서 다른 프로젝트로 일부 Delphi 코드를 복사했는데 이전 프로젝트에서는 컴파일되었지만 새 프로젝트에서는 컴파일되지 않는 것을 발견했습니다.코드는 다음과 같습니다.

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

따라서 새 프로젝트에서 Delphi는 "왼쪽을 할당할 수 없습니다"라고 불평합니다. 이해할 수 있습니다!하지만 이 코드는 이전 프로젝트에서 컴파일됩니다.그래서 내 질문은, ?const를 재할당할 수 있는 컴파일러 스위치가 있습니까?그게 어떻게 작동하나요?컴파일 타임에 const가 해당 값으로 대체되었다고 생각했습니까?

도움이 되었습니까?

해결책

할당 가능한 유형의 상수를 켜야 합니다.프로젝트 -> 옵션 -> 컴파일러 -> 할당 가능한 유형의 상수

또한 추가 할 수 있습니다 {$J+} 또는 {$WRITEABLECONST ON} pas 파일에 저장하세요. 파일을 다른 프로젝트로 옮겨도 작동하므로 더 좋을 것입니다.

다른 팁

유형 추론 상수는 스칼라 값만 될 수 있습니다. 즉,정수, 복식 등과 같은 것들.이러한 종류의 상수에 대해 컴파일러는 실제로 표현식에서 상수 기호를 만날 때마다 상수 기호를 상수 값으로 바꿉니다.

반면에 형식화된 상수는 구조화된 값(배열 및 레코드)일 수 있습니다.이 사람들은 실행 파일에 실제 저장 공간이 필요합니다.OS가 실행 파일을 로드할 때 형식화된 상수의 값이 메모리의 특정 위치에 물리적으로 포함되도록 스토리지를 할당해야 합니다.

역사적으로 초기 Delphi와 이전 버전인 Turbo Pascal에서 입력된 상수가 쓰기 가능한(따라서 본질적으로 전역 변수가 초기화된) 이유를 설명하려면 DOS 시대로 돌아가야 합니다.

DOS는 x86 용어로 리얼 모드에서 실행됩니다.이는 프로그램이 아무런 조치 없이 실제 메모리에 직접 액세스할 수 있음을 의미합니다. MMU 가상-물리적 매핑을 수행합니다.프로그램이 메모리에 직접 액세스할 때는 메모리 보호가 적용되지 않습니다.즉, 특정 주소에 메모리가 있으면 리얼 모드에서 읽고 쓸 수 있습니다.

따라서 런타임 시 메모리의 주소에 값이 할당되는 형식화된 상수가 있는 DOS용 터보 파스칼 프로그램에서는 해당 형식화된 상수를 쓸 수 있습니다.방해가 되어 프로그램이 MMU에 쓰는 것을 방해하는 하드웨어 MMU가 없습니다.마찬가지로 Pascal에는 C++에 있는 'const' 개념이 없기 때문에 유형 시스템에는 사용자를 막을 수 있는 것이 없습니다.당시 터보 파스칼과 델파이는 전역 변수를 기능으로 초기화하지 않았기 때문에 많은 사람들이 이 기능을 활용했습니다.

Windows로 이동하면 메모리 주소와 물리적 주소 사이에 계층이 있습니다.메모리 관리 유닛.이 칩은 액세스하려는 메모리 주소의 페이지 인덱스(이동 마스크)를 가져와서 이 페이지의 속성을 검색합니다. 페이지 테이블.이러한 속성에는 읽기 가능, 쓰기 가능 및 최신 x86 칩의 경우 실행 불가능 플래그가 포함됩니다.이 지원을 사용하면 Windows 로더가 실행 가능한 이미지를 메모리에 로드할 때 이러한 섹션 내의 디스크 페이지에 매핑되는 메모리 페이지에 적절한 페이지 속성을 할당하도록 .EXE 또는 .DLL의 섹션에 속성을 표시할 수 있습니다.

32비트 Windows 버전의 Delphi 컴파일러가 등장했을 때 const와 유사한 것을 만드는 것이 합리적이었습니다. 정말 const, OS에도 이 기능이 있기 때문입니다.

  1. 왜:왜냐하면 이전 버전의 Delphi에서는 항상 쓰기가 가능한 이전 버전(Delphi 1부터 초기 Pascal까지)과의 호환성을 유지하기 위해 유형화된 상수가 기본적으로 할당 가능했기 때문입니다.
    이제 기본값은 상수를 실제로 일정하게 만들기 위해 변경되었습니다.

  2. 컴파일러 스위치:{$J+} 또는 {$J-} {$WRITEABLECONST ON} 또는 {$WRITEABLECONST OFF}
    또는 컴파일러의 프로젝트 옵션에서:할당 가능한 유형의 상수를 확인하세요.

  3. 작동 방식:컴파일러가 컴파일 타임에 값을 계산할 수 있으면 코드의 모든 위치에서 const를 해당 값으로 대체합니다. 그렇지 않으면 쓰기 가능 여부를 설정할 수 있는 값을 보유하는 메모리 영역에 대한 포인터를 보유합니다.
  4. 3을 참조하세요.

Barry가 말했듯이 사람들은 const를 이용했습니다.이것이 사용된 방법 중 하나는 싱글톤 인스턴스를 추적하는 것이었습니다.클래식 싱글톤 구현을 살펴보면 다음과 같은 내용을 볼 수 있습니다.

  // 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