Welcome to RoboHELP. Click Topic (Ctrl+T) to add your first Help topic.


ダイナミックリンクライブラリ (DLL)

参照

ダイナミックリンクライブラリ (DLL) は他の DLL またはアプリケーションによって使われるコードやリソースが入った実行可能モジュール (拡張子 .DLL) です。Windows 環境では，DLL により複数のアプリケーションがコードやリソースを共有できます。

DLL に最もよく似た C++Builder の概念はユニットです。しかし，ユニット内のルーチンはリンク時に実行可能ファイルとリンクされます (スタティックリンク)。これに対し DLL のルーチンは個別のファイルにあり，実行時に利用可能になります (ダイナミックリンク)。

DLL によって複数のアプリケーションが共通に持つ 1 つのルーチンを共有できます。.DLL ファイルは実行時にアプリケーションと同じディレクトリになくてはなりません。

プログラムがメモリにロードされると，アプリケーションはプログラム内の procedure 呼び出しと function 呼び出しをプログラムが使う DLL 内のエントリポイントに動的にリンクします。

メモ:	DLL がエクスポートできるのは手続きと関数だけです。

C++Builder アプリケーションは Object Pascal で記述されていない DLL を使えます。他の言語で記述されたプログラムも Object Pascal で記述された DLL を使えます。

DLL の使い方についての詳細は次のトピックを参照してください。

DLL に格納してあるルーチンのアクセス

DLL の作成


参照

関数呼び出し

インポートユニット


DLL に格納してあるルーチンのアクセス

参照	例

DLL に格納されたルーチンにアクセスしたり呼び出すには 2 つの方法があります。

プログラム内で external 宣言を使う (静的インポートまたは暗黙のロード)

external 宣言を使って静的 DLL インポートを実行すると，DLL はプログラムの起動前にロードされる。DLL の名前は実行時に変更できない。実行時に使用可能でない DLL を指定するプログラムは実行できない

GetProcAddress と LoadLibrary の WinAPI 呼び出しを使ってプログラム内の手続きポインタを初期化する (動的インポートまたは明示的ロード)

GetProcAddress と LoadLibrary を使って DLL をインポートすると，プログラムはどの DLL ファイルをロードするかを制御できます (GetProcAddress と LoadLibrary の両方を使わなくてはなりません)。たとえば Windows のデバイスドライバはすべて同じインターフェースを持つ DLL ですが，内部ではハードウェア固有の機能を実行します。プログラムはハードウェアについて何も知らずにデバイスドライバの DLL を使えます。動的インポートでは LoadLibrary が DLL を見つけられない場合もプログラムは実行を続けることができます。

DLL は変数を持てますが，それを他のモジュールにはインポートできません。DLL 変数へのアクセスは手続きインターフェースを通じてしなくてはなりません。

DLL を使うプログラムをコンパイルするときにコンパイラは DLL を参照しないので，DLL はなくてもかまいません。

独自の DLL を作成する場合には，別にコンパイルしなくてはなりません。

ルーチンのインポート

インポートされる手続きや関数では宣言部と実行部が external 指令に置き換わります。

Object Pascal には手続きや関数をインポートするための方法が 3 つあります。

手続き名/関数名によるインポート

別名によるインポート

序数によるインポート

手続き名/関数名によるインポート

index 節 または name 節を指定せずに DLL からルーチンをインポートする場合，手続きまたは関数は名前によって明示的にインポートされます。

使われる名前は，手続きまたは関数の識別子とスペルも大文字小文字も同一のものです。

name 節を指定した場合，手続きまたは関数はその識別子とは異なる名前でインポートされます。

メモ:	external キーワードの後の DLL 名と name 節の中で指定する新しい名前は文字列リテラルでなくてもかまいません。任意の文字列式が使えます。

別名によるインポート

name 節を指定して DLL からルーチンをインポートする場合，手続きまたは関数はその識別子とは異なる名前でインポートされます。

序数によるインポート

index 節がある状態で DLL からルーチンをインポートする場合，手続きまたはルーチンは序数によってインポートされます。

序数によるインポートは DLL の名前テーブルにある名前を探す必要がないのでロード時間が短くてすみます。

index 節に指定する序数には任意の定数整数式が使えます。


参照

インポートユニット

DLL の作成


例

例 (手続き名/関数名によるルーチンのインポート)

例 (別名によるルーチンのインポート)

例 (序数によるルーチンのインポート)


例

{次の例は，testlib.dll から ImportByName 手続きをインポートします}

procedure ImportByName; external 'testlib.dll';


例

{次の例は，testlib.dll から名前 'RealName' を使って ImportByNewName 手続きをインポートします}

procedure ImportByNewName; external 'testlib.dll' name 'RealName';


例

{次の例は，testlib.dll 内の 5 番目のエントリポイントとして ImportByOrdinal 手続きをインポートします}

procedure ImportByOrdinal; external 'testlib.dll' index 5;


インポートユニット

インポートする手続きや関数の宣言はそれをインポートするプログラム内に直接配置できます。宣言は DLL 内のすべての手続きと関数の宣言が入ったインポートユニット内で，DLL とのインターフェースに必要な定数や型と一緒にグループ化されます。

インポートユニットを使うには

呼び出し元ユニットの uses 節に追加する

インポートユニットは DLL インターフェースに必須ではありませんが，複数の DLL を使うプロジェクトの管理を簡単にします。関連付けられた DLL を変更する場合，インポートユニットを変更に合わせて更新するだけですみます。

DLL を使うプログラムをコンパイルする場合，コンパイラは DLL を探さないので DLL はなくてもかまいません。しかし，プログラムの実行時には必要です。

独自の DLL を作成する場合には，別にコンパイルしなくてはなりません。


DLL の作成

参照	例

Object Pascal DLL の構造とプログラムの構造は DLL の始めがプログラムヘッダーではなくライブラリヘッダーである点を除き同じです。

ライブラリヘッダーは C++Builder に拡張子 .EXE ではなく .DLL の実行可能ファイルを作成するように指示します。実行可能ファイルに DLL のマークを付けます。

手続きや関数を DLL によってエクスポートするとき，stdcall 手続き指令を使ってコンパイルすることがよくあります。これは必須ではありませんが，stdcall 呼び出し規約を使うことで，ほかの言語で書かれたアプリケーションからその DLL を使うことが可能になります。

実際にルーチンをエクスポートするには exports 節を使います。

ライブラリは複数のユニットでできている場合がよくあります。その場合，ライブラリのソースファイルが uses 節，exports 節，ライブラリ初期化コードになっている場合がよくあります。

グローバル変数

DLL 内で宣言されるグローバル変数はその DLL に対して固有の変数です。

DLL は自分を呼び出すモジュールによって宣言される変数にアクセスできず，他のモジュールが使うための変数をエクスポートできません。このようなアクセスは手続きインターフェースを通じてしなくてはなりません。

1 つの DLL を同時に複数のアプリケーションから使うことはできますが，DLL 側から見ればクライアントは 1 つだけであり，DLL の各インスタンスごとにそれぞれ独自のグローバル変数一式が保持されます。複数の DLL (または 1 つの DLL の複数のインスタンス) がメモリを共有するためには，その DLL ではメモリマップドファイルを使用しなければなりません。詳細は Windows API のドキュメントを参照してください。


例

{次の例は 2 つのエクスポートされる関数を持つ簡単な DLL を実現します}

library MinMax;

{stdcall 手続き指令は，ほかの言語がサポートする呼び出し規約で Min と Max をエクスポートします}

function Min(X, Y: Integer): Integer; export;

  begin

    if X < Y then Min := X else Min := Y;

  end;

function Max(X, Y: Integer): Integer; export;

  begin

    if X > Y then Max := X else Max := Y;

  end;

{exports 節は 2 つのルーチンをエクスポートし, それぞれにオプションの序数を与えます}

exports

  Min index 1,

  Max index 2;

  begin

  end.


参照

DLLに格納してあるルーチンのアクセス

DLL と System ユニット

インポートユニット

ライブラリ初期化コード

DLL での例外と実行時エラー

共有メモリマネージャ

DLLProc 変数


ライブラリ初期化コード

例	DLL の作成

ライブラリの実行部はライブラリの初期化コードを構成しています。初期化コードは，ライブラリが初めてロードされたときに 1 回だけ実行されます。

通常，ライブラリの初期化コードはライブラリに入っているウィンドウプロシージャのウィンドウクラスを登録したり，ライブラリのグローバル変数に初期値を設定したりします。さらに，ExitProc 変数を使って終了手続きをインストールできます。終了手続きはオペレーティングシステムがライブラリをアンロードするときに実行されます。

ライブラリの初期化コードで ExitCode 変数をゼロ以外の値に設定することによって，エラー条件を通知できます。ExitCode は System ユニット内に宣言されており，デフォルト値は初期化の成功を示す 0 です。初期化コードで ExitCode をゼロ以外の値に設定した場合，DLL がメモリからアンロードされ，呼び出し元アプリケーションに DLLのロード失敗が通知されます。

メモ	処理できない例外がライブラリの初期化コードの実行中に発生した場合，呼び出し元アプリケーションへ DLL のロード失敗が通知されます。

DLL がアンロードされると，C++Builder はライブラリの終了手続きを実行するために，ExitProc 変数が nil になるまで ExitProc に格納されているアドレスの呼び出しを続けます。これは Object Pascal プログラム内での終了手続きの取り扱いと同じなので，プログラムとライブラリの両方で同じ終了手続き論理が使えます。

メモ	アプリケーションまたはライブラリが使うすべてのユニットの initialization 部は，常にそのアプリケーションまたはライブラリの実行部より前に実行されます。同様に，ユニットの finalization 部はアプリケーションまたはライブラリがインストールした終了手続きの後に実行されます (ユニットの finalization 部は，実際には ExitProc 変数を使って自分自身をインストールします)。


例

{初期化コードと終了手続きがあるライブラリの例を次に示します。}

library Test;

var

  SaveExit: Pointer;

procedure LibExit;

begin

  :

  { ライブラリ終了コード }

  :

  ExitProc := SaveExit;	{ 1 つ前の終了手続きへのポインタを復元します }

end;

begin

  :

  { ライブラリ初期化コード }

  :

  SaveExit := ExitProc;	{ 1 つ前の終了手続きへのポインタを保存します }

  ExitProc := @LibExit;	{ LibExit 終了手続きをインストールします }

end.


DLL と System ユニット

参照

IsLibrary 論理変数を使うと，コードがアプリケーションとライブラリのどちらのコンテキストで実行されているかを判別できます。IsLibrary はアプリケーション内では常に偽であり，ライブラリ内では常に真です。

DLL の使用中，HInstance 変数はその DLL のインスタンスハンドルを保持します。

DLL 内では CmdLine 変数は常に nil です。


参照

DLL の作成


DLL での例外と実行時エラー

参照

DLL 内で生成された例外が DLL 内で処理されない場合，その例外は DLL の外部へ伝えられます。呼び出し元アプリケーションまたは DLL が，C++Builder で作成されている場合は，通常の try...except 文で例外を処理できます。

呼び出し元アプリケーションまたは DLL が別のプログラミング言語で書かれている場合，その例外は例外コード $0EEDFACE のオペレーティングシステム例外として処理できます。オペレーティングシステム例外レコードの ExceptionInformation 配列の最初のエントリには例外アドレスが入っており，2 番目のエントリには C++Builder 例外オブジェクトへの参照が入っています。

DLL が SysUtils ユニットを使わない場合，C++Builder の例外サポートは使用不可になります。その場合，DLL 内で実行時エラーが発生すると，その DLL を呼び出したアプリケーションは終了します。DLL にはその呼び出し元が Object Pascal アプリケーションであるのか，それとも別のプログラミング言語で書かれたアプリケーションであるのかを識別する手段がないので，DLL はアプリケーションの終了前にそのアプリケーションの終了手続きを呼び出せません。アプリケーションは単に中断し，メモリから削除されます。このようなエラーが起こらないように，必ず DLL コードの中で十分なチェックをしてください。


参照

例外処理

DLL の作成


共有メモリマネージャ

DLL の作成

長い文字列をパラメータまたは関数結果として渡す手続きや関数を DLL か（直接，またはレコードやオブジェクト内にネストして）エクスポートした場合，その DLL とその DLL のクライアントアプリケーション（または DLL）はすべて ShareMem ユニットを使わなければなりません。1 つのモジュール（アプリケーションまたは DLL）が New か GetMem を使ってメモリを割り当て，そのメモリが別のモジュール内の Dispose か FreeMem の呼び出しによって割り当て解除される場合も同じです。

ShareMem は DCP3230MT.DLL 共有メモリマネージャのインターフェースユニットであり，ShareMem を使うアプリケーションかライブラリ，またはその両方と一緒にアプリケーション化されなければなりません。アプリケーションまたは DLL が ShareMem を使う場合，そのアプリケーションまたは DLL のメモリマネージャは CP3230MT.DLL 内のメモリマネージャに置き換えられ，それによって，動的に割り当てられたメモリを複数のモジュールが共有できるようになります。

アプリケーションまたはライブラリで ShareMem ユニットを使う場合は，アプリケーションまたはライブラリの uses 節で ShareMem ユニットを最初のユニットにしなければなりません。


DLLProc 変数

DLL の作成

System ユニットに定義されている DLLProc 変数を使うと，DLL はオペレーティングシステムからその DLL のエントリポイントへのすべての呼び出しを監視できます。通常，この機能はマルチスレッドをサポートする DLL だけに意味があります。

オペレーティングシステムから DLL のエントリポイントへの呼び出しを監視するには，手続きのアドレスを次のパラメータリストと一緒に DLLProc 変数へ代入します。

procedure DLLHandler(Reason: Integer);

System ユニットに定義されている DLLProc 変数を使うと，オペレーティングシステムが DLL エントリを呼び出す所を監視できます。通常，この機能はマルチスレッドをサポートする DLL だけに意味があります。

オペレーティングシステムの DLL エントリの呼び出しを監視するには，以下のパラメータリストを持つ手続きを用意し，アドレスを DLLProc に代入します。指定した手続きが呼び出されるとき，Reason パラメータには以下のいずれかの値が入ります。

DLL_PROCESS_DETACH	FreeLibrary の呼び出し，または正常なプロセスの終了によりメモリ空間から開放されることを示す
DLL_THREAD_ATTACH	現在のプロセスが新しいスレッドを作成中であることを示す
DLL_THREAD_DETACH	スレッドが正常に終了中であることを示す


堅固なアプリケーションの作成

C++Builder は堅固なアプリケーションを作成する機構を備えており，作成したアプリケーションはエラーを一貫した方法で処理するため，アプリケーションは可能ならばエラーから回復し，必要ならばシャットダウンを実行でき，データとリソースも失われません。

C++Builder のエラー条件は例外によって示されます。

例外を使って安全なアプリケーションを作成するには，次の作業を理解しておく必要があります。

コードブロックの保護

リソース割り当ての保護

実行時例外の処理

コンポーネント例外の処理

サイレント例外

ユーザー独自の例外の定義


コードブロックの保護

参照

アプリケーションを堅固にするには，発生した例外を認識し，例外に応答するコードを書く必要があります。応答を指定しないと，アプリケーションはエラーを説明したメッセージボックスを表示します。したがって必要な作業は，特にエラーによってデータやシステムリソースが失われる可能性がある領域でエラーが起きそうな場所を見極め，応答を定義することです。

例外への応答を作成するときは，コードのブロックに対して作成します。エラーに対してすべて同じ種類の応答を必要とする一連の文があるときは，それらの文を 1 つのブロックにまとめ，そのブロック全体に適用するエラー応答を定義できます。

例外に対して特定の応答をするブロックをプロテクトブロックと呼びます。それらのブロックはアプリケーションを終了するかデータを傷付ける可能性があるエラーに対して自分を保護できるからです。

コードブロックを保護するには，次のことを理解しておく必要があります。

例外への応答

例外と実行の流れ

例外応答のネスト


参照

リソース割り当ての保護

実行時例外の処理

コンポーネント例外の処理

サイレント例外

ユーザー独自の例外の定義


例外への応答

参照

エラー条件が発生するとアプリケーションは例外を生成します。つまり，例外オブジェクトを作成します。例外が生成された後，アプリケーションはクリーンアップコードを実行するか，例外を処理するか，あるいはその両方を実行します。

クリーンアップコードの実行

例外に対応する最も簡単な方法は何かのクリーンアップコードが必ず実行されるようにすることです。この種の応答ではエラーの原因となった条件は訂正できませんが，アプリケーションの環境を不安定な状態のまま残さないようにできます。

通常この種の応答は，エラーが起きたかどうかに関係なく確実にアプリケーションにリソースを解放させるために使います。

例外の処理

例外の処理とは特定の種類の例外に対して特定の応答を作成することです。この処理によってエラー条件がクリアされ，例外オブジェクトが廃棄されるため，アプリケーションは実行を続けられます。

通常は例外ハンドラを定義し，アプリケーションがエラーから回復して実行を続けられるようにします。処理できる例外の種類としては，存在しないファイルを開こうとしたこと，いっぱいになったディスクへの書き込み，有効範囲を超えた計算などがあります。これらの一部，たとえば「ファイルが見つかりません」などは訂正と再試行が容易ですが，メモリ不足などアプリケーションやユーザーが簡単に訂正できない例外もあります。


参照

例外の生成

例外応答のネスト

リソース割り当ての保護

実行時例外の処理

コンポーネント例外の処理

サイレント例外

ユーザー独自の例外の定義


例外と実行の流れ

参照	例

Object Pascal では例外が通常のコードの流れの中に入ってこないので，エラー処理を簡単にアプリケーションの中へ組み込めます。エラー検査とエラー処理をアルゴリズムのメインの流れの外へ出すことにより，書くコードも単純になる可能性があります。

プロテクトブロックを宣言するとき，そのブロック内で起きる可能性がある例外に対して特定の応答を定義します。そのブロック内で例外が起きると，定義した応答へすぐに実行が移り，そのブロックの実行は終了します。


例

プロテクトブロックが入ったコードを次に示します。このプロテクトブロック内で例外が起きると，例外処理部へ実行が移るため，警告音が鳴ります。実行はブロックの外部で再開されます。

...
try	{ プロテクトブロックを開始します }
  Font.Name := 'Courier';	{ これらの文の中で ... }

  Font.Size := 24;	{ ... 例外が発生すると ... }

  Color := clBlue;

except	{ ... ここへ実行が移ります }
  on Exception do MessageBeep(0);	{ これは警告音を鳴らすことで例外を処理します }

end;
...	{ 実行はプロテクトブロックの外部のここから再開されます}


参照

例外への応答

例外応答のネスト


例外応答のネスト

参照

ブロック内で発生した例外への応答はコードで定義します。Pascal ではブロックの中に他のブロックをネストできるため，すでに応答をカスタマイズしたブロックの中であっても応答をカスタマイズできます。

たとえば最も単純な場合，リソース割り当てを保護でき，そのプロテクトブロックの中に他のリソースを割り当てて保護するブロックを定義できます。この概念を次に示します。

ネストブロックを使って特定の例外のローカル処理を定義し，そのブロックの上位ブロックでの処理をオーバーライドすることもできます。この概念を次に示します。

各種の例外応答ブロックを混ぜて，例外処理ブロック内でリソース保護をネストしたり，その逆もできます。


参照

例外への応答

例外と実行の流れ

例外ハンドラのスコープ


リソース割り当ての保護 (try..finally ブロック)
リソース割り当ての保護

参照

堅固なアプリケーションを作成する 1 つの鍵は，アプリケーションでリソースを割り当てたら，例外が起きたときでも確実にそのリソースが解放されるようにすることです。たとえばアプリケーションでメモリを割り当てた場合は，最終的にそのメモリが確実に解放されるようにする必要があります。ファイルを開いたら，後でそのファイルを必ず閉じる必要があります。

例外は書いたコードから発生するだけではないことも忘れてはなりません。たとえばアプリケーション内で RTL ルーチンやその他のコンポーネントを呼び出すと，例外が生成される場合があります。それらの条件が発生した場合でも，割り当て済みのリソースが確実に解放されるようコーディングする必要があります。

リソースを効果的に保護するには，次のことを理解しておく必要があります。

保護が必要なリソースの種類

リソース保護ブロックの作成


参照

コードブロックの保護

実行時例外の処理

コンポーネント例外の処理

サイレント例外

ユーザー独自の例外の定義


保護が必要なリソースの種類

参照	例

通常の環境では割り当てと解放の両方のコードを組み込めば，アプリケーションが割り当てたリソースを確実に解放できます。しかし例外が発生したときは，アプリケーションに確実にリソース解放コードを実行させる必要があります。

必ず確実に解放しなくてはならない一般的なリソースを次に示します。

ファイル

メモリ

Windows リソース

オブジェクト


例

次のイベントハンドラはメモリを割り当てた後にエラーを生成するので，メモリを解放するコードを決して実行しません。

procedure TForm1.Button1Click(Sender: TComponent);

var
  APointer: Pointer;
  AnInteger, ADividend: Integer;

begin
  ADividend := 0;

  GetMem(APointer, 1024);	{ 1KB のメモリを割り当てます }

  AnInteger := 10 div ADividend;	{ これはエラーを生成します }

  FreeMem(APointer, 1024);	{ ここには決して到達しません }
end;

ほとんどのエラーはこれほどわかりやすくありませんが，このコードは重要な点を示しています。つまり，ゼロによる除算のエラーが発生すると実行はブロックの外へ移るため，FreeMem 文はメモリを決して解放できません。

FreeMem が GetMem によって割り当てられたメモリを確実に解放できるようにするには，このコードをリソース保護ブロックの中に入れる必要があります。


参照

リソース保護ブロックの作成


リソース保護ブロックの作成

参照	例

割り当て済みのリソースを例外が起きても確実に解放するには，プロテクトブロック内にリソース使用コードを，ブロックの特殊部分にリソース解放コードを埋め込みます。一般的なプロテクトリソース割り当ての概略を次に示します。

{ リソースを割り当てます }

try
  { リソースを使う文 }

finally
  { リソースを解放します }

end;

この try..finally ブロックの重要な点は，プロテクトブロック内で例外が起きた場合でもアプリケーションが必ずこのブロックの finally 部の文を実行することです。このブロックの try 部のコード (または try 部に入っているコードによって呼び出されたルーチン) が例外を生成した場合，すぐに実行がクリーンアップコードと呼ばれる finally 部へ移ります。例外が起きなければ，このクリーンアップコードは通常の順序で，つまり try 部に入っているすべての文の後に実行されます。

終了コード内の文は例外の発生に依存しません。try 部の文が例外を生成しなくても，終了コードが引き続き実行されます。

メモ:	リソース保護ブロックは例外を処理しません。終了コードは例外が発生したかどうかさえ知らされないので，例外を処理する必要があるかどうかを判断できません。リソース保護ブロック内で例外が発生すると，実行はまず終了コードに移り，次に例外が生成されたままの状態でブロックを出ます。その後，プロテクトブロックが入っているブロックは例外に応答できます。


例

次のイベントハンドラはメモリを割り当ててエラーを生成しますが，割り当てたメモリを解放します。

procedure TForm1.Button1Click(Sender: TComponent);

var
  APointer: Pointer;
  AnInteger, ADividend: Integer;

begin
  ADividend := 0;

  GetMem(APointer, 1024);	{ 1KB のメモリを割り当てます }

  try
    AnInteger := 10 div ADividend;	{ これはエラーを生成します }

  finally
    FreeMem(APointer, 1024);	{ エラーにもかかわらず実行はここから再開されます }

  end;

end;


参照

保護が必要なリソースの種類


実行時例外の処理

参照

算術関数やファイル処理手続きなど，ランタイムライブラリ (RTL) 内のルーチンを呼び出すコードを書くと，RTL はエラーを例外の形でアプリケーションへ返します。デフォルトでは RTL 例外はメッセージを生成し，そのメッセージをアプリケーションがユーザーに表示します。他の方法で RTL 例外を処理する独自の例外ハンドラも定義できます。

デフォルトでメッセージを表示しないサイレント例外もあります。

RTL 例外を効果的に処理するには，次のことを理解しておく必要があります。

実行時例外とは

例外ハンドラの作成

デフォルトの例外ハンドラの提供

例外のクラスの処理

例外の再生成


参照

コードブロックの保護

リソース割り当ての保護

コンポーネント例外の処理

サイレント例外

ユーザー独自の例外の定義


実行時例外とは

参照

ランタイムライブラリの例外は SysUtils ユニット内で定義されており，これらの例外はすべて Exception という一般例外オブジェクト型を継承しています。Exception は RTL 例外がデフォルトで表示するメッセージの文字列を提供します。

RTL が生成する例外は次の 7 種類です。

入出力例外

ヒープ例外

整数数値演算例外

浮動小数点数値演算例外

型キャスト例外

変換例外

ハードウェア例外


入出力例外

入出力例外は RTL がファイルまたは入出力デバイスへアクセスしようとしたときに起きることがあります。ほとんどの入出力例外は Windows または DOS がファイルへアクセスしたときに返したエラーコードに関連しています。

SysUtils ユニットは EInOutError という一般入出力例外を定義しており，これにはどのようなエラーが発生したのかを示す ErrorCode というオブジェクトフィールドが含まれています。例外オブジェクトインスタンス内のこのフィールドへアクセスすれば，例外の処理方法がわかります。


ヒープ例外

ヒープ例外は動的メモリの割り当てやアクセスを試みたときに起きることがあります。SysUtils ユニットは EOutOfMemory と EInvalidPointer という 2 つのヒープ例外を定義しています。次の表は特定のヒープ例外を示しており，どちらも Exception を直接継承しています。

例外	意味

EOutOfMemory	要求された操作を実行するのに十分なスペースがヒープ上になかった

EInvalidPointer	アプリケーションはヒープの外部を指すポインタを破棄しようとした。通常，これはポインタがすでに破棄されていることを意味する


整数数値演算例外

整数数値演算例外は整数型の式を演算したときに起きることがあります。SysUtils ユニットは EIntError という一般整数数値演算例外を定義しています。RTL は決して EIntError を生成しませんが，これはすべての特定整数数値演算例外が継承する基底を提供します。

次の表は特定整数数値演算例外を示しており，これらはどれも EIntError を直接継承します。

例外	意味

EDivByZero	ゼロで除算しようとした

ERangeError	式の数値が範囲外

EIntOverflow	整数数値演算がオーバーフローした


浮動小数点数値演算例外

浮動小数点数値演算例外は実数型の式を演算したときに起きることがあります。SysUtils ユニットは EMathError という一般浮動小数点数値演算例外を定義しています。RTL は決して EMathError を生成しませんが，これはすべての特定浮動小数点数値演算例外が継承する基底を提供します。

次の表は特定浮動小数点数値演算例外を示しており，これらの例外はいずれも EMathError を直接継承します。

例外	意味

EInvalidOp	プロセッサが未定義命令を検出した

EZeroDivide	ゼロによる除算を試みた

EOverflow	浮動小数点演算がオーバーフローした

EUnderflow	浮動小数点演算がアンダーフローした


型キャスト例外

型キャスト例外は as パラメータを使ってオブジェクトを別の型へ型キャストしようとしたときに起きることがあります。SysUtils ユニットは要求された型キャストが非合法のときに RTL が生成する EInvalidCast という例外を定義しています。


変換例外

変換例外は IntToStr，StrToInt，StrToFloat などの関数を使ってデータの形式を変換したときに起きることがあります。SysUtils ユニットは関数へ渡されたデータを変換できないときに RTL が生成する EConvertError という例外を定義しています。


ハードウェア例外

ハードウェア例外は 2 つの状況で起きることがあります。1 つはプロセッサが処理できない障害を検出したとき，もう 1 つは実行を中断する割り込みをアプリケーションで意図的に生成したときです。ハードウェア例外の処理コードは DLL に置くことはできず，スタンドアロンのアプリケーションにのみ含めることができます。

SysUtils ユニットは EProcessorException という一般ハードウェア例外を定義しています。RTL は決して EProcessorException を生成しませんが，これは特定ハードウェア例外が継承する基底を提供します。

次の表は特定ハードウェア例外を示しています。

例外	意味

EFault	すべての障害オブジェクトが継承する基底例外オブジェクト

EGPFault	通常は初期化されていないポインタやオブジェクトが原因で起きる一般保護例外

EStackFault	プロセッサのスタックセグメントへの非合法アクセス

EPageFault	Windows のメモリマネージャがスワップファイルを正しく使えなかった

EInvalidOpCode	プロセッサが未定義命令を検出した。通常これはプロセッサがデータメモリまたは初期化されていないメモリを実行しようとしたことを意味する

EBreakpoint	アプリケーションがブレークポイント割り込みを生成した

ESingleStep	アプリケーションがシングルステップ割り込みを生成した

一般保護例外を除けば，これらの例外を検出することはまれです。これらの例外は操作環境の重大な障害を表しているからです。ブレークポイント例外とシングルステップ例外は一般に C++Builder の統合デバッガによって処理されます。


参照

例外ハンドラの作成

デフォルトの例外ハンドラの提供

例外のクラスの処理

例外の再生成


例外ハンドラの作成 (try..except ブロック)
例外ハンドラの作成

参照	例

例外ハンドラはコードの保護ブロック内で起きた特定の例外 (複数の場合もある) を処理するコードです。

例外ハンドラを定義するには保護したいコードを例外処理ブロックの中に埋め込み，そのブロックの except 部に例外処理文を指定します。一般的な例外処理ブロックの概略を次に示します。

try
  { 保護したい文 }

except
  { 例外処理文 }

end;

アプリケーションは try 部の文の実行中に例外が起きた場合にだけ except 部の文を実行します。try 部の文の実行の中には try 部のコードによって呼び出されたルーチンも含まれます。つまり try 部のコードが 1 つのルーチンを呼び出し，そのルーチンが自身の例外ハンドラを定義していない場合，実行は例外処理ブロックへ戻り，例外処理ブロックが例外を処理します。

try 部の文で例外が生成されるとすぐに実行が except 部へ移り，現在の例外に適用されるハンドラが見つかるまで，指定された例外処理文，つまり例外ハンドラが検査されます。

アプリケーションはその例外を処理する例外ハンドラを見つけるとその文を実行し，その後，自動的に例外オブジェクトを廃棄します。実行は現在のブロックの終わりから続行されます。


参照

例外インスタンスの使い方

例外ハンドラのスコープ

デフォルトの例外ハンドラの提供

例外のクラスの処理

例外の再生成


例外処理文

参照	例

try..except ブロックの except 部に入っている文は特定の種類の例外を処理するために実行するコードを定義します。これらの例外処理文の書式は次のとおりです。

on <例外の種類> do <文>;

例外を使うと，アルゴリズムの「通常の」式を詳しく説明して，その式が適用されない例外的な場合を規定できます。例外を使わない場合は，計算の個々のステップで先へ進んでいいかどうかを毎回確認しなくてはなりません。


例

次のコードはゼロによる除算でデフォルトの結果を提供する例外ハンドラを定義しています。

function GetAverage(Sum, NumberOfItems: Integer): Integer;
begin

  try
    Result := Sum div NumberOfItems;

  except
    on EDivByZero do Result := 0;

  end;

end;

例外を利用しない同等の関数を次に示します。

このコードは関数を呼び出すたびに除数がゼロであるかどうかのチェックを行います。

function GetAverage(Sum, NumberOfItems: Integer): Integer;
begin

  if NumberOfItems <> 0 then
    Result := Sum div NumberOfItems
  else Result := 0;

end;

これら 2 つの関数の違いは例外を使ったプログラミングとそうでないプログラミングの違いをよく表しています。これは非常に単純な例ですが，もっと複雑な数百ステップの計算で何十回もの入力の 1 つが無効であったときに，どれかのステップで障害が起こることが想像できます。


参照

例外インスタンスの使い方

例外ハンドラのスコープ


例外インスタンスの使い方

参照	例

ほとんどの場合，例外ハンドラは例外に関してその種類以外の情報を必要としないので，on..do に続く文はその例外の種類だけを対象とします。しかし，場合によっては例外インスタンスの中に入っている情報の一部が必要になります。

例外ハンドラの中で例外インスタンスに関する特定の情報を読み出すには，例外インスタンスへのアクセスを可能にする on..do の特別な変形構文を使います。この特殊構文ではインスタンスを入れておく一時変数を用意する必要があります。

この一時変数 (次のコードでは E) の型はコロンの後に指定されます (次のコードでは EInvalidOperation)。必要ならば as 演算子を使って例外をより特定された種類に型キャストできます。

メモ:	一時例外オブジェクトを廃棄してはなりません。例外を処理すると，その例外オブジェクトは自動的に廃棄されます。オブジェクトを勝手に廃棄すると，アプリケーションはそのオブジェクトを再度廃棄しようとして致命的なアプリケーションエラーが生成されます。


例

フォームが 1 つだけ入った新しいプロジェクトを作成し，フォームへスクロールバーとコマンドボタンを追加して下さい。ボタンをダブルクリックし，次の行をクリックイベントハンドラへ追加してください。

ScrollBar1.Max := ScrollBar1.Min - 1;

スクロールバーの最大値は決して最小値を超えないので，この行は例外を生成します。アプリケーションのデフォルトの例外ハンドラは例外オブジェクトの中のメッセージが入ったダイアログボックスを開きます。このハンドラの中の例外処理をオーバーライドして，例外のメッセージ文字列が入った独自のメッセージボックスを作成できます。

try
  ScrollBar1.Max := ScrollBar1.Min - 1;

except
  on E: EInvalidOperation do
    MessageDlg('Ignoring exception: ' + E.Message, mtInformation, [mbOK], 0);

end;


参照

例外処理文

例外ハンドラのスコープ


例外ハンドラのスコープ

参照

すべてのブロックのすべての種類の例外についてハンドラを提供する必要はありません。特定のブロック内で特に処理したい例外についてだけハンドラを提供する必要があります。

ブロックが特定の例外を処理しなければ，例外は生成されたままの状態で実行がそのブロックを出て，そのブロックの上位ブロック（またはそのブロックを呼び出したコード）へ戻ります。このプロセスは繰り返され，そのたびにスコープの単位が広がります。


参照

例外処理文

例外インスタンスの使い方


デフォルトの例外ハンドラの提供

参照

特定のハンドラが提供されていないすべての例外を処理するため，デフォルトの例外ハンドラを 1 つ提供できます。そのためには次のように例外処理ブロックの except 部に else 部を追加します。

try
  { 文 }

except
  on ESomething do { 特定の例外処理コード };

  else { デフォルトの例外処理コード };
end;

ブロックにデフォルトの例外処理を追加すると，ブロックがすべての例外を何らかの方法で処理し，それによって上位ブロックからのすべての処理が確実にオーバーライドされます。

警告:	このようなすべてを処理できるデフォルト例外ハンドラを定義するときには注意してください。else 節はまったく正体の知れない例外も含め，すべての例外を処理します。一般的に，プログラマは実際に処理方法がわかっている例外だけを処理するコードを書くべきです。それ以外の場合でも，クリーンアップコードを実行してその例外とその処理方法について詳しい情報を持っているコードに処理を任せるのが得策です。


参照

例外ハンドラの作成

例外のクラスの処理

例外の再生成


例外のクラスの処理

参照	例

例外オブジェクトは階層の一部なので，階層のその部分が継承している例外クラスについてハンドラを提供すれば，階層の部分全体についてハンドラを指定できます。

例外をさらに特定して詳細なハンドラを指定することもできますが，それらのハンドラは一般ハンドラの上に配置する必要があります。アプリケーションはハンドラを出現順に検索し，最初に見つかった適用可能なハンドラを実行するからです。


例

次のブロックはすべての整数数値演算例外を特別に処理するコードの概略を示しています。

try
  { 整数数値演算を実行する文 }

except
  on EIntError do { 整数数値演算エラー用の特殊処理 };
end;

たとえば次のブロックは範囲エラーについては特殊な処理を，その他のすべての整数数値演算エラーについてはその他の処理を提供します。

try
  { 整数数値演算を実行する文 }

except
  on ERangeError do { 範囲外の処理 };

  on EIntError do { その他の整数数値演算エラーの処理 };
end;

EIntError 用のハンドラが ERangeError 用のハンドラの前にあると，実行が決して ERangeError 用の特殊ハンドラまで到達しないことに注意してください。


参照

例外ハンドラの作成

デフォルトの例外ハンドラの提供

例外の再生成


例外の再生成

参照	例

例外をローカルに処理するとき，上位ブロックの処理を置き換えるのでなく，拡大したい場合があります。ローカルハンドラは処理を終えると例外インスタンスを廃棄するので，上位ブロックのハンドラは機能しません。しかし，ハンドラが例外を廃棄しないようにして上位ハンドラに応答の機会を与えることができます。

例外が起きた場合，何かの種類のメッセージをユーザーに表示してから標準処理に進むのが普通です。そうするにはメッセージを表示するローカル例外ハンドラを宣言し，その後に予約語の raise を呼び出します。

{ 文 } 部のコードが例外を生成すると外側の except 部のハンドラだけが実行されます。しかし { 特殊な文 } 部のコードが例外を生成すると内側の except 部の処理が実行され，その後に外側の except 部の一般的な処理が続きます。

例外を再生成すれば，既存のハンドラを失わず（または重複させず）に特殊な場合の特殊な例外処理を簡単に提供できます。


例

次のコードは例外を再生成します。

try
  { 文 }

  try
    { 特殊な文 }

  except
    on ESomething do
    begin
      { 特殊な文のためだけの処理 }

      raise;	{ 例外を再生成します }
    end;
  end;

except
  on ESomething do ...;	{ すべての場合の処理 }
end;


参照

例外ハンドラの作成

デフォルトの例外ハンドラの提供

例外のクラスの処理


コンポーネント例外の処理

参照	例

C++Builder コンポーネントはエラー条件を示すために例外を生成します。ほとんどのコンポーネント例外は他の場合なら実行時エラーが生成されるプログラミングエラーを示しています。コンポーネント例外を処理する仕組みは実行時例外の処理と同じです。

コンポーネントでエラーが起きる一般的な原因はインデックス付きプロパティの範囲エラーです。たとえばリストボックスに 3 つの項目 (0..2) が入っていてアプリケーションから項目番号 3 にアクセスしようとすると，リストボックスは「範囲外インデックス」例外を生成します。


例

次のイベントハンドラにはユーザーにリストボックスでの無効インデックスアクセスを通知する例外ハンドラが入っています。

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.Add('a string');	{ リストボックスに文字列を追加します }

  ListBox1.Items.Add('another string');	{ 別の文字列を追加します }

  ListBox1.Items.Add('still another string');	{ 3 番目の文字列を追加します }

  try
    Caption := ListBox1.Items[3];	{ フォームのキャプションにリストボックス内の 4 番目の文字列を設定します }

  except
    on EStringListError do
      MessageDlg('List box contains fewer than four strings', mtWarning, [mbOK], 0);

  end;
end;

ボタンを 1 回クリックすると，リストボックスには 3 つの文字列しか入っていないので，4 番目の文字列 (Items[3]) は例外を生成します。もう 1 回クリックするとリストに文字列が追加されるので，例外はそれ以上起きなくなります。


参照

コードブロックの保護

リソース割り当ての保護

実行時例外の処理

ユーザー独自の例外の定義


サイレント例外

参照	例

C++Builder アプリケーションは処理のためのコードが特に書かれていない例外を処理する場合，たいていは例外オブジェクトからのメッセージ文字列が入ったメッセージボックスを表示します。デフォルトでアプリケーションにエラーメッセージを表示させない「サイレント」例外も定義できます。

サイレント例外は例外を処理するつもりはないが操作を強制終了したいという場合に役立ちます。操作の強制終了は Break 手続きや Exit 手続きを使ってブロックを中断することによく似ていますが，ネストした複数のブロックレベルを中断できます。

すべてのサイレント例外は標準例外型の EAbort を継承しています。C++Builder アプリケーションの場合，デフォルトの例外ハンドラは EAbort を継承した例外を除くすべての例外に対してエラーメッセージダイアログボックスを表示します。

サイレント例外を生成するためのショートカットがあります。手動でオブジェクトを構築するかわりに Abort 手続きを呼び出せます。Abort は自動的に EAbort 例外を生成するので，エラーメッセージが表示されずに現在の操作が中断されます。


例

次のコードは操作を強制終了する単純な例を示しています。空のリストボックスとボタンが入っているフォーム上で，次のコードをボタンの OnClick イベントにアタッチします。

procedure TForm1.Button1Click(Sender: TObject);

var
  I: Integer;

begin

  for I := 1 to 10 do	{ 10 回ループします }
  begin

    ListBox1.Items.Add(IntToStr(I));	{ リストに数値の文字表現を追加します }

    if I = 7 then Abort;	{ 7 回目の後に強制終了します }

  end;
end;


参照

コードブロックの保護

リソース割り当ての保護

実行時例外の処理

コンポーネント例外の処理

ユーザー独自の例外の定義


ユーザー独自の例外の定義

参照

ランタイムライブラリや各種のコンポーネントによって生成された例外からコードを保護できるだけでなく，同じメカニズムを独自のコードの中に使って例外条件を管理できます。

コードの中で例外を使うには，次の手順を理解する必要があります。

例外オブジェクト型の宣言

例外の生成


参照

コードブロックの保護

リソース割り当ての保護

実行時例外の処理

コンポーネント例外の処理

サイレント例外


例外オブジェクト型の宣言

参照	例

例外はオブジェクトなので，新しい種類の例外を定義することは新しいオブジェクト型を宣言するのと同じくらい簡単です。どのようなオブジェクトインスタンスでも例外として生成できますが，標準例外ハンドラは Exception を継承した例外だけを処理します。

したがって，新しい例外型は Exception またはその他の標準例外から派生させるのが得策です。そうすれば新しい例外をその例外用の特定の例外ハンドラによって保護されていないコードブロックの中で生成した場合でも，標準ハンドラの 1 つがかわりにその例外を処理します。


例

たとえば次の宣言を考えてみます。

type
  EMyException = class(Exception);

EMyException を生成し，EMyException 用の特定のハンドラを提供しなかった場合，Exception (またはデフォルトの例外ハンドラ) がそれを処理します。Exception 用の標準の処理は生成された例外の名前を表示することなので，少なくとも自分が作成した新しい例外が生成されたことがわかります。


参照

例外の生成


例外の生成

例	参照

アプリケーションの中でエラー条件を示すため，例外を生成し，それに同じ例外型のインスタンスを構築させて予約語 raise を呼び出させることができます。

例外を生成するには，予約語 raise をその後に例外オブジェクトのインスタンスを付けて呼び出します。

例外を実際に処理した例外ハンドラは最後に例外インスタンスを廃棄するので，廃棄のためのコードを書く必要はありません。

例外アドレスの設定

例外が生成されると，アプリケーションが例外を生成したアドレスが System ユニット内の ErrorAddr 変数に格納されます。例外ハンドラの中で ErrorAddr を参照すれば，ユーザーにエラーの発生場所を通知したりできます。例外を生成するときに ErrorAddr の値を指定することもできます。

例外のエラーアドレスを指定するには，例外インスタンスの後に予約語 at とそれに続けて識別子などのアドレス式を追加します。


例

たとえば次の宣言があるとします。

type
  EPasswordInvalid = class(Exception);

次のように raise に EPasswordInvalid のインスタンスを付けて呼び出せば「パスワード無効」例外を生成できます。

if Password <> CorrectPassword then
  raise EPasswordInvalid.Create('Incorrect password entered');


参照

例外オブジェクト型の宣言

例外の再生成


スコープ

参照	例	言語定義

プログラムまたはユニット内の識別子のスコープは，その識別子がプログラムまたはユニット内の他の手続きまたは関数で使えるかどうかを定義します。

スコープはローカルかグローバルのどちらかです。ローカル識別子はその識別子を宣言したブロックに含まれるルーチンと宣言に対してだけ可視になります。

グローバル識別子はユニットのインターフェースセクション内で宣言され，そのユニット内のすべてのルーチンと宣言に対して可視になります。

プログラムの構造設計では，スコープに関する次の 3 つの規則に従ってください。

各識別子はその識別子が宣言されたブロック内で，宣言された位置以降でだけ意味を持つ

ブロック内でグローバル識別子を再定義する場合，宣言位置からブロックの終わりまでの間，最も内側の (最もネストが深い) 定義が優先される

手続きを再帰的に呼び出す場合，グローバル変数への参照ではその変数が定義された手続きを一番最後に呼び出したときの変数インスタンスが常に参照される

スコープにはいくつかの種類があります。

ブロックのスコープ

コンポーネントのスコープ

コンポーネントの可視性

ユニットのスコープ

インターフェース識別子と標準識別子のスコープ


参照

グローバル変数とローカル変数

スコープの規則


コンポーネントのスコープ

参照	スコープ

クラス型で宣言されたコンポーネント識別子のスコープは，宣言の位置からクラス型定義の終わりまでにわたり，さらにクラス型のすべての下位クラスとクラス型のすべてのメソッド宣言のブロックに及びます。また，コンポーネント識別子のスコープにはフィールド，メソッド，プロパティの指定子に加えて，そのクラス型の変数を操作する with 文が含まれます。

クラス型で宣言されたコンポーネント識別子はクラス型のメソッド宣言のブロックで再宣言できます。その場合，Self パラメータを使って識別子が再宣言されたコンポーネントにアクセスできます。

上位のクラス型で宣言されたコンポーネント識別子はそのクラス型の下位クラスで再宣言できます。このような再宣言では継承コンポーネントを効果的に隠しますが，キーワード inherited を使って継承コンポーネントをスコープ内に戻すこともできます。


参照

ブロックのスコープ

スコープの規則

インターフェース識別子と標準識別子のスコープ

ユニットのスコープ


ブロックのスコープ

参照	例	スコープ

ブロック内では，識別子またはラベルのスコープは宣言の位置から現在のブロックの終わりまでになり，すべてのネストブロックが含まれます。

ネストしたブロック内で識別子をオーバーライドした場合，新しい識別子のスコープはネストブロック内だけに限られ外へは広がりません。

型識別子のスコープは型宣言がされたブロック内でのローカルなものになります。ポインタ型を除いて，宣言にはそれ自身は含まれません。


例

program Outer;	{ 外部スコープの始まり }

type

  I = Integer;	{ I を整数型として定義します }

var

  T: I;	{ T を整数変数として定義します }

procedure Inner;	{ 内部スコープの始まり }

type

  T = I;	{T を整数型として再定義します }

var

  I: T;	{ I を整数変数として再定義します }

begin

  I := 1;

end;	{ 内部スコープの終わり }

begin

  T := 1;

end.	{ 外部スコープの終わり }


参照

ユニットのスコープ

スコープの規則


レコードのスコープ

参照	スコープ

レコード型定義で宣言されるフィールド識別子のスコープは，宣言の位置からレコード型定義の終わりにまで及びます。

フィールド識別子のスコープにはフィールド指定子とそのレコードの変数参照を操作する with 文が含まれます。


参照

レコード型

スコープの規則


ユニットのスコープ

参照	スコープ

ユニットのインターフェース部で宣言される識別子は，その識別子を含むユニットを uses 節で指定する他のプログラムまたはユニットで使用できます。

uses 節で複数のユニットが指定される場合，次の規則が適用されます。

各ユニットのスコープにはそれに続くすべてのユニットと，uses 節を含むプログラム (またはユニット) が含まれる

最初のユニットが最も外側のスコープを定義し，最後のユニットが最も内側のスコープを定義する。したがって，識別子が複数のユニットで宣言される場合，識別子への限定のない参照では最後のユニットによって宣言されたインスタンスが選択される。別のユニットで宣言されたインスタンスを指定するには，限定識別子を使う

メモ:	System ユニットのスコープはグローバルであるため，すべてのプログラムが Object Pascal 標準識別子にアクセスできます。System ユニットは uses 節で指定する必要はありません。


参照

限定子

スコープの規則


例

program scope2;

var

  A: integer;	{グローバル変数}

procedure SetA;

var

  A :  integer;	{ローカル変数 A を作成します}

begin

  A := 4

end;	{ローカル変数 A を廃棄します}

begin

  A := 3;	{グローバル変数 A に値を代入します}

  SetA;	{手続き SetA を呼び出します}

    Writeln(A)	{ A の値は 4 ではなく 3 になります}

end.


スコープの規則

参照	スコープ

宣言に識別子またはラベルが含まれる場合，識別子またはラベルが定義され，その識別子やラベルが再び使われる場合には，この宣言のスコープ内でなくてはなりません。

識別子またはラベルのスコープは宣言位置から現在のブロックの終わりまでになり，現在のブロックが包含しているすべてのブロックが含まれます。

スコープはオブジェクト型のすべての下位オブジェクトにも広がり，そのオブジェクト型への変数参照を操作するフィールド指定子と with 文も含まれます。

次の 3 つの規則は例外です。

1.	包含されたブロック内での再宣言

Exterior ブロックが別のブロック Interior を包含すると想定します。Exterior と Interior が同じ名前の識別子 (たとえば J) を持つ場合，Interior は自分が宣言した J にだけアクセスでき，Exterior も 自分が宣言した J にだけアクセスできます。

2.	ブロック内の宣言の位置

識別子とラベルは宣言されるまでは使えません。

識別子とラベルは，プログラムテキスト内でその識別子またはラベルが使われる前に宣言しなくてはなりません。ただし，識別子やラベルが未宣言のポインタ型の基本型である場合を除きます。その場合も結局はポインタ型を指定するのと同じ型宣言部で識別子を宣言しなくてはなりません。

3.	ブロック内での再宣言

識別子またはラベルは，ブロックの外部レベルで 1 回だけ宣言できます。ただし包含されているブロック内で宣言する場合や，レコードのフィールドリストで指定されている場合を除きます。

レコードフィールド識別子はレコード型内で宣言され，そのレコード型の変数への参照と組み合わせた場合にだけ意味を持ちます。

フィールド識別子は同じブロック内で (同じ綴りで) 再宣言できますが，同じレコード型内の同じレベルでは宣言できません。

ただし，すでに宣言された識別子は同じブロック内でフィールド識別子として再宣言できます。


参照

ブロックのスコープ

インターフェース識別子と標準識別子のスコープ

コンポーネントのスコープ

レコードのスコープ

ユニットのスコープ


インターフェースと標準識別子のスコープ

参照	スコープ

uses 節を持つプログラムまたはユニットはその uses 節で指定されたユニットのインターフェース部に属する識別子にアクセスできます。

uses 節の各ユニットは使われる残りのユニットと uses 節を含むプログラムまたはユニットを包含する新しいスコープを有効にします。

uses 節の最初のユニットは最も外側のスコープを表し，最後のユニットは最も内側のスコープを表します。

複数のユニットが同じ識別子を宣言する場合，識別子への限定のない参照では uses 節の最後のユニットによって宣言されたインスタンスが選択されます。


参照

ブロックのスコープ

コンポーネントのスコープ

スコープの規則

ユニットのスコープ

Uses 節


コンパイラ指令: 定義と用途

参照	コンパイラ指令

コンパイラ指令を使うとコンパイラのデフォルトの動作をカスタマイズできます。コンパイラ指令は特別な構文を持つコメントで，コメントを記述できる場所ならどこでも使えます。コンパイラ指令のスコープはローカルにもグローバルにもできますが，すべての指令が両方のコンテキストで使えるわけではありません。

ローカルな指令はプログラムユニット内のどこにでも指定できる。これらの指令はコンパイル処理の一部にだけ作用する

グローバルな指令はコンパイルするプログラムまたはユニットの宣言部の前で指定しなくてはならない。これらの指令はコンパイル処理全体に作用する

コンパイラ指令は 3 つのカテゴリに分類されます。

スイッチ指令

スイッチ指令はコンパイラの機能をオンまたはオフにします。

1 文字の指令は，指令の文字の直後に + または - を指定します。

長い名前の指令の場合は，指令名の後に on または off を指定します。

複数のスイッチ指令をグループ化し，カンマで区切って (スペースを含めずに) 指定できます。次に例を示します。

{$F+,R+,D-}

パラメータ指令

パラメータ指令はファイル名，テキスト，メモリ仕様などの情報をコンパイラに渡します。指令名とパラメータとの間には 1 つ以上の空白スペースが必要です。次に例を示します。

{$I TYPES.INC}

{$L YOUR.DOC}

条件指令と条件シンボル

条件指令はソーステキストの各部分のコンパイルを，指令に続いて指定されるシンボルの評価に基づいて制御します。自分で独自のシンボルを定義したり Object Pascal の定義済みシンボルを使えます。条件指令はコード内で指定しなくてはなりません。


参照

条件指令と条件シンボル

条件指令の使い方


定義済みシンボル定義済みの条件シンボルは CONSOLE，WIN32，CPU386，VER90 です。


コンパイラ指令のアルファベット順一覧

参照

ここでは C++Builder がサポートしているすべてのコンパイラ指令をアルファベット順に一覧表示してあります。リストから各指令の詳細表示にジャンプできます。

指令	型	説明

$A	スイッチ	データアラインメント

$ALIGN	スイッチ	データアラインメント

$APPTYPE	パラメータ	アプリケーションの種類

$B	スイッチ	論理評価

$BOOLEVAL	スイッチ	論理評価

$D	スイッチ	デバッグ情報

$DEBUGINFO	スイッチ	デバッグ情報

$D Text	パラメータ	説明

$DESCRIPTION Text	パラメータ	説明

$EXTENDSYNTAX	スイッチ	拡張構文

$H	スイッチ	長い文字列

$HINTS	スイッチ	コンパイラヒント

$I	スイッチ	入出力チェック

$I FileName	パラメータ	ファイルのインクルード

$IMAGEBASE	パラメータ	コードイメージベースアドレス

$IOCHECK	スイッチ	入出力チェック

$J	スイッチ	書き込み可能な型付き定数

$L	スイッチ	ローカルシンボル情報

$L FileName	パラメータ	リンクオブジェクトファイル

$LINK FileName	パラメータ	リンクオブジェクトファイル

$LOCALSYMBOLS	スイッチ	ローカルシンボル情報

$LONGSTRINGS	スイッチ	長い文字列

$M	スイッチ	実行時型情報

$M StackSize	パラメータ	最大スタックサイズ

$MAXSTACKSIZE StackSize	パラメータ	最大スタックサイズ

$MINENUMSIZE	スイッチ/パラメータ	列挙型サイズ

$MINSTACKSIZE StackSize	パラメータ	最小スタックサイズ

$O	スイッチ	最適化

$OPENSTRINGS	スイッチ	オープン文字列パラメータ

$OPTIMIZATION	スイッチ	最適化

$OVERFLOWCHECKS	スイッチ	数値演算オーバーフローチェック

$P	スイッチ	オープン文字列パラメータ

$Q	スイッチ	数値演算オーバーフローチェック

$R	スイッチ	範囲チェック

$R FileName	パラメータ	リソースファイル

$RANGECHECKS	スイッチ	範囲チェック

$REFERENCEINFO	スイッチ	シンボル参照情報

$RESOURCE FileName	パラメータ	リソースファイル

$SAVEDIVIDE	スイッチ	Pentium の安全な FDIV 演算

$STACKFRAMES	スイッチ	Windows スタックフレーム

$T	スイッチ	型付き @ 演算子

$TYPEDADDRESS	スイッチ	型付き @ 演算子

$TYPEINFO	スイッチ	実行時型情報

$U	スイッチ	Pentium の安全な FDIV 演算

$V	スイッチ	変数文字列チェック

$VARSTRINGCHECKS	スイッチ	変数文字列チェック

$W	スイッチ	Windows スタックフレーム

$WARNINGS	スイッチ	コンパイラ警告

$WRITABLECONST	スイッチ	書き込み可能な型付き定数

$X	スイッチ	拡張構文

$Y	スイッチ	シンボル参照情報

$Z	スイッチ	ワードサイズ列挙型


参照

条件指令と条件シンボル

コンパイラ指令の定義と用途

条件指令の使い方


条件指令と条件シンボル

参照

条件指令はソーステキストの各部分のコンパイルを，指令の後に続くシンボルの評価に基づいて制御します。自分で独自のシンボルを定義したり Object Pascal の定義済みシンボルを使えます。

条件指令	意味

$DEFINE	条件シンボルを定義する

$ELSE	ソーステキストの一部をコンパイルまたは無視する

$ENDIF	条件セクションを終了する

$IFDEF	Name が定義されていればソーステキストをコンパイルする

$IFNDEF	Name が定義されていなければソーステキストをコンパイルする

$IFOPT	コンパイラスイッチの状態が指定された状態 (+ または -) であればソーステキストをコンパイルする

$UNDEF	前に定義した条件シンボルの定義を取り消す

条件シンボル	意味

CONSOLE	アプリケーションはコンソールアプリケーションとしてコンパイルされる

CPU386	CPU はインテルの 80386 またはそれ以上である

WIN32	動作環境は Win32 API である

VER90	指定されたバージョンに基づいてコンパイルする。たとえば，先頭に {$IFDEF VER90} が指定されたコードはコンパイラのバージョンが 9.0 の場合にだけコンパイルされる


参照

コンパイラ指令のアルファベット順一覧

コンパイラ指令の定義と用途

条件指令の使い方


条件指令の使い方

参照	コンパイラ指令

条件指令は条件シンボルの状態に基づいて，同じソーステキストから異なるコードを生成します。Object Pascal の識別子は条件指令では使えません。

メモ:	条件の定義を変更した場合，一般にその後でプログラムを再構築する必要があります。

条件構文には次の 2 つがあります。

{$IFxxx} ... {$ENDIF}

{$IFxxx} ... {$ELSE} ... {$ENDIF}

$IF ... $ENDIF

$IFxxx ... $ENDIF 構文は $IFxxx で指定した条件が True と評価された場合にだけ $IFxxx と $ENDIF の間のソースコードをコンパイルします。

条件が False の場合，2 つの指令の間のソーステキストは無視されます。

$IF ... $ELSE ... $ENDIF

$IFxxx ... $ELSE ... $ENDIF 構文内のソースコードは次の条件が該当するときコンパイルされます。

$IFxxx が True の場合 $IFxxx と $ELSE の間のソーステキストがコンパイルされる

$IFxxx が False の場合 $ELSE と $ENDIF の間のソーステキストがコンパイルされる

条件構文は 16 レベルまでネストすることができます。

$IFxxx にはそれぞれ対応する $ENDIF がなくてはなりません。

$IFDEF

Name が定義されている場合に，後に続くソーステキストをコンパイルします。

構文

{$IFDEF Name}

ソーステキストの $IFDEF (または $IFNDEF) と $ENDIF で区切られた部分内で，$IFDEF (または $IFNDEF) 条件が False の場合，$ELSE の後に続くソースコードをコンパイルします。

$IFDEF (または $IFNDEF) 条件が True の場合，$ELSE に続くソースコードは無視されます。

$IFNDEF

Name が定義されていない場合に，後に続くソーステキストをコンパイルします。

構文

{$IFNDEF Name}

$IFOPT

スイッチが現在指定された状態になっている場合に，後に続くソーステキストをコンパイルします。

構文

{$IFOPT Switch}

Switch はスイッチオプションの名前で，後ろに + または - を指定します。

Switch+	Switch はオンです。

Switch-	Switch はオフです。


参照

$DEFINE と $UNDEF の条件シンボル指令


$DEFINE と $UNDEF の条件シンボル指令

参照	コンパイラ指令

$DEFINE と $UNDEF はコンパイラがコンパイルを実行する前に評価する条件シンボルを定義するために使います。条件シンボルは True か False であるという点で論理変数と似ています。条件シンボルは Object Pascal の識別子命名規則に従いますが，Object Pascal の識別子が条件指令で使えないように，実際のプログラムでは使えません。

$DEFINE

指定された Name を使って条件シンボルを定義します (シンボルを True として設定します)。スコープは現在のソースファイル内に限られ，すべてのソースファイルにグローバルには適用されません。すべてのモジュールにわたって定義するには，コマンドラインオプションの /D を使うか，［プロジェクト(P)｜オプション(O)］で表示される［プロジェクトオプション］ダイアログボックスの［ディレクトリ/条件］ページで［条件定義(C)］テキストボックスに入力してください。

構文

{$DEFINE Name}

プログラム内で，コンパイラはシンボルが $UNDEF Name 指令で指定されるまで，定義されたシンボルを認識します。Name がすでに定義されている場合 $DEFINE Name は無効です。

$UNDEF

定義済みの Name の条件シンボルを取り消します (False として設定します)。

構文

{$UNDEF Name}

取り消されたシンボルは $DEFINE 指令で再び指定されるまでは，以降のコンパイル処理には存在しません。Name の定義がすでに取り消されている場合，$UNDEF Name 指令は無効です。


参照

識別子

条件指令の使い方


定義済み条件シンボル

参照	コンパイラ指令

C++Builder は次の条件シンボルを定義します。

CONSOLE

アプリケーションがコンソールアプリケーションとしてコンパイルされる場合に定義されます。

CPU386

CPU がインテルの 386 またはそれ以上であることを示します。

VER90

常に定義され，このコンパイラが Object Pascal コンパイラのバージョン 9.0 であることを示します。各バージョンごとに同様の定義済みシンボルが定義されることになり，バージョン 9.1 では VER91，バージョン 9.5 では VER95 などのようになります。

WIN32

動作環境が Win32 API であることを示します。


参照

条件指令の使い方


フィールドアラインメント指令 {$A}，{$ALIGN}

コンパイラ指令

レコード型のフィールドのアラインメントを制御します。

構文:	{$A+} または {$A-}

{$ALIGN ON} または {$ALIGN OFF}

デフォルト:	{$A+}

{$ALIGN ON}

スコープ:	ローカル

注意

$A 指令の状態とは関係なく，変数と型付き定数は常に最適なアクセスが可能になるようにアラインメントされます。

オン {$A+}，{$ALIGN ON}

フィールドアラインメントがオンの場合，packed 限定子が指定されていないレコード型のフィールドは機械語ワード境界 (偶数アドレス) に配置されます。必要に応じて，ワードアラインメントのために未使用のバイトが変数の間に挿入されます。

この指令はバイトサイズの変数，レコード構造またはオブジェクトのフィールド，配列の要素には作用しません。レコードまたはオブジェクトのフィールドは，そのフィールドの前のすべてのフィールドの合計サイズが偶数の場合にだけ，ワード境界に配置されます。配列のすべての要素がワード境界に配置されるのは，各要素のサイズが偶数の場合です。

オフ {$A-}，{$ALIGN OFF}

フィールドアラインメントがオフの場合，アラインメント処理は実行されません。


アプリケーションの種類指令 {$APPTYPE}
アプリケーションの種類

コンパイラ指令

$APPTYPE 指令はコンソールとグラフィカルユーザーインターフェースのどちらのアプリケーションを生成するかを制御します。

構文:	{$APPTYPE GUI}
{$APPTYPE CONSOLE}

デフォルト:	{$APPTYPE GUI}

スコープ:	グローバル

グラフィカルユーザーインターフェース {$APPTYPE GUI}

{$APPTYPE GUI} 状態では，コンパイラはグラフィカルユーザーインターフェースアプリケーションを生成します。C++Builder アプリケーションの場合は，これが通常の状態です。

コンソール {$APPTYPE CONSOLE}

{$APPTYPE CONSOLE} 状態では，コンパイラはコンソールアプリケーションを生成します。コンソールアプリケーションを起動すると，Windows がテキストモードのコンソールウィンドウを作成し，ユーザーはそのウィンドウを通してアプリケーションと対話できます。

コンソールアプリケーションでは，標準テキストファイルの Input と Output が自動的にコンソールウィンドウへ関連付けられます。

説明

System ユニット内で宣言した IsConsole 論理変数を使うと，プログラムがコンソールアプリケーションとグラフィカルユーザーインターフェースアプリケーションのどちらとして実行中なのかを検出できます。

メモ	$APPTYPE 指令はプログラムの中でだけ意味があります。ライブラリやユニットの中では使わないでください。


完全論理評価指令 {$B}，{$BOOLEVAL}

参照	コンパイラ指令

AND と OR の論理演算子について 2 つの異なるコード生成モデルの間で切り替えをします。

構文:	{$B+} または {$B-}

{$BOOLEVAL ON} または {$BOOLEVAL OFF}

デフォルト:	{$B-}

{$BOOLEVAL OFF}

スコープ:	ローカル

オン {$B+}，{$BOOLEVAL ON}

この指令がオンの場合，コンパイラは AND 演算子と OR 演算子から構築された論理式のすべてのオペランドを評価するコードを生成します。このコードでは式全体の結果がすでに明確な場合でもすべてのオペランドが評価されます。

オフ {$B-}，{$BOOLEVAL OFF}

この指令がオフの場合，コンパイラはショートサーキット論理式評価をするコードを生成します。

式全体の結果が明らかになるとすぐに評価は停止します。


参照

論理演算子


デバッグ情報指令 {$D}，{$DEBUGINFO}

参照	コンパイラ指令

デバッグ情報の生成をオンまたはオフにします。

構文:	{$D+} または {$D-}

{$DEBUGINFO ON} または {$DEBUGINFO OFF}

デフォルト:	{$D+}

{$DEBUGINFO ON}

スコープ:	グローバル

注意

デバッグ情報は各手続きごとにオブジェクトコードアドレスをソーステキスト番号にマップする行番号テーブルで構成されます。

デバッグ情報を生成するとユニットファイルのサイズが増加し，ユニットを使うプログラムをコンパイルするときに領域が余分に必要になりますが，実行プログラムのサイズや速度には影響しません。デバッグ情報はユニットのオブジェクトコードとともに .DCU (ユニット) ファイルに記録されます。

オン {$D+}，{$DEBUGINFO ON}

この指令がオンの場合，コンパイラはデバッグ情報をユニット (.DCU) ファイルに記録します。

デバッグ情報指令をオンにしてコンパイルしたモジュールは，スタンドアロンのデバッガや統合デバッガを使ってシングルステップ実行したり，ブレークポイントを設定したりできます。実行時エラーが発生した場合，コンパイラはエラーの原因になった文に自動的に移動できます。

［プロジェクト(P)｜オプション(O)］で表示される［プロジェクトオプション］ダイアログボックスの［リンカ］ページにある［マップファイル］のラジオボタンは，デバック情報指令をオンにしてモジュールをコンパイルした場合にだけ，そのモジュールについての完全な行情報を生成します。

デバッグ情報指令は通常ローカルシンボル指令とともに使います。

Turbo Debugger for Windows を使ってプログラムをデバッグする場合は，［プロジェクトオプション］ダイアログボックスの［リンカ］ページで［TDW デバッグ情報を含める(T)］チェックボックスにチェックマークを付けてからプログラムを再コンパイルしてください。


参照

デバッグ情報とシンボル情報


シンボル情報スイッチ指令を使ったデバッグ

参照	コンパイラ指令

$D，$L，$Y コンパイラ指令は一緒に組み合わせて使います。$L と $Y は $D のサブセットと考えることができ，$D のスコープが最も外側で，$L のスコープがその次，$Y のスコープが最も内側となります。次の表はこれらの指令を組み合わせて使った場合に相互にどのように修飾しあうかを示します。

シンボル	結果

{$D+, L-, Y+}	インターフェースセクションのすべてのコードのデバッグ情報を生成する。実現部のシンボルについての情報は生成しない ($Y は無視される)

{$D+, L-, Y-}	インターフェースセクションのすべてのコードのデバッグ情報を生成する。実現部のシンボルについての情報は生成しない ($Y は無視される)

{$D-, L+, Y+}	デバッグ情報をまったく生成しない ($L，$Y は無視される)

{$D+, L+, Y-}	シンボル参照や他のオブジェクトブラウザ情報は生成しない。この設定を使うとリンク時間が短くなる

{$D+, L+, Y+}	モジュール内のすべてのシンボルのデバッグ情報を生成する。ローカル変数と型の行番号とシンボル情報を生成する。シンボルのクロスリファレンスと他のブラウザ情報を生成する


参照

$D デバッグ情報

$L ローカルシンボル情報

$Y シンボル参照情報


入出力チェック指令 {$I}，{$IOCHECKS}

参照	コンパイラ指令

ファイル入出力手続きへの呼び出しの結果をチェックするコードの自動生成をオンまたはオフにします。ファイル入出力手続きには Read，Write，Erase などがあります。

構文:	{$I+} または {$I-}

{$IOCHECKS ON} または {$IOCHECKS OFF}

デフォルト:	{$I+}

{$IOCHECKS ON}

スコープ:	ローカル

オン {$I+}，{$IOCHECKS ON}

この指令がオンの場合，コンパイラは各入出力呼び出しの後に入出力エラーをチェックするコードを生成します。チェックが失敗した場合，アプリケーションは実行時エラーによって停止します。

オフ {$I-}，{$IOCHECKS OFF}

この指令がオフの場合，IOResult 関数を使って入出力エラーをチェックしなくてはなりません。


参照

$I ファイルインクルード

例外処理


書き込み可能な型付き定数指令 {$J} と {$WRITEABLECONST}

コンパイラ指令

$J 指令は型付き定数を変更できるかどうかを制御します。

構文:	{$J+} または {$J�}
{$WRITEABLECONST ON} または {$WRITEABLECONST OFF}

デフォルト:	{$J�}
{$WRITEABLECONST OFF}

スコープ:	ローカル

オン {$J+}，{$WRITEABLECONST ON}

{$J+} 状態では型付き定数は変更でき，実質的には初期化済み変数になります。

オフ {$J-}，{$WRITEABLECONST OFF}

{$J-} 状態では型付き定数は正規の定数であり，型付き定数を変更しようとするとコンパイルエラーになります。


ローカルシンボル情報指令 {$L}，{$LOCALSYMBOLS}

参照	コンパイラ指令

ローカルシンボル情報の生成をオンまたはオフにします。

構文:	{$L+} または {$L-}

{$LOCALSYMBOLS ON} または {$LOCALSYMBOLS OFF}

デフォルト:	{$L+}

{$LOCALSYMBOLS ON}

スコープ:	グローバル

注意

ローカルシンボル情報には，モジュールの手続きと関数の内部にある識別子が含まれます。ローカルシンボル情報にはユニットのインターフェースセクションで宣言されたグローバルな変数や名前は含まれません。

ローカルシンボル情報指令はデバッグ情報指令がオフの場合は無視されます。

オン {$L+}，{$LOCALSYMBOLS ON}

プログラムまたはユニットに対してこの指令がオンの場合，スタンドアロンのデバッガまたは統合デバッガを使ってそのモジュールのローカル変数を調査して変更できます。

［プロジェクト(P)｜オプション(O)］で表示される［プロジェクトオプション］ダイアログボックスの［リンカ］ページで［マップファイル］オプションを選択したとき，モジュールを $L+ の状態でコンパイルした場合にだけそのモジュールのローカルシンボル情報が生成されます。

ローカルシンボル情報はユニットのオブジェクトコードとともにユニットファイルに記録されます。ローカルシンボル情報を生成するとユニットファイルのサイズが大きくなります。実行プログラムのサイズや速度には影響しません。

オフ {$L-}，{$LOCALSYMBOLS OFF}

この指令がオフの場合，プログラムのコンパイルに必要なメモリが減少し，ユニットファイルが小さくなり，デバッガシンボル情報のボリュームが小さくなります。


参照

デバッグ情報とシンボル情報


オープンパラメータ指令 {$P}，{$OPENSTRINGS}

参照	例	コンパイラ指令

string キーワードを使って宣言された変数パラメータの意味を制御します。オープンパラメータは各種のサイズの文字列変数を同じ手続きや関数に渡せるようにします。

構文:	{$P+} または {$P-}

{$OPENSTRINGS ON} または {$OPENSTRINGS OFF}

デフォルト:	{$P-}

{$OPENSTRINGS OFF}

スコープ:	グローバル

オン {$P+}，{$OPENSTRINGS ON}

この指令がオンの場合，string キーワードを使って宣言した変数パラメータはオープン文字列パラメータになります。この指令の設定に関係なく，OpenString 識別子を使っていつでもオープン文字列パラメータを宣言できます。

オープン文字列パラメータの実パラメータには任意の文字列型の変数を指定できます。手続きまたは関数内で，仮パラメータのサイズ属性 (最大長) は実パラメータと同じになります。

オープン文字列パラメータは文字列型の変数パラメータとまったく同じように動作します。ただし，通常の変数パラメータのように他の手続きや関数に渡すことはできません。

オフ {$P-}，{$OPENSTRINGS OFF}

この指令がオフの場合，オープンパラメータは使用不可になります。この状態では，string キーワードを使って宣言された変数パラメータは通常の変数パラメータになります。これにより Turbo Pascal の以前のバージョンとの互換性が保たれます。


例

procedure MyProc(var S:string);

begin

  S:= 'abcdefghijk';

end;

var

   shortstring: string[5];

begin

  MyProc(ShortString);

end.

コンパイラスイッチ	結果

$P-, V+	MyProc (ShortString) は型不一致のコンパイルエラーを生成する

$P+, V-	MyProc (ShortString) は許可され，生成されるコードは S への割り当てが実パラメータで宣言されたサイズを超えないことを保証する。MyProc への呼び出しの後，ShortString は 'abcde' になる

$P-, V-	MyProc はコンパイルエラーを生成しないが，プログラム内でメモリ上書きエラーになり，システムがクラッシュする可能性がある


参照

$V 変数文字列チェック


オーバーフローチェック指令 {$Q}，{$OVERFLOWCHECKS}

参照	コンパイラ指令

算術演算オーバーフローチェックコードの生成を制御します。

構文:	{$Q+} または {$Q-}

{$OVERFLOWCHECKS ON} または {$OVERFLOWCHECKS OFF}

デフォルト:	{$Q-}

{$OVERFLOWCHECKS OFF}

スコープ:	ローカル

注意

算術演算オーバーフローは，計算結果が計算型のサイズを超えた場合に発生します。情報が失われることもあります。

オン {$Q+}，{$OVERFLOWCHECKS ON}

この指令がオンの場合，コンパイラは次の整数演算について算術演算オーバーフローをチェックするコードを生成します。

\	+	-	*	Abs	Sqr	Succ	Pred 	Inc	Dec

これらの算術演算のコードの後に，演算結果がサポート範囲内であることを確認するコードが追加されます。

オーバーフローチェックが失敗した場合，プログラムは実行時エラーにより停止します。

オーバーフローチェックをすると，プログラムの速度が低下しサイズも大きくなります。この指令はプログラム開発とデバッグの間に使い，最終的な製品を構築するときにはオフにしてください。

$Q 指令は通常 $R 指令 directiveと一緒に使います。

オフ {$Q-}，{$OVERFLOWCHECKS OFF}

この指令がオフの場合，算術演算オーバーフローはチェックされません。


参照

例外処理


範囲チェック指令 {$R}，{$RANGECHECKS}

参照	コンパイラ指令

範囲チェックコードの生成をオンまたはオフにします。

構文:	{$R+} または {$R-}

{$RANGECHECKS ON} または {$RANGECHECKS OFF}

デフォルト:	{$R-}

{$RANGECHECKS OFF}

スコープ:	ローカル

オン {$R+}，{$RANGECHECKS ON}

この指令がオンの場合，コンパイラは配列や文字列の添え字が範囲内であるかどうかと，スカラー型変数への割り当てが定義範囲を超えていないかをチェックするコードを生成します。範囲チェックは Inc と Dec には適用されません。

チェックが失敗した場合，プログラムは実行時エラーによって停止します。

範囲チェックをすると，プログラムの速度が低下しサイズも大きくなります。この指令はプログラム開発とデバッグの間に使い，最終的な製品を構築するときにはオフにしてください。

オフ {$R-}，{$RANGECHECKS OFF}

この指令がオフの場合，範囲チェックコードは生成されません。


参照

$Q 算術演算オーバーフローチェック

例外処理


スタックオーバーフローチェック指令 {$S}，{$STACKCHECKS}

コンパイラ指令

スタックオーバーフローチェックコードの生成をオンまたはオフにします。

構文:	{$S+} または {$S-}

{$STACKCHECKS ON} または {$STACKCHECKS OFF}

デフォルト:	{$S+}

{$STACKCHECKS ON}

スコープ:	ローカル

オン {$S+}，{$STACKCHECKS ON}

この指令がオンの場合，コンパイラは各手続きまたは関数の先頭に，ローカル変数とその他の一時的記憶のための十分なスタックスペースがあるかどうかをチェックするコードを生成します。

メモ:	プログラムが絶対にスタックのオーバーフローを生じないと確信できる場合以外は，プログラムが完成してもスタックチェックを残してください。

オフ {$S-}，{$STACKCHECKS OFF}

この指令がオフで使用可能なスタックスペースが十分にない場合，手続きまたは関数への呼び出しによってシステムがクラッシュしたり，実行時エラーでプログラムが中断する可能性があります。


型付き @ 演算子指令 {$T}，{$TYPEDADDRESS}

参照	コンパイラ指令

@ 演算子が変数参照に使われたとき，この演算子が返すポインタ値の型を制御します。

構文:	{$T+} または {$T-}

{$TYPEDADDRESS ON} または {$TYPEDADDRESS OFF}

デフォルト:	{$T-}

{$TYPEDADDRESS OFF}

スコープ:	ローカル

オフ {$T-}，{$TYPEDADDRESS OFF}

この指令がオフの場合，@ 演算子の結果は型なしポインタ (Pointer) になり，他のすべてのポインタ型と互換になります。

オン {$T+}，{$TYPEDADDRESS ON}

この指令がオンの場合，@ 演算子の結果は ^T になります。^T は変数参照の型を示します。たとえば，整数の変数に適用される @ は常に整数ポインタ型を返します。

手続き，関数，メソッドに @ を適用する場合，この指令の状態に関係なく，結果のポインタの型は常に Pointer になります。


参照

@ 演算子


Pentium 対応の FDIV 演算指令 {$U} と {$SAFEDIVIDE}

コンパイラ指令

$U 指令は，以前の Pentium プロセッサでの FDIV 命令の欠陥に備えた浮動小数点コードの生成を制御します。

構文:	{$U+} または {$U-}
{$SAFEDIVIDE ON} または {$SAFEDIVIDE OFF}

デフォルト:	{$U-}
{$SAFEDIVIDE OFF}

スコープ:	ローカル

オン {$U+}，{$SAFEDIVIDE ON}

{$U+} 状態では，すべての浮動小数点除算はランタイムライブラリルーチンを使って実行されます。浮動小数点除算ルーチンを初めて呼び出したときに，このルーチンはプロセッサの FDIV 命令が正しく動作するかどうかをチェックし，チェック結果に応じて TestFDIV 変数 (System ユニットで宣言) を更新します。以降の浮動小数点除算演算では，TestFDIV に格納された値によって，どのような処理をするかが決まります。

次の表に TestFDIV の値を示します。

値	意味
-1	FDIV 命令の不良がテストによりわかった
0	FDIV 命令はテストされていない
1	FDIV 命令の正常動作がテストによりわかった
FDIV に欠陥のないプロセッサの場合，{$U+} 状態では処理速度がわずかに低下します。欠陥のある Pentium プロセッサの場合，{$U+} 状態では浮動小数点除算演算に最高で 3 倍の時間が掛かることがありますが，必ず正しい結果が得られます。

オフ {$U-}，{$SAFEDIVIDE OFF}

{$U-} 状態では，浮動小数点除算演算はインラインの FDIV 命令を使って実行されます。処理速度とコードサイズが最適になりますが，Pentium プロセッサに欠陥があれば間違った結果になる可能性があります。欠陥のある Pentium プロセッサではコードが実行されないと確信できる場合にだけ，{$U-} 状態を使うようにしてください。


変数文字列チェック指令 {$V}，{$VARSTRINGCHECKS}

コンパイラ指令

変数パラメータとして渡される短い文字列の型チェックを制御します。

構文:	{$V+} または {$V-}

{$VARSTRINGCHECKS ON} または {$VARSTRINGCHECKS OFF}

デフォルト:	{$V+}， {$VARSTRINGCHECKS ON}

スコープ:	ローカル

オン {$V+}，{$VARSTRINGCHECKS ON}

この指令がオンの場合は厳密な型チェックが行われ，仮パラメータと実パラメータが同一の文字列型であることが要求されます。

オフ {$V-}，{$VARSTRINGCHECKS OFF}

この指令がオフの場合には，短い文字列型変数はすべて実パラメータとして許可されます。宣言された最大長が仮パラメータの最大長と一致しない場合でも同様です。


ウィンドウスタックフレーム指令 {$W}，{$STACKFRAMES}

コンパイラ指令

Windows 3.0 リアルモードで動作するプログラムに対し，far 手続きと far 関数のための特殊なプロローグコードとエピローグコードを生成します。

構文:	{$W+} または {$W-}

{$STACKFRAMES ON} または {$STACKFRAMES OFF}

デフォルト:	{$W+}

{$STACKFRAMES ON}

スコープ:	ローカル

オン {$W+}，{$STACKFRAMES ON}

この指令がオンの場合，コンパイラは必要のないときであっても手続きと関数のためのスタックフレームを生成します。

オフ {$W-}，{$STACKFRAMES OFF}

この指令がオフの場合，コンパイラは必要なときだけスタックフレームを生成します。

注意

デバッギングツールの中にはすべての手続きと関数についてスタックフレームを生成する必要のあるものもありますが，それを除けば {$W+} を使用する必要はまずありません。


拡張構文指令 {$X}，{$EXTENDSYNTAX}

コンパイラ指令

C++Builder の拡張構文をオンまたはオフにします。

構文:	{$X+} または {$X-}

{$EXTENDSYNTAX ON} または {$EXTENDSYNTAX OFF}

デフォルト:	{$X+}

{$EXTENDSYNTAX ON}

スコープ:	グローバル

オン {$X+}，{$EXTENDSYNTAX ON}

この指令がオンの場合，ユーザー定義の関数呼び出しを (手続きであるかのように) 文として扱えるように Object Pascal の構文が拡張されます。拡張構文ではヌルで終わる文字列も使えます。

関数呼び出しは文として扱えます。関数呼び出しの結果は破棄できます。ただし，拡張構文指令は組み込み関数 (System ユニットで定義された関数) には適用されません。

拡張構文指令は組み込み PChar 型とインデックスがゼロから始まる文字配列に適用される特殊な規則を有効にすることによって，ヌルで終わる文字列をサポートしています。

オフ {$X-}，{$EXTENDSYNTAX OFF}

この指令がオフの場合，これらの拡張構文を使うとコンパイルエラーになります。


シンボル情報指令 {$Y}，{$REFERENCEINFO}

参照	コンパイラ指令

デバッグを目的としたシンボル参照情報の生成をオンまたはオフにします。

構文:	{$Y+} または {$Y-}

{$REFERENCEINFO ON} または {$REFERENCEINFO OFF}

デフォルト:	{$Y+}

{$REFERENCEINFO ON}

スコープ:	グローバル

注意

シンボル参照情報はモジュール内のすべてのシンボルの宣言位置とシンボルへの参照位置を示す行番号の表で構成されます。

オン {$Y+}，{$REFERENCEINFO ON}

シンボル情報を使ってプログラムまたはユニットをコンパイルすると，オブジェクトブラウザでそのモジュールのシンボル定義と参照情報を表示できます。

ユニットのシンボル参照情報はそのユニットのオブジェクトコードとともに .DCU ファイルに記録されます。シンボル参照情報を記録するとユニットファイルのサイズが大きくなりますが，実行プログラムのサイズや速度には影響しません。

$Y スイッチは $D と $L の両方のスイッチがオンのときに有効です。

オフ {$Y-}，{$REFERENCEINFO OFF}

この指令がオフの場合，シンボル参照情報は生成されません。


参照

デバッグ情報とシンボル情報


ファイルインクルード指令 {$I filename}，{$INCLUDE filename}

コンパイラ指令

指定したファイルをコンパイルにインクルードするようコンパイラに指示します。

構文:	{$I filename}

{$INCLUDE filename}

スコープ:	ローカル

注意

filename のデフォルトの拡張子は .PAS です。

filename にディレクトリを指定しないと，C++Builder は次のようにファイルを検索します。

まず現在のソースのディレクトリを検索する

次に検索パスを検索する

インクルードするファイルはコンパイルするテキストの {$I filename} 指令の直後に挿入されます。

メモ:	ファイルインクルード指令は文部の途中では指定できません。

文部の begin と end の間の文はすべて同じソースファイルに置かれなくてはなりません。


リンクオブジェクトファイル指令 {$L filename}，{$LINK filename}

コンパイラ指令

指定したファイルを，コンパイルするプログラムまたはユニットとリンクするようコンパイラに指示します。

構文:	{$L filename}

{$LINK filename}

スコープ:	ローカル

注意

$L 指令は，external として宣言された手続きと関数のための他の言語で記述された外部ルーチンをリンクするために使います。

指定するファイルは Intel の再配置可能なオブジェクトファイル (.OBJ ファイル) でなくてはなりません。

filename のデフォルトの拡張子は .OBJ です。

filename にディレクトリを指定しないと，C++Builder は次のように検索します。

まず現在のソースのディレクトリを検索する

次に検索パスを検索する


実行時型情報指令 {$M} と {$TYPEINFO}

コンパイラ指令

実行時型情報の生成を制御します。

構文:	{$M+} または {$M-}
{$TYPEINFO ON} または {$TYPEINFO OFF}

デフォルト:	{$M-}
{$TYPEINFO OFF}

スコープ:	ローカル

説明

$M スイッチ指令は実行時型情報の生成を制御します。クラスが {$M+} 状態で宣言されるか，{$M+} 状態で宣言された別のクラスから派生している場合，コンパイラは published 部で宣言されているフィールド，メソッド，プロパティの実行時型情報を生成します。クラスが {$M-} 状態で宣言されており，{$M+} 状態で宣言された別のクラスから派生していない場合は，クラスで published 部は使えません。

メモ	C++Builder の VCL にある Classes ユニットで定義された TPersistent クラスは {$M+} 状態で宣言されています。したがって，TPersistent から派生したクラスには published 部を入れることができます。VCL は published 部について生成された実行時型情報を使って，フォームファイルの保存やロードのときにコンポーネントのプロパティの値にアクセスします。また，IDE はコンポーネントの実行時型情報を使って，オブジェクトインスペクタに表示するプロパティのリストを決めます。

アプリケーションでは，直接 $M コンパイラスイッチを使う必要はほとんどありません。


メモリ割り当てサイズ指令 {$M}，{$MAXSTACKSIZE}，{$MINSTACKSIZE}

コンパイラ指令

プログラムのスタック割り当てパラメータを指定します。

構文:	{$M minstacksize, maxstaxksize}

{$MAXSTACKSIZE maxstacksize}

{$MINSTACKSIZE minstacksize}

デフォルト:	{$M 16384, 1048576}

スコープ:	グローバル

注意

$M 指令はアプリケーションのスタック割り当てパラメータを指定します。minstacksize は 1024 ～ 2147483647 の範囲の整数で，アプリケーションのスタックの最小サイズを指定する値でなくてはなりません。maxstacksize は minstacksize ～ 2147483647 の範囲の整数で，アプリケーションのスタックの最大サイズを指定する値でなくてはなりません。

最小スタックサイズの要求を満たすだけのメモリがない場合，アプリケーションを起動しようとしたときに Windows がエラーを報告します。

アプリケーションのスタックが最大スタックサイズを超えることは許されません。スタックを最大スタックサイズより大きくしようとすると EStackOverflow 例外が生成されます。

$MINSTACKSIZE 指令と $MAXSTACKSIZE 指令を使うと，最小スタックサイズと最大スタックサイズを別々に指定できます。

メモ:	メモリ割り当て指令はメインプログラムでのみ意味を持ちます。ライブラリやユニットでは使えません。


記述説明指令 {$D text}，{$DESCRIPTION text}

コンパイラ指令

指定されたテキストを EXE ファイルまたは DLL のヘッダーのモジュール記述エントリに挿入します。

構文:	{$D text}

{$DESCRIPTION text}

スコープ:	グローバル

注意

プログラムまたは DLL ソースファイルには記述説明指令を一度だけ指定できます。ユニットソースファイルには $D を指定しないでください。


リソースファイル指令 {$R filename}，{$RESOURCE filename}

コンパイラ指令

アプリケーションまたはライブラリにインクルードするリソースファイルの名前を指定します。

構文:	{$R filename}

{$RESOURCE filename}

スコープ:	ローカル

注意

filename のデフォルトの拡張子は .RES です。このファイルは Windows のリソースファイルでなくてはなりません。

filename にディレクトリを指定しないと，コンパイラはファイルを次のように検索します。

まず現在のソースのディレクトリを検索する

次に検索パスを検索する

ユニットで使う場合，リソースファイル名は単に結果のユニットファイルに記録されます。コンパイル時にファイルの存在を確認するためのチェックはされません。

アプリケーションまたはライブラリをリンクする場合，すべてのユニットで指定されたリソースファイルと，プログラムまたはライブラリ自体で指定されたリソースファイルが処理され，それぞれのリソースファイル内の各リソースは生成される .EXE ファイルまたは .DLL ファイルにコピーされます。

メモ:	この指令では 1 ユニットに複数の .RES ファイルを指定できます。コンパイル時に .RES ファイルの内容についての確認や，有効な .RES ファイルであるか (そのファイルが存在するか) の確認はされません。$R 指令で指定するファイルはリンク時には存在しなくてはならず，存在しない場合には「ファイルが見つかりません (<ファイル名>.RES)」というエラーメッセージが表示されます。


ワードサイズ列挙型 {$Z}
ワードサイズ列挙型指令 {$Z}

コンパイラ指令

$Z 指令は列挙型の最小格納サイズを制御します。

構文:	{$Z1} または {$Z2} または {$Z4}
{$MINENUMSIZE 1} または {$MINENUMSIZE 2} または
{$MINENUMSIZE 4}

デフォルト:	{$Z1}
{$MINENUMSIZE 1}

スコープ:	ローカル

説明

列挙型は {$Z1} 状態 (デフォルト) で宣言された場合，列挙する値が 256 個以下のときは符号なしバイトとして格納されます。列挙型が 256 個を超える値を持っているか，または {$Z2} 状態で宣言された場合，その列挙型は符号なしワードとして格納されます。列挙型が {$Z4} 状態で宣言された場合，その列挙型は符号なしダブルワードとして格納されます。

{$Z2} と {$Z4} の状態は，列挙型を一般的にワードまたはダブルワードとして表す C や C++ のライブラリとのインターフェースに役立ちます。


警告指令 {$WARNINGS}

参照	コンパイラ指令

$WARNINGS コンパイラ指令はコンパイラによる警告の生成を制御します。

構文:	{$WARNINGS ON} または {$WARNINGS OFF}

デフォルト:	{$WARNINGS OFF}

スコープ:	ローカル

オン {$WARNINGS ON}

警告がオンの状態では，コンパイラは初期化されていない変数や関数結果の欠落，抽象オブジェクトの作成などを検出したときに警告メッセージをメッセージウィンドウに生成します。

オフ {$WARNINGS OFF}

オフの状態では，コンパイラは警告メッセージを生成しません。


参照

ヒント指令


ヒント指令 {$HINTS}

参照	例	コンパイラ指令

$HINTS 指令はコンパイラによるヒントメッセージの生成を制御します。

構文:	{$HINTS ON} または {$HINTS OFF}

デフォルト:	{$HINTS OFF}

スコープ:	ローカル

オン {$HINTS ON}

ヒントがオンの状態では，コンパイラは未使用の変数，未使用の代入，決して実行されない for または while のループなどを検出したときにヒントメッセージをメッセージウィンドウに生成します。

オフ {$HINTS OFF}

オフの状態では，コンパイラはヒントメッセージを生成しません。

説明

{$HINTS OFF} 指令と {$HINTS ON} 指令の間にコードを入れると，重要でないと思われるヒントを選択してオフにできます。


例

{ 次のコード例は，未使用の変数に関するヒントをコンパイラが生成しないようにする方法を示す }

{$HINTS OFF}

procedure Test;

var

  I: Integer;

begin

end;

{$HINTS ON}


参照

警告指令


コードイメージベースアドレス指令 {$IMAGEBASE}
コードイメージベース指令 {$IMAGEBASE address}

コンパイラ指令

$IMAGEBASE 指令はアプリケーションまたは DLL のデフォルトのロードアドレスを指定します。

構文:	{$IMAGEBASE number}

デフォルト:	{$IMAGEBASE $00400000}

スコープ:	グローバル

説明

引数 number はイメージベースアドレスを指定する 32 ビット整数値でなければなりません。引数 number は $00010000 以上でなければならず，この引数の下位 16 ビットは無視され，ゼロでなければなりません。

モジュール (アプリケーションまたは DLL) をプロセスのアドレス領域の中へロードした場合，Windows はそのモジュールをデフォルトのイメージベースアドレスに配置しようとします。それが成功しなかった場合，つまり与えられたアドレス範囲がすでに予約済みの場合には，モジュールは Windows が割り当てるアドレスへ再配置されます。

アプリケーションのイメージベースアドレスを変更する理由は，ほとんどありません。しかし DLL の場合は，$IMAGEBASE 指令を使ってデフォルト以外のイメージベースアドレスを指定するようお勧めします。なぜなら，デフォルトのイメージベースアドレスである $00400000 は，ほとんど使用可能な場合がないからです。推奨される DLL イメージのアドレス範囲は $40000000～$7FFFFFFF です。この範囲のアドレスは Windows NT と Windows 95 の両方のプロセスから常に使用可能です。

Windows が DLL をその DLL のイメージベースアドレスへ正常にロードできる場合，再配置による修正が必要ないので，DLL のロード時間は短くなります。さらに，与えられたアドレス範囲がその DLL を使う複数のプロセスから使用可能な場合には，DLL のイメージのコード部分をプロセス間で共有でき，それによってロード時間とメモリ消費が減少します。


長い文字列指令 {$H} と {$LONGSTRINGS}

参照	コンパイラ指令

$H 指令は型宣言の中で単独で使われる予約語 string の意味を制御します。

構文:	{$H+} または {$H-}
{$LONGSTRINGS ON} または {$LONGSTRINGS OFF}

デフォルト:	{$H+}
{$LONGSTRINGS ON}

スコープ:	ローカル

説明

汎用型の string は動的割り当ての長い文字列 (基本型は AnsiString) と，静的割り当ての短い文字列 (基本型は ShortString) のどちらでも表せます。

オン {$H+}，{$LONGSTRINGS ON}

デフォルトの {$H+} では，汎用文字列型は長い AnsiString として定義されます。ビジュアルコンポーネントライブラリ (VCL) 内のすべてのコンポーネントは，この状態でコンパイルされます。コンポーネントを作成する場合，VCL 文字列型プロパティからデータを受け取るすべてのコードと同様に，そのコンポーネントも長い文字列を使わなければなりません。

オフ {$H-}，{$LONGSTRINGS OFF}

{$H-} 状態は短い文字列をデフォルトで使っていた Object Pascal バージョンのコードを使う場合にもっとも便利です。開発にあたって短い文字列を確実に生成するため，文字列型定義の意味をローカルにオーバーライドすることもできます。短い文字列型の宣言を string[255] または ShortString に変更してもかまいません。これらの宣言は一意に解釈され，$H の設定に依存しません。


参照

長い文字列型

短い文字列型


最適化指令 {$O} と {$OPTIMIZATION}

コンパイラ指令

構文:	{$O+} または {$O�}
{$OPTIMIZATION ON} または {$OPTIMIZATION OFF}

デフォルト:	{$O+}
{$OPTIMIZATION ON}

スコープ:	ローカル

$O 指令はコードの最適化を制御します。{$O+} 状態では，コンパイラは CPU レジスタへの変数の配置，共通した部分式の削除，誘導変数の生成など，多数のコード最適化を実行します。{$O-} 状態では，そのようなすべての最適化は使用不可になります。

特殊なデバッグ作業の場合を除けば，最適化をオフにする必要はまったくありません。C++Builder の Object Pascal コンパイラが実行するすべての最適化は，決してプログラムの意味を変更しません。つまり，C++Builder はプログラマが特に注意しなければならないような「安全でない」最適化はしません。


言語定義

言語リファレンス

Object Pascal 言語の正式な定義の要素については次の各トピックを参照してください。

構文図を使って Object Pascal 言語の特徴を説明しているトピックもあります。構文図の読み方がわからないときは，構文図の読み方を参照してください。

言語定義はヘルプ目次画面やヘルプ検索エンジンで表示できます。〔Ctrl〕+〔F1〕を押してコードエディタで直接表示することもできます。

配列

ブロック

文字列

コメント

コンパイラ指令

定数宣言

DLL

例外処理

式

関数

識別子

ラベル

ループ

メソッド

数

演算子

手続き

予約語

スコープ

特殊シンボル

文

文字列

トークン

型付き定数

型宣言

変数

ユニット


言語リファレンス

言語定義

言語リファレンスはヘルプメニューやヘルプ目次画面で表示できます。〔Ctrl〕+〔F1〕を押してコードエディタで直接表示することもできます。

コンパイラ指令

条件指令と条件シンボル

予約語

標準指令


構文図の読み方

Object Pascal 言語の学習では，構文図の読み方を理解することが基本的に必要です。このヘルプシステムでは，いたるところで構文図が使われています。Object Pascal 言語の各部分について，構文要素の適切な順序が構文図によって示されます。

構文図は矢印に従って読み進んでください。複数の進路があり，そのすべてが有効な場合がよくあります。

構文図では，コードで実際に使われる用語が太字で示されます。

構文図の図形は特定の構文要素を次のように表します。

図形	意味

四角形	構成要素

円	予約語，演算子，区切り子


ブロック

参照

ブロックは文で構成されます。

各ブロックは手続き宣言，関数宣言，メソッド宣言，プログラム，ユニットなどに含まれます。

宣言部

ブロックの宣言部には次の要素が含まれます。

ラベル

定数

型

変数

手続き

関数

exports 節

ブロックで宣言するすべての識別子とラベルについて，スコープがそのブロックにローカルになります。

実行部

ブロックの実行部は複合文です。つまり，予約語の begin と end で定められた範囲内に文が 1 つ以上あります。


参照

begin..end

ブロックのスコープ

文


定数宣言

参照

定数は変更できない値を表す識別子です。定数のスコープはその定数の宣言があるブロック内に限られます。定数識別子をそれ自身の宣言に含めることはできません。

定数は予約語の const を使って宣言します。

Object Pascal では定数式を使えます。定数式とは，実際にプログラムを実行せずにコンパイラが評価できる式です。

コンパイル時に定数式を完全に評価しなくてはならないため，定数式には次の構文が使えません。

変数や型付き定数への参照 (定数アドレス式にあるものを除く)

@ 演算子 (定数アドレス式にあるものを除く)

関数呼び出し (次の関数を除く)

Abs	Odd

Addr	Ord

Chr	Pred

Hi	Round

High	SizeOf

Length	Succ

Lo	Swap

Low	Trunc

定数式には次の二項算術演算子や論理演算子も使えます。

+	shr

-	shl

/	and

div	or

mod	xor

=


参照

スコープ

型付き定数


変数

参照	例

変数は変更できる値を表す識別子です。ユニット，手続き，関数，プログラムの変数宣言部で変数を宣言できます。

変数宣言では，識別子とその型を宣言しなくてはなりません。

変数の型として，次のいずれかですでに宣言されている型識別子を使うことができます。

同じブロック内の type 宣言部

外側のブロック

ユニット

変数には新しい型も宣言できます。

変数識別子のスコープはその変数の宣言があるブロック内に限られます。内側に封入されているブロックで識別子を再宣言しない限り，ブロック内のどこででもその変数を参照できます。

再宣言をすると，元の変数の値に影響を及ぼさずに，同じ識別子で新しい変数が作成されます。


参照

グローバル変数とローカル変数

スコープ

ユニット

var (予約語)

変数参照

変数型キャスト

初期化変数


例

var

  X, Y, Z: Real;

  I, J, K: Integer;

  Digit: 0..9;

  C: TColor;

  Done,Error: Boolean;

  Operator: (Plus, Minus, Times);

  Hue1, Hue2: set of TPenStyle;

  Today: TDateTime;

  Matrix: array[1..10, 1..10] of Real;


グローバル変数とローカル変数

参照	変数

グローバル変数は手続きや関数の外部で宣言されます。グローバル変数は以下のすべてで使えます。

手続き

関数

メソッド

ローカル変数は手続き，関数，メソッドの内部で宣言されます。ローカル変数は外側の内だけで使え，手続きや関数が呼び出し側に戻ると破棄されます。

ローカル変数とスタック

手続きや関数の内部で宣言された変数はローカル変数と呼ばれ，アプリケーションのスタックに保持されます。手続きや関数の呼び出しのたびに，ローカル変数がスタック上に割り当てられます。終了時に各ローカル変数は破棄されます。

アプリケーションのスタックは minimum stack size と maximum stack size の 2 つの値によって定義されます。この 2 つの値は $MINSTACKSIZE と $MAXSTACKSIZE のコンパイラ指令で制御します。$MINSTACKSIZE と $MAXSTACKSIZE のデフォルトはそれぞれ 16,384 (16K) と 1,048,576 (1M) です。アプリケーションは最小スタックサイズを常に利用できるよう保証されており，そしてアプリケーションのスタックが最大スタックサイズより大きくなることは決してありません。

アプリケーションの最小スタックサイズ条件を満たすメモリが利用できない場合は，そのアプリケーションを起動しようとすると Windows からエラーが出されます。

最小スタックサイズで指定されるよりも多いスタック領域がアプリケーションに必要であれば，追加のメモリが 4K 単位で自動的に割り当てられます。追加メモリが利用できないか，スタックの合計サイズが最大スタックサイズを超えるため追加スタック領域の割り当てに失敗すると，EStackOverflow 例外が生成されます。


参照

スコープ


初期化済み変数

参照	変数

変数宣言で単一のグローバル変数を宣言する場合，その変数には宣言で初期値を指定できます。グローバル変数宣言が初期値を明示的には指定しない場合，その変数が占有するメモリの初期値はゼロに設定されます。

ローカル変数には初期値を指定できず，手続きまたは関数の入口ではすべてのローカル変数の値が未定義の状態です。


参照

型付き定数

グローバル変数とローカル変数


変数参照

参照

変数参照とは次のいずれかを表します。

変数

構造化型変数または文字列型変数の要素

ポインタ型変数が指す動的変数

変数参照の構文は次のようになります。

変数参照の構文では，ポインタ型の値を計算する式が使えます。実際に変数参照を生成するには，ポインタの値を逆参照する限定子 ({$X+} 指令によって拡張構文が有効になっている場合はポインタの値に添字付けする限定子) をこの式の後に付けなくてはなりません。


参照

ポインタ型変数

限定子

文字列型変数

構造化型変数

変数

変数型キャスト


限定子

参照	変数参照

限定子は変数参照の意味を限定します。変数にはいくつでも限定子を付けることができますが，付けないこともあります。

配列識別子に限定子を付けなければ，配列全体が参照されます。

配列識別子の後に添字を付けると，配列の特定要素を表せます。

レコード型やオブジェクト型の要素の場合は，添字の後にフィールド指定子を付けると，配列の特定要素内の特定フィールドを表せます。

ポインタ型フィールドのフィールド指定子の後にポインタシンボル (^) を付けると，ポインタ型フィールドとそのフィールドが指す動的変数とを区別できます。

ポインタ型フィールドが指す変数が配列の場合，添字を付けるとその配列の要素を指定できます。

構造化型を逆参照するときにはポインタシンボルは省略できます。


参照

配列型

フィールドとオブジェクト型要素の指定子

添字

ポインタと動的変数

ポインタ型

変数参照


添字

参照	変数参照

添字は配列，文字列，文字列リストの特定の要素へのアクセスに使います。

配列の添字

配列の添字を使うと，配列の特定の要素にアクセスできます。

添字式は配列の対応する各次元の要素を選択します。
配列の添字には以下の制限事項があります。

添字式の数は，配列宣言の添字型の数を超えることはできない

各添字式の型は，対応する添字型と代入の互換性がなければならない

文字列の添字

短い文字列型変数には添字式を 1 つだけ付けられます。添字式の値は，0～N (N は短い文字列の宣言された最大長) の範囲になければなりません。短い文字列に添字を付けてアクセスされる文字の型は Char です。文字列の最初の文字の添字は 1 です。添字 0 の要素はその文字列の動的な長さを保持します。

空でない長い文字列型変数には添字式を 1 つだけ付けられます。添字式の値は，1～N (N は長い文字列の動的な長さ) の範囲になければなりません。長い文字列に添字を付けてアクセスされる文字の型は Char です。長い文字列の最初の文字の添字は 1 です。

PChar，PAnsiChar，PWideChar の各型の値には Integer 型の添字式を 1 つだけ付けられます。添字式は，文字ポインタの逆参照によって Char 型，AnsiChar 型，WideChar 型のいずれかの変数参照を生成する前に，その文字ポインタに加算されるオフセット (文字またはワイド文字の数) を指定します。

文字列の長さを確認するには

Length 関数を使います。

文字列リストの添字

文字列リストの添字を使うと文字列リストの特定の文字列にアクセスできます。

文字列リストには Strings という添字付きプロパティがあり，文字列配列のように文字列リストを処理できます。

Strings プロパティは文字列リストでもっとも一般的にアクセスする部分なので，文字列リストのデフォルトプロパティになります。つまり，識別子 Strings を省略して，文字列リストそのものを添字付き文字列配列として処理できます。

文字列リストの特定の文字列にアクセスするには，その文字列を添字で参照します。文字列の添字値はゼロから始まるので，文字列リストに文字列が 3 つあれば，添字の範囲は 0～2 になります。

添字の最大値を確認するには，Count プロパティを調べます。有効な添字の範囲にない文字列にアクセスしようとすると，文字列リストから例外が生成されます。


参照

配列型

限定子

文字列型


例

次の例は配列のセルにアクセスします。

Matrix[I, J];

次の 2 つの例はまったく同じで，メモ型フィールドの 1 行目にテキストを設定します。

Memo1.Lines.Strings[0] := 'This is the first line.';

Memo1.Lines[0] := 'This is the first line.';


フィールドとオブジェクトの指定子

参照	例	変数参照

フィールド指定子

フィールド指定子はレコードの特定フィールドにアクセスするときに使います。

with 文中の文では，フィールド指定子の前に，そのフィールドがあるレコードへの変数参照を付ける必要はありません。

オブジェクト型要素指定子

オブジェクト型要素指定子はオブジェクトの特定要素にアクセスするときに使います。メソッドを指定する要素指定子はメソッド指定子といいます。

次の場合はインスタンスとピリオドを省略できます。

with 文を使って要素を参照する場合

メソッドブロック内 (要素参照の前に Self とピリオドが付いた場合と同じになるため)


参照

クラス型

レコード型

with 文


例

次の例はレコード内のフィールドにアクセスします。

Today.Year

Results[1].Count

Results[1].When.Month


ポインタと動的変数

参照	例

ポインタ変数は nil 値または動的変数のアドレスを保持します。

ポインタ変数が指す動的変数はポインタ変数の後にポインタシンボル (^) を付けて参照します。

New 手続きと GetMem 手続きを使うと，動的変数とそのポインタ値を生成できます。

@ (アドレス) 演算子と Addr 関数を使うと，動的変数へのポインタとして処理されるポインタ値を生成できます。

nil はどの変数も指しません。ポインタの値が nil または未定義のときに動的変数にアクセスした場合，結果は未定義です。


参照

ポインタ型

変数


例

次の例は動的変数への参照です。

Pl^

Pl^.Siblings^

Results[1].Data^


変数型キャスト

参照	例	変数参照

変数型キャストにより，ある型の変数参照が別の型の変数参照に変わります。

変数参照に対して変数型キャストをすると，その変数参照は型識別子で指定した型のインスタンスとして処理されます。変数のサイズは型識別子で指定した型のサイズと同じでなくてはなりません。as 演算子を使って型キャストをすると，型キャストの有効性がチェックされ，型キャスト後の型との代入の互換性が変数にない場合は例外が生成されます。型識別子の後に変数名をカッコに入れて型キャストをすると，型キャストはチェックされません。

変数型キャストの後に，指定した型で許可されているだけ限定子を付けることができます。

Object Pascal では，手続き型を含むさまざまな変数型キャストがサポートされています。


参照

限定子

値型キャスト

変数


例

次のような宣言があるとします。

type

  Func = function(X: Integer): Integer;

var

  F: Func;

  P: Pointer;

  N: Integer;

次のような代入ができます。

  F := Func(P);     { P の手続き値を F に代入します }

  Func(P) := F;     { F の手続き値を P に代入します }

  @F := P;          { P のポインタ値を F に代入します }

  P := @F;          { F のポインタ値を P に代入します }

  N := F(N);        { F を使って関数を呼び出します }

  N := Func(P)(N);  { P を使って関数を呼び出します }


識別子

例	言語定義

識別子は Object Pascal プログラムの次の各要素を表すのに割り当てる名前です。

定数

レコードのフィールド

関数

ラベル

手続き

プログラム

型

ユニット

変数

識別子には大文字と小文字の区別はありません。

識別子の名前には次の制限事項が適用されます。

長さは任意だが，意味のあるのは最初の 63 文字だけである

英字または下線記号 (_) で始めなくてならない

2 文字目以降には英字，数字，下線記号のいずれかを使わなくてはならない

空白を入れてはならない

限定識別子

同じ識別子のインスタンスが複数ある場合，名前の競合が起こらないようにするのに限定識別子が役立ちます。識別子を別の識別子を使って限定すると，特定インスタンスを選択できます。


例

次の例は標準の識別子です。

TextFile

Exit

Real2String

次の例は限定識別子です。

System.MemAvail  (* ユニット = System, 識別子 = MemAvail *)

System.CloseFile


型付き定数

参照	例

型付き定数の宣言は読み出し専用変数の宣言に相当します。型付き定数は変更できないことを除いて，同じ型の変数のように使えます。

通常の定数式のほかに，型付き定数の値は定数アドレス式でも指定できます。

型付き定数には以下の 5 種類があります。

ポインタ型定数

手続き型定数

単純型定数

文字列型定数

構造化型定数

メモ	$J コンパイラ指令は変更できる型付き定数の宣言を可能にします。デフォルトの {$J-} 状態で宣言した型付き定数は読み出し専用で変更はできません。


参照

定数宣言

初期化変数


例

(* 型付き定数宣言 *)

type

  Point = record X, Y: real end;

const

  Minimum: Integer = 0;

  Maximum: Integer = 9999;

  Factorial: array[1..7] of Integer = (1, 2, 6, 24, 120, 720, 5040);

  HexDigits: set of Char = ['0'..'9', 'A'..'Z', 'a'..'z'];

  Origin: Point = (X: 0.0; Y: 0.0);


構造化型定数

参照	型付き定数

構造化型定数の宣言は構造の各要素の値を指定します。

Object Pascal では，次の型の定数の宣言がサポートされています。

配列

レコード

集合

ポインタ

ファイル型定数と，file 型要素を含む array 型定数や record 型定数は使えません。


参照

ポインタ型定数

手続き型定数

単純型定数

文字列型定数


配列型定数

例	構造化型定数

配列型定数は要素が初期化済みの配列を宣言します。

配列型定数の宣言は要素の値を指定します。配列型定数の要素の型には，ファイル型以外であればどの型でも使えます。

文字配列

パック文字列型定数 (文字配列) は 1 文字としてでも文字列としてでも指定できます。

添字が 0 から始まる文字配列

文字配列の最初の要素の添字は 0 で，最後の要素の添字は 0 以外の正の整数です。

添字が 0 から始まる文字配列は，その配列に対して宣言された長さよりも短い文字列を使って初期化できます。

文字列が配列の長さよりも短い場合，残りの文字は NULL (#0) に設定され，配列にはヌルで終わる文字列が入ることになります。

多次元配列定数

多次元配列定数は，各次元の定数をカンマで区切ってカッコで囲み，さらにその周りをカッコで囲んで定義します。

最も内側の定数が最も右側の次元に対応します。


配列型定数の例
例

次の例は配列型定数 StatStr を作成します。

type

  Status = (Active, Passive, Waiting);

  StatusMap = array[Status] of string[7];

const

  StatStr: StatusMap = ('Active', 'Passive', 'Waiting');

StatStr の要素を次に示します。

  StatStr[Active] = 'Active'

  StatStr[Passive] = 'Passive'

  StatStr[Waiting] = 'Waiting' }

次の例は初期化済みの多次元配列 Maze を宣言します。

  type

    Cube = array[0..1, 0..1, 0..1] of Integer;

  const

    Maze: Cube = (((0, 1), (2, 3)), ((4, 5), (6, 7)));

配列 Maze の値を次に示します。

  Maze[0, 0, 0] = 0

  Maze[0, 0, 1] = 1

  Maze[0, 1, 0] = 2

  Maze[0, 1, 1] = 3

  Maze[1, 0, 0] = 4

  Maze[1, 0, 1] = 5

  Maze[1, 1, 0] = 6

  Maze[1, 1, 1] = 7


ポインタ型定数

参照	例	型付き定数

ポインタ型定数はポインタ値を事前に初期化するときに使います。

一般に，ポインタ型定数の宣言では定数アドレス式を使ってポインタ値を指定します。

PChar 型の型付き定数は文字列定数を使って初期化できます。


参照

PChar

ポインタ型


例

次の例はポインタ型定数を宣言します。

type

  TDirection = (Left, Right, Up, Down);

  TStringPtr = ^String;

  TNodePtr = ^TNode;

  TNode = record

    Next: TNodePtr;

    Symbol: TStringPtr;

    Value: TDirection;

  end;

const

  S1: string[4] = 'DOWN';

  S2: string[2] = 'UP';

  S3: string[5] = 'RIGHT';

  S4: string[4] = 'LEFT';

  N1: TNode = (Next: nil; Symbol: @S1; Value: Down);

  N2: TNode = (Next: @N1; Symbol: @S2; Value: Up);

  N3: TNode = (Next: @N2; Symbol: @S3; Value: Right);

  N4: TNode = (Next: @N3; Symbol: @S4; Value: Left);

  DirectionTable: TNodePtr = @N4;


手続き型定数

参照	例	型付き定数

手続き型定数は手続き型を事前に初期化するときに使います。

手続き型定数では，その定数の型との代入の互換性のある手続きまたは関数の識別子か，値 nil を指定しなくてはなりません。


参照

手続き型

型付き定数


例

次の例は手続きを型の定数に代入します。

type

  ErrorProc = procedure(ErrorCode: Integer);

procedure DefaultError(ErrorCode: Integer); far;

begin

  WriteLn('Error ', ErrorCode, '.');

end;

const

  ErrorHandler: ErrorProc = DefaultError;


レコード型定数

参照	例	構造化型定数

レコード型定数はレコードのフィールドを事前に初期化するときに使います。

レコード型定数の宣言では，各フィールドの識別子と値をカンマで区切り，カッコで囲んで指定します。

フィールドはレコード型の定義の場合と同じ順序で指定しなくてはなりません。

レコードに file 型のフィールドがある場合，そのレコード型の定数は宣言できない

レコードに可変部がある場合，選択した可変部のフィールドだけが指定できる

可変部にタグフィールドがある場合，その値を指定しなくてはならない


参照

レコード

型付き定数


例

次の例はレコード型定数 TPoint を宣言します。

type

  TPoint = record

    X, Y: Real;

  end;

  TVector = array[0..1] of TPoint;

  TMonth = (Jan, Feb, Mar, Apr, May, Jun, Jly, Aug, Sep, Oct, Nov, Dec);

  TDate = record

    D: 1..31;

    M: TMonth;

    Y: 1900..1999;

  end;

const

  Origin: TPoint = (X: 0.0; Y: 0.0);

  Line: TVector = ((X: -3.1; Y: 1.5), (X: 5.8; Y: 3.0));

  SomeDay: TDate = (D: 2; M: Dec; Y: 1960);


集合型定数

参照	例	構造化型定数

集合型定数は集合の要素を事前に初期化するときに使います。

集合型定数の宣言では，定数式を使って集合の値を指定します。


参照

集合

集合型

型付き定数


例

次の例は Digits と Letters の集合型定数を宣言します。

type

  Digits = set of 0..9;

  Letters = set of 'A'..'Z';

const

  EvenDigits: Digits = [0, 2, 4, 6, 8];

  Vowels: Letters = ['A', 'E', 'I', 'O', 'U', 'Y'];

  HexDigits: set of '0'..'z' = ['0'..'9', 'A'..'F', 'a'..'f'];


単純型定数

参照	例	型付き定数

単純型定数の宣言では，定数の値を指定します。

定数アドレス式を使うと，型付き定数の値を指定できます。

型付き定数は実際には定数値を持つ変数なので，他の定数の宣言の中で使うことはできません。


参照

型

型付き定数


例

次の例は単純型定数を宣言します。

const

  Maximum: Integer = 9999;

  Factor: Real = -0.1;

  Breakchar: Char = #3;


文字列型定数

参照	例	型付き定数

文字列型の型付き定数の宣言は単純に文字列定数を指定します。

短い文字列の型付き定数を宣言するには，宣言に長さ指定子を指定します。


参照

文字列型

型付き定数


例

次の例は長い文字列型定数を宣言します。

const

  Heading: string = 'Section';

  NewLine: string = #13#10;

  TrueStr: string = 'Yes';

  FalseStr: string = 'No';

次の例は短い文字列型定数を宣言します。

const

ShortStr: string[5] = 'Short';


式

参照

式は演算子とオペランドの組み合わせであり，評価によって結果の値が 1 つ得られます。

オペランドを次に示します。

定数

関数呼び出し

手続き文

集合構成子

変数

部分式をカッコで囲むと，優先順位を変更できます。


参照

@ 演算子

ブロック

コメント

定数宣言

関数呼び出し

演算子の優先順位

集合型

文

値型キャスト

変数参照


関数呼び出し

参照

関数呼び出しは次のいずれかで指定された関数を起動します。

関数識別子

メソッド指定子

限定メソッド指定子

手続き型変数参照

対応する関数宣言に仮パラメータのリストがある場合，関数呼び出しには実パラメータのリストが入っていなくてはなりません。パラメータの規則に従って，各パラメータが対応する仮パラメータのかわりに使われます。

Object Pascal では関数呼び出しの結果を破棄することが可能で，実質的に関数呼び出しを手続き文として扱うことができます。


参照

メソッドの起動

限定メソッドの起動

パラメータ

手続き型


値型キャスト

参照	例

値型キャストにより，式の型が別の型に変わります。

式の型と指定した型は両方とも次のどちらかの型でなくてはなりません。

順序型

ポインタ型

順序型については，結果の値は式の変換によって得られます。指定した型のサイズが式のサイズと異なっている場合，元の値の切り捨てまたは拡張が必要になることがあります。値が拡張される場合，値の符号は常に保持されます。

値型キャストは値に作用します。後に限定子を付けることはできません。


例

次の例は値型キャストの文です。

Integer('A')

Char(48)

Boolean(0)

Color(2)

Longint(@Buffer)


参照

変数型キャスト


式での手続き型の使い方

参照	例

式の文で手続き変数を使うと，変数に格納された手続きや関数が呼び出されます。ただし，代入文の左辺に手続き変数がある場合，右辺に手続き値が必要になることをコンパイラが認識します。残念ながら，構文からは必要な処理をコンパイラが判断できないことがあります。

手続き型と @ 演算子

手続き識別子や関数識別子にアドレス演算子 (@) を付けると，引数がポインタに変換され，コンパイラが手続きを呼び出せなくなります。

@ 演算子は型なしポインタ値を手続き変数に代入するときによく使います。

手続き変数に格納されているアドレスではなく，手続き変数のメモリアドレスを取得するには，二重アドレス演算子 (@@) を使います。


例

type

  IntFunc = function: Integer;

var

  F: IntFunc;

  N: Integer;

function ReadInt: Integer;

var

  I: Integer;

begin

  Read(I);

  ReadInt := I;

end;

begin

  F := ReadInt;   { 手続き値を代入します }

  N := ReadInt;   { 関数の結果を代入します }

end.


参照

@ 演算子

手続き型


特殊シンボル

参照

特殊シンボルは特定の意味を持つ ASCII 文字セットの文字です。したがって，プログラムで特殊シンボルを使うときは，Object Pascal 言語での各シンボルの定義に必ず従います。

次の各文字は特殊シンボルです。

+     -     *     /     =     <     >     [     ]     .     ,     (     )     :     ;     ^     @     {     }     $     #

次の文字の組も特殊シンボルです。

<=     >=     :=     ..     (*  *)     (.  .)     <>

特殊シンボルには演算子もあります。

特殊シンボルでは，1 文字と文字の組とで働きが同じ場合があります。

文字	相当する文字の組

 [	(.

 ]	.)

 {	(*

 }	*)

Object Pascal では，ASCII 文字セットの次のサブセットが使われます。

英字。A ～ Z，a ～ z

数字。0 ～ 9

16 進数字。0 ～ 9，A ～ F，a ～ f

空白。スペース (ASCII 32) と，行の終わりや復帰文字 (ASCII 13) などのすべての ASCII 制御文字 (ASCII 0 ～ 31)


参照

コメント

演算子


数

整数型や実数型の定数である数を表すには，通常の 10 進表記を使います。

小数点または指数部のある数は実数型定数を表します。その他の 10 進数は整数型定数を表し，-2,147,483,648 から 2,147,483,647 の範囲になくてはなりません。

16 進数

16 進整定数にはプレフィックスとしてドル記号 ($) を付けます。

16 進数を整数型定数として使う場合，$00000000 から $FFFFFFFF の範囲になくてはなりません。結果の値の符号は 16 進表記に含まれています。

指数表記

指数表記 (E または e と後続の指数部) は実数型で「～掛ける 10 の…乗」と解釈します。次に例を示します。

7E-2  は 7 x 0.01 を意味します。

12.25e+6 と 12.25e6 は両方とも 12.25 x 1000000 を意味します。


文字列

例

文字列は拡張 ASCII 文字セットの文字の列です (文字が何も含まれない場合もあります)。プログラムでは，文字列は単引用符で囲んで 1 行で書きます。

単引用符の間に何もない文字列はヌル文字列になります。

文字列中の連続した 2 つの単引用符は 1 つの単引用符を表します。

文字列の長さの属性は単引用符の間にある文字の実際の数を表します。文字列の最大長は 255 文字です。

制御文字

標準 Object Pascal の拡張として，文字列内で制御文字が使えます。

# 文字の後に 0 から 255 までの符号なし整定数を続けると，対応する ASCII 値の文字が表されます。

# 文字と整定数との間にセパレータを入れてはなりません。

文字列に複数の制御文字を入れる場合，制御文字間にセパレータを入れてはなりません。

文字列の互換性

長さが 0 の文字列 (ヌル文字列) は文字列型とだけ互換性がある

長さが 1 の文字列はどの Char 型や string 型とも互換性がある

長さが N (N は 2 以上) の文字列は次のものと互換性がある

任意の文字列型

N 文字のパック配列

{$X+} コンパイラ指令によって拡張構文が有効になっている場合は PChar 型


例

'BORLAND'        { BORLAND }

'You''ll see'    { You'll see }

''''             { ' }

''               { ヌル文字列 }

' '              { スペース }


コメント

参照	例

コードのブロックの用途がわかるようにしたいときは，説明のためのコメントを中カッコ ({ }) またはアスタリスクとカッコ ((* *)) で囲んで挿入できます。

コメントの区切り記号に囲まれたテキストはコンパイラでは無視されます。

コメントの終わりの区切り記号 (} または *)) をコメントのテキスト内に入れると，コンパイラでコメントの終わりとみなされるので，入れてはなりません。

始まりの { または (* の直後にドル記号 ($) のあるコメントはコンパイラ指令です。$ の後にコンパイラ指令のニーモニックを続けます。

コメントテキストの前にスラッシュを 2 つ (//) を置くことで単一行コメントを作成することもできます。コンパイラは，そこから行末までを無視します。


参照

ブロック


例

  { 途中に右中カッコのない任意のテキスト }

  (* 途中にアスタリスクと右カッコの組み合わせがない任意のテキスト *)

  // 2 つのスラッシュから行末までの任意のテキスト


トークン

参照

トークンは Object Pascal プログラムのテキストで意味のある最小の単位です。トークンの種類を次に示します。

文字列

識別子

ラベル

数

予約語

特殊シンボル

プログラムでトークンを続けて 2 つ使う場合，そのトークンのどちらかが予約語，識別子，ラベル，数のときはトークン間にセパレータを入れる必要があります。文字列定数以外では，セパレータをトークンの一部として使うことはできません。


参照

コメント

標準指令


ラベル

参照

ラベルは goto 文の飛び先をマークする 0 から 9999 の範囲の数字の列です (先頭のゼロには意味がありません)。

標準 Pascal の拡張として，Object Pascal でも識別子をラベルとして使えます。


参照

ブロック

label (予約語)


文

参照

文はプログラムで実行可能なアルゴリズム的処理を表します。

文の基本的な種類として次の 2 つがあります。

単純文

構造化文

単純文

単純文では値の代入，手続きや関数の起動，コードの別の文への実行プログラムの転送ができます。

Object Pascal でサポートされている単純文を次に示します。

代入 (:=) 文

goto 文

手続き文

構造化文

構造化文は順に実行される文，条件付きで実行される文，繰り返し実行される文で構成されます。

Object Pascal では，次の構造化文がサポートされています。

複合文

条件文

ループ

with 文


参照

ブロック


代入文

参照	例

代入文は代入演算子の右側にある式の値を左側にある識別子に与えます。代入演算子として，代入文の両辺の間で := を使います。

代入文を使うと次の処理ができます。

変数の現在の値を式で指定した新しい値で置き換える

関数が返す値を持つ式を指定する

オブジェクト型の代入文

オブジェクト型のインスタンスには，その下位型であればどの型のインスタンスでも代入できます。このような代入は，上位型の及ぶ空間への下位型の射影になっています。

メモ:	オブジェクト型のインスタンスを代入しても，そのインスタンスは初期化されません。


参照

代入の互換性

代入演算子

オブジェクト型

型の互換性


例

X := Y + Z;

Done := (I >= 1) and (I < 100);

Hue1 := [Blue, Succ(C)];

I := Sqr(J) - I * K;


goto 文

参照

goto 文は指定のラベルでマークされた文へプログラムの実行を転送します。

goto 文を使うときは，次の規則に従わなくてはなりません。

goto 文で参照するラベルは goto 文と同じブロックになくてはならない。手続きや関数にジャンプしたり，手続きや関数から飛び出すことはできない

構造化文に外側からジャンプすると，コンパイラがエラーを出していなくても，予期しない結果になることがある

簡潔なプログラミングのためには，goto 文はできるだけ使わないようにしてください。


参照

goto (予約語)

スコープ


手続き文

参照

手続き文は次のいずれかで指定された手続きを起動します。

手続き識別子

メソッド指定子

限定メソッド指定子

手続き型変数参照

対応する手続き宣言に仮パラメータのリストがある場合，手続き文には実パラメータのリストが入っていなくてはなりません。

実パラメータは呼び出しの一部として仮パラメータに渡されます。


参照

関数呼び出し

メソッドの起動

パラメータ

手続き型

procedure (予約語)

限定メソッドの起動

変数参照


複合文

参照	例	言語定義

複合文では，それを構成する文を書かれている順で実行するように指示します。複合文は 1 つの文として処理されます。このことは，Object Pascal の構文上 1 つの文しか使えないときに重要になります。

複合文は予約語の begin と end で囲み，複合文を構成する各文はセミコロンで区切ります。


例

次の例は複合文のコードです。

begin

  Z := X;

  X := Y;

  Y := Z;

end;


参照

begin..end ブロック

ブロック


ループ

参照	言語定義

ループは，ある条件が満たされるまでまたは満たされている間，文を繰り返し実行するときに使います。

ループには次の 3 種類があります。

for..to/downto..do

while...do

repeat..until

どのループを使うかは次の 2 つの基準によって決まります。

実行したい処理

ループに入る前に処理についてどの程度理解しているか

ループ	使うとき

for	ループの繰り返し回数が正確にわかっている

while...do	ループに入る前に条件をテストしたい

repeat...until	条件をテストする前にループを少なくとも 1 回実行したい

標準手続きの Break と Continue を使うと，ループの流れを制御できます。


参照

条件文

論理式


条件文

参照

条件文は一定の式を評価するかどうかを制御するときに使います。条件文では，特定条件が満たされているかどうかテストしてから，後続の文のブロックを実行します。

条件文には次の 2 種類があります。

if 文

case 文

文の選択肢が 2 つだけの場合は if 文を使います。

文の選択肢が多くある場合は case 文を使います。


参照

論理式

ループ


論理式

参照

論理式は True または False に評価されます。すべてのループと条件文が論理式に左右されます。

論理式では 2 つのオペランドを比較します。その結果は論理型の変数に代入されなくてはなりません。

論理演算子の and と or は論理値の組に作用します。Object Pascal では，論理演算子についてのコード生成のモデルとして次の 2 種類がサポートされています。

完全評価

ショートサーキット評価

評価モデルは $B コンパイラ指令によって制御します。デフォルトの {$B-} 状態ではコンパイラでショートサーキット評価のコードが生成され，{$B+} 状態では完全評価のコードが生成されます。


参照

論理演算子

論理型

関係演算子


パラメータ

参照

パラメータは手続きや関数とのデータの受け渡しに使います。

手続きや関数の宣言では仮パラメータリストを指定します。

仮パラメータリストで宣言された各パラメータは，それが宣言されている手続きや関数にローカルなパラメータです。手続きや関数に関連付けられたブロック文では，識別子によってパラメータを参照できます。

パラメータには次の 5 種類があります。

値パラメータ	var が先頭になく，型が後に付いているパラメータのグループ

定数パラメータ	const が先頭にあり，型が後に付いているパラメータのグループ

変数パラメータ	var が先頭にあり，型が後に付いているパラメータのグループ

型なしパラメータ	var または const が先頭にあり，型が後に付いていないパラメータのグループ

オープン配列パラメータ	配列型のパラメータのグループ


参照

関数呼び出し

関数

手続き


値パラメータ

参照

仮値パラメータはそれが宣言されている手続きや関数にローカルなパラメータです。ただし，呼び出し側の手続きや関数の対応する実パラメータから初期値を取得します。

仮値パラメータへの変更は実パラメータの値には影響を及ぼしません。

手続き文や関数呼び出しでは，値パラメータに対応する実パラメータは式でなくてはなりません。この実パラメータの値はファイル型や，ファイル型を含む構造化型であってはなりません。

実パラメータには仮値パラメータの型との代入の互換性がなくてはなりません。


参照

関数呼び出し

パラメータ

変数パラメータ


定数パラメータ

参照

仮定数パラメータはローカルな読み出し専用変数で，対応する実パラメータから値を取得します。

仮定数パラメータへの代入はできません。仮定数パラメータを別の手続きや関数に実変数パラメータとして渡すこともできません。

手続き文や関数では，定数パラメータに対応する実パラメータは式でなくてはなりません。この実パラメータの値はファイル型や，ファイル型を含む構造化型であってはなりません。

手続きや関数の実行中に仮パラメータの値を変更したくない場合に，値パラメータのかわりに定数パラメータを使います。定数パラメータを使うと，過って仮パラメータへ代入するのを防げます。

構造化型パラメータと文字列型パラメータの場合，値パラメータのかわりに定数パラメータを使うと，コンパイラで生成されるコードの効率が上がります。


参照

関数呼び出し

パラメータ


変数パラメータ

参照

変数パラメータは参照によって手続きや関数に変数を渡します。つまり，パラメータの値に対してアクセスや変更ができるように，パラメータのアドレスが渡されます。

実パラメータを変数パラメータにするには，その実パラメータを変数参照によって渡さなくてはなりません。変数参照は手続き宣言や関数宣言のパラメータリストに予約語の var を入れて作成します。

仮変数パラメータは手続きや関数の起動時の実変数を表します。したがって，仮変数パラメータの値への変更は実パラメータに反映されます。

メモ:	ファイル型は変数パラメータとしてだけ渡すことができます。

手続きや関数の内部では，仮変数パラメータへの参照は実パラメータそのものにアクセスします。実パラメータの型は仮変数パラメータの型と同じでなくてはなりません (型なしパラメータを使うとこの制約を無視できます)。

実変数パラメータへの参照で配列に添字付けしたりポインタの対象を探す必要がある場合，そのような処理は手続きや関数の起動の前に実行されます。


参照

代入の互換性

関数呼び出し

パラメータ

型なしパラメータ


型なしパラメータ

参照	例

仮パラメータが型なしパラメータの場合，対応する実パラメータはその型に関係なくどの変数参照や定数参照であってもかまいません。

予約語の var を使って宣言した型なしパラメータは変更できます。

予約語の const を使って宣言した型なしパラメータは読み出し専用です。

手続きや関数の内部では，型なしパラメータの型は決まっていません。つまり，変数型キャストによって特定の型を与えない限り，ほかのどの型の変数とも互換性がありません。

型なしパラメータを使うと柔軟性が増します。ただし，有効な演算の照合がコンパイラでできないために，型なしパラメータを使うのは危険なことがあります。


例

function Equal(var Source, Dest; Size: Integer): Boolean;

type

  TBytes = array[0..MaxInt - 1] of Byte;

var

  N:Integer;

begin

  N := 0;

  while (N < Size) and (TBytes(Dest)[N] = TBytes(Source)[N]) do

    Inc(N);

  Equal := N = Size;

end;


オープン配列パラメータ

参照	例

オープン配列パラメータは各種サイズの配列を手続きや関数に渡すときに使います。

次の構文を使って仮パラメータをオープン配列パラメータとして宣言します。

array of T

T は型識別子でなくてはなりません。実パラメータは T 型の変数か，要素が T 型の配列変数でなくてはなりません。

手続きや関数の内部では，仮パラメータは次のように宣言した場合と同じように動作します。

array[0..N - 1] of T

N は実パラメータの要素の数です。実パラメータの添字の範囲は 0 から N-1 の整数になります。実パラメータが T 型の単純変数の場合，T 型の要素が 1 つある配列として処理されます。

仮オープン配列パラメータへのアクセスは要素単位でしかできません。オープン配列全体への代入はできません。

オープン配列はオープン配列パラメータまたは型なし変数パラメータとしてだけほかの手続きや関数に渡すことができます。

オープン配列パラメータとして値パラメータ，定数パラメータ，変数パラメータが使えます。各パラメータの制限事項がこの場合も適用されます。

メモ:	オープン配列値パラメータの場合，手続きや関数のスタックフレーム内に実パラメータのローカルコピーがコンパイラによって作成されます。したがって，大きな配列をオープン配列値パラメータとして渡すときに，スタックのオーバーフローが発生しないように注意してください。スタックのオーバーフローが発生しないようにするには，オープン配列値パラメータを渡すときに var または const を使います。

オープン文字配列として渡す場合，空の文字列はヌル文字の要素が 1 つある文字列に変換されます。したがって，PrintStr('') という文は PrintStr(#0) という文と同じです。

オープン配列パラメータの要素の型が Char の場合，実パラメータとして文字列定数が使えます。

オープン配列パラメータに対して次の標準関数が使えます。

関数	戻り値

Low	ゼロ

High	実配列パラメータの最後の要素の添字

SizeOf	実配列パラメータのサイズ

オープン配列パラメータの作成

必要な配列要素をカンマで区切って大カッコ [ ] で囲み，さらにその周りをカッコで囲むと，変数や定数の宣言や代入をしなくてもすぐにオープン配列パラメータを作成できます。したがって，配列を宣言して必要な要素を入れるかわりに，配列を作成して同時に渡せます。

MyProcedure([3, 2, 1900, 42]);


参照

配列型

オープンパラメータ

型可変オープン配列パラメータ


例

procedure Clear(var A: array of Real);  { Real 型の配列の各要素に 0 を代入します }

var

  I: Word;

begin

  for I := 0 to High(A) do A[I] := 0;

end;

function Sum(const A: array of Real): Real;   { Real 型の配列のすべての要素の合計を求めます }

var

  I: Word;

  S: Real;

begin

  S := 0;

  for I := 0 to High(A) do S := S + A[I];

  Sum := S;

end;

procedure PrintStr(const S: array of Char);  { 文字列定数を手続きに渡せるようにします }

var

  I: Integer;

begin

  for I := 0 to High(S) do

    if S[I] <> #0 then Write(S[I]) else Break;

end;


型可変オープン配列パラメータ

参照

array of const という新しい構文は複数の型のオブジェクトからなるオープン配列を型保障方式で手続きや関数に渡すときに使います。これにより，複数の型の項目をいくつでも有効にする形式ルーチンを宣言できます。

次の手続き宣言では，文字列形式関数の宣言で array of const を実際にどのように使うかを示します。パラメータの Args は任意の型の変数をいくつでも入れることができるオープン配列を有効にします。

procedure FmtStr(var Result: string; const Format: string; const Args: array of const);

array of const はコンパイラで array of TVarRec と同じように処理されます。


参照

オープン配列パラメータ


external 宣言

参照	例

external 宣言は次の処理に使います。

アセンブリ言語で作成して別々にコンパイルした手続きや関数との接続

DLL からの手続きや関数のインポート

予約語の external だけからなる external 指令を {$L filename} 指令と一緒に使うと，.OBJ ファイルで実現されている外部手続きや外部関数とリンクできます。

DLL 名を指定して external 指令を使うと (インポート名やインポートの序数も指定できます)，DLL から手続きや関数をインポートできます。

インポートされる手続きや関数では，宣言部と実行部のかわりに外部指令を指定します。この違いを除いて，インポートされる手続きや関数は通常の手続きや関数と同じように動作します。


例

次は外部手続きの宣言の例です。

procedure MoveWord(var Source, Dest; Count: Integer); external;

procedure MoveLong(var Source, Dest; Count: Integer); external;

procedure FillWord(var Dest; Data: Integer; Count: Integer); external;

procedure FillLong(var Dest; Data: Longint; Count: Integer); external;

次の外部宣言は，user32.dll という DLLから MessageBox という関数 (Windows API の一部) をインポートします。

function MessageBox(HWnd: Integer; Text, Caption: Pchar;

Flags: Integer): Integer; stdcall;

external 'user32.dll' name 'MessageBoxA';


参照

ダイナミックリンクライブラリ

関数

手続き


メソッドの宣言

参照	例

オブジェクト型の内部でのメソッドの宣言はそのメソッドの forward 宣言に相当します。

オブジェクト型宣言の後ろのどこかで，そのオブジェクト型宣言と同じスコープ内に，定義宣言によってメソッドを実現しなくてはなりません。

手続きメソッドや関数メソッドの場合，定義宣言は通常の手続きや関数と同じ形式をとります。ただし，手続き識別子や関数識別子のかわりに限定メソッド識別子を使います。

コンストラクタメソッドやデストラクタメソッドの場合，定義宣言は手続きメソッド宣言と同じ形式をとります。ただし，予約語の procedure のかわりに予約語の constructor または destructor を使います。

メソッドの定義宣言では，オブジェクト型でのメソッド頭部の仮パラメータリストを繰り返すことができます。その場合，定義宣言のメソッド頭部はパラメータの順序，型，名前と，(もしあれば) 関数結果の型に正確に一致していなくてはなりません。

Self パラメータ

メソッドの定義宣言では，暗黙の Self パラメータが常にあり，オブジェクト型の仮変数パラメータに対応しています。

メソッドブロック内では，メソッド要素がメソッドを起動するように指定されているインスタンスが Self によって表されます。したがって，Self のフィールドの値への変更はインスタンスに反映されます。


例

{ メソッドの宣言例です }

procedure TRectangle.Intersect(var R: TRectangle);

begin

  if A.X < R.A.X then A.X := R.A.X;

  if A.Y < R.A.Y then A.Y := R.A.Y;

  if B.X > R.B.X then B.X := R.B.X;

  if B.Y > R.B.Y then B.Y := R.B.Y;

  if (A.X >= B.X) or (A.Y >= B.Y) then Init(0, 0, 0, 0);

end;

procedure TField.Display;

begin

  GotoXY(X, Y);

  Write(Name^, ' ', GetStr);

end;

function TNumField.PutStr(S: String): Boolean;

var

  E: Integer;

begin

  Val(S, Value, E);

  PutStr := (E = 0) and (Value >= Min) and (Value <= Max);

end;


参照

コンストラクタとデストラクタ

メソッド

オブジェクト型


コンストラクタとデストラクタ

参照	例

コンストラクタとデストラクタはオブジェクトの作成と廃棄を制御する特殊なメソッドです。

クラスには，そのクラス型のオブジェクトに対してコンストラクタやデストラクタをいくつでも使えますが，使わないこともあります。それぞれのコンストラクタやデストラクタは手続きメソッドや関数メソッドの場合と同じように，クラスの要素として指定します。ただし，procedure や function のかわりに予約語の constructor または destructor で各宣言を始めます。ほかのメソッドと同じように，コンストラクトやデストラクタは継承できます。

コンストラクタ

コンストラクタは新しいオブジェクトを作成して初期化するときに使います。一般に，パラメータとしてコンストラクタに渡される値に基づいてオブジェクトが初期化されます。

通常のメソッドはオブジェクト参照で呼び出さなくてはなりませんが，コンストラクタはクラス参照でもオブジェクト参照でも呼び出せます。

新しいオブジェクトを作成するには，コンストラクタをクラス参照で呼び出さなくてはなりません。コンストラクタをクラス参照で呼び出すと，次のようになります。

新しいオブジェクト用の記憶域がヒープから割り当てられる

割り当てられた記憶域がクリアされる。これによりすべての順序型フィールドの順序値がゼロになり，すべてのポインタ型フィールドとクラス型フィールドの値が nil になり，すべての文字列型フィールドの値が空になる

コンストラクタのユーザー定義の処理が実行される

新しく割り当てられ初期化されたオブジェクトへの参照がコンストラクタから返される。戻り値の型はコンストラクタ呼び出しで指定したクラス型と同じである

コンストラクタをオブジェクト参照で呼び出すと，新しいオブジェクトの割り当てもクリアもされず，コンストラクタ呼び出しでオブジェクト参照が返されません。そのかわりに，コンストラクタが指定のオブジェクト参照に作用し，コンストラクタの実行部に示されたユーザー定義の処理だけを実行します。一般に，コンストラクタをオブジェクト参照で呼び出すのは，キーワードの inherited を一緒に使って継承コンストラクタを実行する場合だけです。

ほとんどの場合，コンストラクタはまず継承コンストラクタを呼び出して，オブジェクトの継承フィールドを初期化します。次に，クラスに導入されたオブジェクトのフィールドを初期化します。コンストラクタは新しいオブジェクト用に割り当てた記憶域を必ずクリアするため，すべてのフィールドにデフォルト値としてゼロ (順序型)，nil (ポインタ型とクラス型)，空 (文字列型)，Unassigned (Variant 型)が自動的に与えられます。フィールドのデフォルト値がゼロ以外の値でなければ，コンストラクタのフィールドを初期化する必要はありません。

クラス参照で呼び出したコンストラクタの実行中に例外が生成された場合，Destroy デストラクタが自動的に呼び出されて未完成のオブジェクトが廃棄されます。

ほかのメソッドと同じように，コンストラクタは仮想にできます。クラス型識別子を使って呼び出す通常の場合，仮想コンストラクタは静的コンストラクタと同じです。ただし，オブジェクト参照型を一緒に使うと，多態性を考慮したオブジェクトの作成，つまりコンパイル時には型がわからないオブジェクトの作成が仮想コンストラクタでできるようになります。

デストラクタ

デストラクタはオブジェクトを廃棄するときに使います。デストラクタを呼び出すと，デストラクタのユーザー定義の処理が実行され，オブジェクト用に割り当てられている記憶域が処分されます。一般に，デストラクタのユーザー定義の処理には，埋め込みオブジェクトの廃棄と，オブジェクトによって割り当てられたリソースの解放があります。

通常，デストラクタは最後に継承デストラクタを呼び出して，オブジェクトの継承フィールドを廃棄します。

クラスに対して複数のデストラクタを宣言できますが，できるだけ継承デストラクタ Destroy のオーバーライドだけをクラスで実現するようにしてください。Destroy は TObject で宣言されるパラメータなしの仮想デストラクタです。TObject はすべてのクラスにとっての最上位クラスなので，Destroy デストラクタはどのオブジェクトに対してでも常に使えます。

コンストラクタの実行中に例外が生成された場合，Destroy デストラクタが呼び出されて未完成のオブジェクトが廃棄されます。つまり，部分的にしか完成していないオブジェクトの廃棄処理のためにデストラクタを作成しておかなくてはなりません。コンストラクタは新しいオブジェクトのすべてのフィールドをヌル値に設定してからユーザー定義の処理を実行するため，部分的にしか完成していないオブジェクトのクラス型フィールドとポインタ型フィールドは必ず nil になります。したがって，デストラクタは常に nil 値のチェックをしてからクラス型フィールドやポインタ型フィールドの操作をしなくてはなりません。

オブジェクト参照では Destroy を呼び出すかわりに Free メソッドを呼び出すと，nil のチェックがされるので便利です。クラス型フィールドに対して Destroy のかわりに Free を呼び出すと，コンストラクタでの例外のために部分的にしか完成していないオブジェクトを処理するデストラクタが自動的に作成されます。したがって，Destroy はできるだけ直接呼び出さないようにしてください。


例

次の例は TShape に対するコンストラクタとデストラクタです。

type

  TShape = class(TGraphicControl)

  private

    FPen: TPen;

    FBrush: TBrush;

    procedure PenChanged(Sender: TObject);

    procedure BrushChanged(Sender: TObject);

  public

    constructor Create(Owner: TComponent); override;

    destructor Destroy; override;

    :

  end;

constructor TShape.Create(Owner: TComponent);

begin

  inherited Create(Owner);	{ 継承部分を初期化します }

  Width := 65;	{ 継承プロパティを変更します }

  Height := 65;

  FPen := TPen.Create;	{ 新しいフィールドを初期化します }

  FPen.OnChange := PenChanged;

  FBrush := TBrush.Create;

  FBrush.OnChange := BrushChanged;

end;

destructor TShape.Destroy;

begin

  FBrush.Free;

  FPen.Free;

  inherited Destroy;

end;

procedure TObject.Free;

begin

  if Self <> nil then Destroy;

end;


参照

オブジェクトのインスタンス化

メソッドの宣言

オブジェクト型


間接ユニット参照

参照	例

モジュールの uses 節では，そのモジュールで直接使うユニットだけに名前を付ける必要があります。

ただし，あるモジュールが別のモジュールに直接依存していることがよくあります。モジュールをコンパイルするには，直接的か間接的かに関係なくそのモジュールが依存しているすべてのユニットをコンパイラで探せなくてはなりません。

ユニットの interface 部を変更した場合，変更したユニットを使うほかのすべてのユニットを再コンパイルしなくてはなりません。［プロジェクト(P)｜再構築(B)］を使うと，この再コンパイルはコンパイラによって実行されます。

ただし，implementation 部や initialization 部だけを変更した場合は，変更したユニットを使うほかのユニットを再コンパイルする必要はありません。

メモ:	C などの言語のユーザーは次の点に注意してください。C++Builder プログラムの uses 節には，他の言語のメイクファイルやプロジェクトファイルに従来からある「make」の論理情報が示されています。この uses 節により，依存関係のすべての情報をモジュールそのものに組み込んで，エラーの可能性を少なくできます。

C++Builder では，ユニットをコンパイルするときにユニットのバージョン番号が計算されるため，ユニットの interface 部がいつ変更されたかがわかります。


参照

ユニット

Uses


例

{ 次の例はユニット間の依存関係を示します。Unit2 が Unit1 に直接依存し, Prog が Unit2 に直接依存していることに注意してください }

program Prog;

uses Unit2;

const a = b;

begin

end.

unit Unit2;

interface

uses Unit1;

const b = c;

implementation

end.

unit Unit1;

interface

const c = 1;

implementation

const d = 2;

end.


ユニット循環参照

参照	例

ユニットの循環参照はユニットが相互に依存しているときに設定されます。

ユニットの implementation 部に uses 節を入れると，相互に依存するユニットが設定され，uses 節で参照されているユニットの内部の詳細が完全に隠れます。参照されているユニットはプライベートなユニットになり，それを参照しているユニットを使うプログラムやユニットでは利用できなくなります。

C++Builder では完全な interface 部をコンパイルできるため，2 つのユニットはそれぞれの implementation 部の uses 節で相互に参照できます。2 つのユニットの interface 部が相互に依存していない限り，一方のユニットの implementation 部に示されている部分コンパイルユニットへの参照をコンパイラは受け付けます。したがって，この 2 つのユニットは Pascal での宣言順序に関する厳密な規則に従います。

interface 部が相互に依存している場合，ユニットの循環参照のエラーが生成されます。

相互に依存するユニットが役立つのは特殊な場合ですが，いつ使うかを考慮してください。必要もないのにこのようなユニットを使うと，プログラムが管理しにくくなり，エラーを起こしやすくなることがあります。


参照

ユニット

Uses


例

{ 次のプログラムは 2 つのユニットが互いに相手を「使う」方法を示します }

program Circular;

{ WriteXY を使ってテキストを表示します }

uses

  WinCrt, Display;

begin

  ClrScr;

  WriteXY(1, 1, 'Upper left corner of screen');

  WriteXY(1000, 1000, 'Way off the screen');

  WriteXY(81 - Length('Back to reality'), 15, 'Back to reality');

end.

unit Display;

{ 単純なビデオ表示ルーチンを含んでいます }

interface

procedure WriteXY(X, Y: Integer; Message: String);

implementation

uses

  WinCrt, Error;

procedure WriteXY(X, Y: Integer; Message: String);

begin

  if (X in [1..80]) and (Y in [1..25]) then

  begin

    GoToXY(X, Y);

    Write(Message);

  end

  else

    ShowError('Invalid WriteXY coordinates');

end;

end.

unit Error;

{ 単純なエラーレポートルーチンを含んでいます }

interface

procedure ShowError(ErrMsg: String);

implementation

uses Display;

procedure ShowError(ErrMsg: String);

begin

  WriteXY(1, 25, 'Error: ' + ErrMsg);

end;

end.


ヒープマネージャ

参照

Windows では，次の 2 種類のヒープで動的メモリ割り当てがサポートされています。

グローバルヒープ

ローカルヒープ

Delphi には，次の標準手続きを実現するヒープマネージャがあります。

New

Dispose

GetMem

FreeMem

ヒープマネージャはすべての割り当てにグローバルヒープを使います。グローバルヒープにはシステム全体で 8192 メモリブロックという制限があるため (アプリケーションによってはこれより多くのメモリブロックが必要になる場合があります)，ヒープマネージャはセグメントサブアロケータのアルゴリズムによって処理効率を上げ，8192 をかなり上回る数のメモリブロックを割り当てられるようにしています。

ブロックのセグメントアドレスが変更されないように，グローバルブロックは割り当ての直後に GlobalLock によってロックされます。割り当て解除の直前までこのロックは解除されません。

Windows のスタンダードモードと 386 エンハンスドモードでは，物理メモリの固定ブロックを移動して，ほかのメモリ割り当て要求のために空き領域を確保できます。したがって，C++Builder のヒープマネージャを使っても処理効率が下がることはありません。


参照

DLL


終了手続き

参照	例

終了手続きはプログラムの終了プロセスを制御するときに使います。プログラムを終了する前に特定の処理をしたいときに (たとえばファイルを更新して閉じる処理などが一般的です)，この制御が役立ちます。

アプリケーションの終了には次の 3 種類があります。

正常終了

Halt の呼び出しによる終了

実行時エラーによる終了 (C++Builder ではアプリケーションを終了しなくても例外処理によって実行時エラーを処理できる)

終了手続きをインストールするには，ポインタ変数の ExitProc を使います。

終了手続きはパラメータをとりません。

正しく実現した終了手続きは，終了手続きの連鎖に組み込まれています。これにより，ユニットとプログラムの両方で終了手続きをインストールできます。ユニットで初期化コードの一部として終了手続きをインストールした場合，その手続きがユニットの後始末のために必ず呼び出されるようになります。

終了手続きの連鎖では，インストールのときとは逆の順序で手続きが実行されます。したがって，各ユニットの終了コードは，そのユニットに依存しているユニットの終了コードが終わるまで実行されません。

終了手続きの連鎖を保持するには，次の 2 つを実行しなくてはなりません。

ExitProc を終了手続きのアドレスに変更する前に，ExitProc の現在の内容を保存する

保存した ExitProc の値を終了手続きの最初の文に再び挿入する

ラインタイムライブラリの終了ルーチンは ExitProc が nil になるまで終了手続きを呼び出し続けます。

無限ループを避けるために，どの呼び出しの前でも ExitProc が nil に設定されるので，現在の終了手続きで ExitProc にアドレスが代入されたときだけ次の終了手続きが呼び出されます。終了手続きでエラーが発生した場合，その終了手続きが再び呼び出されることはありません。

終了手続きでは，整変数の ExitCode とポインタ変数の ErrorAddr を調べることにより，終了の原因がわかります。終了の種類に応じて，ExitCode と ErrorAddr の値は次のようになります。

変数	正常終了	停止	実行時エラー

ExitCode	ゼロ	Halt に渡された値	エラーコード

ErrorAddr	nil	nil	エラー文のアドレス

最後の終了手続き (ラインタイムライブラリによってインストールされた終了手続き) は Input ファイルと Output ファイルを閉じます。ErrorAddr が nil でなければ，実行時エラーメッセージを出力します。

エラーメッセージ

実行時エラーメッセージを自分で表示したい場合は，ErrorAddr を調べて nil でなければメッセージを出力するような終了手続きをインストールします。制御を戻す前に必ず ErrorAddr を nil に設定し，同じエラーがほかの終了手続きで再びレポートされないようにします。

すべての終了手続きを呼び出すと，ラインタイムライブラリは Windows に制御を戻し，ExitCode の値を戻りコードとして渡します。


参照

DLL

例外処理


例

{ 次の例は終了手続きの実現方法の概略を示しています }

program Testexit;

var

 ExitSave: Pointer;

procedure MyExit;  far;

begin

  ExitProc := ExitSave;  { 必ず古いベクタから先に回復します }

end;

begin

  ExitSave := ExitProc;

  ExitProc := @MyExit;

end.


 コンポーネントの Z オーダーの変更

フォーム上でコンポーネントが重なり合っている場合，最後に追加されたコンポーネントを含む面が，それ以前に追加されているコンポーネントを含む面より常に前にきます。つまり，フォーム上で重なり合うコンポーネントは層状になります。

   後方   [image]  前方

表示したい順に並ぶようにコンポーネントを追加していない場合もあります。その場合，コンポーネントを別のコンポーネントの後ろに移動できます。コンポーネントを移動するには，その表示層の位置を変更しなくてはなりません。コンポーネントはレイアウトの Z 軸 (深さ) 上にあるため，フォーム上のコンポーネントの表示層は Z オーダーといいます。どのコンポーネントの前に (または上に) どのコンポーネントがくるかは Z オーダーによって決まります。

フォームの背景に表示したいグラフィックや図形を追加するときに，Z オーダーが非常に役に立ちます。

コンポーネントの Z オーダーを変更するには

1.	コンポーネントを選択します。

2.	コンポーネントの移動方向に応じて［編集(E)｜前面に移動(F)］または［編集(E)｜背面に移動(B)］を選択します。

メモ:	ウィンドウコントロールと非ウィンドウコントロールには，それぞれ専用の Z オーダー論理があります。非ウィンドウコントロール (Label コンポーネントや Shape コンポーネント) はウィンドウコントロール (ボタンなど) の Z オーダーには挿入できません。


呼び出し規約

参照

Object Pascal には 4 つの指令があり，手続きや関数へパラメータを渡すための呼び出し規約を指定できるようになっています。デフォルトの呼び出し規約は常に register です。

呼び出し規約は以下の 3 つの点で異なります。

パラメータを渡す順序

スタックからのパラメータの削除 (クリーンアップ)

レジスタを使ったパラメータ渡し

register 規約と pascal 規約では，パラメータは左から右へ渡されます。つまり，左端のパラメータが最初に評価されて渡され，右端のパラメータが最後に評価されて渡されます。cdecl 規約と stdcall 規約では，パラメータは右から左へ渡されます。cdecl を除くすべての規約では，手続きまたは関数が戻りと同時にスタックからパラメータを削除します。cdecl 規約では，呼び出し側が呼び出しの戻り時にスタックからパラメータを削除しなければなりません。register 規約では 3 つまでの CPU レジスタを使ってパラメータが渡されますが，その他の規約ではスタック上にあるすべてのパラメータが常に渡されます。

次の表に呼び出し規約の概要を示します。

指令	順序	クリーンアップ	レジスタ使用
register	左から右	関数	あり
pascal	左から右	関数	なし
cdecl	右から左	呼び出し側	なし
stdcall	右から左	関数	なし

register 規約はスタックフレームの作成を回避する場合が多いのでもっとも効率的です。pascal 規約と cdecl 規約は通常，C，C++ などの言語で書かれたダイナミックリンクライブラリ内のルーチンを呼び出す場合に役立ちます。stdcall 規約は Windows API ルーチンを呼び出すために使われます。


参照

手続き

関数


演算子の優先順位

参照

演算子は 1 つまたは複数のデータに対して演算をすることを示すシンボルまたは予約語です。

Object Pascal の演算子の優先順位を次に示します。

演算子	優先順位	カテゴリ

@ not	1 番目 (高)	単項演算子

* / div mod as	2 番目	乗除と型キャストの

and shl shr 	演算子

+ - or xor	3 番目	加減演算子

= <> < >	4 番目 (低)	関係，集合帰属関係，

<= >= in is 	型比較の演算子

優先順位の規則

1.	優先順位が異なる 2 つの演算子の間のオペランドは優先順位が高い方の演算子と結びつきます。

2.	等価な 2 つの演算子の間のオペランドは左側の演算子に結びつきます。

3.	カッコ内の式は評価された後に 1 つの演算子として取り扱われます。


参照

@ 演算子

代入演算子

二項算術演算子

ビット演算子

論理演算子

文字ポインタ演算子

関係演算子

集合演算子

文字列演算子

単項算術演算子

バリアント演算子


二項算術演算子

参照	演算子

二項算術演算子は 2 つのオペランドに対して算術演算をします。

次の二項算術演算子があります。

演算子	演算	オペランド	結果

+	加算	整数型	整数型

実数型	実数型

-	減算	整数型	整数型

実数型	実数型

*	乗算	整数型	整数型

実数型	実数型

/	除算	整数型	実数型

実数型	実数型

div	整数除算	整数型	整数型

mod	剰余	整数型	整数型

型が順序型の部分範囲であるオペランドは順序型として取り扱われます。

+，-，*，div, mod 演算子の一方または両方のオペランドが整数型の場合，結果の型は 2 つのオペランドの共通型です。

+，-，* 演算子の両方のオペランドが実数型の場合，結果の型は Extended です。

X/Y の値はオペランドの型に関係なく常に Extended 型です。 Y が 0 の場合， 実行時エラーになります。 実行時エラーは例外を使って処理できます。

I div J  は I / J の算術商を 0 の方向の整数型値に丸めた値です。 J が 0 の場合， エラーになります。 実行時エラーは例外を使って処理できます。

mod 演算子は 2 つのオペランドによる除算の剰余を返します。

  I mod J = I - (I div J) * J

mod の結果の符号は I の符号と同じです。J が 0 の場合，エラーになります。

メモ:	+，-，* 演算子は集合演算子，文字ポインタ演算子，単項演算子としても使えます。+ 演算子は文字列演算子でもあります。


参照

型


Is 演算子

参照

is 演算子は動的型チェックをするのに使います。is 演算子を使うと，オブジェクト参照の実際 (実行時) の型が特定のクラスに属するかどうかをチェックできます。is 演算子の構文を次に示します。

ObjectRef is ClassRef

ObjectRef はオブジェクト参照で，ClassRef はクラス参照です。is 演算子は論理値を返します。結果は ObjectRef が ClassRef によって示されるクラスのインスタンスまたは ClassRef によって示されるクラスから派生したクラスのインスタンスならば True です。それ以外の場合は，False です。ObjectRef が nil ならば結果は常に False です。ObjectRef と ClassRef の宣言された型が関係ないことがわかっている場合，すなわち ObjectRef の宣言された型が ClassRef の上位，等価，下位のいずれでもないことがわかっている場合，コンパイラは型不一致エラーを報告します。

is 演算子は保護された型キャストのために if 文と一緒に使うことがよくあります。たとえば，次のように使います。

if ActiveControl is TEdit then TEdit(ActiveControl).SelectAll;

ここでは is テストが True の場合，ActiveControl を安全にクラス TEdit に型キャストできます。

演算子優先順位の規則では is 演算子は関係演算子 (=，<>，<，>，<=，>=，in) と同じグループに属します。つまり，and と or 演算子を使って他の論理式と結合する場合，is テストはカッコで囲まなくてはなりません。

if (Sender is TButton) and (TButton(Sender).Tag <> 0) then ...;


参照

条件文


As 演算子

参照

as 演算子はチェック付きの型キャストをするのに使います。as 演算子の構文を次に示します。

ObjectRef as ClassRef

ObjectRef はオブジェクト参照で，ClassRef はクラス参照です。結果の値は ObjectRef と同じオブジェクトへの参照ですが，ClassRef によって与えられる型です。実行時に評価する場合，ObjectRef は nil, ClassRef によって示されるクラスのインスタンス，ClassRef によって示されるクラスから派生したクラスのインスタンスのいずれかでなくてはなりません。いずれの条件も True でない場合，例外が生成されます。ObjectRef と ClassRef の宣言された型が関係ないことがわかっている場合，すなわち ObjectRef の宣言された型が ClassRef の上位，等価，下位のいずれでもないことがわかっている場合，コンパイラは型不一致エラーを報告します。

as 演算子は with 文と一緒に使うことがよくあります。たとえば，次のように使います。

with Sender as TButton do

begin

  Caption := '&Ok';

  OnClick := OkClick;

end;

演算子優先順位の規則では as 演算子は乗除算演算子 (*，/，div, mod, and, shl, shr) と同じグループに属します。つまり，変数参照内で使う場合，as 型キャストはカッコで囲まなくてはなりません。

(Sender as TButton).Caption := '&Ok';


参照

変数の型キャスト

With 文


単項算術演算子

演算子

単項算術演算子はオペランドの符号を示します。

次の単項算術演算子があります。

演算子	演算	オペランド	結果

+	符号識別	整数型	整数型

実数型	実数型

-	符号否定	整数型	整数型

実数型	実数型

メモ:	型が順序型の部分範囲のオペランドは順序型として取り扱われます。

+ または - 演算子のオペランドが実数型の場合，結果の型は Extended です。

メモ:	+ と - 演算子は集合演算子，文字ポインタ演算子，二項演算子としても使えます。+ 演算子は文字列演算子でもあります。


ビット演算子

演算子

ビット演算子は整数のビット値を変更します。

次のビット演算子があります。

演算子	演算	オペランド	結果

not	ビット否定	整数型	整数型

and	ビットの論理積	整数型	整数型

or	ビットの論理和	整数型	整数型

xor	ビットの

排他的論理和	整数型	整数型

shl	ビットの左シフト	整数型	整数型

shr	ビットの右シフト	整数型	整数型

not はビット値を反転します。たとえばビットが 1 ならば，not によって 0 になります。

not は単項演算子です。not 演算子のオペランドが整数型の場合，結果は同じ整数型です。

ビット演算子 and, or, xor は対応するビット間の論理演算をします。

and, or, xor 演算子の両方のオペランドが整数型の場合，結果の型は 2 つのオペランドの共通型です。

演算 I shl J と I shr J は I の値を左または右に J ビットだけシフトします。結果の型は I の型と同じです。

not, and, or, xor は論理演算子でもあります。


論理演算子

参照	演算子

論理演算子は式を評価するために論理ロジックを使います。

次の論理演算子があります。

演算子	演算	オペランド	結果

not	論理否定	論理	論理

and	論理積	論理	論理

or	論理和	論理	論理

xor	排他的論理和	論理	論理

not は論理値を反転します。たとえば not True は False です。not は単項演算子です。

and は両方のオペランドが True ならば，True を返します。

or はいずれかまたは両方のオペランドが True ならば，True を返します。

xor は両方ではなくいずれか一方のオペランドだけが True ならば，True を返します。両方のオペランドが True の場合は，False を返します。

and と or 演算子は論理値のペアに対して作用し，Object Pascal はこれらの演算子について 2 種類のコード生成モデルをサポートしています。

完全評価

ショートサーキット評価

評価モデルは $B コンパイラ指令によって制御します。デフォルト状態 {$B-} ではコンパイラはショートサーキット評価コードを生成します。{$B+} 状態ではコンパイラは完全評価を生成します。

not, and, or, xor はビット演算子でもあります。


参照

論理式

論理型


文字列演算子

参照	演算子

+ 演算子は 2 つの文字列を結合します。

演算子	演算	オペランド	結果

+	結合	文字列型，char 型，	文字列型

パック文字列型の

いずれか

結果は文字列型と互換性があります (しかし，char とパック文字列型とは互換性がありません)。

両方のオペランドが短い文字列で結果の文字列が 255 文字より長い場合，256 文字以降は切り捨てられます。一方または両方のオペランドが長い文字列の場合は結果も長い文字列になります。

メモ:	+ 演算子は集合演算子，単項演算子，文字ポインタ演算子，二項演算子としても使えます。


参照

関係演算子


文字ポインタ演算子

演算子

正符号 (+) と負符号 (-) 演算子はポインタ値をインクリメントしたりデクリメントします。負符号演算子は 2 つの文字ポインタのオフセット部分間の距離 (差) を計算できます。

P と Q が PChar 型の値で，I が Integer 型の値だとすると，次の構文が許されます。

構文	結果

P + I	P に I を加算する

I + P	P に I を加算する

P - I	P から I を減算する

P - Q	P から Q を減算する

演算 P + I と I + P は P によって与えられたアドレスに I を加算し，P より I 文字後ろの文字を指すポインタを生成します。

演算 P - I は P によって与えられたアドレスから I を減算し，P より I 文字前の文字を指すポインタを生成します。

演算 P - Q は Q (下位アドレス) と P (上位アドレス) 間の距離を計算し，Q と P の間の文字数を与える Integer 型の値を生成します。

この演算では P と Q が同じ文字配列内を指すものとします。2 つの文字ポインタが別の文字配列を指す場合，結果は未定義になります。


集合演算子

演算子

集合演算子は 2 つの集合の和，差，積を求めたり，集合の帰属関係をテストするのに使います。

次の集合演算子があります。

演算子	演算	オペランド

+	和	互換性のある集合型

-	差	互換性のある集合型

*	積	互換性のある集合型

in	帰属関係	左のオペランド: 任意の順序型 T
右のオペランド: 基本型が T と互換性のある集合

集合演算の結果は集合論理の次の規則に従います。

順序値 C は A または B に含まれる場合だけ，A  +  B に含まれる

順序値 C は A に含まれ，しかも B に含まれない場合だけ，A  -  B に含まれる

順序値 C は A と B の両方に含まれる場合だけ，A  *  B に含まれる

集合演算の結果に帰属する最も小さな順序値が A で，最も大きな順序値が B の場合，結果の型は set of A..B です。+，-，* 演算子の結果は集合で，in 演算子の結果は論理型です。


関係演算子

参照	演算子

関係演算子はオペランドを比較し，結果に基づく論理値を返します。

演算子	演算	結果	オペランド

=	等しい	論理	互換性のある単純，クラス，クラス参照，ポインタ，集合，文字列，パック文字列，Variant の各型

<>	等しくない	論理	互換性のある単純，クラス，クラス参照，ポインタ，集合，文字列，パック文字列，Variant の各型

<	より小さい	論理	互換性のある単純，文字列，パック文字列，PChar，Variant の各型

>	より大きい	論理	互換性のある単純，文字列，パック文字列，PChar，Variant の各型

<=	以下	論理	互換性のある単純，文字列，パック文字列，PChar，Variant の各型

>=	以上	論理	互換性のある単純，文字列，パック文字列，PChar，Variant の各型

<=	左辺が右辺の	論理	互換性のある集合型

部分集合

>=	右辺が左辺の	論理	互換性のある集合型

部分集合


参照

論理式

論理演算子

型の互換性


@ (at) 演算子: ポインタ操作

参照	例	演算子

@ 演算子は変数，手続き，関数，メソッドのアドレスを計算するためにアドレス因子内で使います。

@ 演算子はオペランドのアドレスを返します。つまり，オペランドを指すポインタ値を作成します。

@ 演算子によって変数へのポインタを作成できます。

@ は単項演算子です。

@ 演算子を手続き型変数と一緒に使う場合は，特殊な規則が適用されます。

値の型は nil の型と同じなので，どのポインタ変数にも代入できます。

@ と一緒に使うもの	返すポインタが指すもの

変数	変数

値パラメータ	実際の値が入ったスタック場所

変数パラメータ	実パラメータ。ポインタ型の値は $T コンパイラ指令によって制御する

手続きまたは関数	手続きまたは関数のエントリポイント

メソッド	メソッドのエントリポイント

@ 演算子を変数参照に適用した場合，結果のポインタ値の型は {$T} コンパイラ指令によって制御されます。

ルーチンのエントリポイントを指す結果のポインタの型は常に Pointer です。

メソッドまたは手続きポインタはアセンブリ言語ルーチンに渡すことだけが許されます。

メソッドは限定メソッド識別子によって参照するようにしてください。


例

{次のコードはパラメータのコピーを変更します}

procedure ValueEx (X :Integer);

var

  ptr : ^integer;

begin

  ptr := @X;

  writeln(Ptr^);

  Ptr^ := 15;

end;

var

  Fred : integer;

begin

  Fred := 10;

  ValueEx (Fred);

  Writeln (Fred);    {10}

end.

{次のコードは実パラメータを変更します}

procedure VarEx(var Y : integer);

var Ptr : ^integer;

begin

  Ptr := @Y;

  writeln (Ptr^);

  Ptr^ := 15;

end;

var Fred : integer;

begin

  Fred := 10;

  VarEx (Fred);

  writeln (Fred);    {15}

end.


参照

手続き値

値パラメータ

変数パラメータ


代入演算子 ( :=)
代入演算子

参照	例	演算子

構文

説明

代入演算子 := は (右辺の) 式の値を (左辺の) 同じ型の変数に与えます。


例

X    := Y;

Done := (I > 0) and (I < 100)

A[I] := A[I] + 1;


参照

代入の互換性

式

文

変数


バリアント演算子

参照	演算子

+，-，*，/，div，mod，shl，shr，and，or，xor，not の各演算子はバリアント型のオペランドをサポートしています。二項演算子の場合，一方のオペランドがバリアント型ならばもう一方のオペランドもバリアント型に自動変換されます。


参照

バリアント型

バリアント式


予約語

参照

予約語には Object Pascal 言語の中で決められた意味があります。予約語は再定義できません。

Object Pascal は大文字と小文字を区別しないので，予約語を記述するときは大文字と小文字を任意に組み合わせて使えます。

ボーランドのマニュアルやこのヘルプシステムでは，予約語を太字体で表記しています。

Object Pascal の予約語のアルファベット順一覧を次に示します。

and

as

asm

array

begin

case

class

const

constructor

destructor

div

do

downto

else

end

except

exports

file

finalization

finally

for

function

goto

if

implementation

in

inherited

inline

initialization

interface

is

label

library

mod

nil

not

object

of

on

or

packed

procedure

program

property

raise

record

repeat

set

shl

shr

string

then

threadvar

to

try

type

unit

until

uses

var

while

with

xor


参照

標準指令


標準指令

参照

Object Pascal の標準指令には定義済みの意味があり，再定義も可能です。ただし再定義はなるべくしないでください。指令はユーザー定義の識別子が出現できないコンテキストでのみ使います。

ボーランドのマニュアルやこのヘルプシステムでは，標準指令を太字体で表記しています。

Object Pascal は大文字と小文字を区別しないので，指令を記述するときは大文字と小文字を任意に組み合わせて使えます。

Object Pascal の標準指令のアルファベット順一覧を次に示します。

absolute

abstract

assembler

at

automated

cdecl

default

dispid

dynamic

external

forward

index

message

name

nodefault

on

override

pascal

private

protected

public

published

read

register

resident

stdcall

stored

virtual

write

private，protected，public，published，automated の各指令はクラス型宣言の中では予約語として働きますが，それ以外の状況では予約語として扱われます。


参照

予約語


Absolute (標準指令)
Absolute

例	標準指令

構文

absolute <address>

説明

標準指令 absolute は特定のメモリアドレスに位置する変数を宣言します。

次のどちらかの指定ができます。

変数を特定のアドレスに直接割り当てる

別の変数と同じメモリアドレスに位置する変数を宣言する

最初の形式では変数のアドレスを直接指定します。

2 番目の形式は既存の変数の上 (同じアドレス位置) に新しい変数を宣言します。

変数宣言に absolute 節がある場合，識別子リストには 1 つの識別子だけを指定できます。


例

var

  Str: ShortString;

  StrLen: Byte absolute Str;


Abstract (標準指令)
Abstract

例	標準指令

説明

abstract 指令はオブジェクト定義で使われ，この指令が指定されたオブジェクト内では仮想メソッドまたは動的メソッドが宣言されないことを示します。この定義は下位のクラスにも継承されます。有効な抽象メソッドはインターフェースを定義しますが，基本操作の定義はしません。

メソッドを抽象として宣言するには先に virtual または dynamic と宣言しなくてはなりません。抽象メソッドはオーバーライドせずに呼び出してはなりません。抽象メソッドのオーバーライドは通常の仮想メソッドまたは動的メソッドのオーバーライドと同じですが，オーバーライドする側のメソッドの実現で inherited メソッドを呼び出せない点が異なります。

オーバーライドされていない抽象メソッドを呼び出そうとすると，ランタイムライブラリの手続き Abstract が呼び出され，プログラムはランタイムエラーで終了します。


例

type

  TMyObject = class

    procedure Something; virtual; abstract;

  end;


Array (予約語)
Array

参照	例

構文

array [index-type] of element-type

説明

予約語 array は配列型を定義します。

複数のインデックス型をカンマで区切って指定できます。

要素型はどの型でもかまいませんが，インデックス型は順序型でなくてはなりません。


例

type

  IntList  = array[1..100]     of Integer;

  CharData = array['A'..'Z']   of Byte;

  Matrix   = array[0..9, 0..9] of real;


参照

配列型

配列型定数

インデックス


Asm (予約語)
Asm

参照	予約語

構文

  asm

    AssemblerStmt <Separator AssemblerStmt>

  end

AssemblerStmt はアセンブラ文を示す

Separator はセミコロン，改行，Pascal コメントのいずれかである

説明

予約語 asm は組み込みアセンブラにアクセスします。

複数のアセンブラ文を 1 行に指定する場合，それぞれをセミコロンで区切ります。アセンブラ文を別々の行に置く場合はセミコロンは不要です。

asm 文では，セミコロンは行の残り部分がコメントであることを意味しません。コメントは { と } または (* と *) を使う Pascal スタイルでなくてはなりません。

レジスタの使い方

asm 文でのレジスタの使い方の規則は外部の手続きまたは関数での規則と同じです。

asm 文では次のレジスタを保証しなくてはなりません。

EDI	ESI

EBP	EBX

asm 文では次のレジスタを自由に変更できます。

EAX	EDX	ECX

EDI，ESI，EBP，EBX レジスタ以外については，asm 文はレジスタの内容について何も想定しません。


参照

Assembler 指令

コメント

External


Assembler (手続き指令)
Assembler

参照	標準指令

構文

説明

標準指令 assembler を使うと，begin...end 文を使わずにインラインアセンブリ言語で完全な手続きや関数を記述できます。

assembler を使うとコンパイラは次のようなコード生成の最適化を実行します。

値パラメータ: コンパイラは値パラメータをローカル変数にコピーするコードを生成しない。この最適化はすべての文字列型の値パラメータとサイズが 1，2，4 バイト以外の値パラメータに作用する

手続きや関数内では，これらのパラメータは var パラメータとして扱わなくてはならない

関数結果変数: コンパイラは関数結果変数を割り当てず，@Result シンボルへの参照はエラーになる

文字列関数は関数結果の最適化では例外として扱われる。文字列関数は呼び出し側によって割り当てられた @Result ポインタを常に持っている

スタックフレーム: コンパイラはパラメータやローカル変数を持たない手続きと関数にはスタックフレームを生成しない

アセンブラ手続きまたは関数に自動的に生成されるエントリコードと終了コードは次のようになります。

  PUSH   BP          ;Locals <> 0 または Params <> 0 ならば生成します

  MOV    BP, SP      ;Locals <> 0 または Params <> 0 ならば生成します

  SUB    SP, Locals  ;Locals <> 0 ならば生成します

    .

    .

    .

  MOV    SP, BP      ;Locals <> 0 ならば生成します

  POP    BP          ;Locals <> 0 または Params <> 0 ならば生成します

  RET    Params      ;常に生成されます

Locals と Params がともにゼロの場合，エントリコードは生成されず，終了コードは RET 命令だけになります。

assembler を使う関数は結果を次のように返さなくてはなりません。

関数の型	返される結果

順序型	AL (8 ビット値)
AX (16 ビット値)
EAX (32 ビット値)

実数	コプロセッサのレジスタスタック上の ST(0)

ポインタ	EAX

短い文字列	@Result で示される一時的な位置


参照

Asm


automated (標準指令)
automated

参照	標準指令

オートメーションコンポーネントの可視性規則はパブリックコンポーネントの場合とほぼ同じです。オートメーションコンポーネントがパブリックコンポーネントと異なる唯一の点は，automated 部の中で宣言されたメソッドとプロパティ用にオートメーション型情報が生成される点です。このオートメーション型情報によって，OLE オートメーションサーバーの作成が可能になります。

メモ	automated 部は通常，OleAuto ユニットの中に定義されている TAutoObject クラスの派生クラスの中だけで使われます。C++Builder を使った OLE オートメーションサーバーの作成についての詳細は，『C++Builder ユーザーズガイド』を参照してください。

automated 部の中で宣言したメソッドとプロパティには以下の制限事項が適用されます。

メソッドの場合，すべてのメソッドパラメータの型と関数の結果 (もしあれば) はオートメーションが可能な型でなければならない。同様にプロパティの場合，プロパティの型と配列プロパティパラメータの型はオートメーションが可能な型でなければならない

オートメーションが可能な型は，Byte，Currency，Double，Integer，Single，Smallint，string，TDateTime，Variant，WordBool である

オートメーションが不可能な型を使うメソッドまたはプロパティを automated 部で宣言するとエラーになる

メソッド宣言には register 呼び出し規約 (デフォルト) を使わなければならない

メソッドは virtual で仮想にできるが，dynamic で動的にはできない

プロパティ宣言にはアクセス指定子 (read と write) だけを使え，ほかの指定子 (index，stored，default，nodefault) は使えない

プロパティアクセス指定子ではメソッド識別子を指定しなければならない。フィールド識別子は使えない

プロパティアクセスメソッドには register 呼び出し規約を使わなければならない

プロパティオーバーライド (プロパティ型を含まないプロパティ宣言) は許されない

automated 部内のメソッド宣言またはプロパティ宣言には，オプションの dispid 指令を指定できます。この指令の後には，メソッドまたはプロパティの OLE オートメーションディスパッチ ID を指定する整数定数を置かなければなりません。dispid 指令を指定しないと，コンパイラはそのクラスと上位クラスのメソッドまたはプロパティが使っている最大のディスパッチ ID より 1 だけ大きい数を自動的に選択します。すでに使われているディスパッチ ID を dispid 指令の中に指定すると，コンパイルエラーになります。


参照

コンポーネントの可視性

private

protected

public

published


begin...end ブロック (予約語)
begin ... end ブロック

参照	例	予約語

構文

説明

予約語 begin と end は一連の文をグループ化して複合文にします。

複合文は 1 つの文として扱われます。


例

(* 複合文を if 文内で使います *)

if First < Last then

begin

  Temp := First;

  First := Last;

  Last := Temp;

end;


参照

文


Case (予約語)
Case

参照	例	予約語

構文

説明

case 文はコード内で検出された結果または値に基づいてコードを分岐するために使います。

case 文は式 (セレクタ) と文のリストで構成され，各文の先頭には 1 つまたは複数の定数 (case 定数) または予約語 else が置かれます。セレクタは順序型でなくてはならないため，文字列型はセレクタの型としては無効です。

すべての case 定数はユニークでなくてはならず，セレクタ型と互換の順序型でなくてはなりません。

プログラムが case 文に入ると，一致する値が見つかるまで各式が評価されます。一致する値が見つかるとプログラムはその式に関連付けられているアクションを実行します。一致する値が見つからない場合，else 文がデフォルトとして使われます。else 部がない場合，case 文の次の文が続いて実行されます。

case 文の範囲は重複してはなりません。したがって，次の case 文は認められません。

case MySelector of

  5: Writeln('Special case');

  1..10: Writeln('General case');

end;

case 定数を昇順に配置するとコンパイラは case を最適化してジャンプに置き換えるため，毎回計算をする必要がなくなります。たとえば，コンパイラは次の case 文をジャンプに置き換えます。

case MySelector of

  1: Writeln('One');

  2: Writeln('Two');

  else Writeln('More');

end;

次の場合は計算が複数回実行されます。

case MySelector of

  2: Writeln('Two');

  1: Writeln('One');

  else Writeln('More');

end;


例

case Ch of

  'A'..'Z', 'a'..'z':  WriteLn('Letter');

  '0'..'9':            WriteLn('Digit');

  '+', '-', '*', '/':  WriteLn('Operator');

else

  WriteLn('Special character');

end;


参照

Else

式

文


cdecl (標準指令)
Cdecl

参照	標準指令

構文

procedure A; cdecl;

説明

cdecl 指令は，手続きまたは関数がパラメータの受け渡しに C/C++ の呼び出し規約を使うことを指定します。

C/C++ 呼び出し規約では，パラメータは右から左の順で渡され，スタック上のパラメータは呼び出し側が取り除きます。

C/C++ 呼び出し規約は，C/C++ あるいは他の言語で書かれたダイナミックリンクライブラリ (DLL) からエクスポートするルーチンを呼び出すためには最も便利です。


参照

呼び出し規約

pascal

register

stdcall


Class (予約語)
Class

参照	予約語

構文

説明

予約語 class はオブジェクト型またはクラスメソッドを宣言するために使います。クラス参照型を定義するためにも使います。

オブジェクト型は決められた個数のコンポーネントを持つデータ構造です。各コンポーネントはフィールド (特定の型のデータを含む)，オブジェクトに対して操作を実行するメソッド，またはプロパティのいずれかです。

フィールドの宣言ではフィールドの名前を指定する識別子と，データ型を指定します。

メソッドの宣言では手続き，関数，コンストラクタ，またはデストラクタのヘッダーを指定します。

プロパティの定義ではプロパティとそのアクセスメソッドを指定し，さらに処理の流れの間にプロパティがどのように動作するかについての情報を指定できます。

オブジェクト型は別のオブジェクト型からコンポーネントを継承できます。継承されるオブジェクトは下位オブジェクトであり，継承元のオブジェクトは上位オブジェクトです。

オブジェクト型のドメインはそのオブジェクト自体とすべての下位オブジェクトで構成されます。

クラス参照型は予約語 class of とクラス名からなるシーケンスを使って定義します。クラス参照型の変数を実行時に設定し，宣言で指定されたクラスまたはそのクラスの下位クラスを参照できます。


参照

フィールドとオブジェクト型要素の指定子

オブジェクト型のスコープ

オブジェクト型


Const (予約語)
Const

参照	例	予約語

構文

説明

予約語 const はこの宣言を含むブロック内で値の変更ができない識別子を定義します。定数識別子をそれ自体の宣言に含めることはできません。

C++Builder では定数式が使えます。

定数宣言で使う式はコンパイラがコンパイル時にその式を評価できるように記述しなくてはなりません。


参照

定数宣言

式

型付き定数


例

(* 定数宣言 *)

const

  MaxData  = 1024 * 64 - 16;

  NumChars = Ord('Z') - Ord('A') + 1;

  Message  = 'Hello world...';

(* 型付き定数 *)

const

  identifier: type = value;

  ...

  identifier: type = value;


Default (標準指令)
Constructor

参照	予約語

構文

説明

コンストラクタはオブジェクトの作成に関連するアクションを定義します。コンストラクタは予約語 constructor を使って宣言しなくてはなりません。C++Builder のすべてのオブジェクトは最低でも TObject から基本コンストラクタを継承します。

コンストラクタは呼び出されると，クラス型の新しく割り当てられた初期化インスタンスへの参照を返します。


参照

コンストラクタとデストラクタ

Destructor

オブジェクトのインスタンス化

メソッド

Object

Virtual


Default (standard directive)
Default

参照	標準指令

構文

説明

default 指令はオブジェクトのデフォルトの配列プロパティを指定するために使います。

配列プロパティをデフォルトとして宣言すると，オブジェクト名だけを使って配列プロパティにアクセスできます。

default 指定子は順序型と小さい集合型のプロパティに対してだけサポートされています。プロパティ定義で default を指定する場合，プロパティと同じ型の定数を続けて指定しなくてはなりません。

プロパティ定義に default または nodefault 指定子を含めない場合 (または含めることができない場合)，結果は nodefault 指定子を含めた場合と同じになります。


参照

Nodefault


Destructor (予約語)
Destructor

参照	予約語

構文

説明

デストラクタはオブジェクトの廃棄に関連するアクションを定義します。デストラクタは予約語 destructor を使って宣言しなくてはなりません。

デストラクタは呼び出されると，コンストラクタによってオブジェクトに割り当てられたメモリの割り当てを解除します。

デストラクタは virtual として宣言でき，パラメータをとることはほとんどありません。


参照

Constructor

コンストラクタとデストラクタ

Object

Virtual


Dispid (標準指令)
Dispid

参照	標準指令

説明

dispid 標準指令は，クラスのオートメートセクションで宣言されているメソッドまたはプロパティの OLE オートメーションディスパッチ ID を指定するために使います。


参照

Automated


Do (予約語)
Do

参照	例	予約語

予約語 do は while，for，on，with 文と組み合わせて使い，条件が True の間に実行する文を指定します。


例

while Ch = ' ' do Ch := GetChar;

for Ch := 1 to 100 do Ch := GetChar;

with Date[I] do month := 1;

on <exception> do...


参照

Except

For

While

With


Dynamic (指令)
Dynamic

参照	標準指令

説明

dynamic 指令はメソッドを動的にします。動的メソッドは意味的には仮想メソッドと同じです。仮想メソッドと動的メソッドは実行時のメソッド呼び出しディスパッチの実現方法だけが異なります。その他の目的では，この 2 つのメソッドは同じとみなせます。

仮想メソッドの実現では，コンパイラはコードサイズよりも呼び出しディスパッチの速度を優先します。反対に動的メソッドの実現では，呼び出しディスパッチの速度よりもコードサイズを優先します。

一般に，多態性のある動作を実現する方法としては仮想メソッドが最も効率的です。動的メソッドが便利なのは，基本クラスが多くの仮想メソッドを宣言し，アプリケーションが多くの下位クラスを宣言し継承仮想メソッドのオーバーライドが少ない状況で使う場合だけです。


参照

メソッド


Else (予約語)
Else

参照	例	予約語

予約語 else は if，case，try 文のデフォルトの条件として使います。


例

(* if 文を使います *)

if ParamCount <> 2 then

begin

  WriteLn('Bad command line');

  Halt(1);

end

else

begin

  ReadFile(ParamStr(1));

  WriteFile(ParamStr(2));

end;

(* case 文を使います *)

case Ch of

  'A'..'Z', 'a'..'z':  WriteLn('Letter');

  '0'..'9':            WriteLn('Digit');

  '+', '-', '*', '/':  WriteLn('Operator');

else

  WriteLn('Special character');

end;


参照

Case

If

Try


End (予約語)
End

参照	例	予約語

予約語 end はブロックの終わりをマークします。end は次のように使います。

begin とともに使い複合文を形成する

case とともに使い case 文を形成する

record とともに使いレコード型を宣言する

object とともに使いオブジェクト型を宣言する

asm とともに使い組み込みアセンブラを呼び出す

except とともに使い例外リストを終了する

finally とともに使い finally ブロックを終了する

モジュールの最後の end にはその後に何もないことを示すためピリオドを付けます。


参照

Asm

Begin

Case

Except

Finally

Object

Record


例

(* begin とともに使い複合文を形成します *)

if First < Last then

begin

  Temp := First;

  First := Last;

  Last := Temp;

end;

(* case 文とともに使います *)

case Ch of

  'A'..'Z', 'a'..'z':  WriteLn('Letter');

  '0'..'9':            WriteLn('Digit');

  '+', '-', '*', '/':  WriteLn('Operator');

else

  WriteLn('Special character');

end;

(* レコード型宣言で使います *)

type

  MyClass  = (Num, Dat, Str);

  Date   = record

    D, M, Y: Integer;

  end;

  Facts = record

    Name: string[10];

    case Kind: MyClass of

      Num: (N: real);

      Dat: (D: Date);

      Str: (S: string[8]);

  end;

(* オブジェクト型宣言で使います *)

type

Location = object

  X, Y: Integer;

  procedure Init(PX, PY: Integer);

  function GetX: Integer;

  function GetY: Integer;

end;

(* asm とともに使います *)

asm

  mov ax,1

  mov cx, 100

end;


Except (予約語)
Except

参照	予約語

構文

説明

予約語 except は例外処理ブロックで例外ハンドラのリストの始まりをマークします。

except 部は特定の例外とそれに対する応答のリストで，それぞれ on...do 文で記述されます。on..do 文のどれも現在の例外に該当しない場合，else 部にあるデフォルトの例外ハンドラが実行されます。

例外処理ブロックで例外が発生した場合，実行はすぐに except 部にジャンプし，その場でアプリケーションはそれぞれの on..do 文を調べ発生した例外に該当するものを探します。ブロック内に該当するハンドラが存在しない場合，アプリケーションはデフォルトのハンドラ (予約語 else を使って指定されたハンドラ) があればそれを実行します。

ハンドラ (特定のハンドラまたはデフォルトハンドラ) が例外を扱うと，その例外は処理されたとみなされ，例外オブジェクトは廃棄され，例外処理ブロックの後から実行が続行されます。

発生した例外に該当する例外ハンドラがない場合，例外を処理しないままブロックの実行が終了します。


参照

Else

例外処理

Finally

Try


Exports (予約語)
Exports

参照	予約語

予約語 exports は DLL 内で使い，DLL によってエクスポートされる手続きと関数を示します。

exports 節はプログラムまたはライブラリの宣言部の中で位置や回数の制限なく使えます。

exports 節の各エントリはエクスポートする手続きまたは関数の識別子を指定します。

エクスポートする手続きまたは関数は exports 節が出現する前に宣言しなくてはなりません。

exports 節の識別子の前にユニット識別子とピリオドを付けることができます。このように指定した識別子は完全限定識別子と呼ばれます。

exports 節には次のものを入れられます。

index 節

name 節

DLL エントリを最も速く参照するにはインデックスを使います。

プログラムにも exports 節を入れられますが，Windows ではアプリケーションモジュールが関数をエクスポートしてもそれを別のアプリケーションから使うことはできないため，通常は exports 節を入れません。


参照

ダイナミックリンクライブラリ

DLL の使い方

DLL の作成


External (手続き指令)
External

参照	例	標準指令

external 指令を使うと，アセンブリ言語で記述され別々にコンパイルされた手続きや関数，または DLL の手続きや関数と，作成するプログラムとを連結できます。

external 指令は，本来ならば宣言部と実行部が存在する場所に置かれます。

アセンブリ言語で記述される外部コードは，$L filename コンパイラ指令によって Pascal ユニットまたはプログラムとリンクされます。

DLL からの外部ルーチンのインポートについての詳細は，「DLL に格納してあるルーチンのアクセス」を参照してください。


例

{ 次の 2 行では, 外部のアセンブリ言語ファイルからルーチンをインポートしています. }

function GetMode: Word; external;

procedure SetMode(Mode: Word); external; {$L CURSOR.OBJ}

{ 次の行では, DLL から関数をインポートしています. }

function GlobalAlloc(Flags: Word; Bytes: Longint): THandle; external 'KERNEL.DLL' index 15;


参照

DLL

関数

手続き


File (予約語)
File

参照	例	予約語

構文

説明

file 型は線状に並んだデータのシーケンスで構成されます。予約語 of を使って file を特定の型に割り当てできます。ファイルはファイル型またはオブジェクト型以外のどの型でも構成できます。

of とコンポーネント型を省略した場合，型なしファイルになります。

定義済みの file 型 Text は行単位に編成された印刷可能な ASCII 文字を含むファイルを意味する


例

(* ファイル型の宣言 *)

type

  Person = record

    FirstName: string[15];

    LastName : string[25];

    Address  : string[35];

  end;

  PersonFile = file of Person;

  NumberFile = file of Integer;

  SwapFile = file;


参照

Of


finalization (予約語)
finalization

参照 	予約語

構文

説明

終了処理部はオプションであり，ユニットに初期化部がある場合にだけ使えます。終了処理部は予約語 finalization と，ユニットを終了する文のリストで構成されます。終了処理は初期化に対応するもので，初期化部の中でユニットが取得したリソース (メモリ，ファイルなど) は一般に終了処理部で解放されます。

ユニットの終了処理部は初期化と逆の順序で実行されます。たとえば，アプリケーションでユニット A，B，C をこの順序で初期化した場合は，C，B，A の順に終了処理が行われます。

いったんユニットの初期化コードが実行を開始すると，それに対応する終了処理部がアプリケーションのシャットダウン時に必ず実行されます。したがって，終了処理部は初期化が不完全だったデータを処理できなければなりません。その理由は，例外が生成された場合に，初期化コードが完全には実行されない可能性があるからです。


参照

interface

implementation

initialization

ユニット


Finally (予約語)
Finally

参照	予約語

構文

説明

予約語 finally は例外が発生した場合でも必ず実行されるプロテクトブロックのセクションをマークします。

例外が発生した場合，例外を処理する前に，割り当てられたリソースを解放するなど何らかのクリーンアップコードを実行する必要があります。try..finally ブロックを使うとこのような操作が可能です。

try..finally ブロック内のすべての文は例外が発生しない限り正常に実行され，例外が発生した時点ですぐに finally 部の文に実行がジャンプします。

try..finally ブロックは特定の例外を処理するものではないので注意してください。このブロックはブロック内の特定のコードを例外の有無に関係なく必ず実行するためのものです。


参照

Except

例外処理

Try

リソース割り当ての保護


For...To，For...Downto (予約語)
For ... To, For ... Downto

参照	例	予約語

構文

説明

for 文は範囲内の初期値から最終値までの各値ごとに 1 回ずつ do の後の文を実行します。ループを何回実行するか前もって正確にわかる場合に for ループを使うと便利です。

制御変数は常に初期値から始まります。

to	ループごとに制御変数を 1 ずつインクリメントします。初期値は最終値よりも小さくなくてはなりません。

downto	ループごとに制御変数を 1 ずつデクリメントします。初期値は最終値よりも大きくなくてはなりません。

制御変数には次の規則が適用されます。

制御変数は for 文を含むブロックの範囲内のローカルな変数識別子でなくてはならない

順序型でなくてはならない

初期値と最終値は制御変数の順序型と代入互換性のある型でなくてはなりません。

for 文が実行された後，goto 文によって for 文の実行に割り込みがかけられない限り，制御変数の値は未定義になります。


例

(* for ... to, for ... downto *)

for I := 1 to ParamCount do

  Writeln(ParamStr(I));

for I := 1 to 10 do

  for J := 1 to 10 do

  begin

    X := 0;

    for K := 1 to 10 do

      X := X + Mat1[I, K] * Mat2[K, J];

    Mat[I, J] := X;

  end;


参照

goto 文

ループ

順序型

スコープ


Forward (予約語)
Forward

参照	例	標準指令

標準指令の forward を使うと手続きまたは関数を実際には定義せずに宣言できます。

forward 宣言の地点から，他の手続きや関数は forward 宣言されたルーチンを呼び出すことができ，相互再帰が可能になります。

forward 宣言の後で，ルーチンの文部を指定する宣言を持つ手続きまたは関数を定義しなくてはなりません。

定義宣言では手続き頭部または関数頭部からパラメータリストを省略できます。

手続きまたは関数の定義宣言としては external 宣言または assembler 宣言が可能ですが，別の forward 宣言であってはなりません。


例

(* forward 宣言される手続き *)

procedure Flip(N: Integer); forward;

procedure Flop(N: Integer);

begin

  WriteLn('Flop');

  if N > 0 then Flip(N - 1);

end;

procedure Flip;

begin

  WriteLn('Flip');

  if N > 0 then Flop(N - 1);

end;


参照

Assembler

External


Function (予約語)
Function

参照	例	予約語

構文

説明

予約語 function は値を計算して返すブロックを定義します。

function ヘッダーは関数の識別子，仮パラメータ (任意)，関数の結果の型を指定します。

関数は，単純型，複合型，標準型またはユーザー定義型でも，古いスタイルのオブジェクト (クラスに対するものとして) ，ファイル型を除いてどの型も返せます。オブジェクトを関数の結果として処理する唯一の方法はオブジェクトポインタを使う方法です。

関数ヘッダーに続いて関数の宣言部を指定できます。

function ヘッダーに続いて次のものを指定します。

ローカル変数，型，ラベル，定数，手続き，関数の各宣言

関数が呼び出されたときに実行される文

文部には関数識別子に値を割り当てる文が最低でも 1 つ必要です。関数の結果は最後に割り当てられた値になります。

宣言部と文部のかわりに，function 宣言では次のものを指定できます。

forward 宣言

external 宣言

関数の Result 変数

すべての関数は関数の戻り値と同じ型のローカル変数 Result を暗黙的に持ちます。Result への代入は関数の名前に対する代入と同じ効果を持ちます。関数は関数呼び出しの評価でアクティブになります。関数呼び出しでは関数の識別子と，関数が必要とする実パラメータがあればそれを指定します。

さらに，代入文の右側で Result を参照できます。この場合再帰関数呼び出しを生成するのではなく現在の戻り値が参照されます。


参照

式

関数呼び出し

順序

パラメータ

ポインタ

実数

文字列


例

(* 関数宣言 *)

function UpCaseStr(S: string): string;

var

  I: Integer;

begin

  for I := 1 to Length(S) do

  if (S[I] >= 'a') and (S[I] <= 'z') then

  Dec(S[I], 32);

  UpCaseStr := S;

end;


Goto (予約語)
Goto

参照	例	予約語

構文

説明

予約語 goto はこの文で参照するラベルが先頭に付いている文にプログラム実行を転送します。

ラベルは goto 文と同じブロックになくてはなりません。手続きまたは関数の外へはジャンプできません。


参照

Label


例

label 1, 2;

goto 1

   .

   .

   .

1: WriteLn ('Abnormal program termination');

2: WriteLn ('Normal program termination');


If...Then...Else (予約語)
If ... Then ... Else

参照	例	予約語

構文

説明

if，then，else は文を実行する条件を指定します。

if に続く論理式が True ならば，then の後の文が実行されます。

そうでなければ，式が False と評価され else 部が存在する場合は，else の後の文が実行されます。else 部が存在しない場合は，if 文の次の文に実行が移ります。

メモ:	else 節の前にセミコロンは指定できません。


参照

論理型

条件文

Else


例

(* if 文 *)

if (I < Min) or (I > Max) then I := 0;

if x < 1.5 then

  z := x + y

else

  z := 1.5;


Implementation (予約語)
Implementation

参照	予約語

ユニットの実現部では，ユニットのインターフェース部で宣言されたパブリックの手続きと関数のすべてのブロックを定義します。またここでは，プライベートの定数，型，変数，手続き，および関数も宣言します。

構文

説明

ユニットの implementation 部で指定された宣言はプライベートな宣言になりユニットのその部分内でだけ使用可能です。interface 部で宣言されたすべての定数，型，変数，手続き，関数は implementation 部でも可視になります。

インターフェース部で宣言された手続きと関数の実装は，実現部内でどのような順序で定義してもよく，また実現部内のどこからでも参照できます。

実現部では予約語 implementation の直後に uses 節を指定できます。ユニットのインターフェース部に uses 節を置いた場合，その uses 節で指定されたユニットは定義側のユニットからは不可視になります。

external として宣言された手続きがある場合，ソースファイル内のユニットの最後の end の前に 1 つまたは複数の $L filename 指令がなくてはなりません。

実現部の手続き頭部と関数頭部は次のいずれかでなくてはなりません。

インターフェースでの宣言と同一である

短い構文である


参照

$L filename

Interface

Initilization

Finalization

ユニット


Initialization (予約語)
Initialization

参照	予約語

構文

説明

ユニットの initialization 部は省略可能で，予約語 initialization で始め，ユニットを初期化するために実行する文のリストをその後に指定します。

プログラムが使うユニットの初期化部はメインプログラムの uses 節にユニットが出現するのと同じ順に実行されます。


参照

Finalization

ユニット


短い構文のヘッダー

参照

短い構文のヘッダーとは implementation 部で宣言される手続きや関数のうちパラメータを指定しないものを指します。このようなヘッダーのパラメータは interface 部で前もって指定されるか，forward 宣言またはオブジェクト型の一部として宣言されます。

短い構文のヘッダーを指定するには，予約語 (procedure または function) に続けてルーチン識別子を入力します。

実現部内のローカルなルーチン (インターフェース部で宣言されていないルーチン) には完全な手続き頭部または関数頭部を指定しなくてはなりません。


参照

Implementation


Index (標準指令)
Index

参照	例	標準指令

index 節ではダイナミックリンクライブラリ (DLL) から手続きまたは関数をエクスポートするための順序数を指定します。exports 節で index 節を使わない場合，コンパイラが順序数を割り当てます。

index 節は exports 節に含まれ，index という語とそれに続く 1 から 32767 までの間の整数定数で構成されます。


例

procedure ImportByOrdinal; external 'TESTLIB' index 5;


参照

ダイナミックリンクライブラリ

Forward

DLL の使い方

DLL の作成


Inherited (予約語)
Inherited

参照	予約語

予約語 inherited は外側のメソッドのオブジェクト型の上位オブジェクトを指定します。

inherited は上位オブジェクトを持たないオブジェクト型のメソッド内では使えません。継承元の宣言オブジェクトがないからです。


参照

オブジェクト型


Inline (予約語)
Inline

予約語

説明

現在のバージョンの Object Pascal では予約語 inline は使われません。ただし将来の使用のために予約されています。


Interface (予約語)
Interface

参照	予約語

ユニットの interface 部はそのユニットを使うプログラム (または他のユニット) に対して何を可視にしアクセス可能にするかを決めます。

構文

説明

interface 部はユニットヘッダーの後に置かれる予約語 interface で始まり，予約語 implementation の前で終わります。

interface 部では，定数，データ型，変数，手続き，関数を宣言します。ここで宣言されたものは，他のプログラムまたはユニットから使えるようになります。

interface 部には手続きまたは関数の頭部だけを列挙します。手続きまたは関数のブロックは，その後の implementation 部に指定します。forward 指令は使われませんが，interface 部の手続きと関数の宣言は実質的には forward 宣言と同様な効果を持ちます。

インターフェース部には uses 節を指定できます (uses 節を指定する場合，予約語 interface の直後に uses を指定しなくてはなりません)。


参照

Implementation

ユニット


Label (予約語)
Label

参照	例	予約語

構文

説明

予約語 label は対応する文部の文をマークするプレースホルダを宣言します。制御は goto 文によってラベルに転送されます。

各ラベルは 1 つの文だけをマークしなくてはなりません。

識別子のほかに，0 から 9999 までの数字のシーケンスをラベルとして使えます。


参照

Goto


Library (予約語)
Library

参照	予約語

構文

説明

ダイナミックリンクライブラリ (DLL) は library ヘッダーで始まります。

ライブラリヘッダーは拡張子 .EXE のかわりに .DLL を持つ実行可能ファイルを生成するようコンパイラに指示します。


参照

Exports 節

インポートユニット

Index 節

Name 節

DLL の作成


Maxint と MaxLongInt (定数)
MaxInt と MaxLongInt

MaxInt と MaxLongInt は定義済みの定数です。現在のバージョンの Object Pascal では 2 つは同じ値です。

MaxInt は使用可能な最大整数 (2,147,483,647) を表す

MaxLongint は使用可能な最大 Longint (2,147,483,647) を表す


Name (標準指令)
Name

参照	標準指令

exports 節には name 節を指定できます。name 節は name という語とそれに続く文字列定数で構成されます。

name 節を使う場合，手続きまたは関数は文字列定数で指定された名前を使ってエクスポートされます。

name 節を使わない場合，手続きまたは関数は識別子を使ってエクスポートされすべて大文字に変換されます。


参照

DLL の使い方

Exports

Index


Nil (予約語)
Nil

予約語

予約語 nil は何も指さないポインタ型の定数を示します。

nil はすべてのポインタ型と互換です。


Nodefault (標準指令)
Nodefault

参照	標準指令

構文

説明

nodefault 指令はプロパティのデフォルト値とみなされる値を制御します。

プロパティの宣言では，nodefault は省略可能な指定子です。この指定子を含めなくても，nodefault 指定子を指定した場合と同じ結果になります。


参照

Default


Object (予約語)
Object

参照

構文

説明

予約語 object は Borland Pascal と Turbo Pascal の以前のバージョンで使われていたオブジェクトモデルと一致するオブジェクト型を宣言するために使います。新しいプログラムでは予約語 class と新しいオブジェクトモデルを使う必要があります。予約語 object と旧オブジェクトモデルを使って宣言したオブジェクト型はクラスメソッドを持たず，コンポーネントとしてのプロパティも持ちません。

オブジェクト型は決められた個数のコンポーネントを持つデータ構造です。

各コンポーネントはフィールド (特定の型のデータを含む) またはメソッドで，オブジェクトに対して操作を実行します。

フィールドの宣言ではフィールドの名前を示す識別子とデータ型を指定します。

メソッドの宣言では手続き，関数，コンストラクタ，またはデストラクタのヘッダーを指定します。

オブジェクト型は別のオブジェクト型からコンポーネントを継承できます。継承されるオブジェクトは下位オブジェクトで，継承元のオブジェクトは上位オブジェクトです。

オブジェクト型のドメインはそのオブジェクト自身とすべての下位オブジェクトで構成されます。


参照

フィールドとオブジェクト型要素の指定子

オブジェクト型のスコープ

オブジェクト型


Of (予約語)
Of

参照	例	予約語

予約語 of は配列，集合，クラス，ファイル型の宣言で型の前に置かれるほか，case 文で使われます。


参照

Array

Case

File

Set


例

(* 配列宣言 *)

type

  IntList  = array[1..100]     of Integer;

  CharData = array['A'..'Z']   of Byte;

  Matrix   = array[0..9, 0..9] of real;

(* 集合型 *)

type

  Day = (Sun, Mon, Tue, Wed, Thu, Fri, Sat);

  CharSet = set of Char;

  Digits = set of 0..9;

  Days = set of Day;

(* ファイル型宣言 *)

type

  Person = record

     FirstName: string[15];

     LastName : string[25];

     Address  : string[35];

  end;

  PersonFile = file of Person;

  NumberFile = file of Integer;

  SwapFile = file;

(* case 文 *)

case Ch of

  'A'..'Z', 'a'..'z':  WriteLn('Letter');

  '0'..'9':            WriteLn('Digit');

  '+', '-', '*', '/':  WriteLn('Operator');

else

  WriteLn('Special character');

end;


On (標準指令)
On

参照	予約語

構文

説明

予約語 on は例外に対する応答を定義します。on は常に予約語 do と組み合わせて使い，これにより例外ハンドラ全体が形成されます。

try..except ブロックの except 部は特定の例外を処理するための 1 つまたは複数の on..do 文のリストで構成されます。


参照

例外処理文

例外への応答

Do

Except

Try


Override (標準指令)
Override

例	標準指令

override 指令は仮想メソッドまたは動的メソッドを再定義するために使います。

メソッドの宣言に override を指定した場合，そのメソッドは継承したメソッドの実装をオーバーライドします。仮想メソッドのオーバーライドでは，元のメソッドのパラメータの順序と型，および関数の場合はその結果型が正確に一致していなければなりません。

仮想メソッドには VMT ベースのディスパッチと動的ディスパッチの 2 種類のディスパッチがあるため，仮想メソッドや動的メソッドをオーバーライドするメソッドは virtual または dynamic を繰り返すかわりに override 指令を使います。


例

次のコードは継承手続き P を置換するために override を使っています。

type
  TAnObject = class
    procedure P; virtual;
  end;

  TAnotherObject = class(TAnObject)
    procedure P; override;
  end;


Packed (予約語)
Packed

参照	予約語

説明

構造化型宣言で使われる予約語 packed はデータ記憶を圧縮するようコンパイラに指示します。圧縮すると，この型の変数のコンポーネントへのアクセスが遅くなるという面があります。


参照

構造化型


Pascal (標準指令)
Pascal

参照	予約語

説明

pascal 指令は，手続きまたは関数がパラメータの受け渡しに Pascal の呼び出し規約を使うことを指定します。

Pascal 呼び出し規約では，パラメータは左から右の順で渡され，スタック上のパラメータは手続きまたは関数が取り除きます。

Pascal 呼び出し規約は，C/C++ あるいは他の言語で書かれたダイナミックリンクライブラリ (DLL) からエクスポートするルーチンを呼び出すためには最も便利です。


参照

呼び出し規約

cdecl

register

stdcall


Private (標準指令)
Private

参照	標準指令

構文

説明

private 指令はオブジェクト内でコンポーネント宣言部を指定するために使います。

モジュール内では，private なコンポーネント識別子は public なコンポーネント識別子と同じように動作する

モジュール外では，private なコンポーネント識別子は不明になりアクセス不能である

それぞれが各自の private コンポーネントを他のモジュールに知らせなくても，互いの private コンポーネントにアクセスできるようにするため，関連するオブジェクト型を同じモジュール (またはユニット) に置いてください。

private として宣言したコンポーネント識別子のスコープはオブジェクト型宣言を含むモジュール内に制限されます。


参照

オブジェクト

Protected

Public

スコープの規則

オブジェクト型のスコープ

ユニット


Procedure (予約語)
Procedure

参照	例	予約語

構文

説明

手続きを使うとメインプログラムブロック内に別のブロックをネストさせることができます。各 procedure 宣言にはヘッダーが指定されその後に文のブロックが続きます。

procedure ヘッダーは手続きの識別子と仮パラメータ (任意) を指定します。

procedure は手続き文でアクティブになります。手続き文では手続きの識別子と，実パラメータがあればそれを指定します。

procedure ヘッダーの後に次のものを指定します。

ローカルオブジェクトを宣言する宣言部

begin と end で囲まれた文。手続きが呼び出されたとき実行する内容を指定する

メモ:	手続きの識別子をその手続きのブロック内の手続き文で使うと，手続きは実行中に自分自身を呼び出します。この結果は無限ループになります。

宣言部や文部のかわりに，手続き宣言で次の指令を指定できます。

assembler

external

forward


例

{ procedure 宣言 }

procedure NumString(N: Integer; var S: string);

var

  V: Integer;

begin

  V := Abs(N);

  S := '';

  repeat

    S := Chr(N mod 10 + Ord('0')) + S;

    N := N div 10;

  until N = 0;

  if N < 0 then

    S := '-' + S;

end;


参照

関数

パラメータ

手続き文

手続き型定数

呼び出し規約


Program (予約語)
Program

参照	予約語

構文

説明

予約語 program はプログラムの先頭に置かれ，プログラムの名前を指定します。


参照

Uses 節

ラベル

定数

型

変数

手続き

関数

文


Property (予約語)
Property

参照

構文

説明

予約語 property はプロパティを宣言するために使います。クラスでのプロパティ定義はそのクラスのオブジェクトに対して名前付き属性を宣言し，その属性の読み出しと書き込みに関連付けるアクションを宣言します。


参照

Read

Write

Stored

オブジェクト型


Protected (標準指令)
Protected

参照	標準指令

構文

説明

protected 指令はオブジェクト型宣言で使います。

protected として宣言したコンポーネントはこれを宣言した型の下位オブジェクトに対してだけアクセス可能になります。

コンポーネントを protected として宣言することによって public コンポーネントと private コンポーネントの利点が結び付けられます。

private コンポーネントの場合と同様に，protected コンポーネントでは実現の詳細をエンドユーザーから隠せます。ただし，private コンポーネントとは異なり，protected コンポーネントでは，プログラマがオブジェクトから新しいオブジェクトを派生させる場合に，下位オブジェクトが同じユニット内で宣言されなくてはならないという制約を受けずに済みます。


参照

コンポーネントの可視性

Private

Public

Published

Automated

オブジェクト型のスコープ


Public (標準指令)
Public

参照	標準指令

構文

説明

public 指令はクラス型宣言で使います。

public コンポーネント部で宣言されたコンポーネント識別子にはスコープに関する特別な制限はありません。


参照

コンポーネントの可視性

Private

Protected

Published

Automated

オブジェクト型のスコープ


Published (標準指令)
Published

参照	標準指令

構文

説明

published 指令はオブジェクト型宣言で使います。

オブジェクトの一部をパブリッシュとして宣言すると，その部分についての実行時型情報が生成され，アプリケーションのパブリッシュインターフェースに含まれます。

アプリケーション内部では，published 部は public 部と同じように動作します。唯一の相違点は他のアプリケーションが published インターフェースを通じてパブリッシュ部の情報を取得できるという点です。

C++Builder のオブジェクトインスペクタは，コンポーネントパレットでオブジェクトのパブリッシュインターフェースを使って，表示するプロパティとイベントを決めます。


参照

コンポーネントの可視性

Private

Protected

Public

Automated

オブジェクト型のスコープ


Read (標準指令)
Read

参照	例

構文

説明

read 指令はプロパティから値を取得するルーチンまたはフィールドを指定するために使います。


参照

Write


例

property Color: TColor read GetColor write SetColor;


Record (予約語)
Record

参照	例	予約語

構文

説明

record にはコンポーネントつまりフィールドが含まれ，各フィールドは異なる型で構成できます。

各フィールドリストでは識別子をカンマで区切って指定し，コロンと型を続けて指定します。

レコード型宣言ではフィールドの名前を指定しフィールド型を割り当てなくてはなりません。

レコード型構文図の可変部はメモリ領域を複数のフィールドリストに配分し，複数の方法で情報にアクセスするためのものです。各フィールドリストはメモリ内の同一領域にオーバーレイする可変タグです。各可変タグは定数によって区別され，いつでもすべての可変タグのすべてのフィールドにアクセスできます。

オプションの識別子であるタグフィールド識別子は，レコードの追加固定フィールド，つまりタグフィールドの識別子です。プログラムはどの可変タグが現在アクティブかを示すためにタグフィールドの値を使います。

レコードへのアクセス

レコード全体にアクセスしたり各フィールド個別にアクセスしたりできます。個々のフィールドから情報を取り出すにはレコード名，ピリオド，フィールド識別子を入力します。次に例を示します。

TDateRec.Year

レコードにサブレコードが含まれる場合は，限定子を使ってアクセスできます。


例

{ レコード型の定義 }

type

  TClass  = (Num, Dat, Str);

  TDate   = record

     D, M, Y: Integer;

  end;

  Facts = record

    Name: string[10];

    case Kind: TClass of

      Num: (N: Real);

      Dat: (D: TDate);

      Str: (S: string[8]);

  end;


参照

フィールドとオブジェクト型要素の指定子

レコード型定数

レコードのスコープ

with 文


register (標準指令)
register

参照	標準指令

説明

register 指令は，手続きや関数でパラメータを渡すのに register 呼び出し規約を使うことを指定します。Object Pascal のこのバージョンでは，register がデフォルトの呼び出し規約です。

register 呼び出し規約ではパラメータは左から右へ渡され，関数がスタックからパラメータを削除します。

register 規約では 3 つまでの CPU レジスタを使ってパラメータが渡されますが，その他の規約ではスタック上にあるすべてのパラメータが常に渡されます。register 規約はスタックフレームの作成を回避する場合が多いのでもっとも効率的な呼び出し規約です。


参照

呼び出し規約

cdecl

pascal

stdcall


Repeat...Until (予約語)
Repeat...Until

参照	例	予約語

構文

説明

repeat と until の間の文は until 文の論理式が True と評価されるまで連続して実行されます。

このループを使うと各シーケンスを実行した後に論理式が評価されるため，シーケンスが最低でも 1 回は実行されることが保証されます。


例

{ repeat 文 }

  repeat Ch := GetChar until Ch <> ' ';

  repeat

    Write('Enter value: ');

    ReadLn(I);

  until (I >= 0) and (I <= 9);


参照

ループ


Resident (標準指令)
Resident

標準指令

標準指令 resident は exports 節で使います。

resident を使う場合，ダイナミックリンクライブラリ (DLL) がロードされたときエクスポート情報がメモリ内に常駐します。

resident オプションを指定すると Windows が DLL エントリを名前を使って参照するときの時間が短縮されます。

DLL を使うクライアントプログラムが特定のエントリを名前を使ってインポートする場合，標準指令 resident を使ってそれらのエントリをエクスポートする必要があります。


Self (暗黙のパラメータ)
Self

予約語

self はメソッドが呼び出されたときに渡される暗黙のパラメータです。

self はメソッドを呼び出すために使われたインスタンスへのポインタとして使うことができます。

self は特に，特定のオブジェクトインスタンスに対して正しい仮想メソッドが呼び出され，オブジェクトメソッドが正しいインスタンスデータを使うことを保証します。


Set (予約語)
Set

参照	例	予約語

構文

説明

予約語 set は 256 個未満の値を持つ同じ順序型からなるオブジェクトの集合を定義します。

基本型の上限と下限の順序値は 0 から 255 の範囲でなくてはなりません。

集合型の値を指定する集合コンストラクタは，式を [ ] で囲んで記述します。それぞれの式は集合の値を表します。

[ ] の表記は空の集合を意味し，すべての集合型と互換です。


例

{ 集合型 }

  type

    Day = (Sun, Mon, Tue, Wed, Thu, Fri, Sat);

    CharSet = set of Char;

    Digits = set of 0..9;

    Days = set of Day;

{ 集合コンストラクタ }

  ['0'..'9', 'A'..'Z', 'a'..'z', '_']

  [1, 5, I + 1 .. J - 1]

  [Mon..Fri]


参照

Of

集合型

集合型定数


stdcall (標準指令)
stdcall

参照	標準指令

説明

stdcall 指令は，手続きや関数でパラメータを渡すのに Windows の標準呼び出し規約を使うことを指定します。

stdcall 規約では cdecl 規約と同様にパラメータは右から左へ渡されますが，関数がスタックからパラメータを削除する点が cdecl 規約とは異なります。

stdcall 呼び出し規約は Windows API ルーチンを呼び出すために使われます。


参照

呼び出し規約

cdecl

pascal

register


String (予約語)
String

参照	予約語

構文

説明

予約語 string は文字列型の変数を宣言するために使います。


参照

インデックス

文字列型


Stored (標準指令)
Stored

標準指令

構文

説明

stored 指令はプロパティを保存するかどうかを制御します。

プロパティ定義に stored 指令を含める場合，次のいずれかを続けて指定しなくてはなりません。

論理定数 (True または False)

論理型のフィールドの識別子

論理型の値を返すパラメータなしの関数メソッドの識別子

プロパティ定義に stored 指定子を含めない場合，結果は stored True 指定子を含めた場合と同じになります。


Threadvar (予約語)
Threadvar

参照	予約語

予約語 threadvar は，スレッドローカル変数を宣言するために使います。threadvar の構文は予約語 var と同じです。


参照

Var


Try (予約語)
Try

参照	例	予約語

予約語 try はプロテクトブロックの最初の部分をマークするために使います。プロテクトブロックには 2 つの種類があります。

try..except ブロック

try..finally ブロック

構文

try...except ブロック

例外を処理するブロックは try..except ブロックです。

ブロックの try 部の中では，例外が発生しない限り文は通常の順序で実行され，例外が発生すると実行が except 部にジャンプします。例外が発生しない場合，except 部や else 部を使わずにブロックが終了します。

except 部は特定の例外とそれに対する応答を記述したリストで，それぞれ on..do 文で記述されます。on..do 文のどれも現在の例外に該当しない場合，else 部にあるデフォルトの例外ハンドラが実行されます。1 つのハンドラ (特定のハンドラまたはデフォルトハンドラ) が例外を処理すると，ブロックは終了します。

例外後はブロック内で実行は再開されません。前の例で，Statement1 で例外が発生した場合，Statement2 は実行されません。

try..finally ブロック

アプリケーションが割り当てたリソースを確実に解放するために，try..finally ブロックを使ってリソース割り当てを保護できます。

try..finally ブロックの finally 部の文は，例外が発生した場合でも必ず実行されます。

try..finally ブロックの文は例外が発生しない限り正常に実行され，例外が発生すると finally 部の文が実行されます。try..finally ブロックはそれ自体は特定の例外を処理するものではないので注意してください。


例

次のコードは保護されたリソースを示します。ブロックの finally 部でファイルを閉じることによって，例外が発生した場合でもアプリケーションが必ずファイルを閉じるようになっています。

var

  F: File;

begin

  Assign(F, 'SOMEFILE.EXT');

  Reset(F);

  try

    { ファイル F にアクセスする文 }

  finally

    Close(F);

  end;

end;


参照

例外処理

リソース割り当ての保護


Type (予約語)
Type

参照	予約語

構文

説明

type 宣言は型を示す識別子を指定します。変数の type はその変数が持つことのできる値の集合と，その変数に対して実行可能な操作を定義します。


参照

型宣言


Unit (予約語)
Unit

参照	予約語

構文

説明

ユニットはモジュールプログラミングの基本です。ユニットを使ってライブラリを作成したり，大きなプログラムを論理的に関連するモジュールに分割したりします。

ユニットの各部を次に示します。

unit ヘッダー

インターフェース部

実現部

初期化部

終了処理部

ユニットヘッダー

unit ヘッダーはユニットの名前を指定します。この名前は uses 節でユニットを参照するときに使います。

名前はユニークでなくてはなりません。同じ名前を持つ 2 つのユニットを同時に使うことはできません。


参照

ユニットの循環参照

ユニットの間接参照


Uses (予約語)
Uses

例	予約語

uses 節ではプログラムが使用するユニットを指定します。

構文

説明

uses 節の各識別子は現在のプログラムまたはユニットがアクセスする関数または手続きを含むユニットを指定します。

System ユニットは常に自動的に使用されます。System ユニットは，ファイル入出力，文字列処理，浮動小数点演算，動的メモリ割り当てといった低レベルのランタイムルーチンを実装しています。

System ユニットとは別に，Object Pascal では，自動的には使用されない多数の標準ユニットを実装しています。これらのユニットを使う場合は uses 節に指定しなければなりません。

uses 節に指定されたユニットの順序によって，ユニットの初期化の順序が決まります。

コンパイル済みのユニットを探し出すために，コンパイラは uses 節で指定されたユニット名にファイル拡張子 .DCU を付加します。

コンパイラはカレントディレクトリにあるユニットと，［プロジェクトオプション］ダイアログボックスの［ディレクトリ/条件］ページの［検索パス(S)］リストボックスで指定されたディレクトリにあるユニットを検索します。


例

program MyProgram;

uses SysUtils;


Var (予約語)
Var

参照	例	予約語

構文

説明

変数 (var) 宣言は識別子と型をその型の値を格納可能なメモリ内の位置と関連付けます。

absolute 節は絶対メモリアドレスを指定するために使います。

予約語 var を使って変数パラメータを宣言することもできます。


例

{ 変数宣言 }

  var

    X, Y, Z: real;

    I, J, K: Integer;

    Done, Error: Boolean;

    Vector: array[1..10] of real;

    Name: string[15];

    InFile, OutFile: Text;

    Letters: set of 'A'..'Z';


参照

グローバル変数とローカル変数

スコープ

変数宣言


Virtual (手続き指令)
Virtual

参照	標準指令

説明

virtual 指令は仮想メソッドを宣言するために使います。

virtual メソッドはレイトバインディングと呼ばれるプロセスによって実行時にコードにリンクされます。

メソッドを virtual として宣言すると，同じ名前を持つメソッドをオブジェクト型の階層内で別の方法で実現できるようになります。

メソッドを仮想にするには，オブジェクト型のメソッド宣言の後にセミコロンを指定し，予約語 virtual を続けて指定します。


参照

オブジェクト

Self

仮想メソッド


While (予約語)
While

参照	例	予約語

構文

説明

while 文は単一文または複合文の繰り返し実行を制御します。

do の後の文は論理式が True である限り実行されます。

式は文を実行する前に評価されるため，式が最初から False になった場合，文は実行されません。


参照

複合文

Do (予約語)

For (予約語)

ループ

Repeat (予約語)


例

{ while 文 }

  while Ch = ' ' do Ch := GetChar;


With (予約語)
With

参照	例	予約語

構文:

説明

with 文はレコードのフィールドやオブジェクトのフィールドとメソッドをすばやく参照するためのものです。

with 文では，1 つまたは複数のレコード変数のフィールドをフィールド識別子だけを使って参照できます。

with 文では，各変数参照はまずレコードのフィールドとして解釈できるかどうか確認されます。解釈可能な場合は，同じ名前の変数がアクセス可能な場合でも，常にレコードのフィールドとして解釈されます。

レコード変数の選択に配列のインデックス付けやポインタの逆参照が関連する場合，複合文が実行される前に一度それらのアクションが実行されます。


参照

レコード


例

type

   TDate = record

      Day : Integer;

      Month: Integer;

      Year : Integer;

   end;

var OrderDate: TDate;

with OrderDate do

  if Month = 12 then

  begin

    Month := 1;

    Year := Year + 1

  end

  else

    Month := Month + 1;


Write (標準指令)
Write

参照	例

構文

説明

write 指令はプロパティアクセス指定子で，これを使ってプロパティの値を設定するルーチンを指定できます。


参照

Read


型宣言

参照	言語定義

変数を宣言する場合，型を指定しなくてはなりません。型は定義済みの型かユーザー定義型のいずれかです。ユーザー定義の型はプログラムまたはユニットの型宣言部で宣言します。

変数の型はその変数が保持できる値の集合と変数に対して実行可能な操作を定義します。

型宣言のスコープはその型を宣言したブロック内になります。

型識別子のスコープには，ポインタ型を例外として，その識別子自体は含まれません。

型には 6 つの主なクラスがあります。

1.	単純型は順序付けされた値の集合を定義します。

2.	文字列型は動的な長さ属性と固定サイズ属性を持つ文字のシーケンスを定義します。

3.	構造化型は複数の値を保持できる構造を定義します。

4.	ポインタ型は指定された型の変数をポイントする値の集合を定義します。

5.	手続き型は手続きと関数をオブジェクトとして扱うために使います。

6.	バリアント型は変数が異なる型の値を持つことを想定します。


参照

スコープ

型の互換性


基本型と汎用型

型

Object Pascal の定義済みの型は以下の 2 種類に分類されます。

基本型

汎用型

基本型の範囲と形式は CPU とオペレーティングシステムに依存せず，Object Pascal の実装が異なっても変わりません。

汎用型の範囲と形式は CPU とオペレーティングシステムに依存します。

現在，基本型と汎用型を区別する定義済みの型には以下の 3 種類があります。

整数型

文字型

文字列型

ほかのすべての型では，定義済みの型を基本型とみなしてください。

通常は汎用型により，CPU とオペレーティングシステムにとって最適な処理効率が得られるため，アプリケーションではできるだけ汎用型を使うようにします。基本型は，実際の範囲や格納形式がアプリケーションで重要な問題となる場合だけ使います。


単純型

型

単純型は順序付けされた値の集合を定義します。単純型には 2 つの基本クラスがあります。

順序型

実数型

実数型識別子は標準識別子 Real，Single，Double，Extended，Comp のいずれかです。

単純型の比較

単純型を比較する場合，オペランドは互換の型でなくてはなりません。ただし，一方のオペランドが実数型の場合，もう一方は整数型でもかまいません。


順序型

参照	型

順序型は単純型の部分集合で，有限個数の要素を持ちます。

Delphi には 12 種類の定義済み順序型と 2 種類のユーザー定義順序型があります。定義済みの型には次のものがあります。

Integer	Shortint	SmallInt	Longint	Byte	Word

Cardinal	Boolean	ByteBool	WordBool	LongBool	Char

ユーザー定義の順序型には次のものがあります。

列挙型

部分範囲型

順序型のすべての値は順序付けされた集合になっており，それぞれの値は集合内のインデックス位置によって表現されます。整数型の値を除き，各順序型は最初の要素の位置インデックスが 0 で，次が 1 という具合に続きます。整数型の値の位置インデックスはその値自体になります。

順序型では次の標準関数が使えます。

関数	動作

Ord	集合内での要素の順序を表す数値を返す

Pred	指定された値の 1 つ前の値を返す。指定された値が順序型の最初の値で，範囲チェックが有効な {$R+} の場合，Pred は例外として処理可能な実行時エラーを生成する

Succ	指定された値の次の値を返す。指定された値が順序型の最後の値で，範囲チェックが有効な {$R+} の場合，Succ は例外として処理可能な実行時エラーを生成する

Low	順序型の範囲内で最下位の値を判定する

High	順序型の範囲内で最上位の値を判定する


参照

例外処理

型の互換性

変数の型キャスト

値の型キャスト


整数型

参照	順序型

Object Pascal の定義済みの整数型は基本型と汎用型の 2 種類に分類されます。

通常は汎用整数型により，CPU とオペレーティングシステムにとって最適な処理効率が得られるため，アプリケーションではできるだけ汎用整数型を使うようにします。基本整数型は，実際の範囲や格納形式がアプリケーションで重要な問題となる場合だけ使います。

基本型

以下の基本整数型があります。

型	範囲	形式

Shortint	-128 .. 127	符号付き 8 ビット

SmallInt	-32768 .. 32767	符号付き 16 ビット

Longint	-2147483648 .. 2147483647	符号付き 32 ビット

Byte	0 .. 255	符号なし 8 ビット

Word	0 .. 65535	符号なし 16 ビット

基本型の範囲と形式は CPU とオペレーティングシステムに依存せず，Object Pascal の実装が異なっても変わりません。

汎用型

汎用整数型には Integer と Cardinal があります。Integer 型は汎用の符号付き整数を表し，Cardinal 型は汎用の符号なし整数を表します。汎用型の実際の範囲と格納形式は Object Pascal の処理系によって異なります。ただし，通常は CPU とオペレーティングシステムにとって整数演算がもっとも効率的になるような範囲と格納形式が適用されます。

型	範囲	形式

Integer	-2147483648 .. 2147483647	符号付き 32 ビット

Cardinal	0 .. 2147483647	符号なし 32 ビット

算術演算

整数型オペランドによる算術演算では，以下の規則に従って 8 ビット，16 ビット，32 ビットのいずれかの精度が使われます。

整数定数は，その整数定数の値を含む整数型のうち最小の範囲の整数型になる

二項演算の両方のオペランドは，両方の型のとりうるすべての値を含む整数型のうち最小の範囲の整数型に変換される。式の結果型は共通の型になる

代入文の右側の式は左側の変数のサイズや型に関係なく評価される

バイトは，式の評価の前に Integer と Word の両方と互換性がある 1 ワードの中間オペランドに変換される

メモ:	型キャストにより，整数型の値を別の整数型に明示的に変換できます。


参照

型の互換性

値の型キャスト

変数の型キャスト

基本型と汎用型


論理型

参照	順序型

定義済みの論理型は 4 種類あります。論理型は False または True と評価される変数を宣言します。

型	メモリ

Boolean	1 バイト

ByteBool	1 バイト

WordBool	2 バイト (1 ワード)

LongBool	4 バイト (2 ワード)

最も一般的な論理式の使い方は関係演算子や条件文とともに使う方法です。論理型は列挙型であるため，次の関係が成立します。

False < True

Ord(False) = 0

Ord(True) = 1

Succ(False) = True

Pred(True) = False

Boolean は通常使われる型で使うメモリ量も最少です。ByteBool，WordBool，LongBool は他の言語や Windows 環境との互換性を提供します。

Boolean 型の変数が値 0 (False) と 1 (True) しか扱えないのに対し，ByteBool，WordBool，LongBool は 0 が False で非ゼロの値がすべて True という順序値を扱えます。Boolean 値が予期されるコンテキストで ByteBool，WordBool，LongBool 値が使われた場合，コンパイラは非ゼロのすべての値を True に変換するコードを自動的に生成します。


参照

論理式

論理演算子

条件文

関係演算子

型の互換性


文字型

参照	順序型

Object Pascal の文字型では 2 つの基本型と 1 つの汎用型が定義されています。

以下の 2 種類の基本文字型があります。

AnsiChar	拡張 ASCII 文字セットに従って順序付けされたバイトサイズの文字群

WideChar	ワードサイズの文字群。

Char が汎用文字型です。

現在の Object Pascal の処理系では Char は 基本型の AnsiChar に対応しますが，CPU やオペレーティングシステムが異なる処理系では Char を WideChar として定義できます。両方のサイズの文字を扱う必要があるコードを作成する場合は，文字サイズを表すハードコードの定数ではなく標準関数の SizeOf を使います。

Ch が文字型値のとき，Ord(Ch) という関数呼び出しは Ch の順序値を返します。

長さが 1 の文字列定数は定数文字値で表せます。Chr 関数は，対応する順序値を持つ文字に整数値を変換できます。


参照

型の互換性

基本型と汎用型


列挙型

参照	例	順序型

列挙型は識別子リストの要素に連続した値を割り当てます。最初の要素の値は 0 になり，2 番目の要素は 1 という具合に続きます。

コンパイラは列挙型の名前を識別子リスト全体の型として認識します。

識別子の順序はその識別子が宣言された識別子リスト内の位置によって決まります。

Succ 関数と Pred 関数を使うと識別子リストの要素間を前方または後方に循環できます。

Ord 関数を列挙型の値に適用する場合，その値が同じ列挙型の他の値と比較してどの位置に置かれるかを示す整数が返されます。


参照

論理型

型の互換性

型宣言


列挙型の例

type

  Suit = (Club, Diamond, Heart, Spade);


部分範囲型

例	順序型

部分範囲型はホスト型と呼ばれる順序型の一部の値範囲です。部分範囲型の定義では部分範囲内の最小値と最大値を指定します。

2 つの定数は同じ順序型でなくてはなりません。

部分範囲型の変数はホスト型のすべてのプロパティを持ちますが，実行時の値は指定された範囲内になくてはなりません。

コンパイラはカッコで始まる型定義を列挙型として定義するため，定数式を記述するときに構文上のあいまいさが 1 つ生じます。この問題を解決する方法は 2 つあります。

最初の部分範囲式がカッコで始まらないよう編成し直す

式の値と等しい定数を設定し，その定数を型定義で使う

$R コンパイラ指令は部分範囲型の範囲チェックを制御します。


部分範囲型の例

部分範囲型の例を次に示します。

0..99

-128..127

Club..Heart

次のコードはカッコで始まる定数式の問題を解決するための 1 つの方法を示しています。

type

  Scale = 2 * (X - Y)..(X + Y) * 2;


実数型

参照	型

実数型は実数の部分集合で，限定された桁数の浮動小数点表記で表現できます。

実数型には 6 つの種類があります。これらは範囲，値の精度，サイズがそれぞれ異なります。

有効	サイズ
型	範囲	桁数	(バイト数)

Real	±2.9e-39 .. 1.7e38	11-12	6

Single	±1.5e-45 .. 3.4e38	7-8	4

Double	±5.0e-324 .. 1.7e308	15-16	8

Extended	±3.4e-4932 .. 1.1e4932	19-20	10

Comp	(-2 の 63 乗) + 1 .. (2 の 63 乗) - 1	19-20	8

Currency	-922337203685477.5808.. 922337203685477.5807	19-20	8

Comp (Computational) 型は (-2 の 63 乗) + 1 から (2 の 63 乗) - 1 までの整数値だけを保持できます。約 -9.2e18 から 9.2e18 に対応します。

Currency 型は金額の計算に適した固定小数点データ型です。これはスケール付きの 64 ビット整数として格納され，下 4 桁が小数点以下の 4 桁を表すものとして扱われます。


ポインタ型

参照	例	型

ポインタ型は基本型の変数をポイントする値です。ポインタ型の変数には変数のメモリアドレスが保持されます。

基本型が未宣言の識別子の場合，ポインタ型と同じ型宣言部でその識別子を宣言しなくてはなりません。

ポインタ変数には次の手続きまたは関数を使って値を代入できます。

手続き/関数	動作

New	アプリケーションヒープに動的変数のための新しいメモリ領域を割り当て，その領域のアドレスをポインタ変数に格納する

@ 演算子	すでに識別子を持っている変数を含めて，既存の変数か手続きか関数のエントリポイントを保持しているメモリ領域をポインタ変数が指し示すようにする

GetMem	指定されたサイズの新しい動的変数を作成し，そのブロックのアドレスをポインタ変数に置く

予約語 nil はポインタ値を表す定数で，何もポイントしていないことを意味します。

ポインタの比較

演算子の = と <> は互換のポインタ型オペランドに対して使えます。2 つのポインタは同じオブジェクトをポイントする場合のみ等しいとみなされます。

互換性についての注意

C++Builder では，ポインタ型の宣言内で未宣言の識別子を使用できるのは，次のような状況のときだけです。

type
PointerType = ^UndefinedType;

ここで UndefinedType は，同じ型宣言ブロック内の後方で定義されます。


参照

ポインタ型定数

ポインタと動的変数

型の互換性

Pointer 型

PChar 型

値の型キャスト


Pointer 型

参照

定義済みの型 Pointer は型なしポインタです。

Pointer 型の変数は逆参照できません。このような変数の後にポインタシンボル ^ を記述するとエラーになります。

汎用ポインタは型キャストによって逆参照できます。

Pointer 型の値は他のすべてのポインタ型と互換です。


参照

ポインタ型

ポインタと動的変数

型の互換性

PChar 型

変数の型キャスト


文字ポインタ型

参照

Object Pascal の文字ポインタ型では 2 つの基本型と 1 つの汎用型が定義されています。

文字ポインタ型は文字型へのポインタにすぎませんが，Object Pascal は文字ポインタ型を使ってヌルで終わる文字列を処理できるようにするために，いくつかの拡張構文規則をサポートしています。

以下の 2 種類の基本文字ポインタ型があります。

PAnsiChar	AnsiChar 型の文字で構成されるヌルで終わる文字列へのポインタ

PWideChar	WideChar 型の文字で構成されるヌルで終わる文字列へのポインタ

以下の汎用文字ポインタ型があります。

PChar	Char 型の文字で構成されるヌルで終わる文字列へのポインタ

System ユニットはポインタ文字型を次のように宣言しています。

type

  PAnsiChar = ^AnsiChar;

  PWideChar = ^WideChar;

  PChar = PAnsiChar;

基本文字ポインタ型は基本文字型への (またはそのような文字で構成されるヌルで終わる文字列への) ポインタであり，汎用文字ポインタ型は汎用文字型へのポインタです。


参照

文字ポインタ演算子

ヌルで終わる文字列

ポインタ型

関係演算子

型の互換性

Pointer 型


ポインタ型の例

{ ポインタ型宣言 }

type

  BytePtr  = ^Byte;

  WordPtr  = ^Word;

  IdentPtr = ^IdentRec;

  IdentRec = record

    Ident: string[15];

    RefCount: Word;

    Next: IdentPtr;

  end;


標準ポインタ

参照

Pascal で構造化型やデータ型を定義するときには，そのデータ型を指すポインタも定義しておくことをお勧めします。リンクトリストや動的に割り当てられるレコードなどの上級プログラミングでは，変数そのものではなく変数へのポインタを使うことが必要とされる場面がたくさんあります。

変数を使うときに，コンパイラはその型の初期化と終了処理に必要なコードを自動的に生成します。AnsiString や Variant などの動的構造体を指すポインタの割り当てと解放を行うコードでは，特別な初期化と終了処理が必要になります。

次の表にこのようなポインタを示します。

ポインタ	ポインタが指すオブジェクト

PAnsiString	AnsiString 変数

PByteArray	TByteArray 型の変数。動的に割り当てられたメモリブロックを配列としてアクセスするための型キャストで使用される

PCurrency	Currency 型変数

PExtended	Extended 型変数

PTextBuf	TextBuf 型変数。TextBuf はテキストファイルレコード TTextRef で使用される内部バッファ

PVarRec	TVarRec 型変数

PVariant	Variant. 型変数

PWordArray	TWordArray 型変数。動的に割り当てられたメモリブロックをワードサイズ値（2 バイト符号なし）の配列としてアクセスするための型キャストで使用される


参照

文字ポインタ演算子


手続き型

参照	例	型

手続き型を使うと，手続きや関数を，変数に代入したり，パラメータとして渡せる実体として扱うことができます。

手続き型の宣言ではパラメータを指定し，関数の場合は結果型も指定します。

手続き型を宣言する構文は，キーワード procedure または function の後に識別子を指定しないこと以外は手続きまたは関数のヘッダーと同じです。手続き型の宣言にはオプションとして呼び出し規約を指定することもできます。デフォルトの呼び出し規約は register です。

手続き型には次の 2 つのカテゴリがあります。

グローバル手続きポインタ

メソッドポインタ

手続き型の値を返す関数は宣言できません。ただし，Pointer 型の関数結果を使って手続きまたは関数のアドレスを返し，その後手続き型に型キャストできます。

関数結果は次のいずれかの型でなくてはなりません。

文字列

実数

整数

char

論理

ポインタ

ユーザー定義の列挙

手続き型の互換性

手続き型が互換であるためには次の条件に従わなくてはなりません。

2 つの型は同じ呼び出し規約を使う

2 つの型は同じ個数のパラメータを持つ

対応する位置にあるパラメータが同じ型である

関数の結果型が同じである

 値 nil はすべての手続き型と互換です。

メモ:	手続き型の互換性を判定する場合，パラメータ名は重要ではありません。

グローバル手続きポインタ型とメソッドポインタ型は相互に非互換です。


参照

手続き型定数

手続き値

型ポインタ

変数の型キャスト


手続き型の例

type

  Proc = procedure;

  SwapProc = procedure(var X, Y: Integer);

  StrProc = procedure(S: string);

  MathFunc = function(X: Double): Double;

  DeviceFunc = function(var F: Text): Integer;

  MaxFunc = function(A, B: Double; F: MathFunc): Double;

var

  P: SwapProc;

  F: MathFunc;

procedure Swap(var A, B: Integer);

var

  Temp: Integer;

begin

  Temp := A;

  A := B;

  B := Temp;

end;

function Tan(Angle: Double);

begin

  Tan := Sin(Angle) / Cos(Angle);

end;

{ 変数 P と F に次の値を代入します }

P := Swap;

F := Tan;

{ P と F を使った次の呼び出しは有効です }

P(I, J);       { Swap(I, J) と等価です }

X := F(X);     { X := Tan(X) と等価です }


グローバル手続きポインタ

参照	例

グローバル手続きポインタは of object 節なしで宣言された手続き型です。グローバル手続きポインタはグローバルな手続きまたは関数を参照でき，グローバルな手続きまたは関数のアドレスを格納するポインタとしてコード化されます。


参照

手続き型


例

type

  TProcedure = procedure;

  TStrProc = procedure(const S: string);

  TMathFunc = function(X: Double): Double;


手続き値

参照	例

手続き型変数には手続き値を代入できます。

手続き値は次のいずれかです。

値 nil

手続き型の変数参照

手続きまたは関数の識別子

メソッド指定子

手続きまたは関数を手続き値として宣言すると，定数宣言とみなされます。

値が nil の手続き変数を手続き文または関数呼び出しで使うと結果はエラーになります。nil は手続き変数に値が代入されていないことを意味します。nil の手続き変数が関与する手続き文または関数呼び出しを使う場合は，次のテストが必要です。@ 演算子は P が呼び出されるのではなくテストされることを示します。

if @P <> nil then P(I, J);

次の型の手続きと関数は手続き値として使えません。

標準

ネスト

メソッド

インライン

標準手続きと標準関数は直接は使えませんが，対処方法があります。標準手続きまたは関数を手続き値として使うには，新しい関数または手続きを宣言し，そのメインボディで標準手続きまたは関数を呼び出さなくてはなりません。


参照

手続き型

型の互換性

式での手続き型の使い方


文字列型

参照	例	型

C++Builder は 2 種類の文字列型をサポートしています。

短い文字列型

長い文字列型

2 つの文字列型は，代入や式で混在して使用することができ，コンパイラは必要な文字列型の変換を行うコードを自動的に生成します。

短い文字列型は，最大長 1～255 バイトの静的に割り当てられる文字列を表し，その動的な長さは 0～最大長になります。

長い文字列型は動的に割り当てられる文字列を表し，その最大長は使用可能なメモリによってのみ制限されます。

メモ:	コンパイラ指令 $H を使って，予約語 string が短い文字列と長い文字列のどちらを表すかを制御できます。デフォルトの状態は {$H+} で，string は長い文字列を表し，string キーワードは定義済み識別子 AnsiString と同じ意味を持ちます。{$H-} の状態では string は最大長 255 バイトの短い文字列を表し，キーワード string は定義済み識別子 ShortString と同じ意味を持ちます。

文字列内では，2 つの連続する単引用符は 1 つの単引用符を表します。


例

{ 文字列型の定義 }

  const

    LineLen = 79;

  type

    Name = string[25];

    Line = string[LineLen];


参照

string (予約語)

文字列演算子

文字列型定数

型の互換性


型
短い文字列型

参照	文字列型

短い文字列型の宣言は 1～255 文字の最大長を指定します。短い文字列型の変数には，動的な長さが 0～宣言された最大長の文字列を格納できます。

定義済みの型 ShortString は最大長が 255 文字の短い文字列型を表します。

短い文字列型変数が占有する記憶域のバイト数は短い文字列型の最大長に 1 を加えたものです。

短い文字列型変数に文字列値を代入する場合，その短い文字列型変数の宣言された最大長より文字列値が長ければ，その文字列値は切り捨てられます。

短い文字列型変数には添字式を 1 つだけ付けられます。添字式の値は，0～N (N は短い文字列の宣言された最大長) の範囲になければなりません。短い文字列に添字を付けてアクセスされる文字の型は Char です。文字列の最初の文字の添字は 1 です。添字 0 の要素はその文字列の動的な長さを保持します。短い文字列の場合，Length(S) は Ord(S[0]) と同じです。短い文字列の 0 番目の要素に値を代入すると文字列の動的な長さが変わりますが，コンパイラはその値が文字列の宣言された最大長より小さいかどうかを調べません。短い文字列に現在の動的な長さを超えて添字が付けられている可能性もあります。その場合に読み出される文字の値は未定義であり，現在の長さを超えた文字位置へ代入しても，短い文字列型変数の実際の値に影響はありません。

短い文字列型変数には標準関数の Low と High が使えます。その場合，Low はゼロを返し，High は短い文字列の宣言された最大長を返します。


参照

文字列型

長い文字列型

string (予約語)


長い文字列型

参照	文字列型

長い文字列型は予約語 string と定義済み識別子 AnsiString で表されます。

メモ:	$H コンパイラスイッチの状態を {$H-} に変更した場合，予約語 string は最大長が 255 文字の短い文字列を表します。しかし，定義済み識別子 AnsiString は常に長い文字列型を表します。

長い文字列は動的に割り当てられ，宣言された最大長を持ちません。長い文字列値の理論上の最大長は 2GB (2 ギガバイト) です。実際には，長い文字列値の最大長はアプリケーションで使用可能なメモリの量によってのみ制限されます。

長い文字列型変数へ関連付けられる動的割り当てメモリの管理は完全に自動化されており，ユーザーコードを追加する必要はありません。長い文字列の自動管理には，以下のような特性があります。

長い文字列型変数は 4 バイトのメモリを占有し，そこには動的割り当て文字列へのポインタが入っている。長い文字列型変数が空である (長さゼロの文字列が中に入っている) 場合，文字列ポインタは nil になり，その文字列変数へ動的メモリは関連付けられない。文字列値が空でない場合，文字列ポインタは動的割り当てメモリブロックを指し，そのメモリブロックには文字列値のほかに 32 ビットの長さインジケータと 32 ビットの参照カウンタが入っている

長い文字列は参照カウンタを持っている。長い文字列型変数へ新しい値が代入された場合，前の値の参照カウンタが (空でなければ) デクリメントされ，新しい値の参照カウンタが (空でなければ) インクリメントされる。文字列値の参照カウンタがゼロになると，その文字列値が入っている動的割り当てメモリは割り当てを解除される。この参照カウンタ機能によって，文字列データのコピー操作とメモリ消費が大幅に減少する。長い文字列の代入でコピーされるデータは 32 ビットの文字列値ポインタだけであり，それ以上のメモリを消費せずに任意の数の長い文字列型変数が同じ値を参照できる。この理由から，長い文字列の代入は短い文字列の代入より実行速度が速いのが普通である

添字付けを使って長い文字列型変数の中にある 1 文字の値を変更する場合，文字列値の参照カウンタが 1 より大きければ，最初に文字列値のコピーが作成される。これは「書き込み時コピー」と呼ばれ，この機能によって，その文字列値を参照する別の長い文字列型変数まで変更が及ばないことが保証される

長い文字列型変数は，最初に作成された時点では常に空になるように初期化される。これはその長い文字列型変数がグローバルでもローカルでも，あるいは配列，レコード，オブジェクトなどの構造の一部であっても同じである

長い文字列型変数がスコープの外に出た場合 (ローカルな長い文字列型変数を使った関数を終了したとき，または長い文字列型フィールドが入っているオブジェクトを廃棄したときなど)，それらの変数値の参照カウンタは自動的にデクリメントされる。これは例外が原因で関数が終了した場合でも同じである

空でない長い文字列型変数には添字式を 1 つだけ付けられる。添字式の値は，1～N (N は長い文字列の動的な長さ) の範囲になければならない。長い文字列に添字を付けてアクセスされる文字の型は Char である。長い文字列の最初の文字の添字は 1 である。短い文字列と異なり，長い文字列には動的な文字列の長さを入れる 0 番目の要素がない。長い文字列の長さを知るには標準関数の Length を使わなければならず，長い文字列の長さを変更するには標準手続きの SetLength を使わなければならない

長い文字列に添字を付けて取得した文字位置へ代入することは可能ですが，そのような文字を var パラメータとして渡すことはできません。

あるレコード型の中にいくつかの長い文字列型フィールドを宣言する場合，それらのフィールドはすべてそのレコード型のバリアント部分以外に存在している必要があります。つまり，長い文字列型フィールドまたは長い文字列が入る型のフィールドをレコード型のバリアント部分に置くことはできません。

長い文字列とヌルで終わる文字列

文字列のためにに割り当てられたメモリブロックには，末尾に自動的にヌル文字が追加されます (ヌル文字は文字列の一部ではなく，文字列の最後の文字の後に自動的に格納されます)。この自動ヌルターミネートのため，長い文字列値は直接，PChar 値へ型キャストできます。そのような型キャストの構文は PChar(S) です (S は長い文字列式)。PChar 型キャストは長い文字列値の最初の文字へのポインタを返し，文字列式が空の場合でも，ヌルで終わる文字列へのポインタを必ず返します。

次の例は，ヌルで終わる文字列パラメータを期待する関数へ PChar 型キャストを使って長い文字列値を渡す方法を示しています。Caption と Message は長い文字列型変数で，MessageBox は Windows ユニットで定義されている Win32 API 関数です。

Caption := 'Hello world';

Message := 'This is a test of long strings';

MessageBox(0, PChar(Message), PChar(Caption), MB_OK);

Pointer(S) という構文 (S は長い文字列式) を使って長い文字列を型なしポインタへ型キャストすることもできます。Pointer 型キャストは長い文字列値の最初の文字のアドレスを返します。PChar 型キャストとは異なり，Pointer 型キャストは文字列式が空の場合には nil を返します。

PChar または Pointer の型キャストが返すポインタの寿命は型キャストの引数によって決まります。引数が長い文字列の式である場合，ポインタは型キャストが実行される文の中でだけ有効です。したがって，そのような型キャストは実質的にパラメータ式の中でしか使えません。引数が長い文字列の変数である場合，ポインタはその変数へ新しい値が代入されるか，その変数がスコープから出るまで有効です。

一般に，PChar または Pointer の型キャストが返したポインタによって参照するヌルで終わる文字列は読み出し専用と考えてください。

PChar または Pointer の型キャストが返したポインタを使うと，対応する長い文字列を変更することが可能ですが，そのような変更は特定の状況でしか安全ではありません。たとえば，PChar(S) または Pointer(S) という形式の型キャストがある場合，その型キャストの結果で参照したヌルで終わる文字列は，以下のすべての条件が満たされた場合にだけ変更できます。

S が長い文字列の変数である (式でない)

S の値が空でない。つまり，S にゼロより大きい長さの文字列が入っていなければならない

S の値がユニークである。つまり，長い文字列値の参照カウントが 1 である。SetLength，SetString，UniqueString の各標準手続きを呼び出した後，長い文字列型変数の値はユニークになり，その文字列変数を文字列式の中で参照しない限り，必ずユニークなまま残っている

S が，型キャストされた後に変更されておらず，スコープから出てもいない

変更されたすべての文字が文字列の長さ以内にある。つまり，返された PChar 値に添字を付けた場合，添字の値が 0～Length(S)-1 でなければならない


参照

文字列型

短い文字列型

string (予約語)

ヌルで終わる文字列


文字列の使い方

参照	文字列型

2 つの文字列値の順序は，対応する位置にある文字値の順序関係によって決まります。長さが等しくない 2 つの文字列の場合，長い方の文字列に入っていて短い方の文字列の中に対応する文字がない文字は，より高いかより大きい値をとります。たとえば，BA は A より大きくなります。長さゼロの文字列は長さゼロの別の文字列とだけ等しく，それらの文字列は文字列として最も小さな値となります。

文字列型の演算子については，文字列演算子と関係演算子を参照してください。

短い文字列型と長い文字列型は代入や式の中で混在できますが，var パラメータとして渡された文字列は適切な型でなければなりません。つまり，長い文字列を期待する手続きや関数へ短い文字列を var パラメータとして渡すことはできません。逆に，短い文字列を期待するものに長い文字列を渡すことも同様にできません。

短い文字列は AnsiString(S) という形式の型キャスト (S は短い文字列式) を使って長い文字列へ明示的に変換できます。デフォルトの {$H+} 状態では，string(S) という形式の型キャストがやはり短い文字列式を長い文字列に変換します。

長い文字列は ShortString(S) という形式の型キャスト (S は長い文字列式) を使って短い文字列へ明示的に変換できます。{$H-} 状態では，string(S) という形式の型キャストがやはり長い文字列式を短い文字列に変換します。


参照

長い文字列型

短い文字列型

string (予約語)


構造化型

参照	型

構造化型は 2 つ以上の値を保持します。構造化型の要素は個別にでも，まとめてでも処理できます。要素そのものを構造化型にすることもできます。構造化型のネスト構造の数に制限はありません。

C++Builder には以下の構造化型があります。

配列型

ファイル型

クラス型

クラス参照型

レコード型

集合型

構造化型はネストしたレベルを持つことができます。

クラス型とクラス参照型は，Object Pascal でのオブジェクト指向プログラミングの基礎となります。

構造化型の宣言にある予約語 packed は，この型の変数の要素へのアクセスの軽減を犠牲にしてもデータ領域を圧縮するようにコンパイラに指示します。デフォルトでは，構造化型の要素は，高速にアクセスできるようにワード境界またはダブルワード境界に配置されます。構造化型の宣言に packed を追加すると，その型ではワードまたはダブルワードのアラインメントがオーバーライドされます。


参照

構造化型定数

型の互換性


配列型

参照	例	構造化型

配列は一次元または多次元のコンテナで，同じ型の複数の変数を保持します。配列の各変数は配列名とインデックスを使って参照できます。インデックスは [ ] で囲んで指定します。

配列型を指定するにはコンパイラに 2 つの情報を与えなくてはなりません。

要素の数を指定する配列の順序インデックス型

基本型

配列内の要素の数は各インデックス型の値の数の積になります。

配列の要素にアクセスするには，配列識別子に [ ] で囲んだインデックス値を加えます。次の文は配列の 3 番目の要素にアクセスします。

array[3];

配列のインデックス型の下限と上限を返すには，標準関数 Low と High を使い，配列型識別子または配列型の変数参照を指定します。

多次元配列型

配列のコンポーネント型もまた配列である場合，結果を配列の配列として，または 1 つの多次元配列として扱えます。次に例を示します。

array[Boolean] of array[1..10] of array[Size] of Real

コンパイラはこれを次と同じように解釈します。

array[Boolean,1..10,Size] of Real

多次元の配列を宣言する場合，配列内の要素の合計数は各インデックス型の値の数の積になります。

インデックスがゼロから始まる配列

インデックスがゼロから始まる配列は配列宣言で最初の要素にインデックスとしてゼロを割り当てることによって宣言します。次に例を示します。

array[0..5] of Char

インデックスがゼロから始まる文字配列はヌルで終わる文字列を格納するために使います。インデックスがゼロから始まる文字配列は PChar 値と互換になります。


配列の例

配列宣言の例を示します。

array[1..100] of Real   { 実数型の 100 個の要素を保持できる配列を宣言します }


参照

array (予約語)

配列型定数

添字

ヌルで終わる文字列

オープン配列パラメータ

型の互換性

変数参照


レコード型

参照	例	構造化型

レコード型はフィールドの集まりで，各フィールドは異なる型であってもかまいません。

レコード型の宣言ではフィールド名とフィールド型を割り当てなくてはなりません。

レコード型の固定部は固定フィールドのリストを指定し，それぞれのフィールドには識別子と型が指定されます。各フィールドに含まれる情報は常に同じ方法で取り出されます。

レコード型の可変部は複数のフィールドリストにメモリ空間を分配し，これにより複数の方法で情報にアクセスできます。

各フィールドリストはメモリ内の同じ空間にオーバーレイする可変要素です。それぞれの可変要素は定数によって区別され，すべての可変要素のすべてのフィールドにいつでもアクセスできます。

各可変要素は最低 1 つの定数によって識別されます。すべての定数はユニークでなくてはならず，タグフィールド型と互換の順序型でなくてはなりません。

省略可能なタグフィールド識別子は，レコードの追加固定フィールド，すなわちタグフィールドの識別子です。プログラムはタグフィールドの値を使ってアクティブな可変要素を示します。

タグフィールドがない場合，プログラムは別の基準によって可変部を選択します。

メモ:	レコードの可変部のフィールドには，長い文字列型およびバリアント型は使えません。同様にレコードの可変部のフィールドには，長い文字列型またはバリアント型を含む構造化型は使えません。

レコードへのアクセス

レコード全体にアクセスしたり，各フィールド個別にアクセスしたりできます。個々のフィールドにアクセスするには，レコード名，ピリオド，フィールド識別子を入力します。たとえば次のように入力します。

TDateRec.Year

レコード全体にアクセスするには，with 文を使います。


参照

レコードのスコープ

型の互換性

with 文


レコード型の例

type

  TDateRec = record

    Year: Integer;

    Month: 1..12;

    Day: 1..31;

  end;

type

  TPerson = record

    FirstName, LastName: string[40];

    BirthDate: TDateTime;

    case Citizen: Boolean of

      True: (BirthPlace: string[40]);

      False: (Country: string[20];

        EntryPort: string[20];

        EntryDate: TDateTime;

        ExitDate: TDateTime);

  end;


クラス型

参照	例	構造化型

クラス型は決められた個数のコンポーネントからなる構造です。

コンポーネントとして可能なクラスは次のものです。

フィールド

メソッド

プロパティ

他の型と異なり，クラス型はプログラムまたはユニットの最も外側のスコープの型宣言部でだけ宣言できます。したがって，クラス型は変数宣言部や手続き，関数，メソッドブロック内では宣言できません。

クラス型は予約語 class を使って宣言され，クラスの内容を定義します。クラスは「オブジェクト型」とも呼ばれます。2 つの用語は相互に置き換え可能です。

クラス型はグローバルに宣言しなくてはなりません。クラス型は変数宣言部や手続き，関数，メソッドブロック内では宣言できません。

ファイルのコンポーネント型は，クラス型やクラス型コンポーネントを持つ構造化型にはできません。

継承

クラス型は別のクラス型からコンポーネントを継承できます。継承されるクラスは下位クラスで，継承元のクラスはその上位クラスです。

継承は推移します。たとえば，T3 が T2 を継承し，T2 が T1 を継承する場合，T3 も T1 を継承します。クラス型のドメインはそのクラス自体とすべての下位クラスで構成されます。

下位クラスは上位クラスによって定義されたすべてのコンポーネントを無条件に含みます。下位クラスは継承するコンポーネントに新しいコンポーネントを追加できます。ただし，上位クラスで定義されたコンポーネントの定義は削除できません。

定義済みのクラス型 TObject はすべてのクラス型に対して最上位のクラスです。クラス型の宣言で上位型を指定しない場合 (すなわち，クラス宣言の継承部を省略した場合)，クラス型は TObject から派生します。TObject は System ユニットによって宣言され，すべてのクラスに適用されるいくつかのメソッドを定義します。

クラス型の互換性

クラス型はすべての上位クラス型と代入の互換性があります。したがって，プログラム実行の間，クラス型変数はその型のインスタンスまたは下位クラス型のインスタンスを参照できます。たとえば，次のような宣言があるとします。

type

  TFigure = class

    :

  end;

  TRectangle = class(TFigure)

    :

  end;

  TRoundRect = class(TRectangle)

    :

  end;

  TEllipse = class(TFigure)

    :

  end;

TRectangle 型の値は TRectangle，TFigure，TObject 型の変数に代入でき，プログラム実行の間，TFigure 型の変数は nil になるか，TFigure，TRectangle，TRoundRect，TEllipse のインスタンスまたは TFigure の他の下位クラスのインスタンスへの参照になります。


参照

class (予約語)

コンポーネントのスコープ

コンポーネントの可視性

オブジェクトのインスタンス化

メソッド


オブジェクト型の例

次のコードはクラス TField を宣言します。

TField = class

private

  X, Y, Len: Integer;

  FName: String;

public

  constructor Copy(F: TField);

  constructor Create(FX, FY, FLen: Integer; FName: String);

  destructor destroy; override;

  procedure Display; virtual;

  procedure Edit; dynamic;

protected

  function GetStr: String; virtual;

  function PutStr(S: String): Boolean; virtual;

private

  procedure DisplayStr(X, Y: Integer; S: String);

public

  property Name: String read GetStr write FName;

end;

  TStrField = class(TField)

  private

    Value: PString;

  public

    constructor Create(FX, FY, FLen: Integer; FName: String);

    destructor Destroy; override;

  protected

    function GetStr: String; override;

    function PutStr(S: String): Boolean; override;

  end;

  TNumField = class(TField)

  private

    Value, Min, Max: Longint;

  public

    constructor Create(FX, FY, FLen: Integer; FName: String;

      FMin, FMax: Longint);

    function GetStr: String; override;

    function PutStr(S: String): Boolean; override;

    function Get: Longint;

    procedure Put(N: Longint);

  end;


メソッド

参照	クラス型

メソッドとはオブジェクト型宣言内で宣言された，オブジェクトに対して操作を行う手続きまたは関数を指します。

オブジェクト型で宣言されたメソッドはデフォルトでは静的になります。静的メソッドが呼び出されると，メソッド呼び出しで使われたクラスまたはオブジェクトの宣言型 (コンパイル時) によって，どのメソッド実現を起動するかが決まります。

オブジェクトのデータフィールドがパラメータとしてメソッドに渡されなくても，メソッドはこれらのフィールドにアクセスできます。

オブジェクト型宣言内の宣言は，そのメソッドの forward 宣言に対応します。

メソッドのボディはオブジェクト型宣言の外部で定義しますが，同じスコープ内でなくてはなりません。ヘッダーにはボディのバインド先のオブジェクト型名を含めなくてはなりません。次に例を示します。

procedure ObjectType.Method(Param1, Param2: Integer);

begin

...

end;  (* メソッド *)

メソッドの実装コード内では，識別子 Self は，そのメソッドが呼び出されたときの対象となるオブジェクトを参照する暗黙のパラメータを表します。

デフォルトではメソッドは静的です。ただし，次の型にすることもできます。

仮想メソッドVirtualmethods

クラスメソッド

コンストラクタとデストラクタはオブジェクトの作成と廃棄を制御する特殊なメソッドです。

メソッド内では，関数呼び出しまたは手続き文で限定メソッド指定子を使って特定のメソッドを起動できます。この種の呼び出しは限定メソッドの起動と呼ばれます。


参照

コンストラクタとデストラクタ

メソッドの起動

メソッドの宣言

オブジェクト型

限定メソッドの起動

Self


メソッドの実現

例

オブジェクト型の中でのメソッドの宣言はそのメソッドの forward 宣言に相当します。オブジェクト型宣言の後，同じモジュール内で，定義宣言によってメソッドを実現しなくてはなりません。

手続きメソッドや関数メソッドの場合，定義宣言は通常の手続き宣言または関数宣言の形式をとりますが，見出しに指定する手続き識別子または関数識別子が限定メソッド識別子である点が異なります。

コンストラクタとデストラクタの場合，定義宣言は手続きメソッド宣言の形式をとりますが，予約語 procedure のかわりに constructor または destructor を使う点が異なります。

メソッドの定義宣言ではオプションでクラス型のメソッド見出しの仮パラメータリストを繰り返し指定できます。定義宣言のメソッド見出しはパラメータの順序，型，名前が正確に一致し，関数結果の型があればそれも一致しなくてはなりません。

メソッドの定義宣言では，クラス型の仮パラメータに対応するものとして，識別子が Self の暗黙のパラメータが必ず存在します。メソッドブロック内で，Self はメソッドを起動したインスタンスを表します。

オブジェクト型のコンポーネント識別子のスコープはクラス型のメソッドを実現するすべての手続き，関数，コンストラクタ，またはデストラクタブロックに及びます。

メソッドブロック内では，再宣言されオーバーライドされたコンポーネント識別子に対し予約語 inherited を使ってアクセスできます。識別子に inherited のプレフィックスが付いている場合，識別子の検索はそのメソッドのオブジェクト型のすぐ上位のオブジェクトから始まります。


例

次のようなオブジェクト型宣言を想定します。

type

  TFramedLabel = class(TLabel)

  protected

    procedure Paint; override;

  end;

Paint メソッドは後の定義宣言で実現しなくてはなりません。たとえば次のようにします。

procedure TFramedLabel.Paint;

begin

  inherited Paint;

  with Canvas do

  begin

    Brush.Color := clWindowText;

    Brush.Style := bsSolid;

    FrameRect(ClientRect);

  end;

end;


仮想メソッド

参照	例

仮想メソッドは実行時にコンパイラによって解決されます。このプロセスはレイトバインディングと呼ばれます。デフォルトでは，コンストラクタメソッド以外のすべてのメソッドが静的ですが，メソッド宣言に virtual 指令を含めることによってメソッドを仮想に指定できます。

仮想メソッドが呼び出されると，メソッド呼び出しで使われたクラスまたはオブジェクトの実際の (実行時の) 型によって，どのメソッド実現を起動するかが決まります。

仮想メソッドのオーバーライド

オブジェクト型は上位オブジェクトから継承するメソッドはどれでもオーバーライド (再定義) できます。オーバーライドメソッドのスコープは定義元オブジェクトのすべての下位オブジェクトに及ぶか，メソッド識別子を再定義するまでになります。

仮想メソッドのオーバーライドはパラメータの順序，型，名前が正確に一致し，関数結果の型が存在する場合はその型も一致しなくてはなりません。オーバーライドには virtual 指令のかわりに override を指定しなくてはなりません。

メモ:	仮想メソッドをオーバーライドする唯一の方法は override 指令を使う方法です。下位クラスのメソッド宣言で同じメソッド識別子を継承メソッドとして指定し，override 指令を指定しない場合，新しいメソッド宣言により継承宣言は隠されますが，オーバーライドはされません。


例

次の 2 つの下位クラスは TFigure から継承した Draw メソッドをオーバーライドします。

type

  TRectangle = class(TFigure)

    procedure Draw; override;

    :

  end;

  TEllipse = class(TFigure)

    procedure Draw; override;

    :

  end;

次のコードは実行時に実際の型が変化するクラス型変数を使って仮想メソッドを呼び出す様子を示しています。

var

  Figure: TFigure;

begin

  Figure := TRectangle.Create;

  Figure.Draw;	{ TRectangle.Draw を呼び出します }

  Figure.Destroy;

  Figure := TEllipse.Create;

  Figure.Draw;	{ TEllipse.Draw を呼び出します }

  Figure.Destroy;

end;


参照

メソッド

オーバーライド指令

virtual (標準指令)


オブジェクトのインスタンス化

参照

オブジェクト型のインスタンスはオブジェクト型によって定義されたレイアウトを使って動的に割り当てられたメモリブロックです。

オブジェクト型のインスタンスは一般にオブジェクトとも呼ばれます。オブジェクト型の各オブジェクトはそのオブジェクト型で宣言されたフィールドのコピーを独自に持ちますが，メソッドに関してはすべてが同じものを共有します。

オブジェクト型の変数にはそのオブジェクト型のオブジェクトへの参照が含まれます。変数にはオブジェクトそのものは含まれず，オブジェクトに対して割り当てられたメモリブロックへのポインタとして機能します。ポインタ変数と同様に，複数のオブジェクト型変数が同じオブジェクトを参照でき，また現在オブジェクトを参照していないことを示す値 nil を持つことができます。

メモ:	ポインタ変数とは異なり，参照先オブジェクトへアクセスするためにオブジェクト型変数を逆参照する必要はありません。つまり，動的に割り当てられたレコードのフィールドにアクセスするには，Ptr^.Field と記述しなくてはなりませんが，オブジェクトのコンポーネントにアクセスするときには ^ 演算子が暗黙的に含まれるため，構文は単に Instance.Field になります。


参照

コンストラクタとデストラクタ

メソッド

仮想メソッド


メソッドの起動

参照

メソッドを起動するには，メソッド指定子と実パラメータリストで構成される関数文または手続き文を呼び出します。

変数参照はオブジェクト参照またはクラス参照のインスタンスでなくてはならず，メソッド識別子はそのオブジェクト型のメソッドでなくてはなりません。

メソッド指定子はメソッドの暗黙の実パラメータになります。これは Self という名前の仮変数パラメータに対応し，起動されたメソッドに対応するオブジェクト型を保持します。

with 文を使う場合，Self パラメータが参照されるため，メソッド指定子の変数参照部は省略できます。

メソッド宣言内では，変数参照を省略できます。メソッド起動の際の暗黙の Self パラメータが，その呼び出しを含むメソッドの Self になります。


参照

関数呼び出し

メソッドの宣言

パラメータ

手続き文

限定メソッドの起動

with 文


限定メソッドの起動

参照	例

限定メソッドの起動では限定子を使って特定のメソッドを呼び出します。次の中でこの呼び出しができます。

メソッド

関数呼び出し

手続き文

限定メソッド指定子のオブジェクト型は，外部メソッドのオブジェクト型またはその上位オブジェクトと同じでなくてはなりません。

予約語 inherited を使って外部メソッドのオブジェクト型の上位オブジェクトを指定できます。上位オブジェクトを持たないオブジェクト型のメソッドで inherited を使うことはできません。

限定メソッドの起動の暗黙の Self パラメータは，呼び出しを含むメソッドの Self になります。

限定メソッドの起動は常に静的になり，常に指定されたメソッドを呼び出します。

オーバーライドされたメソッドを起動するには，オーバーライドメソッド内で限定メソッド起動を使います。


参照

関数呼び出し

メソッドの宣言

オブジェクト型

手続き文


限定メソッドの起動の例

次のコードは限定メソッド起動を示しています。この限定メソッド起動はメソッドをオーバーライドし，オーバーライドするメソッドのコードを再利用します。

constructor TShape.Create(AOwner: TComponent);

begin

  inherited Create(AOwner);

  Width := 65;

  Height := 65;

  FPen := TPen.Create;

  FPen.OnChange := StyleChanged;

  FBrush := TBrush.Create;

  FBrush.OnChange := StyleChanged;

end;


コンポーネントの可視性

クラス型

コンポーネント識別子の可視性は識別子が宣言されたコンポーネント部の可視属性によって制御されます。可視属性には 5 つの種類があります。

パブリッシュ

パブリック

プロテクト

プライベート

オートメーション

オブジェクト型見出しの直後のコンポーネントリストで宣言されたコンポーネント識別子は，オブジェクト型が {$M+} 状態でコンパイルされた場合，または {$M+} 状態でコンパイルされたクラスから派生する場合，パブリッシュの可視属性を持ちます。それ以外の場合，それらのコンポーネント識別子はパブリックの可視属性を持ちます。


参照


集合型

参照	型

集合型は同じ順序型のオブジェクトの集合です。集合型を宣言するには予約語 set of に続けて基本型を指定します。

集合型の値の範囲は特定の順序型 (基本型) のべき集合になります。集合型の可能な値は基本型の可能な値の部分集合になります。

集合型の変数は空または集合のすべての値を保持できます。すべての集合型は値 [ ] を保持でき，この値は空集合と呼ばれます。

基本型の可能な値の数は 256 個以下でなくてはならず，基本型の最大と最小の順序値は 0 から 255 の範囲内でなくてはなりません。

集合の比較

A と B が集合オペランドの場合，これらの比較により次の結果が生成されます。

A = B は A と B がまったく同じメンバーを持つ場合だけ True になり，それ以外の場合は A <> B である

A <= B は A のすべてのメンバーが B のメンバーでもある場合にだけ True になる

A >= B は B のすべてのメンバーが A のメンバーでもある場合にだけ True になる

集合メンバーシップのテスト

関係演算子の in は順序型オペランドの値が集合型オペランドのメンバーである場合に True を返します。それ以外の場合は False を返します。


参照

順序型

関係演算子

set (予約語)

集合演算子

集合型定数

型の互換性


ファイルの種類

参照	型

ファイル型は線状に並んだ要素のシーケンスで，各要素は次の型を除く任意の型で構成できます。

ファイル型

ファイル型のコンポーネントを持つ構造化型

オブジェクト型

ファイル型宣言では要素数は設定しません。

ファイル宣言から of の語と型を省略した場合，ファイルは型なしファイルになります。

標準ファイル型の Text (および TextFile) は行単位で編成された文字を含むファイルを表します。


参照

file (予約語)

型の互換性


型の互換性

参照

式や関係演算では 2 つの型の互換性が要求されます。型の互換性は代入互換性の前提条件です。

型が互換になるのは最低でも次のいずれか 1 つの条件が True の場合です。

2 つの型が同じである

2 つの型が実数型である

2 つの型が整数型である

一方の型が他方の部分範囲である

2 つの型が同じホスト型の部分範囲である

2 つの型が互換の基本型を持つ集合型である

2 つの型が同じ個数のコンポーネントを持つパック文字列型である

一方の型が文字列型で他方が文字列型，パック文字列型，Char 型のいずれかである

一方の型が Pointer で他方が任意のポインタ型である

2 つの型がクラス型またはクラス参照型で，かつ一方の型が他方から派生した型である

一方の型が PChar で他方が array[0..X] of Char の形式のインデックスがゼロから始まる文字配列である

2 つの型が同じ型を指すポインタである ({$T+} 指令によりポインタの型チェックが有効な場合のみ)

2 つの型が同じ結果型と同じ個数のパラメータを持ち，パラメータ型間で 1 対 1 の同一性を持つ手続き型である

一方の型がバリアント型で，他方が整数型，実数型，文字列型，あるいは論理型のいずれかである


参照

代入の互換性


代入の互換性

参照

代入文や値パラメータの受け渡しなどで，値を何かに代入するときには代入の互換性が要求されます。

オブジェクト型はすべての上位オブジェクト型と代入の互換性を持ちます。

次のいずれかが True の場合，T2 型の値は T1 型と代入の互換性があります (すなわち T1 := T2 が許可されます)。

T1 と T2 が同一の型で，どちらもファイル型ではなく，構造化レベル内にファイル型コンポーネントを持つ構造化型でもない

T1 と T2 が互換の順序型で，T2 型の値が T1 の値の範囲内である

T1 と T2 が実数型で，T2 の値が T1 の値の範囲内である

T1 が実数型で，T2 が整数型である

T1 と T2 が文字列型である

T1 が文字列型で，T2 が Char 型である

T1 が文字列型で，T2 がパック文字列型である

T1 が長い文字列型で，T2 が PChar 型である

T1 と T2 が互換性のあるパック文字列型である

T1 と T2 が互換性のある集合型で，T2 型の値のすべてのメンバーが T1 の値の範囲内である

T1 と T2 が互換性のあるポインタ型である

T1 がクラス型で，T2 が T1 から派生したクラス型である

T1 がクラス参照型で，T2 が T1 から派生したクラス参照型である

T1 が PChar 型で T2 が文字列定数である

T1 が PChar で T2 が array[0..X] of Char の形式のインデックスがゼロから始まる文字配列である ({$X+} により拡張構文が有効な場合のみ)

T1 と T2 が互換性のある手続き型である

T1 が手続き型で，T2 が T1 と同じ結果型と同じ数のパラメータを持ち，パラメータ型間で 1 対 1 の同一性を持つ手続きまたは関数である

T1 がバリアント型で，T2 が整数型，実数型，文字列型，論理型のいずれかである

T1 が整数型，実数型，文字列型，論理型のいずれかで，T2 がバリアント型である

代入の互換性が必要な場面で以上のリストのどの項目も True でない場合，コンパイル時エラーが発生します。


参照

型の互換性


クラス参照型

参照	例	オブジェクト型

クラス参照型では，クラスに対して直接の操作が実行できます。これはクラスのインスタンスに対しての操作が実行可能なクラス型とは対照的です。クラス参照型はメタクラスまたはメタクラス型とも呼ばれます。

クラス参照型は以下の場合に役立ちます。

実際の型がコンパイル時に決まっていないオブジェクトを作成するために仮想コンストラクタと一緒に使う場合

実際の型がコンパイル時に決まっていないクラスに対して操作を実行するためにクラスメソッドと一緒に使う場合

is 演算子の右側のオペランドとして，コンパイル時に決まっていない型で動的型チェックを実行する場合

as 演算子の右側のオペランドとして，コンパイル時に決まっていない型にチェック付き型キャストを実行する場合

クラス参照型の宣言は予約語 class of にクラス型識別子を続けて構成します。次に例を示します。

type

  TComponent = class(TPersistent)

    :

  end;

  TComponentClass = class of TComponent;

  TControl = class(TComponent)

    :

  end;

  TControlClass = class of TControl;

var

  ComponentClass: TComponentClass;

  ControlClass: TControlClass;

この宣言では，TComponentClass は TComponent クラスまたは TComponent から派生する任意のクラスを参照できる型として定義され，TControlClass は TCotrol クラスまたは TControl から派生する任意のクラスを参照できる型として定義されます。

クラス型識別子は対応するクラス参照型の値として機能します。たとえば，ほかの用途以外に，TComponent 識別子は TComponentClass 型の値として機能し，TControl 識別子は TControlClass 型の値として機能します。

クラス参照型の値は任意の上位クラス参照型と代入の互換性があります。したがって，プログラムの実行中にクラス参照型変数は，それが定義された対象のクラスや，そのクラスの任意の下位クラスを参照できます。上記の宣言に従うと，次の 2 つの代入文は，

ComponentClass := TComponent;      { 有効 }

ComponentClass := TControl;        { 有効 }

両方とも有効ですが，次の 2 つの代入文では，

ControlClass := TComponent;        { 無効 }

ControlClass := TControl;          { 有効 }

2 番目の文だけが有効です。最初の文がエラーになるのは，TComponent が TControl の下位でないため，TControlClass 型の値にならないからです。

クラス参照型変数は値 nil をとることができます。nil は，変数が現在クラスを参照していないことを示します。

クラスは必ず (TObject から) メソッド関数 ClassType (オブジェクトのクラスへの参照を返す関数) を継承します。ClassType で返される値の型は TClass で，それは class of TObject として宣言されます。つまり，ClassType で返される値は，型キャストによってその使用の前に，より具体的な下位の型にしなければならない場合があることを意味します。次に例を示します。

if Control <> nil then

  ControlClass := TControlClass(Control.ClassType) else

  ControlClass := nil;


参照

class (予約語)


例

type

  {TComponentRef 型の変数を実行時に設定し TComponentClass またはその下位クラスを参照できます}

  TComponentRef = class of TComponent;

var

  TCRef: TComponentRef;

  NewComponent: TComponent;

...

TCRef := TButton; {TCRef は TButton クラスの名前が使用可能な場所ではどこでも使えるようになります}

NewComponent := TCRef.Create; {TCRef はここでは新しい TButton を作成するために使われています}

...


ヌルで終わる文字列

参照

C++Builder は，「ヌルで終わる文字列」と呼ばれる文字列のクラスをサポートしています。ヌルで終わる文字列は，C/C++ プログラミング言語および Windows 自体でも広く用いられています。C++Builder のヌルで終わる文字列のサポートと SysUtils ユニットの文字列処理関数を利用すれば，他の言語や Windows API と容易にインターフェースをとることができます。

ヌルで終わる文字列とは？

ヌルで終わる文字列は，ヌル以外の文字の並びの最後に NULL (#0) が付いたものです。Object Paascal の文字とは異なり，ヌルで終わる文字列には独立した長さインジケータはありません。ヌルで終わる文字列では，最初の NULL が文字列の最後を示します。

ヌルで終わる文字列の使い方

ヌルで終わる文字列は，ゼロから始まる整数をインデックスの型とする文字配列として次の形式で格納されます。

array[0..X] of Char

X は正の整数値です。

この配列は，インデックスがゼロから始まる文字配列として参照されます。

ヌルで終わる文字列は次の 2 つで文字ポインタを使います。

文字列リテラル

文字配列

ヌルで終わる文字列と標準手続き

次の標準手続きをインデックスがゼロから始まる文字配列に適用できます。

Read

Readln

Str

Val

次の手続きは文字ポインタにも適用できます。

AssignFile

Rename

Val

Write

Writeln


参照

文字列型

文字ポインタの添字付け

ヌルで終わる文字列の関数

長い文字列とヌルで終わる文字列の混在

ヌルで終わるワイド文字列


文字ポインタと文字列リテラル

参照	例	ヌルで終わる文字列

文字列リテラルは PChar 型と代入の互換性があります。このことは，文字列リテラルを PChar 型の変数に代入できることを意味します。

この代入の結果，ポインタは文字列リテラルのヌルで終わるコピーのあるメモリ領域を指すことになります。

文字列リテラルは，手続き呼び出しと関数呼び出しの実パラメータとして使えます。ただし，対応する仮パラメータの型が PChar の場合に限られます。代入の場合と同様に，コンパイラは文字列リテラルのヌルで終わるコピーを生成します。

また，PChar の型付き定数を文字列定数で初期化することができます。この機能は PChar 型の配列，PChar フィールドを持つレコード，PChar フィールドを持つオブジェクトなどの構造化型でも適用できます。


参照

文字ポインタと文字配列

文字ポインタのインデックス付け

ヌルで終わる文字列


例

var

  P: PChar;

begin

  P := 'Hello world...';

end;


文字ポインタと文字配列

参照	例	ヌルで終わる文字列

インデックスがゼロから始まる文字配列は PChar 型と互換性があります。このことは，型が PChar とあらかじめわかっている場合は，かわりにインデックスがゼロから始まる文字配列を使えることを意味します。

文字配列を PChar のかわりに使うと，コンパイラはその文字配列をポインタ定数に変換します。変換されたポインタの定数値は，その文字配列の第 1 要素のアドレスを指します。

インデックスがゼロから始まる文字配列の型付き定数を，配列の宣言サイズに満たない文字列リテラルで初期化することができます。初期化されなかった残りの文字には NULL (#0) が設定されるため，配列はヌルで終わる文字列を効果的に持つことになります。


参照

文字ポインタと文字配列

文字ポインタのインデックス付け

ヌルで終わる文字列


例

var

  A: array[0..63] of Char;

  P: PChar;

begin

  P := A;       {P は A の最初の要素を指します}

  PrintStr(A);

  PrintStr(P);  {PrintStr は 同じ値で 2 度呼び出されます}

end;


文字ポインタのインデックス付け

参照	例	ヌルで終わる文字列

インデックスがゼロから始まる文字配列は文字ポインタと互換性があるため，文字ポインタはインデックスがゼロから始まる文字配列のようにインデックス付けできます。

文字ポインタにインデックス付けする場合，そのインデックスには，逆参照する前にポインタに追加する符号なしのオフセットを指定します。したがって，P[0] は P^ に等しく，ポインタ P が指す文字を指します。P[1] は P が指す文字の 1 文字右の文字を指します。P[2] はその次の文字を指すといった具合に続きます。同じように P[-1] は P が指す文字の直前の文字を指し，同様に続きます。

コンパイラは，文字ポインタのインデックス付けで範囲チェックをしません。これは，文字ポインタが指すヌルで終わる文字列の最大長を決める型情報が利用できないためです。したがって，ユーザープログラムで範囲チェックをしなくてはなりません。


例

{次のコードでは, ヌルで終わる文字列を大文字に変換するために文字ポインタのインデックス付けを使います。}

function StrUpper(Str: PChar): PChar;

var

  I: Word;

begin

  I := 0;

  while Str[I] <> #0 do

  begin

    Str[I] := UpCase(Str[I]);

    Inc(I);

  end;

  StrUpper := Str;

end;


参照

PChar


ヌルで終わる文字列の関数

ヌルで終わる文字列

SysUtils ユニットにはヌルで終わる文字列の処理関数が数多くあります。次の表に各関数の簡単な説明を示します。

関数	説明
StrAlloc	与えられたサイズの文字バッファをヒープ上に割り当てる
StrBufSize	StrAlloc または StrNew を使って割り当てた文字バッファのサイズを返す
StrCat	2 つの文字列を結合する
StrComp	2 つの文字列を比較する
StrCopy	文字列をコピーする
StrDispose	StrAlloc または StrNew を使って割り当てた文字バッファを破棄する
StrECopy	文字列をコピーし，その文字列の終わりへのポインタを返す
StrEnd	文字列の終わりへのポインタを返す
StrFmt	1 つまたは複数の値を文字列の形式にする
StrIComp	大文字と小文字を区別せずに 2 つの文字列を比較する
StrLCat	2 つの文字列を結合し，与えられた最大長を持つ文字列にする
StrLComp	与えられた最大長まで 2 つの文字列を比較する
StrLCopy	与えられた最大長まで文字列をコピーする
StrLen	文字列の長さを返す
StrLFmt	1 つまたは複数の値を，与えられた最大長の文字列の形式にする
StrLIComp	大文字と小文字を区別せずに，与えられた最大長まで 2 つの文字列を比較する
StrLower	文字列を小文字に変換する
StrMove	文字のブロックを 1 つの文字列から別の文字列へ移動する
StrNew	ヒープ上に文字列を割り当てる
StrPCopy	Pascal 文字列をヌルで終わる文字列へコピーする
StrPLCopy	与えられた最大長まで Pascal 文字列をヌルで終わる文字列へコピーする
StrPos	与えられた部分文字列が文字列内で最初に出現する位置へのポインタを返す
StrRScan	与えられた文字が文字列内で最後に出現する位置へのポインタを返す
StrScan	与えられた文字が文字列内で最初に出現する位置へのポインタを返す
StrUpper	文字列を大文字に変換する


長い文字列とヌルで終わる文字列の混在

参照	ヌルで終わる文字列

Object Pascal では，長い文字列とヌルで終わる文字列を式や代入の中で混ぜて使えます。長い文字列とヌルで終わる文字列の混在に関する規則の概要は以下のとおりです。

ヌルで終わる文字列は長い文字列と代入の互換性があります。つまり，PChar 値は string 型の変数へ代入でき，string 型の定数パラメータまたは値パラメータとして渡せます。たとえば，S を string 変数，P を PChar 式として S := P という代入をすると，ヌルで終わる文字列が長い文字列の中へコピーされます。

式の中で，二項演算子の一方のオペランドが string 型でもう一方が PChar 型の場合，PChar オペランドは自動的に string 型へ変換されます。

P を PChar 式として string(P) という形式の型キャストを使うと，ヌルで終わる文字列を長い文字列へ明示的に変換できます。これは演算子の両方のオペランドが PChar 型のときに文字列演算を実行したい場合に役立ちます。たとえば，

S := string(P1) + string(P2);

とすると，2 つのヌルで終わる文字列が結合されて長い文字列になります。

S を長い文字列式として PChar(S) という形式の型キャストを使うと，長い文字列をヌルで終わる文字列に変換できます。


参照

長い文字列型


ヌルで終わるワイド文字列

参照	ヌルで終わる文字列

Windows オペレーティングシステムは以下の 3 種類の文字セットをサポートしています。

1 バイト文字セット

2 バイト文字セット

Unicode 文字セット

1 バイト文字

1 バイト文字セット (SBCS) では文字列はバイトの並びであり，1 バイトで 1 文字を表します。

ほとんどの欧米向けバージョンの Windows で使う ANSI 文字セットが 1 バイト文字セットです。

2 バイト文字

2 バイト文字セット (DBCS) でも文字列はバイトの並びですが，1 バイト文字セットと異なり，1 バイトで表される文字と 2 バイトで表される文字があります。

2 バイト文字の 1 バイト目は先行バイトと呼ばれます。

一般に，2 バイト文字セットの下位 128 文字は 7 ビットの ASCII 文字セットにマップし，先行バイトは 128 以上の順序値を持つのが普通です。

2 バイト文字セットはアジアで広く使われており，それらの地域の文字セットには 256 文字をはるかに超える文字が含まれています。

Unicode 文字

Unicode 文字セットは 1 バイト文字セットや 2 バイト文字セットと基本的に異なり，1 文字が 1 ワード (2 バイト) で表されます。Unicode 文字セットの文字列は，バイトでなくワードの並びです。

Unicode 文字はワイド文字とも呼ばれ，Unicode 文字列は多くの場合，ワイド文字列と呼ばれます。

1 文字に 65536 通りの値が考えられる Unicode は，技術分野の記号や出版に使われる特殊文字も含め，現代のコンピュータで使われている世界中のすべての文字を表せます。

Unicode 文字セットの最初の 256 文字は ANSI 文字セットにマップしています。

C++Builder 文字セット

C++Builder は 1 バイト文字と 2 バイト文字をサポートし，AnsiChar，PAnsiChar，AnsiString の基本型から Char，PChar，string の汎用型までの文字列をサポートしています。ワイド文字は WideChar 型と PWideChar 型によってサポートされます。

string 型に相当するワイド文字はありません。

ワイド文字列

Object Pascal のヌルで終わる文字列の処理機能は PWideChar 型にも当てはまります。したがって，文字列リテラルは PWideChar 型と代入の互換性があります (ただし，文字列リテラルには ANSI 文字の範囲内の順序値を持つワイド文字だけを入れることができます)。同様に，

array[0..X] of WideChar

という形式のゼロから始まるワイド文字配列は PWideChar 型と代入の互換性があり，PWideChar 型の値には，ゼロから始まるワイド文字配列とまったく同じように添字を付けられます。さらに，文字ポインタ演算子 (+ と -) はワイド文字ポインタにも適用できます。

メモ:	ワイド文字ポインタへ整数オフセットを加算する場合，またはワイド文字ポインタから整数オフセットを減算する場合，それらのオフセットはワイド文字単位での距離を表します。したがって，ポインタへ加算されるかポインタから減算される前に，自動的に 2 倍にされます。同様に，ワイド文字ポインタを別のワイド文字ポインタから減算する場合，結果の整数は自動的に 2 で除算され，ワイド文字単位での距離が生成されます。

System ユニットには WideCharToString，WideCharLenToString，StringToWideChar という 3 つの関数があり，ヌルで終わるワイド文字列を 1 バイトまたは 2 バイトの長い文字列に変換できるようになっています。


参照

文字型

文字列型

ヌルで終わる文字列の関数


バリアント型

参照	例	型

バリアント型は型を動的に変更する値を表せます。ほかの型の変数がその型へ静的にバインドされるのに対し，バリアント型の変数では実行時にさまざまな型の値を想定できます。バリアント型がもっともよく使われる状況は，演算対象となる実際の型が変化するか，コンパイル時に未定義の場合です。

バリアント型を表すには，定義済み識別子 Variant を使います。バリアント型には以下の特性があります。

バリアント型には整数値，実数値，文字列値，論理値，日付／時刻値，OLE オートメーションオブジェクトを入れることができます。さらに，それらの型の要素からなるさまざまなサイズと次元の配列を入れることができます。

特殊バリアント値 Unassigned はバリアント型にまだ値が割り当てられていないことを示し，特殊バリアント値 Null はデータが未定義か欠落していることを示します。

バリアント型は式の中で別のバリアント型や整数値，実数値，文字列値，論理値と組み合わせることができ，コンパイラは必要な型変換を実行するコードを自動生成します。

バリアント型に OLE オートメーションオブジェクトが入っている場合，そのバリアント型を使ってオブジェクトのプロパティの取得や設定，オブジェクトに対するメソッドの呼び出しができます。

バリアント型の変数は最初の作成時には常に Unassigned として初期化されます。これはそのバリアント型変数がグローバルでもローカルでも，あるいは配列，レコード，オブジェクトなどの構造の一部であっても同じです。

バリアント型は柔軟性に富んでいる一方，通常の変数より多くのメモリを消費し，バリアント型に対する演算は静的に型指定した値に対する演算より実行速度がかなり遅くなります。


バリアント型の例

次のコードはバリアント型の使い方と，バリアント型をほかの型と組み合わせたときに実行される自動型変換の実例です。

var

  V1, V2, V3, V4, V5: Variant;

  I: Integer;

  D: Double;

  S: string;

begin

  V1 := 1;	{ 整数値 }

  V2 := 1234.5678;	{ 実数値 }

  V3 := 'Hello world';	{ 文字列値 }

  V4 := '1000';	{ 文字列値 }

  V5 := V1 + V2 + V4;	{ 実数値 2235.5678 }

  I := V1;	{ I = 1 }

  D := V2;	{ D = 1234.5678 }

  S := V3;	{ S = 'Hello world' }

  I := V4;	{ I = 1000 }

  S := V5;	{ S = '2235.5678' }

end;


参照

バリアント内の値

バリアント型の変換

バリアント式

バリアント配列

バリアントと OLE オートメションオブジェクト


バリアント内の値

バリアント型

バリアント型の変数は 16 バイトのメモリを占有し，内部表現は型コードとその型コードによって与えられた型の値（または値への参照）から構成されます。標準関数 VarType はバリアントの型コードを返します。次の表にバリアント型定数と値，および型コードの意味を示します。

VarType	値	バリアントの内容
varEmpty	$0000	バリアントは Unassigned である。バリアントには値が割り当てられておらず，ゼロであるとみなされる。式の中で使われる場合，VarEmpty はゼロ値または空文字列として扱われる
varNull	$0001	バリアントは Null である。バリアントに値は割り当てられていない。VarNull は式を通じて伝播する。VarNull 値のバリアントを含む式，およびそのような式代入されたバリアントは VarNull と評価される。通常 VarNull は欠損データを示すために使用され，そのデータに対するすべての計算に欠損状態が伝播することを目的とする
varSmallint	$0002	16 ビット符号付き整数 (Smallint 型)
varInteger	$0003	32 ビット符号付き整数 (Integer 型)
varSingle	$0004	単精度浮動小数点値 (Single 型)
varDouble	$0005	倍精度浮動小数点値 (Double 型)
varCurrency	$0006	通貨型の値 (Currency 型)。バリアントには通貨値（8 バイト固定小数点，小数点以下 4 桁）が含まれる
varDate	$0007	日付／時刻値 (TDateTime 型)
varOleStr	$0008	OLE 文字列への参照 (動的割り当て Unicode 文字列)。バリアントには SysAllocStr で割り当てられたヌルで終わる文字列が含まれる
varDispatch	$0009	OLE オートメーションオブジェクトへの参照 (IDispatch インターフェースポインタ)
varError	$000A	オペレーティングシステムエラーコード
varBoolean	$000B	16 ビット論理値 (WordBool 型)
varVariant	$000C	バリアント (バリアント配列でのみ使われる)
varUnknown	$000D	未定義 OLE オブジェクトへの参照 (IUnknown インターフェースポインタ)。バリアントには，不定データまたはカスタムデータが含まれる
varByte	$0011	8 ビット符号なし整数 (Byte 型)
varString	$0100	動的に割り当てられる長い文字列への参照 (AnsiString 型)
varTypeMask	$0FFF	型コードを抽出するためのビットマスク。この定数は，ビットごとの論理和（AND）を使って VType フィールドと組み合わせるマスクとして使用される
varArray	$2000	バリアント配列を示すビット。この定数は，ビットごとの論理和（AND）を使って VType フィールドと組み合わせるマスクとして，バリアントが単一の値なのか値の配列なのかを調べるために使用される
varByRef	$4000	この定数は，ビットごとの論理和（AND）を使って Variant.VType フィールドと組み合わせるマスクとして，バリアントがデータそのものを含むのではなく，そのデータへのポインタを含んでいるかどうかを調べるために使用される

標準関数 varType が返す varXXXX 定数は System ユニット内に定義されています。将来のバージョンの C++Builder で型コードが追加定義される可能性があるので，これらの戻り値だけに依存したコードを作成しないように注意してください。

varArray ビット位置は，ある型の配列がバリアントに入っている場合に設定されます。varTypeMask ビットマスクは varType 関数が返す値から実際の型コードを抽出するために使われます。たとえば，次の式は V に Double 型または Double 型の配列が入っている場合に真になります。

if VarType(V) and varTypeMask = varDouble then ...

System ユニット内に定義されている TVarData レコードを使ってバリアント型の変数を型キャストすると，その内部表現へアクセスできます。詳細は『ライブラリリファレンス』の TVarData の説明を参照してください。


バリアント型の変換

参照	バリアント型

すべての整数型，実数型，文字列型，文字型，論理型はバリアント型と代入の互換性があります。次の表にバリアントへ代入できる型と，代入後のバリアント型コードを示します。

式の型	バリアント型コード
整数型	varInteger
通貨型を除く実数型	varDouble
通貨型	varCurrency
文字列型と文字型	varString
論理型	varBoolean

式は Variant(X) という形式の型キャストを使ってバリアント型へ明示的にキャストできます。X は上の表に示したいずれかの型の式です。

バリアント型はすべての整数型，実数型，文字列型，論理型と代入の互換性があります。以下の表にバリアント型の値から別の型へ変換する場合の型変換規則を示します。

バリアント型から整数型値への変換

バリアント型	結果
varEmpty	0.
varNull	EVariantError 例外を生成する
varByte varSmallint varInteger varError	1 つの整数形式を別の形式へ変換し，値が目的の形式に適合しない場合は EVariantError 例外を生成する
varSingle varDouble varCurrency	実数値をもっとも近い整数へ丸め，結果が目的の形式に適合しない場合は EVariantError 例外を生成する
varDate	日付／時刻値を Double 型として解釈し，値をもっとも近い整数へ丸め，結果が目的の形式に適合しない場合は EVariantError 例外を生成する
varOleStr varString	文字列を整数に変換し，文字列が有効な整数値でないか結果が目的の形式に適合しない場合は EVariantError 例外を生成する
varBoolean	偽の場合に 0，真の場合に -1 (目的の型が Byte の場合は 255)
バリアント型から実数型値への変換

バリアント型	結果
varEmpty	0.
varNull	EVariantError 例外を生成する
varByte varSmallint varInteger varError	整数を実数に変換する
varSingle varDouble varCurrency	1 つの実数形式を別の形式に変換し，結果が目的の形式に適合しない場合は EVariantError 例外を生成する
varDate	値を Double 型として解釈し，目的の形式に変換し，値が目的の形式に適合しない場合は EVariantError 例外を生成する
varOleStr varString	Windows のコントロールパネルの［地域］を使って文字列を実数に変換し，文字列が有効な実数値でないか結果が目的の形式に適合しない場合は EVariantError 例外を生成する
varBoolean	偽の場合に 0，真の場合に -1
バリアント型から日付／時刻値への変換

バリアント型	結果
varEmpty	12/30/1899 12:00:00 am.
varNull	例外を生成する
varByte varSmallint varInteger varError	整数を Double 型に変換し，結果を日付／時刻値として解釈する
varSingle varDouble varCurrency	値を Double 型に変換し，結果を日付／時刻値として解釈する
varDate	変換なし
varOleStr varString	Windows のコントロールパネルの［地域］を使って文字列を日付／時刻値に変換する
varBoolean	論理型を Double 型に変換し，結果を日付／時刻値として解釈する
バリアント型から文字列型値への変換

バリアント型	結果
varEmpty	空の文字列
varNull	例外を生成する
varByte varSmallint varInteger varError	整数値を文字列表現に変換する
varSingle varDouble varCurrency	Windows のコントロールパネルの［地域］を使って実数値を文字列表現に変換する
varDate	Windows のコントロールパネルの［地域］を使って日付／時刻値を文字列表現に変換する
varOleStr	目的の型が varString の場合，Unicode から ANSI に変換する
varString	目的の型が varOleStr の場合，ANSI から Unicode に変換する
varBoolean	真の場合に 0，偽の場合に -1
バリアント型から論理型値への変換

バリアント型	結果
varEmpty	偽
varNull	例外を生成する
varByte varSmallint varInteger varError	値がゼロの場合に偽，値がゼロ以外の場合に真
varSingle varDouble varCurrency	値がゼロの場合に偽，値がゼロ以外の場合に真
varDate	値を Double 型として解釈し，値がゼロの場合には偽，値がゼロ以外の場合には真を返す
varOleStr varString	文字列に「false」（大文字と小文字を区別しない）か，評価がゼロになる数値文字列が含まれている場合は偽，文字列に「true」（大文字と小文字を区別しない）か，評価がゼロ以外になる数値文字列が含まれている場合は真，それ以外の場合は EVariantError 例外を生成する
varBoolean	変換なし

バリアント型の値は TypeName(V) という形式の型キャストを使って整数型，実数型，文字列型，論理型へ明示的にキャストできます。TypeName は整数型，実数型，文字列型，論理型のいずれかの識別子で，V はバリアント型の式です。さらに，標準関数の VarAsType と標準手続きの VarCast を使ってバリアントの内部表現を変更できます。上の表はそのようなすべての型変換に関する規則の一覧です。

バリアント型に OLE オートメーションオブジェクトへの参照 (varDispatch 型コード) が含まれている場合，そのバリアント型を別の型に変換しようとすると，最初にオブジェクトのデフォルトプロパティの値が取得されてから，その値が要求された型に変換されます。与えられた OLE オートメーションオブジェクトにデフォルトプロパティがない場合，EVariantError 例外が生成されます。


参照

バリアント内の値

バリアント式


バリアント式

参照	バリアント型

バリアント型は式の中で使うことができます。次の演算子は Variant 型のオペランドをサポートしています。

    +   �   *   /   div   mod   shl   shr   and   or   xor   not   =   <>   <   >   <=   >=

2 つのオペランドをとる演算子の場合，一方のオペランドがバリアント型ならば，もう一方のオペランドはバリアント型の変換に示した規則で自動的にバリアント型に変換されます。バリアント型値に対する非関係演算 (最後の 6 つを除く演算子) の結果の型は常にバリアント型です。バリアント型の値に対する関係演算の結果の型は常に論理型です。

非関係演算子の場合，一方または両方のオペランドが Unassigned ならば，EVariantError 例外が生成されます。言い換えれば，Unassigned バリアントに対しては比較以外の演算はできません。

さらに非関係演算子の場合，一方または両方のオペランドが Null ならば，演算の結果は Null です。Null 値はそれぞれの式で伝えられ，式の中に Null 値があると式全体が Null になります。

二項演算を実行する場合，2 つのバリアント型オペランドの共通の型が演算を制御します。共通の型は次の表に示すマトリックスで判別されます。次の表を読む場合，Variant 型コード varSmallint，varInteger，varByte は Integer へマップされ，varSingle と varDouble は Double へマップされ，varOleStr と varString は String へマップされます。

バリアント演算の型のマトリックス

	Integer	Double	Currency	String	Boolean	Date
Integer	Integer	Double	Currency	Double	Integer	Date
Double	Double	Double	Currency	Double	Double	Date
Currency	Currency	Currency	Currency	Currency	Currency	Date
String	Double	Double	Currency	String	Boolean	Date
Boolean	Integer	Double	Currency	Boolean	Boolean	Date
Date	Date	Date	Date	Date	Date	Date

たとえば，V1 + V2 の演算では，V1 の型コードが varInteger で V2 の型コードが varString ならば，演算の実行に使われる共通の型は Double です。

非関係演算子の場合，いったん共通の型が設定されると，演算は次の表に示すように進行します。

非関係演算子のバリアント型に対する動作

共通の型	演算子の結果
Integer	/ を除くすべての演算子の場合，オペランドは Integer 型に変換され，結果の型は Integer 型になるか，結果が 32 ビット符号付き整数に適合しなければ Double 型になる。/ 演算子の場合，演算は Double 型演算として実行される
Double	+，-，*，/ の各演算子の場合，オペランドは Double 型に変換され，結果の型は Double 型になる。その他のすべての演算子の場合，演算は Integer 型演算として実行される
Currency	+，-，*，/ の各演算子の場合，オペランドは Currency 型に変換され，結果の型は Currency 型になるか，2 つの Currency 値の除算ならば Double 型になる。その他のすべての演算子の場合，演算は Integer 型演算として実行される
String	+ 演算子の場合，両方のオペランドが文字列ならば，結果は 2 つの文字列の結合になる。+ 演算子のオペランドの少なくとも一方が文字列でない場合と，その他のすべての演算子の場合，演算は Double 型演算として実行される
Boolean	and，or，xor 演算子の場合，オペランドは Boolean 型に変換され，結果の型は Boolean 型になる。その他のすべての演算子の場合，演算は Double 型演算として実行される
Date	+ 演算子と - 演算子の場合，オペランドは Date 型に変換され，結果の型は Date になるか，2 つの Date 値の減算ならば Double 型になる。その他のすべての演算子の場合，演算は Double 型演算として実行される

関係演算子の場合，両方のバリアントが共通の型へ変換され，結果の値が比較されて Boolean 型の結果が生成されます。Unassigned 値はほかのすべての値より小さい比較結果になります。Null 値は Unassigned より大きく，その他のすべての値より小さい比較結果になります。

単項演算子のマイナス（-）の場合，文字列は演算の前に Double 型に変換され，論理値は演算の前に Integer 型に変換されます。

not 演算子の場合，バリアントの型コードが varBoolean ならば論理否定演算が実行されます。その他のすべての型コードの場合，バリアントは Integer 型に変換され，ビット単位の否定演算が実行されます。


参照

バリアント型の変換

バリアント内の値


バリアント配列

参照	例	バリアント型

バリアント型には，いずれかのバリアント基本型の要素からなるさまざまなサイズと次元の配列を入れることができます。バリアント配列の要素はすべて同じ型ですが，要素の型が Variant ならば，当然個々の要素にさまざまな種類のデータ（ほかのバリアント配列を含む）を入れることができます。

バリアント配列は，通常，標準手続きの VarArrayCreate を使って作成します。

次の表にバリアント配列の標準手続きと標準関数を示します。これらはすべて System ユニットの中で定義されています。

バリアント配列の標準手続きと標準関数

名前	説明
VarArrayCreate	与えられた要素型と与えられた各次元の下限と上限を使ってバリアント配列を作成する。要素型は varString を除く任意の varXXXX 型コードである。文字列のバリアント配列を作成するには，varOleStr 型コードを使わなければならない。新しく作成した配列の要素はすべてゼロか空に設定される
VarArrayOf	与えられた要素リストを使って 1 次元のバリアント配列を作成する。返されるバリアント配列の要素型はバリアントである。VarArrayOf 関数は型可変配列パラメータをその場で作る場合に便利である
VarArrayRedim	右端の次元の上限を与えられた値に変更してバリアント配列をサイズ変更する。既存の配列要素は保持され，新しい要素はゼロか空に設定される
VarArrayDimCount	バリアント配列の次元数を返すか，引数がバリアント配列でなければゼロを返す
VarArrayLowBound	バリアント配列の与えられた次元の下限を返す
VarArrayHighBound	バリアント配列の与えられた次元の上限を返す
VarArrayLock	バリアント配列をロックし，バリアント配列内のデータへのポインタを返す。この関数を使うとバリアント配列内のデータへ直接アクセスでき，処理効率が改善される
VarArrayUnlock	前に VarArrayLock でロックしたバリアント配列をロック解除する
VarIsArray	引数にバリアント配列が入っているかどうかをテストする
メモ	バリアント配列の要素型は varString にできません。文字列のバリアント配列を作成するには varOleStr 型コードを使わなければなりません。

バリアントに配列が入っている場合，配列要素へアクセスするにはバリアントの後にカンマで区切った 1 つまたは複数の添字式を大カッコで囲んで指定します。添字式は常に Integer 型です。バリアントに添字を付けるとき，そのバリアントにバリアント配列が入っていない場合や，指定した添字式の数が正しくない場合，さらに 1 つまたは複数の添字式が対応する次元の範囲内にない場合には，EVariantError 例外が生成されます。

バリアント配列の要素には式の中でアクセスでき，代入文を使って新しい値を代入できます。ただし，バリアント配列の要素は var パラメータとして渡せないので注意してください。

バリアント配列が入っているバリアントを別のバリアントへ代入するか値パラメータとして渡す場合，配列全体のコピーが作成され，大量のメモリを消費する可能性があります。この理由から，バリアント配列をほかのバリアントへ代入することは可能な限り避け，どうしても代入しなければならない場合は，バリアント配列を var パラメータか const パラメータとして渡してください。


バリアント配列の例

バリアント配列は，通常，次の例のように標準手続きの VarArrayCreate を使って作成します。

var

  A, B: Variant;

  I: Integer;

begin

  A := VarArrayCreate([0, 9], varInteger);

  for I := 0 to 9 do A[I] := I * I;

  B := VarArrayCreate([1, 3, 0, 9], varVariant);

  for I := 0 to 9 do B[1, I] := I;

  for I := 0 to 9 do B[2, I] := Sqrt(I);

  for I := 0 to 9 do B[3, I] := Format('Value=%d', [I]);

  ...

end;


参照

バリアント配列の大きさの変更

バリアント配列の固定


バリアント配列の大きさの変更

参照	例	バリアント配列

バリアント配列は標準手続きの VarArrayRedim を使ってサイズ変更できます。VarArrayRedim を使うと，バリアント配列の右端 (最後) の次元の上限を変更できます。その他の次元の範囲は変更できません。既存の配列要素はサイズ変更操作をしても保持されています。

VarArrayDimCount，VarArrayLowBound，VarArrayHighBound の各標準関数を使うと，バリアント配列の次元数と個々の次元の範囲を検査できます。これは，次に示す VarArraySum 関数のような汎用バリアント配列操作ルーチンを作成する場合に役立ちます。


バリアント配列のサイズ変更の例

次のコードは VarArrayRedim の使い方を示しています。

var

  A: Variant;

  I: Integer;

begin

  A := VarArrayCreate([0, 4], varOleStr);

  for I := 0 to 4 do A[I] := 'Initial';

  ...

  VarArrayRedim(A, 9);

  for I := 5 to 9 do A[I] := 'Additional';

  ...

end;

function VarArraySum(const A: Variant): Double;

var

  I: Integer;

begin

  if VarArrayDimCount(A) <> 1 then

    raise Exception.Create('One-dimensional variant array expected');

  Result := 0;

  for I := VarArrayLowBound(A, 1) to VarArrayHighBound(A, 1) do

    Result := Result + Double(A[I]);

end;


参照

バリアント配列の固定


バリアント配列の固定

参照	例	バリアント配列

標準関数の VarArrayLock と標準手続きの VarArrayUnlock を使うと，バリアント配列内のデータに直接アクセスできます。

上記の関数で作成したような要素型が varByte のバリアント配列は OLE オートメーションのコントローラとサーバーの間でバイナリデータを受け渡すのによく使われる方法です。そのような配列はデータの変換によって影響を受けず，VarArrayLock ルーチンと VarArrayUnlock ルーチンを使って効率的にアクセスできます。


バリアント配列の固定の例

次に示す VarArrayLoadFile 関数はファイルの内容をバリアント配列のバイトへ読み込みます。この関数は VarArrayLock と VarArrayUnlock を使ってファイルを配列の中へ直接読み出します。

function VarArrayLoadFile(const FileName: string): Variant;

var

  F: file;

  Size: Integer;

  Data: PChar;

begin

  AssignFile(F, FileName);

  Reset(F, 1);

  try

    Size := FileSize(F);

    Result := VarArrayCreate([0, Size - 1], varByte);

    Data := VarArrayLock(Result);

    try

      BlockRead(F, Data^, Size);

    finally

      VarArrayUnlock(Result);

    end;

  finally

    CloseFile(F);

  end;

end;


参照

バリアント配列の大きさの変更


バリアントと OLE オートメーションオブジェクト

参照	例	バリアント型

バリアントに OLE オートメーションオブジェクトへの参照が入っている場合，C++Builder ではメソッドを呼び出してオブジェクトのプロパティの取得と設定ができます。この機能を使用可能にするには，OleAuto ユニットを使います。つまり，いずれかのユニットの uses 節か，プログラムまたはライブラリの uses 節の中に OleAuto への参照を入れます。

OLE オートメーションオブジェクトのメソッド呼び出しまたはプロパティアクセスの構文は，通常のメソッド呼び出しまたはプロパティアクセスの構文によく似ています。

OLE オートメーションオブジェクトのメソッド呼び出しはレイトバインディングされ，メソッドとパラメータを前もって宣言しておく必要がありません。通常のメソッド呼び出しとは異なり，OLE オートメーションのメソッド呼び出しではコンパイラに任意のメソッド識別子と任意の数と種類のパラメータを指定できます。メソッド呼び出しが実際に成功するかどうかは，実行時に指定されたメソッドが存在するかどうかによります。


OLE オートメーションバリアントの例

OLE オートメーションのメソッド呼び出しを使ったコードの例を次に示します。CreateOleObject 関数（OleAuto ユニット内に定義されている）を使って OLE オートメーションオブジェクトへの参照が入っているバリアントを作成している点に注意してください。

var

  Word: Variant;

begin

  Word := CreateOleObject('Word.Basic');

  Word.FileNew('Normal');

  Word.Insert('This is the first line'#13);

  Word.Insert('This is the second line'#13);

  Word.FileSaveAs('c:\temp\test.txt', 3);

end;


参照

OLE オートメーションで使う可変パラメータ

OLE オートメーションのプロパティ


OLE オートメーションで使う可変パラメータ

参照	例	バリアントと OLE オートメーション

OLE オートメーションのメソッド呼び出しは 2 種類のパラメータをサポートしています。

定位置パラメータ

名前付きパラメータ

定位置パラメータは単なる式です。名前付きパラメータはパラメータ識別子の後にコロンと等号（:=）を続け，その後に式を置きます。

定位置パラメータは OLE オートメーションのメソッド呼び出しの中で名前付きパラメータの前に置かなければなりません。定位置パラメータは，パラメータ位置を空で残し，メソッド呼び出しで期待されるより少ないパラメータ式を書くことによって省略できます。

メモ:	多くの場合，OLE オートメーションサーバーは名前付きパラメータをサポートしません。同様に，一部の OLE オートメーションサーバーでは定位置パラメータを省略できません。

OLE オートメーションのメソッド呼び出しパラメータは整数型，実数型，文字列型，論理型，バリアント型のいずれかの型にできます。パラメータはパラメータ式が変数参照だけで構成されている場合，その変数参照が Byte，Smallint，Integer，Single，Double，Currency，TDateTime，AnsiString (または string)，WordBool，Variant のいずれかの型であると参照渡しされます。パラメータ式が単なる変数参照でない場合，または式が上記の型のどれでもない場合，パラメータは値渡しされます。パラメータが参照渡しされた場合，それに対応する変数を，呼び出したメソッドから変更できます。

メモ:	値パラメータを期待するメソッドへパラメータを参照渡しすると，OLE は単に参照パラメータから値を取得します。しかし，逆の状況ではエラーになります。つまり，参照パラメータが期待されている場所へ値のパラメータを渡すとエラーになります。


OLE オートメーションのメソッドで使うパラメータの例

定位置パラメータと名前付きパラメータの例を次に示します。

Word.FileSaveAs('test.doc');

Word.FileSaveAs('test.doc', 6);

Word.FileSaveAs('test.doc',,,'secret');

Word.FileSaveAs('test.doc', Password := 'secret');

Word.FileSaveAs(Password := 'secret', Name := 'test.doc');

最初の呼び出しでは定位置パラメータが 1 です。2 番目の呼び出しでは 2 つの定位置パラメータがあります。3 番目の呼び出しでは 4 つの定位置パラメータがあり，その真ん中の 2 つが省略されています。4 番目の呼び出しには 1 つの定位置パラメータと 1 つの名前付きパラメータがあります。最後に，5 番目の呼び出しには定位置パラメータがなく，2 つの名前付きパラメータが指定されています。名前付きパラメータを使う場合，パラメータを好きな順序で指定できます。


参照

OLE オートメーションのプロパティ


OLE オートメーションのプロパティ

参照	バリアントと OLE オートメーション

OLE オートメーションオブジェクトのプロパティへのアクセスは，メソッド呼び出しと同じ規則に従います。式の中でプロパティアクセスを使ったときはプロパティの値が読み出され，代入文の左辺にプロパティアクセスを使ったときはプロパティの値が書き込まれます。配列プロパティの場合はインデックスパラメータリストを大カッコで囲まなければなりません。

C++Builder コンパイラでは OLE オートメーションのメソッド呼び出しまたはプロパティアクセスに任意のメソッド識別子またはプロパティ識別子と，任意の数と種類のパラメータを指定できます。呼び出し情報はコンパイラによって単にパッケージ化され，実行時に呼び出しまたはプロパティアクセスが実行されるまで，それが成功するかどうかはわかりません。

OLE オートメーションのメソッド呼び出しまたはプロパティアクセスが失敗した場合，EOleError 例外が生成されます。呼び出しまたはプロパティアクセスが失敗する理由としては，以下のことが考えられます。

バリアントメソッド指定子またはバリアントプロパティ指定子の中で指定したバリアント式が，現在 OLE オートメーションオブジェクトを参照していない

メソッドまたはプロパティの識別子が OLE オートメーションオブジェクトによってサポートされていない

指定したパラメータの数が正しくないか，1 つまたは複数のパラメータの型が正しくなかった

1 つまたは複数の必要な定位置パラメータが省略された

指定された名前付きパラメータが OLE オートメーションオブジェクトによってサポートされていない

式の中でメソッド呼び出しが使われたが，そのメソッドが値を返さなかった

メソッドまたはプロパティアクセスが正常に呼び出されたが，例外を返した

OLE オートメーションのメソッド呼び出しまたはプロパティアクセスが失敗した場合，EOleError 例外オブジェクトに失敗の理由を説明したエラーメッセージが入っています。


参照

OLE オートメーションで使う可変パラメータ


コンパイラメッセージ

実行時エラーメッセージ

次の一覧は C++Builder コンパイラが生成するエラー，警告，ヒントのすべてのメッセージをアルファベット順に示したものです。特定のメッセージについて詳細を表示するには，一覧の中でそのメッセージのテキストをクリックしてください。

多くのメッセージには可変テキストが入っているので，一覧の中で特定のメッセージを見つけにくい場合もあります。

メモ:	統合開発環境 (IDE) で受け取ったメッセージについて情報を得るには，メッセージウィンドウの中でメッセージを強調表示し，〔F1〕を押すのがもっとも便利な方法です。

';' not allowed before 'ELSE'

'<clause>' clause not allowed in OLE automation section

<clause1> clause expected, but <clause2> found

<Filename>: <RLink32 error message>

'<name>' is not a type identifier

'<name>' not previously declared as a PROPERTY

<RLink32 error message>

<token1> expected but <token2> found

16-Bit fixup encountered in object file '<Filename>'

486/487 instructions not enabled

Abstract methods must be virtual or dynamic

Array type required

Assignment to FOR-Loop variable '<name>'

Bad argument type in variable type array constructor

Bad file format '<name>'

Bad file format: <Filename>

Bad global symbol definition: '<name>' in object file '<Filename>'

Bad specification of M format

Bad unit format: <Filename>

BREAK or CONTINUE outside of loop

Cannot add or subtract relocatable symbols

Cannot assign to a read-only property

Cannot BREAK, CONTINUE or EXIT out of a FINALLY clause

Cannot initialize local variables

Cannot initialize multiple variables

Cannot initialize thread local variables

Cannot override a static method

Cannot read a write-only property

Case label outside of range of case expression

Circular unit reference to <Unitname>

Class already has a default property

Class does not have a default property

Class or object types only allowed in type section

Class type required

Close error on <Filename>

Compile terminated by user

Constant expected

Constant expression expected

Constant expression violates subrange bounds

Constant object cannot be passed as var parameter

Constant or type identifier expected

Constants cannot be used as open array arguments

Constructing instance of '<name>' containing abstract methods

Constructors and destructors not allowed in OLE automation section

Could not compile used unit '<Unitname>'

Could not create output file <Filename>

Could not load RLINK32.DLL

Data type too large: exceeds 2 GB

Declaration of <name> differs from previous declaration

Default property must be an array property

Default values must be of ordinal, pointer or small set type

Destination cannot be assigned to

Destination is inaccessible

Dispid '<number>' already used by '<name>'

Dispid clause only allowed in OLE automation section

Division by zero

Division by zero

Duplicate case label

Duplicate dynamic method index

Duplicate tag value

Dynamic method or message handler not allowed here

Dynamic methods and message handlers not allowed in OLE automation section

Element 0 inaccessible - use 'Length' or 'SetLength'

Error in numeric constant

EXCEPT or FINALLY expected

EXPORTS allowed only at global scope

Expression has no value

Expression is not a procedure

Expression too complicated

Field definition not allowed in OLE automation section

Field definition not allowed after methods or properties

Field or method identifier expected

File not found: <Filename>

File type not allowed here

Fn requires 2 <= n <= 18

For loop control variable must be simple local variable

For loop control variable must have ordinal type

FOR or WHILE loop executes zero times - deleted

FOR-Loop variable '<name>' cannot be passed as var parameter

FOR-Loop variable '<name>' may be undefined after loop

Format specifier must be C, S, D, H, X, Fn, P, R or nM

Function needs result type

'GOTO <label>' leads into or out of TRY statement

Identifier redeclared: '<name>'

Illegal character in input file: '<Char>' (<Hexadecimal value>)

Illegal message method index

Illegal reference to symbol '<name>' in object file '<Filename>'

Illegal type in OLE automation section: '<typename>'

Illegal type in Read/Readln statement

Illegal type in Write/Writeln statement

Inaccessible value

Incompatible format specification

Incompatible types: '<name>' and '<name>'

Incompatible types: <text>

Incompatible types

Inline assembler stack overflow

Inline assembler syntax error

Instance variable '<name>' inaccessible here

Integer constant or variable name expected

Integer constant too large

Internal error: <ErrorCode>

Invalid combination of opcode and operands

Invalid compiler directive: <Directive>

Invalid function result type

Invalid message parameter list

Invalid register combination

Invalid typecast

Label '<name>' is not declared in current procedure

Label already defined: '<Labelname>'

Label declaration not allowed in interface part

Label declared and referenced, but not set: '<label>'

Label expected

Left side cannot be assigned to

Line too long (more than 255 characters)

Local class or object types not allowed

Local procedure/function '<name>' assigned to procedure variable

LOOP/JCXZ distance out of range

Low bound exceeds high bound

Memory reference expected

Method '<name>' hides virtual method of base type '<name>'

Method '<name>' not found in base class

Method identifier expected

Missing ENDIF directive

Missing operator or semicolon

Missing or invalid conditional symbol in '$<symbol>' directive

Missing parameter type

Necessary library helper function was eliminated by linker

No definition for abstract method '<name>' allowed

No source line for this procedure

Not enough actual parameters

Number of elements differs from declaration

Numeric overflow

Object or class type required

Object type required

Only register calling convention allowed in OLE automation section

Operand size mismatch

Operator not applicable to this operand type

Order of fields in record constant differs from declaration

Ordinal type required

Out of memory

Overflow in conversion or arithmetic operation

Overriding automated virtual method '<name>' cannot specify a dispid

PACKED not allowed here

Pointer type required

Procedure cannot have a result type

Procedure DISPOSE needs destructor

Procedure FAIL only allowed in constructor

Procedure NEW needs constructor

PROCEDURE or FUNCTION expected

Procedure or function name expected

Procedure runs out of local address space

Procedure too long: exceeds 32K

Program or unit recursively uses itself

Property '<name>' does not exist in base class

Published property '<name>' cannot be of type <type>

Published Real property '<name>' must be Single, Double or Extended

Re-raising an exception only allowed in exception handler

Read error on <Filename>

Record, object or class type required

Redeclaration of '<name>' hides a member in the base class

Redeclaration of property not allowed in OLE automation section

Return value of function '<Functionname>' might be undefined

Seek error on <Filename>

Segment/Offset pairs not supported in Borland 32-bit Pascal

Sets may have at most 256 elements

Size of published set '<name>' is >32 bits

Slice standard function only allowed as open array argument

Statement expected, but expression of type '<type>' found

Statements not allowed in interface part

String constant too long

String constant truncated to fit STRING[<number>]

Strings may have at most 255 elements

Structure field identifier expected

Syntax error in real number

System unit out of date or corrupted: missing '<name>'

Text after final 'END.' - ignored by compiler

This form of method call only allowed for class methods

This form of method call only allowed in methods of derived types

This type cannot be initialized

Thread local variables cannot be ABSOLUTE

Thread local variables cannot be local to a function

Too many actual parameters

Too many conditional symbols

Type '<name>' has no type info

Type '<name>' is not yet completely defined

Type '<name>' must be a class to have a PUBLISHED section

Type '<name>' must be a class to have OLE automation

Type '<name>' needs finalization - not allowed in file type

Type '<name>' needs finalization - not allowed in variant record

Type expected

Type not allowed in OLE Automation call

Type of expression must be BOOLEAN

Type of expression must be INTEGER

TYPEINFO standard function expects a type identifier

TYPEOF can only be applied to object types with a VMT

Types of actual and formal var parameters must be identical

Undeclared identifier: '<name>'

Unexpected end of file in comment started on line <Number>

Unit <Unit1> was compiled with a different version of <Unit2>

Unit name mismatch: '<Unitname>'

Unknown directive: '<Directive>'

Unnamed arguments must precede named arguments in OLE Automation call

Unsatisfied forward or external declaration: '<Procedurename>'

Unterminated string

Value assigned to '<name>' never used

Variable '<name>' inaccessible here due to optimization

Variable '<name>' is declared but never used in '<name>'

Variable '<name>' might not have been initialized

Variable required

Virtual constructors are not allowed

Write error on <Filename>

Wrong or corrupted version of RLINK32.DLL


「Ordinal type required」エラーメッセージ
「Ordinal type required」

参照	例	コンパイルエラーメッセージ

説明

コンパイラがこの時点で順序型を必要としました。

順序型は定義済みの整数型，Char 型，ワイド文字型，論理型と，宣言した列挙型です。順序型は以下のような場合に必要です。

配列の添字型は順序型でなければなりません。

部分範囲型の下限と上限は順序型の定数式でなければならない

集合の要素型は順序型でなければならない

case 文の選択式は順序型でなければならない

標準手続き Inc と Dec の第 1 引数は順序型またはポインタ型の変数でなければならない


例

{ 配列の添字型は順序型でなければならない。TByteSet 型は順序型でなく集合である }

program Produce;

type

  TByteSet = set of 0..7;

var

  BitCount: array[TByteSet] of Integer;

begin

end.

{ 順序型を配列の添字型として指定する }

program Solve;

type

  TByteSet = set of 0..7;

var

  BitCount: array[Byte] of Integer;

begin

end.


参照

配列型

部分範囲型

列挙型

case 文


「File type not allowed here」エラーメッセージ
「File type not allowed here」

参照	例	コンパイルエラーメッセージ

説明

ファイル型は値パラメータとして使ったりファイル型自身の基本型として使ったりできません。関数の戻り型としても使えず，代入もできませんが，それらのエラーは別のエラーメッセージが表示されます。


例

{ 次のコードでは，T が Text (標準ファイル) 型の値パラメータである点に問題がある。値パラメータへ書き込んでも，呼び出し側の変数コピーは影響を受けない。したがって，ファイルを値パラメータとして宣言しても意味がない }

program Produce;

procedure WriteInteger(T: Text; I: Integer);

begin

  Writeln(T, I);

end;

begin

end.

{ パラメータを var パラメータとして宣言すれば問題が解決する }

program Solve;

procedure WriteInteger(var T: Text; I: Integer);

begin

  Writeln(T, I);

end;

begin

end.


参照

ファイル型


「Low bound exceeds high bound」エラーメッセージ
「Low bound exceeds high bound」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは部分範囲型の下限が上限より大きい場合か，case ラベルの範囲の下限が上限より大きい場合に表示されます。


例

{ 次のコードでは範囲が空として扱われるのでなく，エラーになる。 }

program Produce;

type

  SubrangeType = 1..0;              { 「下限値が上限値を超えています」エラーになる }

begin

  case True of

  True..False:                      { 「下限値が上限値を超えています」エラーになる }

    Writeln('Expected result');

  else

    Writeln('Unexpected result');

  end;

end.

{ 上限と下限は必ず正しい順序で指定する }

program Solve;

type

  SubrangeType = 0..1;

begin

  case True of

  False..True:

    Writeln('Expected result');

  else

    Writeln('Unexpected result');

  end;

end.


「Program or unit recursively uses itself」エラーメッセージ
「Program or unit recursively uses itself」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは uses 節が結果的に同じユニットかプログラムをロードする場合に表示されます。-P コンパイラ指令 (8.3 形式のファイルを探す) を指定した場合，名前の最初の 8 文字が同じだとファイル名の切り捨てによってこのメッセージが表示される可能性があります。


例

{ Produce_.pas ファイルに入っている次のユニットは，短いファイル名を使うオプションを指定してコンパイルするとエラーになる }

unit Produce_Unit_1;

interface

uses Produce_Unit_2;

implementation

end.


「Procedure runs out of local address space」エラーメッセージ
「Procedure runs out of local address space」

コンパイルエラーメッセージ

説明

このエラーメッセージは Intel アーキテクチャでは使われません。


「Label '<name>' is not declared in current procedure」エラーメッセージ
「Label '<name>' is not declared in current procedure」

例	コンパイルエラーメッセージ

標準 Pascal とは違い，Borland Pascal では goto を使って現在の手続きから外へジャンプできません。エラーが発生した場合の処理の停止には例外処理を使用してください。


例

{ 次のコードではローカルでない goto の実行によって処理を停止しようとする }

program Produce;

label 99;

procedure MyProc;

begin

  { ここで何か大きな問題が起きる }

  goto 99;

end;

begin

  MyProc;

  99:

    Writeln('Fatal error');

end.

{ Borland Pascal では例外処理を使ってプログラムを停止する。この方法にはエラーメッセージも渡せるという利点がある。別の方法として標準手続きの Halt または RunError の使用が考えられる }

program Solve;

uses SysUtils;

procedure MyProc;

begin

  { ここで何か大きな問題が起きる }

  raise Exception.Create('Fatal error');

end;

begin

  try

    MyProc;

  except

    on E: Exception do Writeln(E.Message);

  end;

end.


「Local procedure/function '<name>' assigned to procedure variable」エラーメッセージ
「Local procedure/function '<name>' assigned to procedure variable」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはローカル手続きを手続き変数に代入しようとした場合か，ローカル手続きを手続きのパラメータとして渡そうとした場合に表示されます。そのような操作は，外側の手続きがアクティブでなくてもローカル手続きを呼び出せることになるので違法です。ローカル手続きが外側の手続きの変数にアクセスしようとするとプログラムがクラッシュします。


例

{ 次のコードはローカル手続きを手続き型変数へ代入しようとする。これは実行時に安全でないので違法である }

program Produce;

var

  P: Procedure;

procedure Outer;

  procedure Local;

  begin

    Writeln('Local is executing');

  end;

begin

  P := Local;       { <-- ここでエラーメッセージ }

end;

begin

  Outer;

  P;

end.

{ ローカル手続きを外側の手続きから外へ出せば解決する }

program Solve;

var

  P: Procedure;

procedure NonLocal;

begin

  Writeln('NonLocal is executing');

end;

procedure Outer;

begin

  P := NonLocal;

end;

begin

  Outer;

  P;

end.


「Missing ENDIF directive」エラーメッセージ
「Missing ENDIF directive」

参照	例	コンパイルエラーメッセージ

説明

このエラーメッセージは $IFDEF，$IFNDEF，$IFOPT のいずれかの指令の後に対応する $ENDIF 指令がない場合に表示されます。


例

(* 次のコードでは，{$Endif} 指令の中に $ 文字を入れ忘れたため，コンパイラが指令をコメントと誤解した *)

program Produce;

{$AppType Console}

begin

{$IfOpt O+}

  Writeln('Compiled with optimizations');

{$Else}

  Writeln('Compiled without optimizations');

{Endif}

end.	{ <-- ここでエラーメッセージ }

{ 有効な $ENDIF 指令を条件指令の後に付けるだけで解決する }

program Solve;

{$AppType Console}

begin

{$IfOpt O+}

  Writeln('Compiled with optimizations');

{$Else}

  Writeln('Compiled without optimizations');

{$Endif}

end.


参照

条件指令


「Method identifier expected」エラーメッセージ
「Method identifier expected」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは以下のような場合に表示されます。

automated 部内のプロパティがアクセス用のメソッドを使わなければならず，read 節または write 節の中のフィールドを使えない

「ClassType.MethodName」の構文を使ってクラスメソッドを呼び出そうとしたが，「MethodName」がメソッド名でなかった

「inherited MethodName」の構文を使って継承メソッドを呼び出そうとしたが，「MethodName」がメソッド名でなかった


例

{ 次のコードはフィールドに直接アクセスする automated プロパティを宣言しようとしている。2 番目のエラーは基本クラスのフィールドを取得しようとしたのが原因である }

program Produce;

type

  TMyBase = class

    Field: Integer;

  end;

  TMyDerived = class(TMyBase)

    Field: Integer;

    function Get: Integer;

  automated

    property Prop: Integer read Field;    { <-- ここでエラーメッセージ }

  end;

function TMyDerived.Get: Integer;

begin

  Result := TMyBase.Field;                { <-- ここでエラーメッセージ }

end;

begin

end.

{ 最初の問題はメソッドを通してフィールドにアクセスすれば解決できる。2 番目の問題は Self ポインタを基本クラス型へキャストし，そこからフィールドにアクセスすれば解決する }

program Solve;

type

  TMyBase = class

    Field: Integer;

  end;

  TMyDerived = class(TMyBase)

    Field: Integer;

    function Get: Integer;

  automated

    property Prop: Integer read Get;

  end;

function TMyDerived.Get: Integer;

begin

  Result := TMyBase(Self).Field;

end;

begin

  Writeln( TMyDerived.Create.Prop );

end.


「FOR-Loop variable '<name>' cannot be passed as var parameter」エラーメッセージ
「FOR-Loop variable '<name>' cannot be passed as var parameter」

例	コンパイルエラーメッセージ

説明

この警告は for ループの制御変数を変数パラメータとして渡したときに表示されます。呼び出された手続きまたは関数が制御変数を変更し，それが原因で for ループが正しく実行されない可能性があります。パラメータは値パラメータか定数パラメータのどちらかで宣言してください。パラメータを正しく宣言すると，呼び出される側の手続きと for ループの両方の効率が向上します。


例

{ 次のコードは制御変数 I を変数パラメータとして MyProc 手続きに渡し，そのために警告が表示される }

program Produce;

{$WARNINGS ON}

procedure MyProc(var I: Integer);

begin

  Writeln(I);

end;

var

  I: Integer;

begin

  for I := 1 to 10 do

    MyProc(I);            { <-- ここで警告メッセージ }

end.

{ この場合にはパラメータ宣言を定数パラメータに変更すれば解決する。制御変数を別の補助変数に代入し，その変数を渡す方法もある }

program Solve;

{$WARNINGS ON}

procedure MyProc(const I: Integer);

begin

  Writeln(I);

end;

var

  I: Integer;

begin

  for I := 1 to 10 do

    MyProc(I);

end.


「BREAK or CONTINUE outside of loop」エラーメッセージ
「BREAK or CONTINUE outside of loop」

例	コンパイルエラーメッセージ

説明

while ループまたは repeat ループに入っていない Break 文または Continue 文がありました。Break と Continue はループ内になくてはいけません。


例

{ 次のコードはループ構造の中に continue 文が組み込まれていない }

program Produce;

  procedure Error;

  var

    I: Integer;

  begin

    I := 0;

    while I < 100 do

      Inc(I);

      if Odd(I) then

      begin

        Inc(I);

        Continue;

      end;

  end;

begin

end.

{ 多くの場合，単にループ構造の外に複合文を作成すれば CONTINUE 文または BREAK 文を確実に組み込める }

program Solve;

  procedure Error;

  var

    I: Integer;

  begin

    I := 0;

    while I < 100 do

    begin

      Inc(I);

      if Odd(I) then

      begin

        Inc(I);

        Continue;

      end;

    end;

  end;

begin

end.


「Division by zero」エラーメッセージ
「Division by zero」

コンパイルエラーメッセージ

説明

プログラムの中にゼロによる定数除算がありました。

定数式を調べて，ゼロによる除算が起きないようにしてください。


「Type of expression must be BOOLEAN」エラーメッセージ
「Type of expression must be BOOLEAN」

例	コンパイルエラーメッセージ

説明

このエラーメッセージが出力されるのは，ある式が条件として機能しており，したがってその式が論理型でなければならないときです。たとえば，if，while，repeat 文の制御式や，条件ブレークポイントを制御する式の場合などです。


例

{ ここでは if 文の条件としてポインタ変数を使った }

program Produce;

var

  P: Pointer;

begin

  if P then

    Writeln('P <> nil');

end.

{ この場合，Pascal ではより明示的に指定する必要がある }

program Solve;

var

  P: Pointer;

begin

  if P <> nil then

    Writeln('P <> nil');

end.


「Overflow in conversion or arithmetic operation」エラーメッセージ
「Overflow in conversion or arithmetic operation」

コンパイルエラーメッセージ

説明

算術式の中でオーバーフローが検出されました。式の結果が大きすぎて 32 ビットでは表現できません。

計算式を調べて，コンピュータのハードウェアが表現できる値に収まるようにしてください。


「Data type too large: exceeds 2 GB」エラーメッセージ
「Data type too large: exceeds 2 GB」

例	コンパイルエラーメッセージ

説明

大きすぎてコンパイラが表現できないデータ型を指定しました。型の記述のサイズを小さくしなければなりません。


例

{ これらの宣言がエラーメッセージを発生させた理由は見ればすぐにわかる }

program Produce;

type

  EnormousArray = array[0..MaxLongint] of Longint;

  BigRecord = record

    Points: array[1..10000] of Extended;

  end;

var

  Data: array[0..500000] of BigRecord;

begin

end.

{ このエラーメッセージを回避するには，データ型のサイズを必ず 2GB 未満にとどめれば簡単に解決できる。もっと複雑な方法としては，BigRecord 宣言でしたようにデータの構造を変更する }

program Solve;

type

  EnormousArray = array[0..MaxLongint div 8] of Longint;

  DataPoints = ^DataPointDesc;

  DataPointDesc = array[1..10000] of Extended;

  BigRecord = record

    Points: DataPoints;

  end;

var

  Data: array[0..500000] of BigRecord;

begin

end.


「Integer constant too large」エラーメッセージ
「Integer constant too large」

例	コンパイルエラーメッセージ

説明

表現するのに 32 ビット以上必要な整数定数を指定しました。


例

{ 次のコードでは両方の定数が大きすぎて 32 ビットで表現できないためにコンパイルエラーになる }

program Produce;

const

  VeryDecimal = 123456789;

  VeryBigHex = $123456789;

begin

end.

{ 指定した定数を調べて 32 ビットで表現できるようにする }

program Solve;

const

  VeryDecimal = 12345678;

  VeryBigHex = $12345678;

begin

end.


「16-Bit fixup encountered in object file '%s`」エラーメッセージ
「16-Bit fixup encountered in object file '<Filename>�」

コンパイルエラーメッセージ

説明

$L コンパイラ指令でプログラムへリンクしたオブジェクトモジュールの 1 つに 16 ビットの修正が加えられていました。コンパイラはリンクオブジェクトモジュールでは 32 ビットの修正だけをサポートしています。

リンクオブジェクトモジュールは必ず 32 ビットのオブジェクトモジュールにしてください。


「Inline assembler syntax error」エラーメッセージ
「Inline assembler syntax error」

例	コンパイルエラーメッセージ

説明

インラインアセンブラが有効なアセンブリ命令として解釈できない式を入力しました。

エラーを起こしたインラインアセンブリ文を調べて，正しい構文にしてください。


例

program Produce;

  procedure Assembly;

  asm

    adx	eax, 151

  end;

begin

end.

program Solve;

  procedure Assembly;

  asm

    add	eax, 151

  end;

begin

end.


「Inline assembler stack overflow」エラーメッセージ
「Inline assembler stack overflow」

コンパイルエラーメッセージ

説明

インラインアセンブラコードがインラインアセンブラの容量を超えました。

このエラーが起きた場合は，ボーランドに連絡してください。


「Operand size mismatch」エラーメッセージ
「Operand size mismatch」

例	コンパイルエラーメッセージ

説明

命令のオペランドが必要とするサイズが，指定されたサイズに一致しません。


例

{ 次のコードでは offset 演算子は dword を生成するが，この演算子が byte を必要とするのでコンパイルエラーになる }

program Produce;

var

  V: Integer;

  procedure Assembly;

  asm

    db offset V

  end;

begin

end.

{ この例に限れば，演算子が dword を受け取るように変更すれば解決できる。一般的には，コードをよく調べて演算子とオペランドのサイズを常に一致させる必要がある }

program Solve;

var

  V: Integer;

  procedure Assembly;

  asm

    dd offset v

  end;

begin

end.


「Memory reference expected」エラーメッセージ
「Memory reference expected」

コンパイルエラーメッセージ

説明

インラインアセンブラが予期していたメモリ参照式が見つかりませんでした。

エラーを起こした文がメモリ参照になるようにしてください。


「Constant expected」エラーメッセージ
「Constant expected」

例	コンパイルエラーメッセージ

説明

インラインアセンブラが予期していた定数が見つかりませんでした。

インラインアセンブラの多くの式では，正しくアセンブルするために定数が必要です。エラーを起こした文がアセンブル時に定数を持つように変更してください。


例

{ インラインアセンブラは Pascal 変数に対する MOD 演算ができないので，次のコードはエラーになる }

program Produce;

  procedure Assembly(X: Integer);

  asm

    mov	 ax, X MOD 10

  end;

begin

end.


「Type expected」エラーメッセージ
「Type expected」

コンパイルエラーメッセージ

説明

このエラーが起きた場合は，ボーランドに連絡してください。


「Type of expression must be INTEGER」エラーメッセージ
「Type of expression must be INTEGER」

例	コンパイルエラーメッセージ

説明

このエラーは短い文字列型の文字数を指定した定数式が整数型でないときにだけ発生します。


例

{ 次のコードは文字列内の要素の数を Color 型の最大値要素に依存する値として指定しようとしているが，要素数が違法な Color 型である }

program Produce;

type

  Color = (red,green,blue);

var

  S3: string[Succ(High(Color))];

begin

end.

program Solve;

type

  Color = (red,green,blue);

var

  S3: string[Ord(High(Color))+1];

begin

end.


「Cannot add or subtract relocatable symbols」エラーメッセージ
「Cannot add or subtract relocatable symbols」

例	コンパイルエラーメッセージ

説明

インラインアセンブラはリンカによって変更される可能性があるメモリアドレスの加算や減算はできません。

インラインアセンブラ文の中から再配置可能アドレスの加算や減算をしないようにしてください。


例

{ グローバル変数は再配置可能アドレスを生成する項目のクラスに属し，インラインアセンブラはそれらの加算や減算ができない }

program Produce;

var

  A: array[1..10] of Integer;

  EndOfA: Integer;

  procedure Relocatable;

  begin

  end;

  procedure Assembly;

  asm

    mov eax, A + EndOfA

  end;

begin

end.


「Invalid register combination」エラーメッセージ
「Invalid register combination」

例	コンパイルエラーメッセージ

説明

インラインアセンブラ文の中でレジスタの違法な組み合わせを指定しました。Intel 80x86 ファミリで使えるアドレス指定モードについての詳細は，アセンブリ言語の解説書を参照してください。


例

{ この mov 命令で指定した右側のオペランドは違法である }

program Produce;

  procedure AssemblerExample;

  asm

    mov eax, [ecx + esp * 4]

  end;

begin

end.

{ この mov 命令の右側のオペランドで指定したアドレス指定モードは許される }

program Solve;

  procedure AssemblerExample;

  asm

    mov eax, [ecx + ebx * 4]

  end;

begin

end.


「Numeric overflow」エラーメッセージ
「Numeric overflow」

例	コンパイルエラーメッセージ

説明

インラインアセンブラが式の 1 つで数値オーバーフローを検出しました。


例

{ 32 ビット以下では表現できない数値を指定するとこのエラーが起きる }

program Produce;

  procedure AssemblerExample;

  asm

    mov eax, $0ffffffffffffffffffffff

  end;

begin

end.

{ 指定する数値がすべて 32 ビットに収まるようにする }

program Solve;

  procedure AssemblerExample;

  asm

    mov al, $0ff

  end;

begin

end.


「String constant too long」エラーメッセージ
「String constant too long」

例	コンパイルエラーメッセージ

説明

指定した文字列の終わりをインラインアセンブラが検出できませんでした。もっとも考えられる原因は閉じる引用符の誤った配置です。


例

{ インラインアセンブラは文字列の終わりを検出できないうちに行が終了するため，文字列が長すぎるというエラーを報告する }

program Produce;

  procedure AssemblerExample;

  asm

    db 'Hello world.  I am an inline assembler statement

  end;

begin

end.

{ 閉じる引用符を追加すればこのエラーは解決する }

program Solve;

  procedure AssemblerExample;

  asm

    db 'Hello world.  I am an inline assembler statement'

  end;

begin

end.


「Error in numeric constant」エラーメッセージ
「Error in numeric constant」

例	コンパイルエラーメッセージ

説明

入力した数値定数からインラインアセンブラがエラーを検出しました。


例

{ 次のコードでは，インラインアセンブラは 16 進定数の解析を予期していたが誤った文字を検出した }

program Produce;

  procedure AssemblerExample;

  asm

    mov al, $z0f0

  end;

begin

end.

{ 入力した数値定数とインラインアセンブラが解析を予期している型を必ず適合させる }

program Solve;

  procedure AssemblerExample;

  asm

    mov al, $f0

  end;

begin

end.


「Invalid combination of opcode and operands」エラーメッセージ
「Invalid combination of opcode and operands」

例	コンパイルエラーメッセージ

説明

正しくないインラインアセンブラ文を指定しました。


例

{ インラインアセンブラは $f0*16 の結果を al レジスタに格納できない。型の不一致が原因である }

program Produce;

  procedure AssemblerExample;

  asm

    mov al, $0f0 * 16

  end;

begin

end.

{ 両方のオペランドの型を必ず一致させる }

program Solve;

  procedure AssemblerExample;

  asm

    mov al, $0f * 16

  end;

begin

end.


「486/487 instructions not enabled」エラーメッセージ
「486/487 instructions not enabled」

コンパイルエラーメッセージ

説明

486 命令は常に使用可能になっているので，このインラインアセンブラのエラーは発生しないはずです。


「Division by zero」エラーメッセージ
「Division by zero」

例	コンパイルエラーメッセージ

説明

インラインアセンブラが結果的にゼロによる除算になる式を検出しました。


例

{ 定数リテラルでなくプログラム定数を使っていると，このエラーはあまり目立たない場合がある }

program Produce;

  procedure AssemblerExample;

  asm

    dw	1000 / 0

  end;

begin

end.

{ 高級言語でのプログラミングと同様に，決してゼロによる除算がないようにすれば解決する }

program Solve;

  procedure AssemblerExample;

  asm

    dw	1000 / 10

  end;

begin

end.


「Structure field identifier expected」エラーメッセージ
「Structure field identifier expected」

例	コンパイルエラーメッセージ

説明

インラインアセンブラが「.」の右側に識別子を認識しましたが，それは「.」の左側にあるレコードのフィールドではありませんでした。この種のよくある，しかし見つけるのが難しいエラーは，ch というフィールドがあるレコードを使ったエラーです。インラインアセンブラは常に ch をレジスタ名として解釈します。


例

{ 次のコードでは，インラインアセンブラは Y を有効な識別子として認識したが，Y を D 型のメンバーとしては認識しなかった }

program Produce;

type

  Data = record

    X: Integer;

  end;

  procedure AssemblerExample(D: Data; Y: Char);

  asm

    mov	eax, D.Y

  end;

begin

end.

{ 正しい変数名を指定すればエラーはなくなる }

program Solve;

type

  Data = record

    X: Integer;

  end;

  procedure AssemblerExample(D: Data; Y: Char);

  asm

    mov	eax, D.X

  end;

begin

end.


「LOOP/JCXZ distance out of range」エラーメッセージ
「LOOP/JCXZ distance out of range」

コンパイルエラーメッセージ

説明

インラインアセンブラコードの中で指定した LOOP または JCXZ の行先が範囲外です。距離は -128～127 の範囲でなければなりません。

このエラーが表示された場合は，LOOP または JCXZ を 2 つの命令からなる同じ意味のシーケンスに置換してください。


「Statement expected, but expression of type '<type>' found」エラーメッセージ
「Statement expected, but expression of type '<type>' found」

例	コンパイルエラーメッセージ

説明

コンパイラは文 を予期していましたが，指定された型の式をかわりに検出しました。


例

{ 次のコードは IF，WHILE，REPEAT などの文があるべき場所に，式 (3+4) が存在している }

program Produce;

var

  A: Integer;

begin

  (3 + 4);

end.

{ ここでは式 (3+4) の結果を変数 a に代入すれば解決する。エラーを起こした式をソースコードから削除する方法もある。どちらにするかは状況による }

program Produce;

var

  A: Integer;

begin

  A := (3 + 4);

end.


「Procedure or function name expected」エラーメッセージ
「Procedure or function name expected」

例	コンパイルエラーメッセージ

説明

手続きや関数を表さない識別子を exports 節の中で指定しました。


例

{ 変数が「procedure」型でも，C++Builder ライブラリからは変数をエクスポートできない }

library Produce;

var

  Y: procedure;

exports Y;

begin

end.

{ EXPORTS 節に指定したすべての識別子が必ず手続きまたは関数を表すようにする }

program Solve;

  procedure ExportMe;

  begin

  end;

exports ExportMe;

begin

end.


「PROCEDURE or FUNCTION expected」エラーメッセージ
「PROCEDURE or FUNCTION expected」

例	コンパイルエラーメッセージ

説明

この宣言には procedure または function を付けなくてはいけません。


例

{ 次のどちらの場合も，class というキーワードの後に procedure という語が続かなければならない }

program Produce;

type

  Base = class

    class AProcedure; { ケース 1 }

  end;

  class Base.AProcedure; { ケース 2 }

  begin

  end;

begin

end.

{ procedure キーワードを追加すると，このプログラムからエラーがなくなる }

program Solve;

type

  Base = class

    class procedure AProcedure;

  end;

  class procedure Base.AProcedure;

  begin

  end;

begin

end.


「Instance variable '<name>' inaccessible here」エラーメッセージ
「Instance variable '<name>' inaccessible here」

例	コンパイルエラーメッセージ

説明

クラスメソッドの中からインスタンス変数を参照しようとしています。


例

{ クラスメソッドはインスタンスポインタを持っていないので，クラスのメソッドやインスタンスデータにアクセスできない }

program Produce;

type

  Base = class

    Title: string;

    class procedure Init;

  end;

  class procedure Base.Init;

  begin

    Self.Title := 'Does not work';

    Title := 'Does not work';

  end;

begin

end.

{ このエラーではクラスメソッドの中からメンバーのデータやメソッドにアクセスしないのがただ 1 つの解決法である }

program Solve;

type

  Base = class

    Title: string;

    class procedure Init;

  end;

  class procedure Base.Init;

  begin

  end;

begin

end.


「EXCEPT or FINALLY expected」エラーメッセージ
「EXCEPT or FINALLY expected」

例	コンパイルエラーメッセージ

説明

try ブロックには例外処理部 (except) またはクリーンアップコード部 (finally) が必ず入っていなければなりません。


例

{ 次のコードでは例外処理コードの except 節または finally 節が欠落しているのでコンパイルエラーになる }

program Produce;

begin

  try

  end;

end.

{ 欠落している節を追加すればコードのコンパイルを完了できる。この例では except 節でプログラムを終了できる }

program Solve;

begin

  try

  except

  end;

end.


「Cannot BREAK, CONTINUE or EXIT out of a FINALLY clause」エラーメッセージ
「Cannot BREAK, CONTINUE or EXIT out of a FINALLY clause」

例	コンパイルエラーメッセージ

説明

finally 節へは C++Builder の例外処理メカニズムや通常のプログラム制御を通して出入りが可能なので，プログラムの明示的な制御フローに従わせてはなりません。例外処理メカニズムを通して finally に入った場合，Break，Continue，Exit では節から出られません。例外処理システムが finally 節を実行しているときは例外処理システムへ制御を返されなければなりません。


例

{ 次のプログラムは break 文で finally 節から出ようとしている。この方法で FINALLY 節から出るのは合法ではない }

program Produce;

  procedure A0;

  var

    i : integer;

  begin

    for i:=1 to 10 do

      try

        (* 異常終了する可能性がある何かを試みる *)

      finally

        Break;

      end;

  end;

begin

end.

{ FINALLY 節にエラーを起こす文を入れないように変更しなければならない。この例の場合では

ループの外で例外処理を行うように変更した。BREAK の代わりに RAISE 文による例外の再生成を使う

こともできる。}

program Produce;

  procedure A0;

  var

    i : integer;

  begin

    try

      for i:=1 to 10 do

      begin

        (* 異常終了する可能性がある何かを試みる *)

      end;

    finally

    end;

  end;

begin

end.


「'GOTO <label>' leads into or out of TRY statement」エラーメッセージ
「'GOTO <label>' leads into or out of TRY statement」

例	コンパイルエラーメッセージ

説明

goto 文は例外処理文の中へ，また例外処理文の中から外へジャンプできません。

goto 文を使わないようにするのが理想的な解決法ですが，それが不可能な場合はプログラムを詳しく分析して正しい処置をする必要があります。


例

{ 次のコードの GOTO 文は両方とも正しくない。例外処理ブロックの中へ，また外へはジャンプできない }

program Produce;

label 1, 2;

begin

  goto 1;

  try

1:

  except

    goto 2;

  end;

2:

end.


「<clause1> clause expected, but <clause2> found」エラーメッセージ
「<clause1> clause expected, but <clause2> found」

例	コンパイルエラーメッセージ

説明

Pascal の構文ではプログラム内で <clause1> が必要な場所に，<clause2> がありました。


例

{ 最初のプロパティ宣言では read 節と write 節を指定しなければならず，Ch プロパティに両方が欠落しているため，コンパイルエラーになる。プロパティの場合，基本クラス内で定義したプロパティを別の可視性レベルへ，たとえばパブリックからプライベートへ引き上げるのが当初の意図だった可能性がある。その場合，プロパティ名が基本クラス内で見つからなかったのがエラーの原因としてもっとも考えられる。プロパティ名を正しいスペルで指定したかどうか，そのプロパティ名が実際にいずれかの親クラスの中にあるかどうかを確認する必要がある }

program Produce;

type

  CharDesc = class

    vch: Char;

    property Ch: Char;

  end;

end.

{ 必要な場所に正しく節を指定するのが解決法である }

program Produce;

type

  CharDesc = class

    vch: Char;

    property Ch: Char read vch write vch;

  end;

end.


「Cannot assign to a read-only property」エラーメッセージ
「Cannot assign to a read-only property」

例	コンパイルエラーメッセージ

説明

値を代入しようとしているプロパティは write 節が指定されていないために読み出し専用プロパティになっています。


例

{ プロパティは write 節を指定していなければ読み出し専用プロパティになる。読み出し専用のプロパティには値を代入できないので，コンパイラは「c.Title」への代入でエラーを出力する }

program Produce;

type

  Base = class

    S: string;

    property Title: string read S;

  end;

var

  C: Base;

procedure DiddleTitle;

begin

  if C.Title = '' then

    C.Title := 'Super Galactic Invaders with Turbo Gungla Sticks';

    { C.Title に対してその他の作業をする }

end;

begin

end.

{ ソースコードがある場合には，この読み出し専用プロパティに write 節を指定するのが 1 つの解決法になる。しかしこの方法は基本クラスの意味を大きく変える恐れがあるので軽々しく実行すべきではない。別の解決法としては読み出し専用プロパティの値を入れる仲介用の変数を使う方法がある。次に示すのは 2 番目の方法のコードである }

program Solve;

type

  Base = class

    S: string;

    property Title: string read S;

  end;

var

  C: Base;

procedure DiddleTitle;

var

  Title: string;

begin

  Title := C.Title;

  if Title = '' then

    Title := 'Super Galactic Invaders with Turbo Gungla Sticks';

    { Title に対してその他の作業をする }

end;

begin

end.


「Cannot read a write-only property」エラーメッセージ
「Cannot read a write-only property」

例	コンパイルエラーメッセージ

説明

値を読み出そうとしているプロパティは read 節が指定されていないために書き込み専用プロパティになっています。


例

{ C.Password は read 節を指定していないので，その値を読み出せない }

program Produce;

type

  Base = class

    S: string;

    property Password: string write S;

  end;

var

  C: Base;

  S: string;

begin

  S := C.Password;

end.

{ ソースコードがある場合には，この書き込み専用プロパティに read 節を追加すれば簡単に解決できる。しかし，read 節の追加は望ましくない場合もあり，セキュリティシステムに穴があく恐れもある。たとえば，この例の Password という書き込み専用プロパティを考えてみると，このクラスを使ったプログラムが格納済みパスワードを偶然に読み出すような事態は明らかに望ましくない。プロパティが書き込み専用として作成されている場合にはそのような理由が十分に考えられるので，このプロパティを読み出さなければならない理由を再度検討しなければならない }

program Solve;

type

  Base = class

    S: string;

    property Password: string read S write S;

  end;

var

  C: Base;

  S: string;

begin

  S := C.Password;

end.


「Class already has a default property」エラーメッセージ
「Class already has a default property」

例	コンパイルエラーメッセージ

説明

デフォルトプロパティをすでに定義してあるクラスに対してデフォルトプロパティを割り当てようとしました。


例

{ 次のコードでは Access プロパティをこのクラスのデフォルトプロパティにしようとしているが，すでに Data がデフォルトとして指定済みである。デフォルトプロパティは 1 つのクラスに 1 つだけである }

program Produce;

type

  Base = class

    function GetV(I: Integer): Char;

    procedure SetV(I: Integer; const X: Char);

    property Data[I: Integer]: Char read GetV write SetV; default;

    property Access[I: Integer]: Char read GetV write SetV; default;

  end;

function Base.GetV(I: Integer): Char;

begin

  GetV := 'A';

end;

procedure Base.SetV(I: Integer; const X: Char);

begin

end;

begin

end.

{ プログラムのソースから正しくないデフォルトプロパティの指定を削除すれば解決する }

program Solve;

type

  Base = class

    function GetV(I: Integer): Char;

    procedure SetV(I: Integer; const X: Char);

    property Data[I: Integer]: Char read GetV write SetV; default;

  end;

function Base.GetV(I: Integer): Char;

begin

  GetV := 'A';

end;

procedure Base.SetV(I: Integer; const X: Char);

begin

end;

begin

end.


「Operator not applicable to this operand type」エラーメッセージ
「Operator not applicable to this operand type」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはオペランドへ指定した演算子がそのオペランドには適用できない場合，たとえばポインタへ論理演算子を適用した場合などに表示されます。


例

{ P は論理式ではなく，比較はカッコで囲む必要がある }

program Produce;

var

  P: ^Integer;

begin

  if P and P^ > 0 then

    Writeln('P points to a number greater 0');

end.

{ P と nil を明示的に比較し，カッコで囲めばよい }

program Solve;

var

  P: ^Integer;

begin

  if (P <> nil) and (P^ > 0) then

    Writeln('P points to a number greater 0');

end.


「Default property must be an array property」エラーメッセージ
「Default property must be an array property」

例	コンパイルエラーメッセージ

説明

クラスに指定したデフォルトプロパティが配列プロパティではありません。デフォルトプロパティは配列プロパティでなければなりません。


例

{ デフォルトプロパティは，配列型でなければならない。次のコードの Data プロパティは配列型でなく Char 型を指定している }

program Produce;

type

  Base = class

    function GetV: Char;

    procedure SetV(X: Char);

    property Data: Char read GetV write SetV; default;

  end;

function Base.GetV: Char;

begin

  GetV := 'A';

end;

procedure Base.SetV(X: Char);

begin

end;

begin

end.

{ エラーを起こしたプロパティの指定を配列型に変更するか，default 指令を削除すればこのエラーはなくなる }

program Solve;

type

  Base = class

    function GetV(I: Integer): Char;

    procedure SetV(I: Integer; const X: Char);

    property Data[I: Integer]: Char read GetV write SetV; default;

  end;

function Base.GetV(I: Integer): Char;

begin

  GetV := 'A';

end;

procedure Base.SetV(I: Integer; const X: Char);

begin

end;

begin

end.


「TYPEINFO standard function expects a type identifier」エラーメッセージ
「TYPEINFO standard function expects a type identifier」

例	コンパイルエラーメッセージ

説明

型を表していない識別子について型情報を入手しようとしました。


例

{ TypeInfo 標準手続きにはパラメータとして型識別子が必要である。次のコードでは NotType は型識別子を表していない }

program Produce;

var

  P: Pointer;

procedure NotType;

begin

end;

begin

  P := TypeInfo(NotType);

end.

{ TypeInfo に使うパラメータを型識別子にすれば，このエラーを回避できる }

program Solve;

type

  Base = class

  end;

var

  P: Pointer;

begin

  P := TypeInfo(Base);

end.


「Type '<name>' has no type info」エラーメッセージ
「Type '<name>' has no type info」

例	コンパイルエラーメッセージ

説明

関連した実行時型情報がない型識別子に対して TypeInfo 標準手続きを適用しようとしました。


例

{ レコード型は型情報を生成しないので，この TypeInfo は使用できない }

program Produce;

type

  Data = record

  end;

var

  V: Pointer;

begin

  V := TypeInfo(Data);

end.

{ クラスは RTTI を生成するので，TypeInfo が使用できる }

program Solve;

type

  Base = class

  end;

var

  V: Pointer;

begin

  V := TypeInfo(Base);

end.


「FOR or WHILE loop executes zero times - deleted」エラーメッセージ
「FOR or WHILE loop executes zero times - deleted」

例	コンパイルエラーメッセージ

説明

コンパイラは指定されたループ構造が 1 回も実行されないと判断し，最適化のためにそのループ構造を削除します。


例

{ コンパイラは「FALSE AND (i<100)」を常に FALSE と評価し，そのループは実行されないと容易に判断する }

program Produce;

{$HINTS ON}

var

  I: Integer;

begin

  I := 0;

  while False and (I < 100) do

    Inc(I);

end.

{ while 文を制御する論理式を調べて，常に FALSE になるような状態を回避すれば，このヒントは解決する。for ループでは必ず (上限-下限)>=1 にする }

program Solve;

{$HINTS ON}

var

  I: Integer;

begin

  I := 0;

  while I < 100 do

    Inc(I);

end.


「No definition for abstract method '<name>' allowed」エラーメッセージ
「No definition for abstract method '<name>' allowed」

例	コンパイルエラーメッセージ

説明

<name> を abstract として宣言しましたが，コンパイラはソースファイルの中でそのメソッドの定義を見つけました。abstract 宣言に定義を指定するのは違法です。


例

{ 抽象メソッドは定義できない。このプログラムをコンパイルすると，Base.Foundation のところでエラーが表示される }

program Produce;

type

  Base = class

    procedure Foundation; virtual; abstract;

  end;

procedure Base.Foundation;

begin

end;

begin

end.

{ このエラーを解決するには 2 つの手順が必要である。最初に，基本クラスで宣言した抽象手続きの定義を削除しなければならない。次に，基本クラスを拡張し，この抽象手続きを拡張機能の中で override として宣言した後，新しく宣言した手続きの定義を指定する }

program Solve;

type

  Base = class

    procedure Foundation; virtual; abstract;

  end;

  Derived = class(Base)

    procedure Foundation; override;

  end;

procedure Derived.Foundation;

begin

end;

begin

end.


「Method '<name>' not found in base class」エラーメッセージ
「Method '<name>' not found in base class」

例	コンパイルエラーメッセージ

説明

メソッドに override 指令を適用しましたが，その名前の手続きが基本クラスの中にはありません。


例

{ このエラーの一般的な原因はソースコードでの単なるタイプミスである。override 手続きとして使った名前が基本クラス内の名前と同じスペルであるかどうかを確認する必要がある。あるいは，求める手続きが基本クラスにない場合も考えられる。そのような場合には，問題の解決法を判別するため，より深い分析が必要になる }

program Produce;

type

  Base = class

    procedure Title; virtual;

  end;

  Derived = class(Base)

    procedure Titl; override;

  end;

procedure Base.Title;

begin

end;

procedure Derived.Titl;

begin

end;

begin

end.

{ 次のコードでは単に Derived 内の手続き名のスペルを訂正して解決した }

program Solve;

type

  Base = class

    procedure Title; virtual;

  end;

  Derived = class(Base)

    procedure Title; override;

  end;

procedure Base.Title;

begin

end;

procedure Derived.Title;

begin

end;

begin

end.


「Invalid message parameter list」エラーメッセージ
「Invalid message parameter list」

例	コンパイルエラーメッセージ

説明

メッセージ処理メソッドは var パラメータを 1 つだけとれます。パラメータの型はチェックされません。


例

{ 最初の例ではパラメータが var でないのが明らかなエラーである。2 番目の例では複数のパラメータを宣言したのがエラーである }

program Produce;

type

  Base = class

    procedure Msg1(X: Integer); message 151;

    procedure Msg2(var X, Y: Integer); message 152;

  end;

procedure Base.Msg1(X: Integer);

begin

end;

procedure Base.Msg2(var X, Y: Integer);

begin

end;

begin

end.

{ どちらの場合もメッセージメソッドの宣言で var パラメータを 1 つだけ指定して解決した }

program Solve;

type

  Base = class

    procedure Msg1(var X: Integer); message 151;

    procedure Msg2(var Y: Integer); message 152;

  end;

procedure Base.Msg1(var X: Integer);

begin

end;

procedure Base.Msg2(var Y: Integer);

begin

end;

begin

end.


「Illegal message method index」エラーメッセージ
「Illegal message method index」

参照	例	コンパイルエラーメッセージ

説明

メッセージインデックスに 0 以下の値を指定しました。


例

{ メッセージインデックスとして -151 を指定してはいけません }

program Produce;

type

  Base = class

    procedure Dynamo(var X: Integer); message -151;

  end;

procedure Base.Dynamo(var X: Integer);

begin

end;

begin

end.

{ メッセージインデックスの値は必ず 1 以上にする }

program Solve;

type

  Base = class

    procedure Dynamo(var X: Integer); message 151;

  end;

procedure Base.Dynamo(var X: Integer);

begin

end;

begin

end.


参照

仮想メソッド


「Duplicate dynamic method index」エラーメッセージ
「Duplicate dynamic method index」

例	コンパイルエラーメッセージ

説明

動的メソッドに指定したインデックスが，すでに別の動的メソッドで使われています。


例

{ Second の宣言は First が使っているのと同じメッセージインデックスを再度使おうとしている。 }

program Produce;

type

  Base = class

    procedure First(var X: Integer); message 151;

    procedure Second(var X: Integer); message 151;

  end;

procedure Base.First(var X: Integer);

begin

end;

procedure Base.Second(var X: Integer);

begin

end;

begin

end.

{ この問題には直接的な 2 つの解決法がある。同じメッセージ値を使う必要がなければ，単にメッセージ番号をユニークな番号に変更すればよい。あるいは，基本クラスから新しいクラスを派生させ，基本クラス内で宣言したメッセージハンドラの動作を変更してもよい。両方を次のコードに示す }

program Solve;

type

  Base = class

    procedure First(var X: Integer); message 151;

    procedure Second(var X: Integer); message 152; { ユニークなインデックスに変更する }

  end;

  Derived = class(Base)

    procedure First(var X: Integer); override; { 基本クラスの動作を変更する }

  end;

procedure Base.First(var X: Integer);

begin

end;

procedure Base.Second(var X: Integer);

begin

end;

procedure Derived.First(var X: Integer);

begin

end;

begin

end.


「Bad file format '<name>'」エラーメッセージ
「Bad file format '<name>�」

コンパイルエラーメッセージ

説明

コンパイラの状態ファイルが壊れました。前のコンパイラの状態を再ロードできません。


「Array type required」エラーメッセージ
「Array type required」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは配列でないオペランドに対して添字を指定した場合か，オープン配列パラメータに配列でない引数を渡した場合に表示されます。


例

{ 整数へのポインタに添字を適用しようとする。これは C では合法だが Pascal では違法である }

program Produce;

var

  P: ^Integer;

  I: Integer;

begin

  Writeln(P[I]);

end.

{ Pascal では P が整数配列へのポインタであるということをコンパイラに明示しなければならない }

program Solve;

type

  TIntArray = array[0..MaxInt div sizeof(Integer)-1] of Integer;

var

  P: ^TIntArray;

  I: Integer;

begin

  Writeln(P^[I]);	{ Delphi 2.0 および C++Builder では P[I] としても合法である }

end.


「Inaccessible value」エラーメッセージ
「Inaccessible value」

コンパイルエラーメッセージ

説明

統合デバッガの中からアクセスできない値を表示しようとしました。長さがゼロのバリアント型文字列など，特定の型の値はデバッガの中から表示できません。


「Destination cannot be assigned to」エラーメッセージ
「Destination cannot be assigned to」

コンパイルエラーメッセージ

説明

統合デバッガは指定された代入が現在のコンテキストの中では有効でないと判断しました。


「Expression has no value」エラーメッセージ
「Expression has no value」

コンパイルエラーメッセージ

説明

式の結果を変数へ代入しようとしましたが，式が値を生成しませんでした。


「Destination is inaccessible」エラーメッセージ
「Destination is inaccessible」

コンパイルエラーメッセージ

説明

値を入れようとしたアドレスは統合デバッガの中からアクセスできないアドレスです。


「Expression is not a procedure」エラーメッセージ
「Expression is not a procedure」

コンパイルエラーメッセージ

説明

あるシンボルをプログラムで手続きとして使おうとしましたが，そのシンボルは手続きではありません。


「No source line for this procedure」エラーメッセージ
「No source line for this procedure」

コンパイルエラーメッセージ

説明

要求した手続きのソース行を統合デバッガが見つけられませんでした。ソースがある場合には，求める手続きが入っているユニットを，デバッグ情報をオンにして再コンパイルしてください。ソースがない場合にはこの手続きを表示できません。


「Re-raising an exception only allowed in exception handler」エラーメッセージ
「Re-raising an exception only allowed in exception handler」

例	コンパイルエラーメッセージ

説明

例外を再生成する raise 文の構文を使いましたが，コンパイラはその再生成が例外処理ブロックの外で起きたと判断しました。現在の例外処理メカニズムの制約により，ネストした例外ハンドラからの例外の再生成はできません。


例

{ このエラーにはいくつかの原因が考えられる。第 1 に例外ハンドラの外部で例外コンストラクタを持たない raise を指定した可能性がある。第 2 に例外ハンドラの try ブロックで例外を再生成しようとした可能性がある。第 3 に別の例外ハンドラの中にネストした例外ハンドラの中で例外を再生成しようとした可能性がある }

program Produce;

procedure RaiseException;

begin

  raise; { ケース 1 }

  try

    raise; { ケース 2 }

  except

    try

      raise; { ケース 3 }

    except

    end;

    raise;

  end;

end;

begin

end.

{ このエラーでは新しい例外を明示的に生成するのが 1 つの解決法である。「case 1」と「case 2」のような場合はそれを意図したと思われる。「case 3」の場合には，コードを調べて求める結果が得られるような適切な回避方法を判別する必要がある }

program Solve;

uses SysUtils;

procedure RaiseException;

begin

  raise Exception.Create('case 1');

  try

    raise Exception.Create('case 2');

  except

    try

      raise Exception.Create('case 3');

    except

    end;

    raise;

  end;

end;

begin

end.


「Default values must be of ordinal, pointer or small set type」エラーメッセージ
「Default values must be of ordinal, pointer or small set type」

例	コンパイルエラーメッセージ

説明

default 節が入っているプロパティを宣言しようとしましたが，そのプロパティの型はデフォルト値と互換性がありません。


例

{ 次のプログラムはプロパティを作成してそれにデフォルト値を割り当てようとしているが，プロパティの型がデフォルト値を使えない型なのでエラーが出力される }

program Produce;

type

  VisualGuage = class

    Pos: Single;

    property Position: Single read Pos write Pos default 0.0;

  end;

begin

end.

{ このエラーが発生した場合には簡単な 2 つの解決法がある。1 つはデフォルト値の定義を削除する方法で，もう 1 つはプロパティの型をデフォルト値が使える型に変更する方法である。しかし，実際のプログラムでは修正がそれほど簡単でないときもある。大きすぎる集合プロパティがある場合を考えてみるとよい。その場合にはプログラムを注意深く調べ，この問題の最善の解決法を判別する必要がある }

program Solve;

type

  VisualGuage = class

    Pos: Integer;

    property Position: Integer read Pos write Pos default 0;

  end;

begin

end.


「Property '<name>' does not exist in base class」エラーメッセージ
「Property '<name>' does not exist in base class」

例	コンパイルエラーメッセージ

説明

コンパイラは開発者がプロパティを派生クラスの別の可視性レベルまで引き上げる意図であると判断しましたが，指定されたプロパティが基本クラス内に存在しません。


例

{ このエラーには根本的な原因が 2 つある。1 つは型を指定せずに新しいプロパティを指定した場合で，通常これは新しい可視性レベルへの移動とは考えられない。もう 1 つは基本クラス内に存在するはずのプロパティを指定してコンパイラがそれを見つけられない場合で，ほとんどはタイプミスである。2 番目の形態でもコンパイラは read 節か write 節が必要だというエラーを出力する }

program Produce;

type

  Base = class

  private

    A: Integer;

    property BaseProp: Integer read A write A;

  end;

  Derived = class(Base)

    Ch: Char;

    property Alpha read Ch write Ch; { ケース 1 }

    property BesaProp; { ケース 2 }

  end;

begin

end.

{ 最初の例ではプロパティの型を指定すれば解決する。2 番目の例ではプロパティ名のスペルをチェックすれば解決する }

program Solve;

type

  Base = class

  private

    A: Integer;

    property BaseProp: Integer read A write A;

  end;

  Derived = class(Base)

    Ch: Char;

  public

    property Alpha: Char read Ch write Ch; { ケース 1 }

    property BaseProp; { ケース 2 }

  end;

begin

end.


「Dynamic method or message handler not allowed here」エラーメッセージ
「Dynamic method or message handler not allowed here」

例	コンパイルエラーメッセージ

説明

動的メソッドとメッセージメソッドはプロパティ用のアクセス関数として使えません。


例

{ 次の Velocity と Value はどちらも違法なアクセス関数が割り当てられているのでエラーになる }

program Produce;

type

  Base = class

    V: Integer;

    procedure SetV(var X: Integer); message 1;

    function GetV: Integer; dynamic;

    property Velocity: Integer read GetV write V;

    property Value: Integer read V write SetV;

  end;

procedure Base.SetV(var X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := V;

end;

begin

end.

{ 次のコードではエラーを起こしたコンパイラ指令を手続き宣言から削除して解決したが，これが正しい解決法であるとは限らない。プログラムの論理を詳しく調べて，プロパティにアクセス関数を指定する最善の方法を判別しなければならない場合もある }

program Solve;

type

  Base = class

    V: Integer;

    procedure SetV(X: Integer);

    function GetV: Integer;

    property Velocity: Integer read GetV write V;

    property Value: Integer read V write SetV;

  end;

procedure Base.SetV(X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := v;

end;

begin

end.


「Pointer type required」エラーメッセージ
「Pointer type required」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはポインタでないオペランドに逆参照演算子「^」を適用したときと，非常に特殊な場合として「Raise <exception> at <address>」文の第 2 オペランドがポインタでないときに表示されます。


例

{ クラス型が内部的には実際の情報へのポインタとして実装されていても，逆参照演算子をソースレベルでクラス型に適用するのは違法である。コンパイラは必要であれば自動的に逆参照をするので不必要でもある }

program Produce;

var

  C: TObject;

begin

  C^.Destroy;

end.

{ 単に逆参照演算子を入れないでおけばコンパイラが自動的に正しく処理する }

program Solve;

var

  C: TObject;

begin

  C.Destroy;

end.


「Class does not have a default property」エラーメッセージ
「Class does not have a default property」

例	コンパイルエラーメッセージ

説明

配列式の中でクラスインスタンス変数を使いましたが，そのクラス型はデフォルトの配列プロパティを宣言していません。


例

{ 次のコードでは Base が配列プロパティを宣言しておらず，B 自体が配列でないのでエラーが起きる }

program Produce;

type

  Base = class

  end;

var

  B: Base;

procedure P;

var

  Ch: Char;

begin

  Ch := B[1];

end;

begin

end.

{ クラスのデフォルトプロパティを宣言した場合は，配列式の中でクラスインスタンス変数を実際の配列のように使える。または，プロパティの名前を直接指定できる。メモ: $HINTS を ON にした場合，ch に代入された値は使われていないというヒントが表示される }

program Solve;

type

  Base = class

    function GetChar(I: Integer): Char;

    property data[I: Integer]: Char read GetChar; default;

  end;

var

  B: Base;

function Base.GetChar(I: Integer): Char;

begin

  GetChar := 'A';

end;

procedure P;

var

  Ch: Char;

begin

  Ch := B[1];

  Ch := B.Data[1];

end;

begin

end.


「Bad argument type in variable type array constructor」エラーメッセージ
「Bad argument type in variable type array constructor」

例	コンパイルエラーメッセージ

説明

変数配列の中では使えない型を使って配列を作成しようとしています。


例

{ 配列コンストラクタの中では列挙とレコードはサポートされないので，Examiner の 2 つの呼び出しは両方とも失敗する }

program Produce;

type

  Fruit = (apple, orange, pear);

  Data = record

    X: Integer;

    Ch: Char;

  end;

var

  F: Fruit;

  D: Data;

procedure Examiner(V: array of TVarRec);

begin

end;

begin

  Examiner([D]);

  Examiner([F]);

end.

{ 次のコードに示したように多数のデータ型が配列コンストラクタの中で使える }

program Solve;

var

  I: Integer;

  R: Real;

  V: Variant;

procedure Examiner(V: array of TVarRec);

begin

end;

begin

  I := 0; R := 0; V := 0;

  Examiner([I, R, V]);

end.


「Could not load RLINK32.DLL」エラーメッセージ
「Could not load RLINK32.DLL」

コンパイルエラーメッセージ

説明

RLINK32.DLL が見つかりませんでした。このファイルが必ずパス上にあるようにしてください。


「Wrong or corrupted version of RLINK32.DLL」エラーメッセージ
「Wrong or corrupted version of RLINK32.DLL」

コンパイルエラーメッセージ

説明

RLINK32.DLL に対する内部の一貫性チェックで異常が見つかりました。

古い RLINK32 をロードしようとしている可能性があるので，PATH 上に衝突がないかどうかを調べてください。RLINK32.DLL に確かに異常がないのにこのメッセージが表示される場合は，ボーランドに連絡してください。


「';' not allowed before `ELSE'」エラーメッセージ
「';' not allowed before �ELSE�」

例	コンパイルエラーメッセージ

説明

if..else 文の else の直前に「;」があります。「;」は文の終わりでなく文の区切りとして扱われます。if..else は 1 つの文であり，複合文を使った場合以外，間に「;」は入りません。


例

{ Pascal では ELSE 文の直前に「;」を付けられない。そのために次のコードではエラーが起きる }

program Produce;

var

  B: Integer;

begin

  if B = 10 then

    B := 0;

  else

    B := 10;

end.

{ この問題には 2 つの簡単な解決法がある。1 つはエラーを起こした「;」を削除する方法である。もう 1 つは IF..ELSE の個々の部分に複合文を作成する方法である。$HINTS が ON の場合は，B へ代入した値が決して使われないというヒントが表示される }

program Solve;

var

  B: Integer;

begin

  if B = 10 then

    B := 0

  else

    B := 10;

  if B = 10 then

  begin

    B := 0;

  end

  else

  begin

    B := 10;

  end;

end.


「Type '<name>' needs finalization - not allowed in variant record」エラーメッセージ
「Type '<name>' needs finalization - not allowed in variant record」

例	コンパイルエラーメッセージ

説明

現在所有しているリソースを解放して正しい終了処理をしなければならないという内部的な理由から，いくつかの特定の型はコンパイラによって特別に扱われます。コンパイラは実行時にどの型が実際にレコードのバリアント部に格納されているかを判別できないため，それらの特殊なデータ型が正しく終了処理されるかどうかは保証されません。


例

{ 文字列はリソースを正しく解放するためにコンパイラによる特殊な処理を必要とする型の 1 つである。したがって，バリアント部に String を使うのは違法である }

program Produce;

type

  Data = record

    case Kind:Char of

    'A': (Str: string);

  end;

begin

end.

{ エラーを起こしたすべての宣言をバリアント部から削除するのが 1 つの解決法である。そのほか，ポインタ型 (たとえば ^String) を使ってメモリを自分で管理する解決法もある }

program Solve;

type

  Data = record

    Str: string;

  end;

begin

end.


「Type '<name>' needs finalization - not allowed in file type」エラーメッセージ
「Type '<name>' needs finalization - not allowed in file type」

例	コンパイルエラーメッセージ

説明

現在所有しているリソースを解放して正しい終了処理をしなければならないという内部的な理由から，いくつかの特定の型はコンパイラによって特別に扱われます。

コンパイラは実行時に長い文字列がどれくらい長くなるかを判別できないため，それらの特殊なデータ型が正しく終了処理されるかどうかは保証されません。型付きファイルの中にあるすべてのレコードは同じサイズでなければならないので，長い文字列が入っている型は使えません。


例

{ 文字列は終了処理を必要とするデータ型の 1 つなので，File 型には格納できない }

program Produce;

type

  Data = record

    Name: string;

  end;

var

  InFile: file of Data;

begin

end.

{ String の場合には型を文字の配列として再宣言するのが簡単な解決法である。終了処理を必要とするそれ以外の型では，file of などの標準 Pascal 機能を使ったバイナリファイル構造の保守は一層難しくなる。専用のファイル入出力ルーチンを作成した方が簡単だと思われる }

program Solve;

type

  Data = record

    Name: array[1..25] of Char;

  end;

var

  InFile: file of Data;

begin

end.


「Expression too complicated」エラーメッセージ
「Expression too complicated」

コンパイルエラーメッセージ

説明

ソースコードの中に複雑すぎてコンパイラが処理できない式がありました。

一時変数を使うなどして式を簡単にしてください。


「Element 0 inaccessible - use 'Length' or 'SetLength'」エラーメッセージ
「Element 0 inaccessible - use 'Length' or �SetLength�」

例	コンパイルエラーメッセージ

説明

C++Builder の string 型では要素 0 に文字列の長さは格納されていません。長い文字列では要素 0 にアクセスして文字列の長さを取得したり変更したりする古い方法は使えません。


例

{ このプログラムは文字列の第 1 要素に直接アクセスして文字列の長さを取得しようとしている。 }

program Produce;

var

  Str: string;

  Len: Integer;

begin

  Str := 'Kojo no tsuki';

  Len := Str[0];

end.

{ 標準手続きの SetLength と Length を使えば文字列の第 1 要素に直接アクセスするのと同じ機能が得られる。$HINTS が ON の場合は，使われない len の値に関するヒントが表示される }

program Solve;

var

  Str: string;

  Len: Integer;

begin

  Str := 'Kojo no tsuki';

  Len := Length(Str);

end.


「System unit out of date or corrupted: missing '<name>'」エラーメッセージ
「System unit out of date or corrupted: missing '<name>�」

コンパイルエラーメッセージ

説明

コンパイラは System.dcu の中にある特殊関数を探しましたが，見つかりませんでした。System ユニットは壊れているか古いユニットです。

ライブラリ検索パスの衝突によって別の System.dcu を指すことがないかどうかを確認してください。System.dcu を再インストールしてみてください。それでも解決しない場合は，ボーランドまで連絡してください。


「Record, object or class type required」エラーメッセージ
「Record, object or class type required」

例	コンパイルエラーメッセージ

説明

コンパイラはレコード，オブジェクト，クラスのいずれかを指定した型名を予期していましたが，見つかりませんでした。

このエラーの原因は 2 つあります。1 つはレコードでないオブジェクトへの「.」の適用です。もう 1 つの原因は with 文の中に誤った型の変数を使っていることです。


例

{ このプログラムには同じエラーに 2 つ原因がある。1 つはレコードでないオブジェクトへの「.」の適用である。2 番目の例は WITH 文の中に誤った型の変数を使っている }

program Produce;

type

  RecordDesc = class

    Ch: Char;

  end;

var

  pCh: PChar;

  r: RecordDesc;

procedure A;

begin

  pCh.Ch := 'A'; (* ケース 1 *)

  with pCh do

  begin (* ケース 2 *)

  end;

end;

end.

{ このエラーは「.」と WITH をどちらも必ずレコード，オブジェクト，クラス変数のいずれかにだけ適用するようにすれば簡単に解決する }

program Solve;

type

  RecordDesc = class

    Ch: Char;

  end;

var

  R: RecordDesc;

procedure A;

begin

  R.Ch := 'A';    (* ケース 1 *)

  with r do

  begin (* ケース 2 *)

  end;

end;

end.


「Type not allowed in OLE Automation call」エラーメッセージ
「Type not allowed in OLE Automation call」

例	コンパイルエラーメッセージ

説明

コンパイラがバリアント型へ変換できないデータ型は OLE オートメーションの呼び出しに使えません。


例

{ バリアント型へ変換できないクラスなので OLE 呼び出しに使えない }

program Produce;

type

  Base = class

    X: Integer;

  end;

var

  B: Base;

  V: Variant;

begin

  V.Dispatch(B);

end.

{ これらのデータ型を手動でバリアントへ変換するか，バリアントへ自動的に変換できるデータ型だけを使うのがこの問題のただ 1 つの解決法である }

program Solve;

type

  Base = class

    X: Integer;

  end;

var

  B: Base;

  V: Variant;

begin

  V.Dispatch(B.X);

end.


「<RLink32 error message>」

コンパイルエラーメッセージ

説明

RLINK32 が報告しているとおりのエラーを検出しました。

このエラーについての詳細は，RLINK32 リファレンスを参照してください。


「<Filename>: <RLink32 error message>」

コンパイルエラーメッセージ

説明

RLINK32 が報告しているとおりのエラーを検出しました。

このエラーについての詳細は，RLINK32 リファレンスを参照してください。


「Too many conditional symbols」エラーメッセージ
「Too many conditional symbols」

コンパイルエラーメッセージ

説明

コマンドライン (環境設定ファイルを含む) で定義した条件シンボルが，割り当てられているメモリを超えました。すべての条件シンボルに対して 256 バイト割り当てられます。条件シンボルは条件シンボル領域に格納するときに 1 つの条件シンボルにつき 1 バイト余計に必要とします。

コマンドライン (または環境設定ファイル) に入っている条件コンパイルシンボルの数を減らすのがただ 1 つの解決法です。


「Method '<name>' hides virtual method of base type '<name>'」エラーメッセージ
「Method '<name>' hides virtual method of base type '<name>�」

参照	例	コンパイルエラーメッセージ

説明

基本クラス内にある仮想メソッドと同じ名前のメソッドを宣言しました。新しいメソッドは仮想メソッドではなく，同じ名前を持つ基本クラスのメソッドへのアクセスを隠します。


例

{ Derived の定義内で宣言した 2 つのメソッドはどちらも基本クラス内で宣言された同じ名前の仮想関数を隠す }

program Produce;

{$WARNINGS ON}

type

  Base = class

    procedure VirtuMethod; virtual;

    procedure VirtuMethod2; virtual;

  end;

  Derived = class(Base)

    procedure VirtuMethod;

    procedure VirtuMethod2;

  end;

procedure Base.VirtuMethod;

begin

end;

procedure Base.VirtuMethod2;

begin

end;

procedure Derived.VirtuMethod;

begin

end;

procedure Derived.VirtuMethod2;

begin

end;

begin

end.

{ このエラーを解決する方法は 2 つある。1 つは override を指定して派生クラスの手続きも virtural にする方法で，その場合，継承された呼び出しはそのまま元の手続きを参照できる。派生クラス内で宣言するときに手続きの名前を変更する方法もある。次のコードは両方の方法を示す例である }

program Solve;

type

  Base = class

    procedure VirtuMethod; virtual;

    procedure VirtuMethod2; virtual;

  end;

  Derived = class(Base)

    procedure VirtuMethod; override;

    procedure Virtu2Method;

  end;

procedure Base.VirtuMethod;

begin

end;

procedure Base.VirtuMethod2;

begin

end;

procedure Derived.VirtuMethod;

begin

end;

procedure Derived.Virtu2Method;

begin

end;

begin

end.


参照

メソッドのオーバーライド


「Variable '<name>' is declared but never used in '<name>'」エラーメッセージ
「Variable '<name>' is declared but never used in '<name>'」

例	コンパイルエラーメッセージ

説明

手続きの中で変数を宣言しましたが，その変数は実際には使われません。


例

program Produce;

{$HINTS ON}

procedure Local;

var

  I: Integer;

begin

end;

begin

end.

{ 使わない変数を手続きから削除するのが簡単な解決法である。しかし，実現部内で使用すべき変数の可能性もある }

program Solve;

{$HINTS ON}

procedure Local;

begin

end;

begin

end.


「Compile terminated by user」エラーメッセージ
「Compile terminated by user」

コンパイルエラーメッセージ

説明

コンパイル中に［コンパイル］ダイアログボックスで［キャンセル］ボタンを押しました。


「Unnamed arguments must precede named arguments in OLE Automation call」エラーメッセージ
「Unnamed arguments must precede named arguments in OLE Automation call」

例	コンパイルエラーメッセージ

説明

名前付き OLE オートメーションパラメータの後に名前のない引数を置こうとしました。


例

{ この OLE ディスパッチでは，名前付きパラメータ FileName を名前のないパラメータの後に置かなければならない }

program Produce;

var

  Ole: Variant;

begin

  Ole.Dispatch(FileName:='FrogEggs', 'Tapioca');

end.

{ このようにパラメータを逆にするのはもっとも直接的な解決法だが，適切でない場合もある。名前のないパラメータに名前を指定する解決法もある }

program Solve;

var

  Ole: Variant;

begin

  Ole.Dispatch('Tapioca', FileName:='FrogEggs');

end.


「Abstract methods must be virtual or dynamic」エラーメッセージ
「Abstract methods must be virtual or dynamic」

例	コンパイルエラーメッセージ

説明

基本クラス内で抽象メソッドを宣言する場合，その抽象メソッドは通常の仮想型か動的仮想型でなければなりません。


例

{ 抽象メソッドは virtual か dynamic でなければならないので次の宣言はエラーになる }

program Produce;

type

  Base = class

    procedure DaliVision; abstract;

    procedure TellyVision; abstract;

  end;

begin

end.

{ このエラーはアプリケーションに応じて virtual と dynamic のどちらか最適な方を指定すればなくなる }

program Solve;

type

  Base = class

    procedure DaliVision; virtual; abstract;

    procedure TellyVision; dynamic; abstract;

  end;

begin

end.


「Case label outside of range of case expression」警告メッセージ
「Case label outside of range of case expression」

例	コンパイルエラーメッセージ

説明

case 文の制御変数が生成できないラベルを case 文の内部に指定しました。


例

{ TatesCompass は CompassPoints の値の一部を保持できないので，いくつかの case ラベルがエラーになる }

program Produce;

{$WARNINGS ON}

type

  CompassPoints = (n, e, s, w, ne, se, sw, nw);

  FourPoints = n..w;

var

  TatesCompass: FourPoints;

begin

  TatesCompass := e;

  case TatesCompass of

    n:    Writeln('North');

    e:    Writeln('East');

    s:    Writeln('West');

    w:    Writeln('South');

    ne:   Writeln('Northeast');

    se:   Writeln('Southeast');

    sw:   Writeln('Southwest');

    nw:   Writeln('Northwest');

  end;

end.

{ コードを調べて何が目的かを判別した後，2 つの解決法がある。1 つはすべての case ラベルを生成できるよう case 文の制御変数の型を変更する方法である。2 番目の方法は制御変数が生成できないすべての case ラベルを削除する方法である。次のコードは最初の方法を示す例である }

program Solve;

{$WARNINGS ON}

type

  CompassPoints = (n, e, s, w, ne, se, sw, nw);

  FourPoints = n..w;

var

  TatesCompass: CompassPoints;

begin

  TatesCompass := e;

  case TatesCompass of

    n:    Writeln('North');

    e:    Writeln('East');

    s:    Writeln('West');

    w:    Writeln('South');

    ne:   Writeln('Northeast');

    se:   Writeln('Southeast');

    sw:   Writeln('Southwest');

    nw:   Writeln('Northwest');

  end;

end.


「Object type required」エラーメッセージ
「Object type required」

例	コンパイルエラーメッセージ

説明

このエラーはコンパイラがオブジェクト型を必要としているときに表示されます。たとえば，あるオブジェクトの上位オブジェクトの型もオブジェクト型でなければなりません。


例

{ System ユニット内の TObject はクラス型なので，そこからはオブジェクト型を派生できない }

type

  MyObject = object(TObject)

  end;

begin

end.

{ 型識別子がオブジェクト型を正しく表すようにする。スペルが間違っているか別のユニットからの識別子によって隠されている可能性がある }

program Solve;

type

  MyObject = class  { 実際には，これは class(TObject) を意味する }

  end;

begin

end.


「Field or method identifier expected」エラーメッセージ
「Field or method identifier expected」

例	コンパイルエラーメッセージ

説明

フィールドでもメソッドでもないプロパティに対して read 節または write 節用の識別子を指定しました。


例

{ 次のコードでは 2 つのプロパティの両方がエラーを起こす。最初のプロパティがエラーになる理由はプロパティ自体を読み書きメソッドとして指定できないからである。2 番目のプロパティがエラーになる理由は R が Base クラスのメンバーでないからである }

program Produce;

var

  R: string;

type

  Base = class

    T: string;

    property Title: string read Title write Title;

    property Caption: string read R write R;

  end;

begin

end.

{ このエラーを解決するには，プロパティ用のすべての read 節と write 節で，そのプロパティを所有するクラスのメンバーである有効なフィールド識別子かメソッド識別子を確実に指定する }

program Solve;

type

  Base = class

    T: string;

    property Title: string read T write T;

  end;

begin

end.


「Constructing instance of '<name>' containing abstract methods」エラーメッセージ
「Constructing instance of '<name>' containing abstract methods」

例	コンパイルエラーメッセージ

説明

コンパイル中のコードは抽象メソッドを持ったクラスのインスタンスを作成しようとしています。


例

{ 抽象手続きは実体が存在しないので，抽象手続きを持ったクラスのインスタンスを作成することは危険である。この例では B の作成が警告の原因である。ここで作成した B のインスタンスを通して Abstraction を呼び出すと実行時エラーになる。B へ代入した値は決して使われないというヒントが表示される }

program Produce;

{$WARNINGS ON}

{$HINTS ON}

type

  Base = class

    procedure Abstraction; virtual; abstract;

  end;

var

  B: Base;

begin

  B := Base.Create;

end.

{ ここに示すように，手続宣言から abstract 指令を削除するのがこの問題の 1 つの解決法である。もう 1 つの方法としては Base からクラスを派生させ，その後に Abstraction の具体的なバージョンを指定する。B へ代入した値は決して使われないというヒントが表示される }

program Solve;

{$WARNINGS ON}

{$HINTS ON}

type

  Base = class

    procedure Abstraction; virtual;

  end;

var

  B: Base;

procedure Base.Abstraction;

begin

end;

begin

  B := Base.Create;

end.


「Field definition not allowed after methods or properties」エラーメッセージ
「Field definition not allowed after methods or properties」

例	コンパイルエラーメッセージ

説明

最初のメソッド定義またはプロパティ定義が検出された後，さらにフィールドをクラスに追加しようとしました。すべてのフィールド定義をメソッドとプロパティの前に置かなければなりません。


例

{ FirstMethod の後に A を宣言するとエラーになる }

program Produce;

type

  Base = class

   procedure FirstMethod;

    A: Integer;

  end;

procedure Base.FirstMethod;

begin

end;

begin

end.

{ このエラーを解決するには，通常，すべてのフィールド定義を最初のフィールド宣言またはプロパティ宣言の前へ移動するだけで十分である }

program Solve;

type

  Base = class

    A: Integer;

    procedure FirstMethod;

  end;

procedure Base.FirstMethod;

begin

end;

begin

end.


「Cannot override a static method」エラーメッセージ
「Cannot override a static method」

例	コンパイルエラーメッセージ

説明

派生クラスの中で，仮想型として宣言されていない基本メソッドをオーバーライドしようとしました。


例

{ 次のコードがエラーになる理由は Base.StaticMethod が仮想メソッドとして宣言されておらず，したがってその宣言をオーバーライドできないためである }

program Produce;

type

  Base = class

    procedure StaticMethod;

  end;

  Derived = class(Base)

    procedure StaticMethod; override;

  end;

procedure Base.StaticMethod;

begin

end;

procedure Derived.StaticMethod;

begin

end;

begin

end.

{ 基本クラスのソースコードを持っていない場合，このエラーをプログラムから取り除くには派生メソッドの宣言から override の指定を削除するのがただ 1 つの方法である。基本クラスのソースがある場合には，慎重に考慮した後，基本クラスのメソッドを変更して仮想型の 1 つとして宣言する。ただし，そのような変更はプログラムに大きな影響を及ぼすので注意しなければならない }

program Solve;

type

  Base = class

    procedure StaticMethod;

  end;

  Derived = class(Base)

    procedure StaticMethod;

  end;

procedure Base.StaticMethod;

begin

end;

procedure Derived.StaticMethod;

begin

end;

begin

end.


「Variable '<name>' inaccessible here due to optimization」エラーメッセージ
「Variable '<name>' inaccessible here due to optimization」

例	コンパイルエラーメッセージ

説明

評価または監視式が無効な変数 <name> の値を取り出そうとしましたた。多くの場合，このエラーはプログラムの制御フローの中で特定の点から先は使われない値がローカル変数に代入されたとコンパイラが判断した場合に発生します。


例

1.	新しいアプリケーションを作成します。

2.	フォーム上にボタンを入れます。

3.	ボタンをダブルクリックして click メソッドを作成します。

4.	整数型のグローバル変数 C を実現部へ追加します。

click メソッドに次のコードを追加します。

procedure TForm1.Button1Click(Sender: TObject);

var

  A, B: Integer;

begin

  A := 10;

  B := 20;

  C := B;

  A := C;

end;

5.	C への代入にブレークポイントを設定します。

6.	アプリケーションをコンパイルして実行します。

7.	ボタンを押します。

8.	ブレークポイントに到達した後，［評価／変更］ダイアログボックスを開きます (［実行｜評価／変更(V)］)。

9.	A を評価します。

コンパイラは A への最初の代入は，その値が決して使われないため無効だと認識します。そのため，コンパイラは 2 番目の代入が発生するまで A の使用を延期します。変数 A は C が代入される点まで無効とみなされます。

有効な値を持っている変数を表示するのがただ 1 つの解決法です。


「Necessary library helper function was eliminated by linker」エラーメッセージ
「Necessary library helper function was eliminated by linker」

例	コンパイルエラーメッセージ

説明

要求された評価を実行するために，統合デバッガがコンパイラのヘルパー関数を使おうとしています。一方，リンカはヘルパー関数が実際にはプログラムに使われなかったと判断し，ヘルパー関数をプログラムへリンクしませんでした。


例

1.	新しいアプリケーションを作成します。

2.	フォーム上にボタンを入れます。

3.	ボタンをダブルクリックして click メソッドを作成します。

4.	string 型のグローバル変数 V をインターフェース部に追加します。

5.	PChar 型のグローバル変数 P をインターフェース部に追加します。

click メソッドに次のコードを追加します。

procedure TForm1.Button1Click(Sender: TObject);

begin

  V := 'Initialized';

  P := nil;

  V := 'Abid';

end;

6.	V への 2 番目の代入にブレークポイントを設定します。

7.	アプリケーションをコンパイルして実行します。

8.	ボタンを押します。

9.	ブレークポイントに到達した後，［評価／変更］ダイアログボックスを開きます (［実行｜評価／変更(V)］)。

10.	V を評価します。

11.	カーソルを［新しい値(N)］ボックスまで移動します。

12.	P と入力します。

13.	［変更(M)］ボタンをクリックします。

コンパイラは特殊関数を使って PChar を文字列へコピーします。その特殊関数はプログラムで使われていない場合，生成する実行可能コードのサイズを小さくするためにリンクされません。その場合，文字列への PChar の代入はないので，リンカによってその代入は削除されます。

procedure TForm1.Button1Click(Sender: TObject);

begin

  V := 'Initialized';

  P := nil;

  V := 'Abid';

  V := p;

end;

文字列への PChar の代入を余分に追加すれば，求める手続きがリンカによってプログラムに組み込まれます。このエラーがデバッグセッションで表示される場合は，本来のプログラムに必要ない言語／環境機能を使っています。


「Missing or invalid conditional symbol in '$<symbol>' directive」エラーメッセージ
「Missing or invalid conditional symbol in '$<symbol>' directive」

例	コンパイルエラーメッセージ

説明

$IFDEF，$IFNDEF，$DEFINE，$UNDEF の各指令の後にシンボルを置く必要があります。


例

{ ここでは $IFDEF 条件指令が誤って指定されているのでエラーになる }

program Produce;

{$IFDEF}

{$ENDIF}

begin

end.

{ テストするシンボルを該当の指令の後に必ず指定すれば，この問題は解決する }

program Solve;

{$IFDEF WIN32}

{$ENDIF}

begin

end.


「Incompatible format specification」エラーメッセージ
「Incompatible format specification」

コンパイルエラーメッセージ

説明

インスペクトしようとしているオブジェクトの型との互換性がない形式指定子を watch 文または evaluate 文に指定しました。たとえば論理型変数を文字列として表示しようとすると，このエラーが起きます。


「Format specifier must be C, S, D, H, X, Fn, P, R or nM」エラーメッセージ
「Format specifier must be C, S, D, H, X, Fn, P, R or nM」

コンパイルエラーメッセージ

説明

評価する式に無効な形式指定子を指定しようとしました。

有効な形式を指定してからでなければ評価が先へ進みません。


「Bad specification of M format」エラーメッセージ
「Bad specification of M format」

コンパイルエラーメッセージ

説明

使えない M 形式指定子を指定しました。M 指定子に使えるサフィクスは C，D，H，X，S，M だけです。


「Object or class type required」エラーメッセージ
「Object or class type required」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは「Typename.Methodname」という構文を使った場合に，typename がオブジェクト型またはクラス型を示していないと表示されます。


例

{ Create メソッドを持っているのは TInteger であり，整数型ではない }

program Produce;

type

  TInteger = class

    Value: Integer;

  end;

var

  V: TInteger;

begin

  V := Integer.Create;

end.

{ 識別子がオブジェクト型またはクラス型を示すようにする。識別子のスペルが間違っているか，識別子が別のユニットからの識別子によって隠されている可能性がある }

program Solve;

type

  TInteger = class

    Value: Integer;

  end;

var

  V: TInteger;

begin

  V := TInteger.Create;

end.


「Fn requires 2 <= n <= 18」エラーメッセージ
「Fn requires 2 <= n <= 18」

例	コンパイルエラーメッセージ

説明

統合デバッガの中で浮動小数点形式指定子の範囲外の値を指定しました。

Fn 形式指定子の範囲は 2～18 です。


例

1.	実数型変数を使ったアプリケーションを作成し実行します。

2.	その変数を［評価／変更］ダイアログボックスを使用し，「,F21」の形式指定を付けてで評価します (例  realVar,F21 など)。

3.	f を再評価します。ただし，Fn 指定子に 2～18 の範囲の数値を指定して再評価します。

Fn 指定を伴った実数を評価する場合，必ず 2 <= n <= 18 でなければなりません。


「'<name>' not previously declared as a PROPERTY」警告メッセージ
「'<name>' not previously declared as a PROPERTY」

例	コンパイルエラーメッセージ

説明

再宣言によってプロパティを別の可視性レベルまで引き上げようとしましたが，基本クラス内の <name> がプロパティとして宣言されていません。


例

{ Derived.Title の再宣言は プロパティ Title の読み書きに使うフィールドの変更とパブリックな可視性への引き上げを意図している。しかしプログラマが本当に使おうとしたのは Title でなく TitleProp である }

program Produce;

{$WARNINGS ON}

type

  Base = class

  protected

    Caption: string;

    Title: string;

    property TitleProp: string read Title write Title;

  end;

  Derived = class(Base)

  public

    property Title read Caption write Caption;

  end;

begin

end.

{ このエラーの解決法は 2 つある。1 つは再宣言したい本当のプロパティを指定する方法で，これがもっとも一般的な方法と思われる。もう 1 つは Title の再宣言に見られるように，基本クラス内のフィールドと同じ名前で新しいプロパティを明示的に作成する方法である。この新しいプロパティは基本フィールドを隠すので，基本フィールドへ型キャストなしにアクセスできなくなる (メモ: 警告をオンにしてある場合，Title を再宣言すると基本クラスのメンバーが再宣言によって隠されるという警告が発行される) }

program Solve;

{$WARNINGS ON}

type

  Base = class

  protected

    Caption: string;

    Title: string;

    property TitleProp: string read Title write Title;

  end;

  Derived = class(Base)

  public

    property TitleProp read Caption write Caption;

    property Title: string read Caption write Caption;

  end;

begin

end.


「Field definition not allowed in OLE automation section」エラーメッセージ
「Field definition not allowed in OLE automation section」

例	コンパイルエラーメッセージ

説明

クラス宣言の OLE オートメーション部にフィールド定義を入れようとしました。automated 部にはプロパティとメソッドだけを宣言できます。


例

{ このクラスでの I の宣言はコンパイルエラーになる }

program Produce;

type

  Base = class

  automated

    I: Integer;

  end;

begin

end.

{ I の宣言を automated 部の外へ出せばエラーはなくなる }

program Solve;

type

  Base = class

    I: Integer;

  automated

  end;

begin

end.


「Illegal type in OLE automation section: '<typename>'」エラーメッセージ
「Illegal type in OLE automation section: '<typename>'」

例	コンパイルエラーメッセージ

説明

<typename> は automated 部で使えない型です。オートメーション部では有効なすべての Pascal 型のうちの一部分だけが使えます。


例

{ 文字型は automated 部では使えない型なので，Ch を宣言するとコンパイルエラーになる }

program Produce;

type

  Base = class

    function GetC: Char;

    procedure SetC(C: Char);

  automated

    property Ch: Char read GetC write SetC dispid 151;

  end;

procedure Base.SetC(C: Char);

begin

end;

function Base.GetC: Char;

begin

  GetC := '!';

end;

begin

end.

{ この問題の解決法は 2 つある。1 つはエラーを起こした宣言を automated 部の外へ出す方法である。もう 1 つはエラーを起こした型を automated 部で使える型に変更する方法である }

program Solve;

type

  Base = class

    function GetC: string;

    procedure SetC(C: string);

  automated

    property Ch: string read GetC write SetC dispid 151;

  end;

procedure Base.SetC(C: string);

begin

end;

function Base.GetC: string;

begin

  GetC := '!';

end;

begin

end.


「String constant truncated to fit STRING[<number>]」警告メッセージ
「String constant truncated to fit STRING[<number>]」

参照	例	コンパイルエラーメッセージ

説明

文字列定数を変数に代入しようとしましたが，変数の大きさがその文字列全体を入れるには十分ではありません。コンパイラは変数に収まるようにリテラルを切り捨てたことを警告しています。


例

{ 2 つの文字列定数が変数へ代入されるが，それらの変数は文字列全体を入れるには短すぎる。コンパイラは文字列の末尾を切り捨てて代入を実行する }

program Produce;

{$WARNINGS ON}

const

  Title = 'Super Galactic Invaders with Turbo Gungla Sticks';

  Subtitle = 'Copyright (c) 1968 by Frank Borland';

type

  TitleString = string[25];

  SubtitleString = string[18];

var

  ProgramTitle: TitleString;

  ProgramSubtitle: SubtitleString;

begin

  ProgramTitle := Title;

  ProgramSubtitle := Subtitle;

end.

{ この問題の解決法は 2 つあり，この例では両方を示す。最初の解決法では文字列を保持する変数のサイズを大きくする。2 番目の解決法では宣言した変数サイズに合わせて文字列のサイズを小さくする }

program Solve;

{$WARNINGS ON}

const

  Title = 'Super Galactic Invaders with Turbo Gungla Sticks';

  Subtitle = 'Copyright (c) 1968';

type

  TitleString = string[55];

  SubtitleString = string[18];

var

  ProgramTitle: TitleString;

  ProgramSubtitle: SubtitleString;

begin

  ProgramTitle := Title;

  ProgramSubtitle := Subtitle;

end.


参照

短い文字列型


「Constructors and destructors not allowed in OLE automation section」エラーメッセージ
「Constructors and destructors not allowed in OLE automation section」

例	コンパイルエラーメッセージ

説明

クラス宣言の automated 部の中へコンストラクタかデストラクタを誤って入れようとしました。


例

{ OLE オートメーション部の中ではクラスのコンストラクタやデストラクタを宣言できない。次のコードのコンストラクタ宣言とデストラクタ宣言はどちらもこのエラーを生成する }

program Produce;

type

  Base = class

  automated

    constructor HardHatBob;

    destructor  DemolitionBob;

  end;

constructor Base.HardHatBob;

begin

end;

destructor Base.DemolitionBob;

begin

end;

begin

end.

{ 次のコードに示すように，宣言を automated 部の外へ出すのがこのエラーのただ 1 つの解決法である }

program Solve;

type

  Base = class

    constructor HardHatBob;

    destructor  DemolitionBob;

  end;

constructor Base.HardHatBob;

begin

end;

destructor Base.DemolitionBob;

begin

end;

begin

end.


「Dynamic methods and message handlers not allowed in OLE automation section」エラーメッセージ
「Dynamic methods and message handlers not allowed in OLE automation section」

例	コンパイルエラーメッセージ

説明

クラス宣言の automated 部の中へ動的メソッドかメッセージメソッドを誤って入れようとしました。


例

{ クラスの OLE オートメーション部の中では動的メソッドやメッセージメソッドを宣言できない。したがって，次のプログラムにある 2 つのメソッド宣言はどちらもエラーを生成する }

program Produce;

type

  Base = class

  automated

    procedure DynaMethod; dynamic;

    procedure MessageMethod(var Msg: Integer); message 151;

  end;

procedure Base.DynaMethod;

begin

end;

procedure Base.MessageMethod;

begin

end;

begin

end.

{ プログラムからこのエラーを取り除く方法はいくつかある。まず，次のコードに示すように，このエラーを生成した宣言を automated 部の外へ出す方法がある。あるいは，メソッドの dynamic 属性または message 属性を削除してもよい。これらの属性を削除すると，希望の動作は得られなくなるがエラーもなくなる }

program Solve;

type

  Base = class

    procedure DynaMethod; dynamic;

    procedure MessageMethod(var Msg: Integer); message 151;

  end;

procedure Base.DynaMethod;

begin

end;

procedure Base.MessageMethod;

begin

end;

begin

end.


「Only register calling convention allowed in OLE automation section」エラーメッセージ
「Only register calling convention allowed in OLE automation section」

例	コンパイルエラーメッセージ

説明

クラス宣言の automated 部の中にあるメソッドに対して，違法な呼び出し規約を指定しました。


例

{ 言語の仕様上，OLE オートメーション部では register 以外の呼び出し規約はすべて使えない。次のコードでは cdecl 文がエラーを起こしている }

program Produce;

type

  Base = class

  automated

    procedure Method; cdecl;

  end;

procedure Base.Method; cdecl;

begin

end;

begin

end.

{ このエラーの解決法は 3 つある。1 つは automated 部内で宣言したメソッドに対しては呼び出し規約を指定しない方法である。2 番目の方法は register 呼び出し規約だけを指定する方法である。3 番目の方法はエラーを起こした宣言をオートメーション部の外へ出す方法である }

program Solve;

type

  Base = class

  automated

    procedure Method; register;

    procedure Method2;

  end;

procedure Base.Method; register;

begin

end;

procedure Base.Method2;

begin

end;

begin

end.


「Dispid '<number>' already used by '<name>'」エラーメッセージ
「Dispid '<number>' already used by '<name>�」

参照	例	コンパイルエラーメッセージ

説明

このクラスですでに別のメンバーへ割り当ててある dispid を使おうとしました。


例

{ 個々の automated プロパティの dispid はユニークでなければならないので，SecondValue はエラーである }

program Produce;

type

  Base = class

    V: Integer;

    procedure SetV(X: Integer);

    function GetV: Integer;

  automated

    property Value: Integer read GetV write SetV dispid 151;

    property SecondValue: Integer read GetV write SetV dispid 151;

  end;

procedure Base.SetV(X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := V;

end;

begin

end.

{ SecondValue へユニークな dispid を割り当てればエラーはなくなる }

program Solve;

type

  Base = class

    V: Integer;

    procedure SetV(X: Integer);

    function GetV: Integer;

  automated

    property Value: Integer read getV write setV dispid 151;

    property SecondValue: Integer read GetV write SetV dispid 152;

  end;

procedure Base.SetV(X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := V;

end;

begin

end.


参照

OLE オートメーション


「Redeclaration of property not allowed in OLE automation section」エラーメッセージ
「Redeclaration of property not allowed in OLE automation section」

例	コンパイルエラーメッセージ

説明

automated 部の中ではプロパティを再宣言できません。


例

{ 次のコードでは，再宣言によって Name を Base でのプライベートな可視性から Derived でのパブリックな可視性へ移した。同じ操作を Value に試みたがエラーになった }

program Produce;

type

  Base = class

    V: Integer;

    S: string;

  protected

    property Name: string read S write S;

    property Value: Integer read V write V;

  end;

  Derived = class(Base)

  public

    property Name; (* 再宣言によって Name をパブリックな可視性へ移す *)

  automated

    property Value;

  end;

begin

end.

{ プロパティの可視性を automated 部へ単純には変更できない。したがって，基本クラスのプロパティを automated 部で再宣言しないのがこの問題の解決法である }

program Solve;

type

  Base = class

    V: Integer;

    S: string;

  protected

    property Name: string read S write S;

    property Value: Integer read V write V;

  end;

  Derived = class(Base)

  public

    property Name; (* 再宣言によって Name をパブリックな可視性へ移す *)

    property Value;

  automated

  end;

begin

end.


「Undeclared identifier: '<name>'」エラーメッセージ
「Undeclared identifier: '<name>�」

例	コンパイルエラーメッセージ

説明

指定された識別子が見つかりませんでした。もっとも考えられる原因は宣言または使用の時点でのスペルの誤りです。uses 節でユニットを指定しなかった可能性もあります。


例

{ 次のコードでは Counter として宣言した変数を Count として使った。宣言を変更するか変数を使った場所に変更を加えれば解決する }

program Produce;

var

  Counter: Integer;

begin

  Count := 0;

  Inc(Count);

  Writeln(Count);

end.

{ この例では宣言を変更した。その方が手間がかからない }

program Solve;

var

  Count: Integer;

begin

  Count := 0;

  Inc(Count);

  Writeln(Count);

end.


「Class type required」エラーメッセージ
「Class type required」

例	コンパイルエラーメッセージ

説明

コンパイラは以下の場合にクラス型を必要とします。

クラス型の上位オブジェクトとして

try..except 文の on 節の中で

raise 文の第 1 引数として

forward 宣言クラス型の最終的な型として


例

program Produce;

begin

  raise 'This would work in C++, but does not in C++Builder';

end.

program Solve;

uses SysUtils;

begin

  raise Exception.Create('There is a simple workaround, however');

end.


「'<clause>' clause not allowed in OLE automation section」エラーメッセージ
「'<clause>' clause not allowed in OLE automation section」

例	コンパイルエラーメッセージ

説明

OLE オートメーション部では index，stored，default，nodefault の各指令を使えません。


例

{ automated プロパティには NODEFAULT 節を組み込めない }

program Produce;

type

  Base = class

    V: Integer;

    procedure SetV(X: Integer);

    function GetV: Integer;

  automated

    property Value: Integer read GetV write SetV nodefault;

  end;

procedure Base.SetV(X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := V;

end;

begin

end.

{ エラーを起こした節を削除するだけでエラーはなくなる。あるいは，そのプロパティを automated 部から外に出してもエラーはなくなる }

program Solve;

type

  Base = class

    V: Integer;

    procedure SetV(X: Integer);

    function GetV: Integer;

  automated

    property Value: Integer read GetV write SetV;

  end;

procedure Base.SetV(X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := V;

end;

begin

end.


「Dispid clause only allowed in OLE automation section」エラーメッセージ
「Dispid clause only allowed in OLE automation section」

例

説明

automated 部に入っていないプロパティに dispid を指定しました。


例

{ このプログラムは OLE オートメーションオブジェクトの dispid を設定しようとしているが，そのプロパティは automated 部で宣言されていない }

program Produce;

type

  Base = class

    V: Integer;

    procedure SetV(X: Integer);

    function GetV: Integer;

    property Value: Integer read GetV write SetV dispid 151;

  end;

procedure Base.SetV(X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := V;

end;

begin

end.

{ エラーを解決するには，プロパティ宣言から dispid 節を削除するか，プロパティ宣言を automated 部の中へ入れる }

program Solve;

type

  Base = class

    V: Integer;

    procedure SetV(X: Integer);

    function GetV: Integer;

  automated

    property Value: Integer read GetV write SetV dispid 151;

  end;

procedure Base.SetV(X: Integer);

begin

  V := X;

end;

function Base.GetV: Integer;

begin

  GetV := V;

end;

begin

end.


「Type '<name>' must be a class to have OLE automation」エラーメッセージ
「Type '<name>' must be a class to have OLE automation」

例	コンパイルエラーメッセージ

説明

古いスタイルのオブジェクトには automated 部を指定できません。


例

{ 古いスタイルのオブジェクトには automated 部を指定できないので，この例はエラーになる }

program Produce;

type

  OldObject = object

  automated

  end;

begin

end.

{ 型を object から class に変更するか automated 部を削除すればエラーはなくなる }

program Solve;

type

  NewClass = class

  automated

  end;

begin

end.


「Type '<name>' must be a class to have a PUBLISHED section」エラーメッセージ
「Type '<name>' must be a class to have a PUBLISHED section」

例	コンパイルエラーメッセージ

説明

古いスタイルのオブジェクトには published 部を指定できません。


例

{ 古いスタイルのオブジェクトには published 部を指定できないので，この例はエラーになる }

{$TYPEINFO ON}

program Produce;

type

  OldObject = object

  published

  end;

begin

end.

{ 型を object から class に変更するか published 部を削除すればエラーはなくなる }

{$TYPEINFO ON}

program Solve;

type

  NewClass = class

  published

  end;

begin

end.


「Redeclaration of '<name>' hides a member in the base class」警告メッセージ
「Redeclaration of '<name>' hides a member in the base class」

例	コンパイルエラーメッセージ

説明

基本クラスの 1 つに含まれている変数と同じ名前でクラス内にプロパティを作成しました。

たとえば，新しく基本クラス階層を導入し，それに現在使っているプロパティ名と同じ名前のメンバー変数が入っている場合などが原因と考えられます。


例

{ Derived.v は Base.v をオーバーライドし，したがって隠す。型キャストをしなければ Derived 型の変数から Base.v へアクセスできない }

{$WARNINGS ON}

program Produce;

type

  Base = class

    V: Integer;

  end;

  Derived = class(Base)

    Ch: Char;

    property V: Char read Ch write Ch;

  end;

begin

end.

{ 派生クラス内のプロパティ名を変更するだけでエラーはなくなる }

{$WARNINGS ON}

program Solve;

type

  Base = class

    V: Integer;

  end;

  Derived = class(Base)

    Ch: Char;

    property ChV: Char read Ch write Ch;

  end;

begin

end.


「Overriding automated virtual method '<name>' cannot specify a dispid」エラーメッセージ
「Overriding automated virtual method '<name>' cannot specify a dispid」

例	コンパイルエラーメッセージ

説明

派生クラス内でオーバーライドするすべての手続きは，元の仮想 automated 手続き宣言用に宣言された dispid を使わなければなりません。


例

{ Derived 内にある Base.Automatic のオーバーライド宣言 (Derived.Automatic) が手続用に別の dispid を定義しようとしているのが誤りである }

program Produce;

type

  Base = class

  automated

    procedure Automatic; virtual; dispid 151;

  end;

  Derived = class(Base)

  automated

    procedure Automatic; override; dispid 152;

  end;

procedure Base.Automatic;

begin

end;

procedure Derived.Automatic;

begin

end;

begin

end.

{ エラーを起こした dispid 節を削除すれば，このプログラムをコンパイルできる }

program Solve;

type

  Base = class

  automated

    procedure Automatic; virtual; dispid 151;

  end;

  Derived = class(Base)

  automated

    procedure Automatic; override;

  end;

procedure Base.Automatic;

begin

end;

procedure Derived.Automatic;

begin

end;

begin

end.


「Published Real property '<name>' must be Single, Double or Extended」エラーメッセージ
「Published Real property '<name>' must be Single, Double or Extended」

例	コンパイルエラーメッセージ

説明

Real 型のプロパティはパブリッシュに設定できません。パブリッシュに設定できる浮動小数点プロパティは Single，Double，Extended のいずれかです。


例

{ 次のプログラムでは，パブリッシュに設定した Real プロパティを削除するか，パブリッシュに設定しない部へ移動するか，または受け入れ可能な型に変更しなければならない }

program Produce;

type

  Base = class

    R: Real;

  published

    property RVal: Real read R write R;

  end;

end.

{ この解決法ではプロパティを実数型に変更した。これによって実行時の型情報が実際に生成される }

program Produce;

type

  Base = class

    R: Single;

  published

    property RVal: Single read R write R;

  end;

end.


「Size of published set '<name>' is >32 bits」エラーメッセージ
「Size of published set '<name>' is >32 bits」

例	コンパイルエラーメッセージ

説明

published 部には 32 ビットを超える集合型を入れられません。集合型のサイズ (バイト単位) は High(setname) div 8 - Low(setname) div 8 + 1 で計算できます。


例

{$TYPEINFO ON}

program Produce;

type

  CharSet = set of Char;

  NamePlate = class

    Characters: CharSet;

  published

    property TooBig: CharSet read Characters write Characters ;

  end;

begin

end.

{$TYPEINFO ON}

program Solve;

type

  CharSet = set of 'A'..'Z';

  NamePlate = class

    Characters: CharSet;

  published

    property TooBig: CharSet read Characters write Characters ;

  end;

begin

end.


「Published property '<name>' cannot be of type <type>」エラーメッセージ
「Published property '<name>' cannot be of type <type>」

例	コンパイルエラーメッセージ

説明

パブリッシュプロパティは順序型，Single，Double，Extended，Comp，文字列型，32 ビットに収まる集合型，メソッドポインタ型のいずれかでなければなりません。それ以外のプロパティ型が published 部にあった場合，コンパイラは published 属性を削除します。


例

{ 配列はパブリッシュに設定できないデータ型なのでエラーが起きる }

{$TYPEINFO ON}

program Produce;

type

  TitleArr = array[0..24] of Char;

  NamePlate = class

    TitleStr: TitleArr;

  published

    property Title: TitleArr read TitleStr write TitleStr;

  end;

begin

end.

{ プロパティ宣言を published 部の外へ出せばエラーを回避できる。あるいは，プロパティの型を次のコードのように，実際にパブリッシュに設定できる型に変更してもよい }

{$TYPEINFO ON}

program Solve;

type

  TitleArr = Integer;

  NamePlate = class

    TitleStr: TitleArr;

  published

    property Title: TitleArr read TitleStr write TitleStr;

  end;

begin

end.


「Thread local variables cannot be local to a function」エラーメッセージ
「Thread local variables cannot be local to a function」

例	コンパイルエラーメッセージ

説明

スレッドローカル変数はグローバルスコープで宣言しなければなりません。


例

{ スレッド変数は手続きに対してローカルには宣言できない }

program Produce;

procedure NoTLS;

threadvar

  X: Integer;

begin

end;

begin

end.

{ このエラーには簡単な回避方法が 2 つある。1 つは threadvar セクションをローカルスコープへ移動する方法である。もう 1 つは，手続き内の threadvar を通常の var セクションに変更する方法である。コンパイラのヒントがオンの場合には，宣言しても使われない localX についてのヒントが表示される }

program Solve;

threadvar

  X: Integer;

procedure YesTLS;

var

  LocalX: Integer;

begin

end;

begin

end.


「Function needs result type」エラーメッセージ
「Function needs result type」

例	コンパイルエラーメッセージ

説明

関数を宣言しましたが，戻りの型を指定しませんでした。


例

{ 関数 Sum の戻り値型が指定されていない }

program Produce;

function Sum(A: array of Integer);

var

  I: Integer;

begin

  Result := 0;

  for I := 0 to High(A) do

    Result := Result + A[I];

end;

begin

end.

{ 結果の型を必ず指定するだけでよい }

program Solve;

function Sum(A: array of Integer): Integer;

var

  I: Integer;

begin

  Result := 0;

  for I := 0 to High(A) do

    Result := Result + A[I];

end;

begin

end.


「Thread local variables cannot be ABSOLUTE」エラーメッセージ
「Thread local variables cannot be ABSOLUTE」

例	コンパイルエラーメッセージ

説明

スレッドローカル変数は別の変数を参照できず，絶対メモリアドレスも参照できません。


例

{ absolute 指令は threadvar 宣言セクションでは使えない }

program Produce;

threadvar

  SecretNum: Integer absolute $151;

begin

end.

{ この種の問題には簡単な解決法が 2 つある。1 つは threadvar セクションから absolute 指令を単に削除する方法である。もう 1 つは絶対変数を通常の var 宣言セクションへ移動する方法である }

program Solve;

threadvar

  SecretNum: Integer;

var

  sNum: Integer absolute $151;

begin

end.


「EXPORTS allowed only at global scope」エラーメッセージ
「EXPORTS allowed only at global scope」

例	コンパイルエラーメッセージ

説明

ソースプログラムの中にスコープがグローバルでない exports 節がありました。


例

{ EXPORTS 節はグローバルスコープでだけ使える }

program Produce;

procedure ExportedProcedure;

exports ExportedProcedure;

begin

end;

begin

end.

{ EXPORTS 節を必ずグローバルスコープにし，節の中に指定したすべての手続きの後に置けば解決する。一般的な規則として，EXPORTS 節はソースファイルの初期化コードの直前に置くのが最善の方法である }

program Solve;

procedure ExportedProcedure;

begin

end;

exports ExportedProcedure;

begin

end.


「Constants cannot be used as open array arguments」エラーメッセージ
「Constants cannot be used as open array arguments」

例	コンパイルエラーメッセージ

説明

オープン配列パラメータは実際の配列変数または作成済み配列と一緒に指定するか，パラメータの要素型の単一変数と一緒に指定しなければなりません。


例

{ 次のコードでエラーが起きる原因は，配列が渡されるべき手続きに文字列リテラルが提供されるからである。定数からは配列を暗黙に作成できない }

program Produce;

procedure TakesArray(S: array of string);

begin

end;

begin

  TakesArray('Hello Error');

end.

{ この解決法では配列が明示的に作成されるのでエラーを回避できる }

program Solve;

procedure TakesArray(S: array of string);

begin

end;

begin

  TakesArray(['Hello Error']);

end.


「Slice standard function only allowed as open array argument」エラーメッセージ
「Slice standard function only allowed as open array argument」

例	コンパイルエラーメッセージ

説明

固定サイズの配列へ配列スライスを渡そうとしました。配列スライスはオープン配列パラメータにだけ送れます。


例

{ 次のコードでは TakesArray が固定サイズの配列を期待しているためにエラーが生成される }

program Produce;

type

  IntegerArray = array[1..10] of Integer;

var

  SliceMe: array[1..200] of Integer;

procedure TakesArray(X: IntegerArray);

begin

end;

begin

  TakesArray(Slice(SliceMe, 5));

end.

{ 次のコードでは TakesArray がパラメータとしてオープン配列をとるのでエラーは生成されない }

program Solve;

type

  IntegerArray = array[1..10] of Integer;

var

  SliceMe: array[1..200] of Integer;

procedure TakesArray(X: array of Integer);

begin

end;

begin

  TakesArray(Slice(SliceMe, 5));

end.


「Cannot initialize thread local variables」エラーメッセージ
「Cannot initialize thread local variables」

例	コンパイルエラーメッセージ

説明

スレッドローカル変数は初期化できません。


例

{ 次の tls の宣言と初期化はできない }

program Produce;

threadvar

  tls: Integer = 151;

begin

end.

{ スレッドローカル記憶域を通常の記憶域として宣言しておけば，ソースファイルの初期化部で初期化できる }

program Solve;

threadvar

  tls: Integer;

begin

  tls := 151;

end.


「Cannot initialize local variables」エラーメッセージ
「Cannot initialize local variables」

例	コンパイルエラーメッセージ

説明

ローカルで初期化済み変数は使えません。


例

{ Show 手続き内の i の宣言と初期化は違法である }

program Produce;

var

  J: Integer;

procedure Show;

var

  I: Integer = 151;

begin

end;

begin

end.

{ プログラムのスタイルを使ってすべての変数に値を設定できる }

program Solve;

var

  J: Integer;

procedure Show;

var

  I: Integer;

begin

  I := 151;

end;

begin

  J := 0;

end.


「Cannot initialize multiple variables」エラーメッセージ
「Cannot initialize multiple variables」

例	コンパイルエラーメッセージ

説明

変数の初期化は変数を個別に宣言したときにだけ実行できます。


例

{ 一度に複数の変数の宣言と初期化はできない }

program Produce;

var

  I, J: Integer = 151, 152;

begin

end.

{ 単に個々の変数を単独で宣言すれば初期化できる }

program Solve;

var

  I: Integer = 151;

  J: Integer = 152;

begin

end.


「Constant object cannot be passed as var parameter」エラーメッセージ
「Constant object cannot be passed as var parameter」

例	コンパイルエラーメッセージ

説明

変数パラメータは呼び出された手続きまたは関数によって変更されるのを前提としているので，定数オブジェクトは渡せません。呼び出された関数にそのデータ構造を変更させたくなければ，かわりに定数パラメータが使えます。


例

{ 次のコードでは関数に変数パラメータがあるが，それに定数を渡している }

program Produce;

{$AppType Console}

function Max(var A: array of Integer): Integer;

var

  I: Integer;

begin

  Result := Low(Integer);

  for I := 0 to High(A) do

    if Result < A[I] then

       Result := A[I];

end;

begin

  Writeln( Max([1,2,3]) ); { <-- ここでエラーメッセージ }

end.

{ パラメータを定数パラメータとして宣言すれば (パラメータに変更を加える意図はないので) 解決する。定数を渡さないように呼び出しを変更する方法もある }

program Solve;

{$AppType Console}

function Max(const A: array of Integer): Integer;

var

  I: Integer;

begin

  Result := Low(Integer);

  for I := 0 to High(A) do

    if Result < A[I] then

      Result := A[I];

end;

begin

  Writeln( Max([1,2,3]) );

end.


「Invalid function result type」エラーメッセージ
「Invalid function result type」

例	コンパイルエラーメッセージ

説明

ファイル型は関数の結果の型としては使えません。


例

{ 関数からはファイル型を返せない }

program Produce;

function OpenFile(Name: string): file;

begin

end;

begin

end.

{ ファイル型は変数パラメータとして返せる。ファイルを動的に割り当て，そのファイルへのポインタを返す方法もある }

program Solve;

procedure OpenFile(Name: string; var F: file);

begin

end;

begin

end.


「Procedure cannot have a result type」エラーメッセージ
「Procedure cannot have a result type」

例	コンパイルエラーメッセージ

説明

手続きを宣言しましたが，それに結果の型を指定しました。本当は関数を宣言する意図だったか，あるいは結果の型を削除しなければなりません。


例

{ ここで本当は DotProcuct を関数にする意図だったが，誤ったキーワードを使った }

program Produce;

procedure DotProduct(const A,B: array of Double): Double;

var

  I: Integer;

begin

  Result := 0.0;

  for I := 0 to High(A) do

    Result := Result + A[I]*B[I];

end;

const

  C: array[1..3] of Double = (1,2,3);

begin

  Writeln( DotProduct(C,C) );

end.

{ 関数を宣言するときは必ず結果の型を宣言し，手続きを宣言するときは結果の型を宣言しない }

program Solve;

function DotProduct(const A,B: array of Double): Double;

var

  I: Integer;

begin

  Result := 0.0;

  for I := 0 to High(A) do

    Result := Result + A[I]*B[I];

end;

const

  C: array[1..3] of Double = (1,2,3);

begin

  Writeln( DotProduct(C,C) );

end.


「Text after final 'END.' - ignored by compiler」警告メッセージ
「Text after final 'END.' - ignored by compiler」

例	コンパイルエラーメッセージ

説明

この警告はプログラムの論理上の終わりを構成する最後の end とピリオドの後に，まだソーステキストがある場合に表示されます。begin..end のネストが矛盾している (どこかに余分な end がある) と思われます。そのソーステキストをコンパイラに無視させる意図であったかどうかを調べてください。実際にはそのテキストが非常に重要かもしれません。


例

program Produce;

{$WARNINGS ON}

begin

end.

ここにテキストがあると 16 ビットの Delphi では無視され，32 ビットの Delphi および C++Builder では警告が表示される

//-------------------------------

program Solve;

begin

end.

{ end. の後でもコメントアウトしてあれば警告は表示されない }


「Constant expression expected」エラーメッセージ
「Constant expression expected」

例	コンパイルエラーメッセージ

説明

コンパイラはここで定数式を期待しましたが，見つかった式は定数式ではありませんでした。


例

{ Pos の呼び出しはその引数が定数であってもコンパイラに対する定数式ではなく，原則的にはコンパイル時に評価される }

program Produce;

const

  Message = 'Hello World!';

  WPosition = Pos('W', Message);

begin

end.

{ したがってこの例では，WPosition の正しい値を開発者自身が計算しなければならない }

program Solve;

const

  Message = 'Hello World!';

  WPosition = 7;

begin

end.


「Constant expression violates subrange bounds」エラーメッセージ
「Constant expression violates subrange bounds」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，定数が範囲外であるとコンパイラが判断できた場合に表示されます。たとえば，部分範囲型の変数へ範囲外の定数を代入した場合などです。


例

program Produce;

var

  Digit: 1..9;

begin

  Digit := 0;	{ 「範囲外の定数式です」のメッセージが表示される }

end.

program Solve;

var

  Digit: 0..9;

begin

  Digit := 0;

end.


「Duplicate tag value」エラーメッセージ
「Duplicate tag value」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはバリアントレコードの宣言の中で定数を 2 つ以上使ったときに表示されます。


例

program Produce;

type

  VariantRecord = record

    case Integer of

    0: (IntField: Integer);

    0: (RealField: Real); { <-- ここでエラーメッセージ }

  end;

begin

end.

program Solve;

type

  VariantRecord = record

    case Integer of

    0: (IntField: Integer);

    1: (RealField: Real);

  end;

begin

end.


「Sets may have at most 256 elements」エラーメッセージ
「Sets may have at most 256 elements」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは要素の数が 256 個を超える集合型を宣言しようとしたときに表示されます。正確に言えば，基本型の上限と下限の順序値は 0～255 の範囲でなければなりません。


例

{ 次のコードでは BigSet に実際には 256 個の要素しかないが，それでも違法である }

program Produce;

type

  BigSet = set of 1..256; { <-- ここでエラーメッセージが表示される }

begin

end.

{ 上限と下限が 0～255 の範囲になるようにする必要がある }

program Solve;

type

  BigSet = set of 0..255;

begin

end.


「<Token1> expected but <token2> found」エラーメッセージ
「<Token1> expected but <token2> found」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは構文エラーで表示されます。ソース内にスペルの誤りがあるか，何かが欠けています。行頭でエラーが起きているときは，前の行に実際のエラーがある場合が少なくありません。


例

{ コンパイラは整数型の後に変数宣言を終了するセミコロンを探す。しかし，この行にはセミコロンがないので，次の行頭まで読み進んで begin キーワードを見つける。この時点でコンパイラはエラーであると判断する }

program Produce;

var

  I: Integer

begin               { <-- ここでエラーメッセージ「';' の代わりに 'BEGIN' があります」が表示される }

end.

{ 一般に何かの欠落やスペルの誤りを見つけるには，エラーメッセージが表示された行とその上の行を詳しく調べる必要がある }

program Solve;

var

  I: Integer; { セミコロンが欠けていた }

begin

end.


「Identifier redeclared: '<name>`」エラーメッセージ
「Identifier redeclared: '<name>'」

例	コンパイルエラーメッセージ

説明

メッセージに表示された識別子はこのスコープ内ですでに宣言済みです。その識別子の名前を別の何かに再使用しようとしました。


例

{ ここではプログラム名が変数名と同じである。どちらかを変更する必要がある }

program Tests;

var

  Tests: Integer;

begin

end.

program Tests;

var

  TestCnt: Integer;

begin

end.


「Duplicate case label」エラーメッセージ
「Duplicate case label」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，case 文の中に 1 つの値に対して複数の case ラベルがあるときに表示されます。


例

{ ここでは不注意から case ラベル 0 を 2 回指定した }

program Produce;

function DigitCount(I: Integer): Integer;

begin

  case Abs(I) of

  0:                    DigitCount := 1;

  0        ..9:         DigitCount := 1; { <-- ここでエラーメッセージ }

  10       ..99:        DigitCount := 2;

  100      ..999:       DigitCount := 3;

  1000     ..9999:      DigitCount := 4;

  10000    ..99999:     DigitCount := 5;

  100000   ..999999:    DigitCount := 6;

  1000000  ..9999999:   DigitCount := 7;

  10000000 ..99999999:  DigitCount := 8;

  100000000..999999999: DigitCount := 9;

  else                  DigitCount := 10;

  end;

end;

begin

  Writeln( DigitCount(12345) );

end.

{ 一般に，case ラベルの定数と範囲にシンボルを使っていると，問題の箇所をつきとめるのはこれほど簡単ではない。エラーを見つけるには定数の実値をメモして調べなければならない場合もある }

program Solve;

function DigitCount(I: Integer): Integer;

begin

  case Abs(I) of

  0        ..9:         DigitCount := 1;

  10       ..99:        DigitCount := 2;

  100      ..999:       DigitCount := 3;

  1000     ..9999:      DigitCount := 4;

  10000    ..99999:     DigitCount := 5;

  100000   ..999999:    DigitCount := 6;

  1000000  ..9999999:   DigitCount := 7;

  10000000 ..99999999:  DigitCount := 8;

  100000000..999999999: DigitCount := 9;

  else                  DigitCount := 10;

  end;

end;

begin

  Writeln( DigitCount(12345) );

end.


「Label expected」エラーメッセージ
「Label expected」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，goto 文の中で指定した識別子またはインラインアセンブラの中でラベルとして使った識別子がラベルとして宣言されていない場合に表示されます。


例

program Produce;

begin

  if 2*2 <> 4 then

    goto Exit; { <-- ここでエラーメッセージ。「ラベルが必要です」が表示される }

  { ... }

Exit: { ここでもさらにエラーメッセージ }

end.

program Solve;

label

  Exit; { Pascal でラベルを宣言しなければならない }

begin

  if 2*2 <> 4 then

    goto Exit;

  { ... }

Exit:

end.


「For loop control variable must be simple local variable」エラーメッセージ
「For loop control variable must be simple local variable」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，for 文の制御変数が単純変数でない (たとえば，レコードのコンポーネントになっている) か，for 文が入っている手続きのローカル変数でない場合に表示されます。下位互換性のために，グローバル変数を制御変数として使うこともできますがコンパイラは警告を表示します。ローカル変数を使った方が効率的なコードを生成できる点に注意してください。


例

program Produce;

{$WARNINGS ON}

var

  I: Integer;

  A: array[0..9] of Integer;

procedure Init;

begin

  for I := Low(A) to High(a) do  { <-- ここで警告が表示される }

    A[I] := 0;

end;

begin

  Init;

end.

program Solve;

var

  A: array[0..9] of Integer;

procedure Init;

var

  I: Integer;

begin

  for I := Low(A) to High(a) do

    A[I] := 0;

end;

begin

  Init;

end.


「For loop control variable must have ordinal type」エラーメッセージ
「For loop control variable must have ordinal type」

例	コンパイルエラーメッセージ

説明

for ループの制御変数は論理型，Char 型，ワイド文字型，整数型，列挙型，部分範囲型のいずれかでなければなりません。


例

{ 次のコードはループの制御変数に Real 型の変数を使おうとしてエラーになる }

program Produce;

var

  X: Real;

begin { 正弦波を描く }

  for X := 0 to 2*Pi/0.2 do                            { <-- ここでエラーメッセージ }

    Writeln( '*': Round((Sin(X*0.2) + 1)*20) + 1 );

end.

{ ここでは Integer 型を指定するとエラーはなくなる }

program Solve;

var

  X: Integer;

begin { 正弦波を描く }

  for X := 0 to Round(2*Pi/0.2) do

    Writeln( '*': Round((Sin(X*0.2) + 1)*20) + 1 );

end.


「Types of actual and formal var parameters must be identical」エラーメッセージ
「Types of actual and formal var parameters must be identical」

例	コンパイルエラーメッセージ

説明

変数パラメータの実際の引数は仮パラメータと正確に同じ型でなければなりません。


例

{ 引数 C1 と C2 は メモリ上の表現と範囲が Byte と同じだが SwapBytes には使えない }

program Produce;

procedure SwapBytes(var B1, B2: Byte);

var

  Temp: Byte;

begin

  Temp := B1; B1 := B2; B2 := Temp;

end;

var

  C1, C2: 0..255; { Byte 型ではない }

begin

  SwapBytes(C1,C2); { <-- ここでエラーメッセージ }

end.

{ このコードをコンパイルするには C1 と C2 を実際に Byte として宣言しなければならない }

program Solve;

procedure SwapBytes(var B1, B2: Byte);

var

  Temp: Byte;

begin

  Temp := B1; B1 := B2; B2 := Temp;

end;

var

  C1, C2: Byte;

begin

  SwapBytes(C1,C2);

end.


「Too many actual parameters」エラーメッセージ
「Too many actual parameters」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，手続きまたは関数の呼び出しで手続き宣言または関数宣言に指定したより多いパラメータを指定したときに表示されます。

OLE オートメーション呼び出しでパラメータが多すぎる (255 を超える) 場合や名前付きパラメータが多すぎる場合にも，このエラーメッセージが表示されます。


例

{ Max が 3 つのパラメータを受け入れるようにしておけばよかったが... }

program Produce;

function Max(A,B: Integer): Integer;

begin

  if A > B then Max := A else Max := B

end;

begin

  Writeln( Max(1,2,3) ); { <-- ここでエラーメッセージ }

end.

{ 通常は正しい数のパラメータが供給されるような呼び出しに変更する。しかし，ここでは Max に無制限の数の引数を実装する方法を示す。Max をやや異なる方法で呼び出さなければならない点に注意する必要がある }

program Solve;

function Max(const A: array of Integer): Integer;

var

  I: Integer;

begin

  Result := Low(Integer);

  for I := 0 to High(A) do

    if Result < A[I] then

      Result := A[I];

end;

begin

  Writeln( Max([1,2,3]) );

end.


「Not enough actual parameters」エラーメッセージ
「Not enough actual parameters」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，手続きまたは関数の呼び出しで手続き宣言または関数宣言に指定したより少ないパラメータを指定したときに表示されます。このエラーは標準手続きや標準関数の呼び出しで起きる場合もあります。


例

{ 標準手続きの Val はエラーコードを返すためにパラメータを 1 つ余分にとる。次のコードではそのパラメータを指定していない }

program Produce;

var

  X: Real;

begin

  Val('3.141592', X);	{ <-- ここでエラーメッセージ }

end.

{ 通常，呼び出す手続きの宣言かヘルプと呼び出しを照合してチェックすると，必要なパラメータを指定し忘れたことがわかる }

program Solve;

var

  X: Real;

  Code: Integer;

begin

  Val('3.141592', X, Code);

end.


「Variable required」エラーメッセージ
「Variable required」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，式または定数のアドレスを使おうとしたときに表示されます。


例

{ 1 のような定数にはメモリアドレスがないので，@ 演算子や Addr 標準関数を適用できない }

program Produce;

var

  I: Integer;

  PI: ^Integer;

begin

  PI := Addr(1);

end.

{ 変数のアドレスを使う必要がある }

program Solve;

var

  I: Integer;

  PI: ^Integer;

begin

  PI := Addr(I);

end.


「Declaration of <name> differs from previous declaration」エラーメッセージ
「Declaration of <name> differs from previous declaration」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，手続き，関数，メソッド，コンストラクタ，デストラクタのいずれかの宣言が前の (forward) 宣言と異なっているときに表示されます。

仮想メソッドをオーバーライドしようとしたときに，オーバーライドするメソッドのパラメータリストや呼び出し規約などが異なっている場合にも，このエラーメッセージが表示されます。


例

{ 次に示すように，このエラーメッセージが発行される原因はいくつもある }

program Produce;

type

  MyClass = class

    procedure Proc(Inx: Integer);

    function Func: Integer;

    procedure Load(const Name: string);

    procedure Perform(Flag: Boolean);

    constructor Create;

    destructor Destroy(Msg: string); override; { <-- ここでエラーメッセージ }

    class function NewInstance: MyClass; override; { <-- ここでエラーメッセージ }

  end;

procedure MyClass.Proc(Index: Integer); { <-- ここでエラーメッセージ }

begin

end;

function MyClass.Func: Longint; { <-- ここでエラーメッセージ }

begin

end;

procedure MyClass.Load(Name: string); { <-- ここでエラーメッセージ }

begin

end;

procedure MyClass.Perform(Flag: Boolean); cdecl; { <-- ここでエラーメッセージ }

begin

end;

procedure MyClass.Create; { <-- ここでエラーメッセージ }

begin

end;

function MyClass.NewInstance: MyClass; { <-- ここでエラーメッセージ }

begin

end;

begin

end.

{ 「前の宣言」とエラーを起こした宣言を注意深く比較して 2 つの相違点を判別する必要がある }

program Solve;

type

  MyClass = class

    procedure Proc(Inx: Integer);

    function Func: Integer;

    procedure Load(const Name: string);

    procedure Perform(Flag: Boolean);

    constructor Create;

    destructor Destroy; override; { パラメータがない }

    class function NewInstance: TObject; override; { 結果の型 }

  end;

procedure MyClass.Proc(Inx: Integer); { パラメータ名 }

begin

end;

function MyClass.Func: Integer; { 結果の型 }

begin

end;

procedure MyClass.Load(const Name: string); { パラメータの種類 }

begin

end;

procedure MyClass.Perform(Flag: Boolean); { 呼び出し規約 }

begin

end;

constructor MyClass.Create; { コンストラクタ }

begin

end;

destructor MyClass.Destroy;

begin

end;

class function MyClass.NewInstance: TObject; { クラス関数 }

begin

end;

begin

end.


「Illegal character in input file: '<Char>' (<Hexadecimal value>)」エラーメッセージ
「Illegal character in input file: '<Char>' (<Hexadecimal value>)」

例	コンパイルエラーメッセージ

説明

コンパイラが Pascal プログラム内では違法となる文字を見つけました。このエラーメッセージが表示される原因のほとんどは文字列定数またはコメントでのエラーです。


例

{ ここではプログラマが C++ の習慣で文字列を二重引用符で囲んだ }

program Produce;

begin

  Writeln("Hello world!");	{ <-- ここでエラーメッセージ }

end.

{ 単引用符を使えば解決する。一般に，違法な文字を削除する必要がある }

program Solve;

begin

  Writeln('Hello world!');	{ Pascal では単引用符が必要 }

end.


「'<name>' is not a type identifier」エラーメッセージ
「'<name>' is not a type identifier」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，型の名前を指定するべき場所で型を表していない名前を検出したときに表示されます。


例

{ 次のコードは型名でなく変数名を引数の型として誤って使っている }

program Produce;

type

  TMyClass = class

    Field: Integer;

  end;

var

  MyClass: TMyClass;

procedure Proc(C: MyClass);	{ <-- ここでエラーメッセージ }

begin

end;

begin

end.

{ エラーを起こした識別子が本当に型であるかどうか確認する。スペルが間違っていたか，参照したい識別子が同名の識別子によって隠されている可能性がある }

program Solve;

type

  TMyClass = class

    Field: Integer;

  end;

var

  MyClass: TMyClass;

procedure Proc(C: TMyClass);

begin

end;

begin

end.


「File not found: <Filename>」エラーメッセージ
「File not found: <Filename>」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはコンパイラが入力ファイルを見つけられないときに表示されます。その入力ファイルはソースファイル，コンパイル済みのユニットファイル (.dcu ファイル)，インクルードファイル，オブジェクトファイル，リソースファイルのいずれかです。名前と関連の検索パスのスペルをチェックしてください。


例

program Produce;

uses SysUtis; { <-- ここでエラーメッセージ }

begin

end.

program Solve;

uses SysUtils; { スペルを修正した }

begin

end.


「Could not create output file <Filename>」エラーメッセージ
「Could not create output file <Filename>」

コンパイルエラーメッセージ

説明

コンパイラが出力ファイルを作成できませんでした。その出力ファイルはコンパイル済みのユニットファイル (.dcu ファイル)，実行可能ファイル，マップファイル，オブジェクトファイルのいずれかです。もっとも考えられる原因はディレクトリが存在しないかファイルまたはディスクが書き込み禁止です。


「Seek error on <Filename>」エラーメッセージ
「Seek error on <Filename>」

コンパイルエラーメッセージ

説明

コンパイラが入力ファイルまたは出力ファイルでシークエラーを検出しました。このエラーが起きるとは考えられませんが，万一起きた場合，もっとも考えられる原因はデータの破損です。


「Read error on <Filename>」エラーメッセージ
「Read error on <Filename>」

コンパイルエラーメッセージ

説明

コンパイラが入力ファイルで読み出しエラーを検出しました。このエラーが起きるとは考えられませんが，万一起きた場合，もっとも考えられる原因はデータの破損です。


「Write error on <Filename>」エラーメッセージ
「Write error on <Filename>」

コンパイルエラーメッセージ

説明

コンパイラが出力ファイルへ書き込み中に書き込みエラーを検出しました。ほとんどの場合，出力先のディスクに空きがないのが原因です。


「Close error on <Filename>」エラーメッセージ
「Close error on <Filename>」

コンパイルエラーメッセージ

説明

コンパイラが入力ファイルまたは出力ファイルを閉じる際にエラーを検出しました。このエラーはめったに起きませんが，起きた場合，もっとも考えられる原因はディスクに空きがないかディスクの不良です。


「Bad file format: <Filename>」エラーメッセージ
「Bad file format: <Filename>」

コンパイルエラーメッセージ

説明

このエラーは $L 指令または $LINK 指令でロードしたオブジェクトファイルが正しい形式でない場合に発生します。

以下の制限事項を満たさなければなりません。

ヘルプファイル内のセグメント名について名前の制限を確認する

セグメントを 10 個以下にする

外部シンボルを 255 個以下にする

LNAMES レコード内のローカル名を 50 個以下にする

LEDATA レコードと LIDATA レコードをオフセット順にしなければならない

THREAD サブレコードは FIXU32 レコード内ではサポートされない

32 ビットのオフセットだけを修正できる

セグメント修正と自己相対修正だけが可能

修正のターゲットはセグメント，グループ，EXTDEF のいずれかでなければならない

オブジェクトは 32 ビットのオブジェクトファイルでなければならない

各種の内部一貫性条件はオブジェクトファイルが壊れた場合にしか障害を生じない


「Out of memory」エラーメッセージ
「Out of memory」

コンパイルエラーメッセージ

説明

コンパイラがメモリ不足になりました。このエラーはほとんど起きません。起きた場合は，スワップファイルが十分な大きさであるかどうか，ディスク上に空きがあるかどうかを確認してください。


「Circular unit reference to <Unitname>」エラーメッセージ
「Circular unit reference to <Unitname>」

例	コンパイルエラーメッセージ

説明

1 つまたは複数のユニットがインターフェース部で互いに使い合っています。コンパイラがユニットのインターフェース部を変換した後でなければ，そのユニットを別のユニットから使えないので，コンパイラは各ユニットのインターフェース部のコンパイル順序を検出できなければなりません。uses 節の中にあるすべてのユニットが本当に必要かどうかと，実現部へ移動できるユニットがないかどうかを調べてください。


例

{ A と B がインターフェース部でそれぞれを使っているので問題が起きる }

unit A;

interface

uses B; { A は B を使い，B は A を使う }

implementation

end.

unit B;

interface

uses A;

implementation

end.

{ この循環は一方または両方を実現部へ移動すれば切れる }

unit A;

interface

uses B; { コンパイル順序は B.interface，A，B.implementation }

implementation

end.

unit B;

interface

implementation

uses A; { 実現部へ移動した }

end.


「Bad unit format: <Filename>」エラーメッセージ
「Bad unit format: <Filename>」

コンパイルエラーメッセージ

説明

このエラーはコンパイル済みのユニットファイル (.dcu ファイル) の形式が正しくない場合に表示されます。ほとんどの場合，.dcu ファイルが壊れているのが原因です。ファイルを再コンパイルするか C++Builder をインストールし直してください。


「PACKED not allowed here」エラーメッセージ
「PACKED not allowed here」

例	コンパイルエラーメッセージ

説明

packed キーワードは集合型，配列型，レコード型，オブジェクト型，クラス型，ファイル型だけに有効です。16 ビットバージョンの Delphi とは異なり，packed はレコード型，オブジェクト型，クラス型のレイアウトに影響を及ぼします。


例

{ packed は実数型には適用できない。記憶域を節約したい場合は，もっとも小さい実数型の Single 型を使う必要がある }

program Produce;

type

  SmallReal = packed Real;

begin

end.

program Solve;

type

  SmallReal = Single;

begin

end.


「Label declaration not allowed in interface part」エラーメッセージ
「Label declaration not allowed in interface part」

例	コンパイルエラーメッセージ

説明

このエラーはユニットのインターフェース部でラベルを宣言したときに起きます。


例

{ ユニットのインターフェース部でラベルを宣言するのは違法である }

unit Produce;

interface

label 99;

implementation

begin

99:

end.

{ ラベルを実現部へ移動しなければならない }

unit Solve;

interface

implementation

label 99;

begin

99:

end.


「Statements not allowed in interface part」エラーメッセージ
「Statements not allowed in interface part」

例	コンパイルエラーメッセージ

説明

ユニットのインターフェース部には文でなく宣言だけが入ります。手続きの本体を実現部へ移動してください。


例

{ うっかりして MyProc の本体をインターフェース部に置いた }

unit Produce;

interface

procedure MyProc;

begin                { <-- ここでエラーメッセージ }

end;

implementation

begin

end.

{ 本体を実現部へ移動すればうまく行く }

unit Solve;

interface

procedure MyProc;

implementation

procedure MyProc;

begin

end;

begin

end.


「Unit <Unit1> was compiled with a different version of <Unit2>」エラーメッセージ
「Unit <Unit1> was compiled with a different version of <Unit2>」

コンパイルエラーメッセージ

説明

このエラーはユニットのインターフェース部にあるシンボル宣言を変更した場合に，その宣言に依存するユニットのソースがその宣言を使えなくなって再コンパイルできないときに起きます。

複数の解決法が考えられます。Unit1 を再コンパイルする (ソースコードがあると想定した場合) か，Unit2 の古いバージョンを使うか，Unit2 を変更するか，Unit1 のソースコードを持っている人から新しいバージョンの Unit1 を入手してください。


「Unterminated string」エラーメッセージ
「Unterminated string」

例	コンパイルエラーメッセージ

説明

文字列の末尾に閉じる単引用符がありませんでした。

文字列は次の行へ継続できませんが，「+」演算子を使うと別々の行にある 2 つの文字列を連結できます。


例

{ 文字列に閉じる引用符を付け忘れた。よくあるエラーである }

program Produce;

begin

  Writeln('Hello world!); { <-- ここでエラーメッセージ }

end.

{ 閉じる引用符を指定して解決した }

program Solve;

begin

  Writeln('Hello world!');

end.


「Syntax error in real number」エラーメッセージ
「Syntax error in real number」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは数値の中に位取り因数の始め (E か e の文字) があって，その後に数字がない場合に表示されます。


例

{ 次のコードでは 3.0E の後にスペース文字を付けたため，コンパイラにとっては数値がそこで終了し，不完全な数値になる }

program Produce;

const

  SpeedOfLight = 3.0E 8; { <-- ここでエラーメッセージ }

begin

end.

{ 空白を削除しておくだけでもよかったが，+ 符号を挿入して見やすくした }

program Solve;

const

  SpeedOfLight = 3.0E+8;

begin

end.


「Procedure too long: exceeds 32K」エラーメッセージ
「Procedure too long: exceeds 32K」

コンパイルエラーメッセージ

説明

このエラーメッセージはインテルのプロセッサでは使われていません。


「Illegal type in Write/Writeln statement」エラーメッセージ
「Illegal type in Write/Writeln statement」

例	コンパイルエラーメッセージ

説明

このエラーは合法でない型を Write 文または Writeln 文に正しくない型の引数が渡されたときに起きます。


例

{ Color を直接 writeln 文の引数には指定できない }

program Produce;

type

  TColor = (red,green,blue);

var

  Color: TColor;

begin

  Writeln(Color);

end.

{ Color を出力するには，補助配列を使わなければならない }

program Solve;

type

  TColor = (red,green,blue);

var

  Color: TColor;

const

  ColorString: array[TColor] of string = ('red', 'green', 'blue');

begin

  Writeln(ColorString[Color]);

end.


「Illegal type in Read/Readln statement」エラーメッセージ
「Illegal type in Read/Readln statement」

例	コンパイルエラーメッセージ

説明

このエラーは型が正しくない変数を Read 文または Readln 文で読み出そうとしたときに起きます。変数の型をチェックし，逆参照，インデックス付け，フィールド選択のいずれかの演算子を欠かさないようにしてください。


例

{ 列挙型の変数は直接読み出せない }

program Produce;

type

  TColor = (red,green,blue);

var

  Color: TColor;

begin

  Readln(Color); { <-- ここでエラーメッセージ }

end.

{ 文字列を読み出し，その文字列を補助テーブル内で参照すれば解決する。次のコードではエラーチェックの手間を省いたので，すべての文字列は blue として扱われる。実際にはエラーメッセージを出力してユーザーにやり直しを求める場合が多い }

program Solve;

type

  TColor = (red,green,blue);

var

  Color: TColor;

  InputString: string;

const

  ColorString: array[TColor] of string = ('red', 'green', 'blue');

begin

  Readln(InputString);

  Color := red;

  while (color < blue) and (ColorString[color] <> InputString) do

    Inc(color);

end.


「Strings may have at most 255 elements」エラーメッセージ
「Strings may have at most 255 elements」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは，要素数が 255 を超える短い文字列型を宣言したとき，あるいは 1 つの文字列に 255 個を超える文字が入っているときに表示されます。

「+」演算子を使って複数の文字列リテラルを連結すれば，複数の行にまたがる長い文字列リテラルを作成できることに注意してください。


例

{ 次のコードでは，文字列の長さは限度を 1 文字超えただけである }

program Produce;

var

  LongString: string[256]; { <-- ここでエラーメッセージ }

begin

end.

{ 長い文字列型を使うのがもっとも便利な解決法である。そうすれば合理的な最大長を考えて時間を費やす必要もない }

program Solve;

var

  LongString: AnsiString;

begin

end.


「Unexpected end of file in comment started on line <Number>」エラーメッセージ
「Unexpected end of file in comment started on line <Number>」

例	コンパイルエラーメッセージ

説明

このエラーはコメントを開いて閉じなかった場合に表示されます。「{」で開始したコメントは「}」で，「(*」で開始したコメントは「*)」で必ず閉じなければなりません。


例

{ この例はコメントを閉じなかった }

program Produce;

{ ここでコメントを開始したが，閉じるのを忘れた

begin

end.

{ コメントを閉じれば問題は解決される }

program Solve;

{ ここでコメントを開始したが，忘れずに閉じた }

begin

end.


「Constant or type identifier expected」エラーメッセージ
「Constant or type identifier expected」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは型を期待していたコンパイラが定数でも型識別子でもないシンボルを検出したときに表示されます (定数は部分範囲型の始めに置かれる場合があります) 。


例

{ ここでは ExceptionClass は型でなく変数である }

program Produce;

var

  C: ExceptionClass; { ExceptionClass は System 内の変数である }

begin

end.

{ 必ず型を指定する必要がある。識別子のスペルが間違っているか，たとえば別のユニットの識別子などによって隠されている可能性がある }

program Solve;

uses SysUtils;

var

  C: Exception; { Exception は SysUtils 内の型である }

begin

end.


「Invalid compiler directive: '<Directive>`」エラーメッセージ
「Invalid compiler directive: '<Directive>'」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはコンパイラ指令かコマンドラインオプションにエラーがあることを意味しています。

以下のようなエラーが考えられます。

外部宣言の構文が正しくなかった

コマンドラインオプションまたは DCC32.CFG ファイル内のオプションがコンパイラによって認識されなかったか無効だった。たとえばスタックの最小サイズは 1024 以上でなければならないので，{$M 100} は無効である

コンパイラが $XXXXX 指令を検出したが，それを認識できなかった。スペルの誤りだったと思われる

コンパイラが $ELSE 指令または $ENDIF 指令を検出したが，前に $IFDEF，$IFNDEF，$IFOPT のいずれの指令もない

{$IFOPT} の後に switch オプションと「+」または「-」がなかった

長い形式のスイッチ指令の後に ON または OFF がなかった

数値パラメータをとる指令の後に有効な数値がなかった

$DESCRIPTION 指令の後に文字列がなかった

$APPTYPE 指令の後に CONSOLE または GUI がなかった

$ENUMSIZE 指令 (短い形式の $Z) の後に 1，2，4 のいずれもなかった


例

{ 次のコードは 3 つの典型的なエラーを示しており，最後の 2 つのエラーはコンパイラが $If を認識できなかったために起きた }

{$Description Copyright Borland International 1996}    { <-- ここでエラー }

program Produce;

{$ApType Console}                                      { <-- ここでエラー }

begin

{$If O+}                                               { <-- ここでエラー }

  Writeln('Optimizations are ON');

{$Else}                                                { <-- ここでエラー }

  Writeln('Optimizations are OFF');

{$Endif}                                               { <-- ここでエラー }

  Writeln('Hello world!');

end.

{ $Description には引用符で囲んだ文字列が必要であり，$AppType のスペルを正しく入力する必要があり，チェックオプションには $IfOpt を指定する。これらの変更を加えればコードは正しくコンパイルできる }

{$Description 'Copyright Borland International 1996'}  { 文字列が必要 }

program Solve;

{$AppType Console}                                     { AppType }

begin

{$IfOpt O+}                                            { IfOpt }

  Writeln('Optimizations are ON');

{$Else}                                                { これでよい }

  Writeln('Optimizations are OFF');

{$Endif}                                               { これでよい }

  Writeln('Hello world!');

end.


「Bad global symbol definition: '<name>' in object file '<Filename>`」エラーメッセージ
「Bad global symbol definition: '<name>' in object file '<Filename>'」

コンパイルエラーメッセージ

説明

この警告は $L 指令または $LINK 指令でリンクしたオブジェクトファイルに Pascal の external 手続きとして宣言されていない (たとえば，変数などとして宣言されている) シンボルの定義が入っているときに表示されます。この場合，オブジェクト内の定義は無視されます。


「Invalid relocation information」エラーメッセージ
「Invalid relocation information」

コンパイルエラーメッセージ

説明

このエラーメッセージは現在使われていません。


「Class or object types only allowed in type section」エラーメッセージ
「Class or object types only allowed in type section」

例	コンパイルエラーメッセージ

説明

クラス型またはオブジェクト型は常に type セクションで明示的に型宣言しなければなりません。レコード型と異なり，それらの型には名前が必要です。明示的な型宣言が必要な主な理由は，型名がないためにその型のメソッドを宣言できなくなるからです。


例

{ 次のコードは変数宣言の中でクラス型を宣言しようとしており，違法である }

program Produce;

var

  MyClass: class

    Field: Integer;

  end;

begin

end.

{ 単にそのクラス型の型宣言を導入すれば解決する。あるいは，クラス型をレコード型へ変更してもよい }

program Solve;

type

  TMyClass = class

    Field: Integer;

  end;

var

  MyClass: TMyClass;

begin

end.


「Local class or object types not allowed」エラーメッセージ
「Local class or object types not allowed」

例	コンパイルエラーメッセージ

説明

クラスとオブジェクトはローカルには宣言できません。


例

{ MyProc はクラス型をローカルに宣言しようとしており，違法である }

program Produce;

procedure MyProc;

type

  TMyClass = class

    Field: Integer;

  end;

begin

{ ... }

end;

begin

end.

{ 単にそのクラス型またはオブジェクト型の宣言をグローバルスコープへ移動すれば解決する }

program Solve;

type

  TMyClass = class

    Field: Integer;

  end;

procedure MyProc;

begin

{ ... }

end;

begin

end.


「Virtual constructors are not allowed」エラーメッセージ
「Virtual constructors are not allowed」

例	コンパイルエラーメッセージ

説明

クラス型と異なり，オブジェクト型は静的コンストラクタだけを持てます。


例

{ 次のコードはオブジェクト型では持てない仮想コンストラクタを宣言しようとしている }

program Produce;

type

  TMyObject = object

    constructor Init; virtual;

  end;

constructor TMyObject.Init;

begin

end;

begin

end.

{ コンストラクタを静的にするか，仮想コンストラクタを持てるクラス型を使えば解決する }

program Solve;

type

  TMyObject = object

    constructor Init;

  end;

constructor TMyObject.Init;

begin

end;

begin

end.


「Could not compile used unit '<Unitname>`」エラーメッセージ
「Could not compile used unit '<Unitname>'」

コンパイルエラーメッセージ

説明

この致命的エラーは別のユニットから使われているユニットがコンパイルできないときに起きます。その場合，結果的に非常に多くのエラーが起きると思われるので，コンパイラは従属ユニットのコンパイルを断念します。


「Left side cannot be assigned to」エラーメッセージ
「Left side cannot be assigned to」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは定数，定数パラメータ，関数の戻り値のような読み出し専用オブジェクトを変更しようとしたときに表示されます。


例

{ 次のコードは定数パラメータ，定数，関数呼び出しの結果へ代入を実行する。それらの操作はすべて違法である }

program Produce;

const

  C = 1;

procedure P(const S: string);

begin

  S := 'changed'; { <-- ここでエラーメッセージ }

end;

function F: PChar;

begin

  F := 'Hello'; { これはよい。戻り値を設定している }

end;

begin

  C := 2; { <-- ここでエラーメッセージ }

  F := 'h'; { <-- ここでエラーメッセージ }

end.

{ この種の問題の解決法は 2 つある。代入先の定義を代入可能に変更する方法と代入を削除する方法である }

program Solve;

var

  C: Integer = 1; { 初期化済み変数を使う }

procedure P(var S: string);

begin

  S := 'changed'; { 変数パラメータを使う }

end;

function F: PChar;

begin

  F := 'Hello'; { これはよい。戻り値を設定している }

end;

begin

  C := 2;

  F^ := 'h'; { これはコンパイルできるが実行時にクラッシュする }

end.


「Unsatisfied forward or external declaration: '<Procedurename>`」エラーメッセージ
「Unsatisfied forward or external declaration: '<Procedurename>'」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはクラス型やオブジェクト型の中に手続きや関数の forward 宣言または external 宣言があるか，メソッドの宣言があるにもかかわらず，その手続き，関数，メソッドがどこにも定義されていないときに表示されます。実際に定義が欠落しているか，定義名のスペルが間違っている可能性があります。

ユニットのインターフェース部での手続き宣言または関数宣言は forward 宣言と同じです。実現部に実現 (手続きまたは関数の本体) を与えなければなりません。同様に，クラス型またはオブジェクト型の中でのメソッド宣言も forward 宣言と同じです。


例

{ 次の Sum の定義では簡単にタイプミスが見つかるが，数千行に及ぶ実際のコードでは forward 宣言と手続き定義の区別がこのように明確でない場合がある }

program Produce;

type

  TMyClass = class

    constructor Create;

  end;

function Sum(const A: array of Double): Double; forward;

function Summ(const A: array of Double): Double;

var

  I: Integer;

begin

  Result := 0.0;

  for I:= 0 to High(A) do

    Result := Result + A[I];

end;

begin

end.

{ したがって，すべての手続き，関数，メソッドの定義が存在することを確認し，スペルを正しく入力する必要がある }

program Solve;

type

  TMyClass = class

    constructor Create;

  end;

constructor TMyClass.Create;

begin

end;

function Sum(const A: array of Double): Double; forward;

function Sum(const A: array of Double): Double;

var

  I: Integer;

begin

  Result := 0.0;

  for I:= 0 to High(A) do

    Result := Result + A[I];

end;

begin

end.


「Missing operator or semicolon」エラーメッセージ
「Missing operator or semicolon」

参照	例	コンパイルエラーメッセージ

説明

このエラーメッセージは 2 つの部分式の間に演算子がない場合か，2 つの文の間にセミコロンがない場合に表示されます。多くの場合，前の行でセミコロンが欠落しています。


例

{ 次のコードでは最初の文に「+」演算子とセミコロンの欠落という 2 つのエラーがある。最初のエラーはその文について報告され，2 番目のエラーは次の行について報告される }

program Produce;

var

  I: Integer;

begin

  I := 1 2                 { <-- ここでエラーメッセージ }

  if I = 3 then            { <-- ここでエラーメッセージ }

    Writeln('Fine')

end.

{ 必要な演算子とセミコロンを必ず付ければ解決する }

program Solve;

var

  I: Integer;

begin

  I := 1 + 2; { 「+」演算子とセミコロンがなかった }

  if I = 3 then

    Writeln('Fine')

end.


参照

複合文


「Incompatible types」エラーメッセージ
「Incompatible types」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはコンパイラが 2 つの型に要求された互換性が持てなかったときに表示されます。このエラーはさまざまな場合に発生します。たとえば，プロパティ内の read 節か write 節で指定したメソッドのパラメータリストがそのプロパティに適合しない場合や，標準手続きまたは標準関数へのパラメータの型が誤っている場合などです。


例

{ 標準関数 Hi には整数型またはワード型の引数が必要だが，ここでは配列型の引数を指定した }

program Produce;

var

  A: array[0..9] of Char;

  I: Integer;

begin

  I:= Hi(A);

end.

{ 本当は Hi でなく標準関数 High を使うつもりだった }

program Solve;

var

  A: array[0..9] of Char;

  I: Integer;

begin

  I:= High(A);

end.


「Missing parameter type」エラーメッセージ
「Missing parameter type」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはパラメータリストで値パラメータに型を指定しなかったときに表示されます。型を省略できるのは定数パラメータと変数パラメータです。


例

{ 手続き P に 2 つの整数パラメータを持たせようとしたが，第 1 パラメータの後にカンマではなくセミコロンを付けた。関数 ComputeHash は型のない第 1 パラメータを持つとみなされたが，型なしパラメータは変数パラメータか定数パラメータでなければならず，値パラメータであってはならない }

program Produce;

procedure P(I;J: Integer); { <-- ここでエラーメッセージ }

begin

end;

function ComputeHash(Buffer; Size: Integer): Integer; { <-- ここでエラーメッセージ }

begin

end;

begin

end.

{ この例では P のパラメータリストで型を修正し，ComputeHash への Buffer パラメータを定数パラメータとして宣言して解決した。Buffer パラメータを修正するつもりはないためである }

program Solve;

procedure P(I,J: Integer);

begin

end;

function ComputeHash(const Buffer; Size: Integer): Integer;

begin

end;

begin

end.


「Illegal reference to symbol '<name>' in object file '<Filename>`」エラーメッセージ
「Illegal reference to symbol '<name>' in object file '<Filename>'」

コンパイルエラーメッセージ

説明

このエラーメッセージは $L 指令または $LINK 指令でロードしたオブジェクトファイルに，手続き，関数，変数，型付き定数，スレッドローカル変数のいずれでもない Pascal シンボルへの参照が入っている場合に表示されます。


「Line too long (more than 255 characters)」エラーメッセージ
「Line too long (more than 255 characters)」

コンパイルエラーメッセージ

説明

このエラーメッセージはソースファイル内で 1 行の長さが 255 文字を超えているときに表示されます。通常，長い行は 2 つの短い行に分割できます。

長い文字列定数が本当に必要な場合には，その定数を連続した複数の行に分け，「+」演算子で連結できます。


「Unknown directive: '<Directive>`」エラーメッセージ
「Unknown directive: '<Directive>'」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは手続きまたは関数の宣言の中でコンパイラが未定義の指令を検出したときに表示されます。指令のスペルが間違っているか，セミコロンが欠落していると思われます。


例

{ P の宣言の中で呼び出し規約のスペルが間違っている。Q と GetLastError の宣言の中にセミコロンがない }

program Produce;

procedure P; stcall;

begin

end;

procedure Q forward;

function GetLastError: Integer external 'kernel32.dll';

begin

end.

{ 指令のスペルを正しく入力し，必要なセミコロンを必ず付ければ解決する }

program Solve;

procedure P; stdcall;

begin

end;

procedure Q; forward;

function GetLastError: Integer; external 'kernel32.dll';

procedure Q;

begin

end.

begin

end.


「This type cannot be initialized」エラーメッセージ
「This type cannot be initialized」

例	コンパイルエラーメッセージ

説明

ファイル型とバリアント型は初期化できません。つまり，それらの型の型付き定数や初期化済み変数は宣言できません。


例

{ 次のコードはバリアント型の初期化済み変数を宣言しようとしており，違法である }

program Produce;

var

  V: Variant = 0;

begin

end.

{ 単に通常の変数を代入文で初期化すれば解決する }

program Solve;

var

  V: Variant;

begin

  V := 0;

end.


「Number of elements differs from declaration」エラーメッセージ
「Number of elements differs from declaration」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは配列型の型付き定数または初期化済み変数を宣言して適切な数の要素を指定しなかったときに表示されます。


例

{ 次のコードは 10 個の要素からなる配列を宣言しているが，初期化で 9 個の要素しか与えていない }

program Produce;

var

  A: array[1..10] of Integer = (1,2,3,4,5,6,7,8,9);

begin

end.

{ 欠落していた要素を追加すればコンパイルできる。もっと大きな配列を初期化するときには，要素を正しい数だけ指定したかどうかがよくわからない場合がある。そのような場合には，要素を数えやすい方法で (たとえば 1 行に 10 個ずつ) ソースファイルをレイアウトするか，要素の隣に要素の添字をコメントとして付ければよい }

program Solve;

var

  A: array[1..10] of Integer = (1,2,3,4,5,6,7,8,9,10);

begin

end.


「Label already defined: '<Labelname>`」エラーメッセージ
「Label already defined: '<Labelname>'」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは複数の文に同じラベルを設定したときに表示されます。


例

{ 次のコードはラベル 1 を 2 回設定しようとしている }

program Produce;

label 1;

begin

1:

  goto 1;

1:	  { <-- ここでエラーメッセージ }

end.

{ すべてのラベルを正確に 1 回だけ設定する }

program Solve;

label 1;

begin

1:

  goto 1;

end.


「Label declared and referenced, but not set: '<label>`」エラーメッセージ
「Label declared and referenced, but not set: '<label>'」

例	コンパイルエラーメッセージ

説明

プログラムの中でラベルを宣言して使いましたが，ソースコード内でラベル定義が検出されませんでした。


例

{ ラベル 10 を手続き Labeled の中で宣言して使ったが，コンパイラがそのラベルの定義を検出できない }

program Produce;

procedure Labeled;

label 10;

begin

  goto 10;

end;

begin

end.

{ 宣言して使っているラベルの定義を必ずプログラムの同じスコープ内に置けば問題は簡単に解決する }

program Produce;

procedure Labeled;

label 10;

begin

  goto 10;

  10:

end;

begin

end.


「This form of method call only allowed in methods of derived types」エラーメッセージ
「This form of method call only allowed in methods of derived types」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは上位の型のメソッドを呼び出そうとしたときに，実際にはメソッドの中にいない場合に表示されます。


例

{ 次のコードは手続き Create の中で継承コンストラクタを呼び出そうとしているが，Create はメソッドではない }

program Produce;

type

  TMyClass = class

    constructor Create;

  end;

procedure Create;

begin

  inherited Create; { <-- ここでエラーメッセージ }

end;

begin

end.

{ この形式の呼び出しを使うときは必ず実際にメソッドの中にいるようにする }

program Solve;

type

  TMyClass = class

    constructor Create;

  end;

constructor TMyclass.Create;

begin

  inherited Create;

end;

begin

end.


「This form of method call only allowed for class methods」エラーメッセージ
「This form of method call only allowed for class methods」

例	コンパイルエラーメッセージ

説明

インスタンスでなくクラス型を指定するだけで通常のメソッドを呼び出そうとしました。それができるのはクラスメソッドとコンストラクタの場合だけで，通常のメソッドとデストラクタの場合はできません。


例

{ 次のコードは TMyClass 型そのものを廃棄しようとしている }

program Produce;

type

  TMyClass = class

    { ... }

  end;

var

  MyClass: TMyClass;

begin

  MyClass := TMyClass.Create; { これでよい。コンストラクタ }

  Writeln(TMyClass.ClassName); { これでよい。クラスメソッド }

  TMyClass.Destroy; { <-- ここでエラーメッセージ }

end.

{ 実際には型そのものでなく型のインスタンスを廃棄しなくてはならない }

program Solve;

type

  TMyClass = class

    { ... }

  end;

var

  MyClass: TMyClass;

begin

  MyClass := TMyClass.Create; { これでよい。コンストラクタ }

  Writeln(TMyClass.ClassName); { これでよい。クラスメソッド }

  MyClass.Destroy; { これでよい。インスタンスに対して呼び出される }

end.


「Incompatible types: <text>」エラーメッセージ
「Incompatible types: <text>」

参照	例	コンパイルエラーメッセージ

説明

手続きの宣言と使い方の間に違いがありました。


例

{ ProcedureParm0 型が stdcall 手続きを期待しているにもかかわらず，register 呼び出し規約を使って WrongConvention を宣言したため，TakesParm0 を呼び出すとエラーになる。同様に，TakesParm1 の呼び出しはパラメータリストの不一致によって失敗する }

program Produce;

type

  ProcedureParm0 = procedure; stdcall;

  ProcedureParm1 = procedure(var X: Integer);

procedure WrongConvention; register;

begin

end;

procedure WrongParms(x, y, z: Integer);

begin

end;

procedure TakesParm0(p: ProcedureParm0);

begin

end;

procedure TakesParm1(p: ProcedureParm1);

begin

end;

begin

  TakesParm0(WrongConvention);

  TakesParm1(WrongParms);

end.

{ この 2 つの問題は単に呼び出し規約またはパラメータリストを宣言に一致させればどちらも解決する }

program Solve;

type

  ProcedureParm0 = procedure; stdcall;

  ProcedureParm1 = procedure(var X: Integer);

procedure RightConvention; stdcall;

begin

end;

procedure RightParms(var X: Integer);

begin

end;

procedure TakesParm0(p: ProcedureParm0);

begin

end;

procedure TakesParm1(p: ProcedureParm1);

begin

end;

begin

  TakesParm0(RightConvention);

  TakesParm1(RightParms);

end.


参照

手続き型

呼び出し規約


「Variable '<name>' might not have been initialized」警告メッセージ
「Variable '<name>' might not have been initialized」

例	コンパイルエラーメッセージ

説明

この警告は値が代入されていない変数を使おうとした場合に表示されます。


例

{ if 文では両方の分岐で変数に値が代入されるようにしなければならない。case 文では考えられるすべての場合に必ず変数へ値が代入されるよう，else 部を追加する必要がある。try-except 構造の場合，try 部での代入は，その代入が try 部の冒頭にあって例外を生成すると思われないほど単純であっても，実際には代入が実行されない可能性があるとみなされる }

program Produce;

{$WARNINGS ON}

var

  B: Boolean;

  C: (Red,Green,Blue);

procedure Simple;

var

  I: Integer;

begin

  Writeln(I); { <-- ここで警告 }

end;

procedure IfStatement;

var

  I: Integer;

begin

  if B then

    I := 42;

  Writeln(I); { <-- ここで警告 }

end;

procedure CaseStatement;

var

  I: Integer;

begin

  case C of

    Red..Blue: I := 42;

  end;

  Writeln(I); { <-- ここで警告 }

end;

procedure TryStatement;

var

  I: Integer;

begin

  try

    I := 42;

  except

    Writeln('Should not get here!');

  end;

  Writeln(I); { <-- ここで警告 }

end;

begin

  B := False;

end.

{ 代入が欠落していたコードパスへ代入を追加するか，条件文や try-except 構造の前に代入を追加すれば解決する }

program Solve;

{$WARNINGS ON}

var

  B: Boolean;

  C: (Red,Green,Blue);

procedure Simple;

var

  I: Integer;

begin

  I := 42;

  Writeln(I);

end;

procedure IfStatement;

var

  I: Integer;

begin

  if B then

    I := 42

  else

    I := 0;

  Writeln(I); { else 部で I への代入が必要 }

end;

procedure CaseStatement;

var

  I: Integer;

begin

  case C of

    Red..Blue: I := 42;

  else       I := 0;

  end;

  Writeln(I); { else 部で I への代入が必要 }

end;

procedure TryStatement;

var

  I: Integer;

begin

  I := 0;

  try

    I := 42;

  except

    Writeln('Should not get here!');

  end;

  Writeln(I); { try の前で I への代入が必要 }

end;

begin

  B := False;

end.


「Value assigned to '<name>' never used」ヒントメッセージ
「Value assigned to '<name>' never used」

例	コンパイルエラーメッセージ

説明

コンパイラは変数へ代入した値が使われていない場合にこのヒントメッセージを表示します。最適化が使用可能に設定されている場合，その代入は削除されます。その変数をどこにも使っていなかったり使う前に再代入していると，このメッセージが表示される場合があります。

このヒントメッセージはプログラムの誤りを示しているのではなく，単に不必要な代入があるというコンパイラの判断を意味しています。通常はその代入を単に削除でき，削除しなくても最適化をオンにしてコンパイルするとコンパイル後のコードには組み込まれません。ただし，誤った変数へ代入した場合，たとえば J へ代入するつもりで I へ代入した場合などには問題が起きることがあります。したがって，問題のありそうな代入は注意深く調べる価値があります。


例

{ 手続き Propagate の中でコンパイラは変数 I が while ループの後で使われていないので，I を while 内でインクリメントする必要はないと認識し，したがってそのインクリメントと while ループの前の代入も不必要であると認識する。手続き TryFinally では try-finally 構造の前にある I への代入は必要ない。例外が発生した場合，最後の Writeln 文は実行されないので I の値は意味がない。例外が発生しなかった場合，Writeln 文で表示される I の値は常に 42 である。したがって最初の代入はこの手続きの動作を変更しないので削除できる }

program Produce;

{$HINTS ON}

procedure Simple;

var

  I: Integer;

begin

  I := 42; { <-- ここでヒントメッセージ }

end;

procedure Propagate;

var

  I: Integer;

  K: Integer;

begin

  I := 0; { <-- ここでヒントメッセージ }

  Inc(I); { <-- ここでヒントメッセージ }

  K := 42;

  while K > 0 do

  begin

    if Odd(K) then

      Inc(I); { <-- ここでヒントメッセージ }

    Dec(K);

  end;

end;

procedure TryFinally;

var

  I: Integer;

begin

  I := 0; { <-- ここでヒントメッセージ }

  try

    I := 42;

  finally

    Writeln('Reached finally');

  end;

  Writeln(I); { 常に 42 を出力する。例外が発生した場合はここへ到達しない }

end;

begin

end.


「Return value of function '<Functionname>' might be undefined」警告メッセージ
「Return value of function '<Functionname>' might be undefined」

例	コンパイルエラーメッセージ

説明

この警告は一部のコードパスで関数の戻り値へ値が代入されなかった場合に表示されます。言い換えれば，関数を実行しても戻り値へ何も値を代入されない可能性があります。


例

{ 手続き IfStatement と CaseStatement の問題点は一部のコードパスで結果へ値が代入されない点である。TryStatement では，コンパイラは Result へ値が代入される前に例外が発生する可能性があるとみなす }

program Produce;

{$WARNINGS ON}

var

  B: Boolean;

  C: (Red, Green, Blue);

function Simple: Integer;

begin

end; { <-- ここで警告 }

function IfStatement: Integer;

begin

  if B then

    Result := 42;

end; { <-- ここで警告 }

function CaseStatement: Integer;

begin

  case C of

    Red..Blue: Result := 42;

  end;

end; { <-- ここで警告 }

function TryStatement: Integer;

begin

  try

    Result := 42;

  except

    Writeln('Should not get here!');

  end;

end; { <-- ここで警告 }

begin

  B := False;

end.

{ 考えられるすべてのコードパスで結果の変数へ値が代入されるようにすれば解決する }

program Solve;

{$WARNINGS ON}

var

  B: Boolean;

  C: (Red, Green, Blue);

function Simple: Integer;

begin

  Result := 42;

end;

function IfStatement: Integer;

begin

  if B then

    Result := 42

  else

    Result := 0;

end;

function CaseStatement: Integer;

begin

  case C of

    Red..Blue: Result := 42;

  else Result := 0;

  end;

end;

function TryStatement: Integer;

begin

  Result := 0;

  try

    Result := 42;

  except

    Writeln('Should not get here!');

  end;

end;

begin

  B := False;

end.


「Procedure FAIL only allowed in constructor」エラーメッセージ
「Procedure FAIL only allowed in constructor」

コンパイルエラーメッセージ

説明

標準手続き Fail はコンストラクタの中からだけ呼び出せます。それ以外の呼び出しは違法です。


「Procedure NEW needs constructor」エラーメッセージ
「Procedure NEW needs constructor」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは New へのパラメータリストの中で指定した識別子がコンストラクタでないときに表示されます。


例

{ 不注意からコンストラクタでなくデストラクタを指定して New を呼び出した }

program Produce;

type

  PMyObject = ^TMyObject;

  TMyObject = object

    F: Integer;

    constructor Init;

    destructor Done;

  end;

constructor TMyObject.Init;

begin

  F := 42;

end;

destructor TMyObject.Done;

begin

end;

var

  P: PMyObject;

begin

  New(P, Done); { <-- ここでエラーメッセージ }

end.

{ New 標準関数には必ずコンストラクタを指定するか，追加引数をまったく指定しないようにする }

program Solve;

type

  PMyObject = ^TMyObject;

  TMyObject = object

    F: Integer;

    constructor Init;

    destructor Done;

  end;

constructor TMyObject.Init;

begin

  F := 42;

end;

destructor TMyObject.Done;

begin

end;

var

  P: PMyObject;

begin

  New(P, Init);

end.


「Procedure DISPOSE needs destructor」エラーメッセージ
「Procedure DISPOSE needs destructor」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは Dispose へのパラメータリストの中で指定した識別子がデストラクタでないときに表示されます。


例

{ 次のコードでは不注意から Dispose へコンストラクタを渡した }

program Produce;

type

  PMyObject = ^TMyObject;

  TMyObject = object

    F: Integer;

    constructor Init;

    destructor Done;

  end;

constructor TMyObject.Init;

begin

  F := 42;

end;

destructor TMyObject.Done;

begin

end;

var

  P: PMyObject;

begin

  New(P, Init);

  { ... }

  Dispose(P, Init); { <-- ここでエラーメッセージ }

end.

{ Dispose へデストラクタを渡すか，第 2 引数を削除すれば解決する }

program Solve;

type

  PMyObject = ^TMyObject;

  TMyObject = object

    F: Integer;

    constructor Init;

    destructor Done;

  end;

constructor TMyObject.Init;

begin

  F := 42;

end;

destructor TMyObject.Done;

begin

end;

var

  P: PMyObject;

begin

  New(P, Init);

  Dispose(P, Done);

end.


「Assignment to FOR-Loop variable '<name>`」エラーメッセージ
「Assignment to FOR-Loop variable '<name>'」

例	コンパイルエラーメッセージ

説明

for ループの内部で for ループの制御変数へ値を代入するのは違法です。予定より早くループを出るのが目的ならば，Break か goto 文を使ってください。


例

{ この例ではプログラマは I へ 99 を代入すればプログラムがループから出ると考えた }

program Produce;

var

  I: Integer;

  A: array[0..99] of Integer;

begin

  for I := 0 to 99 do

  begin

    if A[I] = 42 then

      I := 99;

  end;

end.

{ for ループを出るには break 文を使った方が問題が少ない }

program Solve;

var

  I: Integer;

  A: array[0..99] of Integer;

begin

  for I := 0 to 99 do

  begin

    if A[I] = 42 then

      Break;

  end;

end.


「FOR-Loop variable '<name>' may be undefined after loop」警告メッセージ
「FOR-Loop variable '<name>' may be undefined after loop」

例	コンパイルエラーメッセージ

説明

この警告は for ループの制御変数の値をループの後に使った場合に表示されます。for ループの制御変数の最終値を当てにしてもよいのは，goto 文か Exit 文でループを出た場合だけです。これはコンパイラが for ループに効率的なコードを生成できるようにするための制約事項です。


例

{ 次のコードではループの後で Result 変数が暗黙に使われているが，ループを完了した場合，Result は未定義となる。そのために警告が表示される }

program Produce;

{$WARNINGS ON}

function Search(const A: array of Integer; Value: Integer): Integer;

begin

  for Result := 0 to High(A) do

    if A[Result] = Value then

      Exit;

end;

const

  A: array[0..9] of Integer = (1,2,3,4,5,6,7,8,9,10);

begin

  Writeln( Search(A,11) );

end.

{ ループを完了した場合に備えて，意図する値を単に制御変数へ代入すれば解決する }

program Solve;

{$WARNINGS ON}

function Search(const A: array of Integer; Value: Integer): Integer;

begin

  for Result := 0 to High(A) do

    if A[Result] = Value then

      Exit;

  Result := High(A)+1;

end;

const

  A: array[0..9] of Integer = (1,2,3,4,5,6,7,8,9,10);

begin

  Writeln( Search(A,11) );

end.


「TYPEOF can only be applied to object types with a VMT」エラーメッセージ
「TYPEOF can only be applied to object types with a VMT」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは仮想メソッドテーブル (VMT) がないオブジェクト型へ標準関数 TypeOf を適用しようとした場合に表示されます。単純な回避方法としては，ダミーの仮想メソッドを宣言して強制的にコンパイラに VMT を生成させます。


例

{ 次のコードは仮想メソッドテーブル (VMT) を持たない TMyObject 型へ TypeOf 標準関数を適用しようとしている }

program Produce;

type

  TMyObject = object

    procedure MyProc;

  end;

procedure TMyObject.MyProc;

begin

  { ... }

end;

var

  P: Pointer;

begin

  P := TypeOf(TMyObject); { <-- ここでエラーメッセージ }

end.

{ 単にダミーの仮想メソッドを導入するか TypeOf の呼び出しを削除すれば解決する }

program Solve;

type

  TMyObject = object

    procedure MyProc;

    procedure Dummy; virtual;

  end;

procedure TMyObject.MyProc;

begin

  { ... }

end;

procedure TMyObject.Dummy;

begin

end;

var

  P: Pointer;

begin

  P := TypeOf(TMyObject);

end.


「Order of fields in record constant differs from declaration」エラーメッセージ
「Order of fields in record constant differs from declaration」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは型付き定数または初期化済み変数のレコードフィールドが宣言の順序で初期化されていない場合に表示されます。


例

{ 次のコードは宣言とは逆の Y，X の順で初期化しようとしている }

program Produce;

type

  TPoint = record

    X, Y: Integer;

  end;

var

  Point: TPoint = (Y: 123; X: 456);

begin

end.

{ 単に初期化の順序を宣言の順序に対応させれば解決する }

program Solve;

type

  TPoint = record

    X, Y: Integer;

  end;

var

  Point: TPoint = (X: 456; Y: 123);

begin

end.


「Incompatible types: '<name>' and '<name>`」エラーメッセージ
「Incompatible types: '<name>' and '<name>'」

例	コンパイルエラーメッセージ

説明

このエラーメッセージはコンパイラが 2 つの型を互換 (つまり類似している) として期待していたにもかかわらず，それらの型が異なっていたときに表示されます。


例

{ Pascal では除算演算子「/」で整数の結果が得られない }

program Produce;

procedure Proc(I: Integer);

begin

end;

begin

  Proc( 22 / 7 ); { 「/」演算子の結果は実数型になる }

end.

{ この例では整数除算演算子の div を使えば解決する。一般的にはプログラムを注意深く調べて型の非互換性を解決する方法を決める必要がある }

program Solve;

procedure Proc(I: Integer);

begin

end;

begin

  Proc( 22 div 7 ); { div 演算子で整数型の結果が得られる }

end.


「Internal error: <ErrorCode>」エラーメッセージ
「Internal error: <ErrorCode>」

コンパイルエラーメッセージ

説明

このエラーメッセージはコンパイラ内のプログラミングエラーを意味しており，表示される事態は考えられません。万一表示された場合はボーランドのテクニカルサポートに連絡のうえ，エラーメッセージに表示されたエラーコード (たとえば「C1196」など) を知らせてください。このエラーコードでエラーの原因がだいたいわかります。このメッセージが生成されたプログラムのサンプルをご提供いただければ原因究明にさらに役立ちます。


「Unit name mismatch: '<Unitname>`」エラーメッセージ
「Unit name mismatch: '<Unitname>'」

例	コンパイルエラーメッセージ

説明

ユニット識別子がユニットファイル名に一致しません。このエラーは長いファイル名と短いユニット識別子が混在しているときに起きる可能性があります。


例

{ この例ではファイル名が 8 文字で切り捨てられていたためにコンパイラが誤ったユニットを検出したのが問題である }

----- MY_UNIT_.PAS の内容 ---------------------------------------------

unit My_Unit_With_A_Long_Name;

interface

implementation

end.

----- MY_UNIT_.PAS の終わり --------------------------------------------------

program Produce;

uses My_Unit_With_Another_Long_Name; { -P コマンドラインスイッチがアクティブの場合に MY_UNIT_.PAS を検出するが，それは誤ったユニットである }

begin

end.

{ 長いファイル名を使うか最初の 8 文字が必ず異なるファイル名を使えば解決する。ユニットのファイル名とユニット名も必ず対応させる必要がある }


「No identifiers referenced from unit <unit>」エラーメッセージ
「No identifiers referenced from unit <unit>」

コンパイルエラーメッセージ

説明

このエラーメッセージは現在使われていません。


「Type '<name>' is not yet completely defined」エラーメッセージ
「Type '<name>' is not yet completely defined」

例	コンパイルエラーメッセージ

説明

このエラーは現在定義中の型を参照した場合か，forward 宣言したクラス型が type セクションに入っていてその型の終了宣言がない場合に発生します。


例

{ 次のコードは定義が完了していないレコード型を参照しようとしている。タイプミスがあるので，コンパイラは TMyClass の完全な宣言も検出できない }

program Produce;

type

  TListEntry = record

    Next: ^TListEntry; { <-- ここでエラーメッセージ }

    Data: Integer;

  end;

  TMyClass = class; { <-- ここでエラーメッセージ }

  TMyClassRef = class of TMyClass;

  TMyClasss = class                         { <-- タイプミス }

    { ... }

  end;

begin

end.

{ 最初の問題は補助的なポインタ型の型宣言を使えば解決する。2 番目の問題は TMyClass のスペルを正しく入力すれば修正される }

program Solve;

type

  PListEntry = ^TListEntry;

  TListEntry = record

    Next: PListEntry;

    Data: Integer;

  end;

  TMyClass = class;

  TMyClassRef = class of TMyClass;

  TMyClass = class

    { ... }

  end;

begin

end.


「This Demo Version has been patched」エラーメッセージ
「This Demo Version has been patched」

コンパイルエラーメッセージ

説明

このエラーメッセージは現在使われていません。


「Integer constant or variable name expected」エラーメッセージ
「Integer constant or variable name expected」

例	コンパイルエラーメッセージ

説明

このエラーメッセージは absolute 指令の後に整数定数や変数名を置いてはならないのに absolute 変数を宣言しようとした場合に表示されます。


例

program Produce;

var

  I: Integer;

  J: Integer absolute Addr(I); { <-- ここでエラーメッセージ }

begin

end.

program Solve;

const

  Addr = 0;

var

  I: Integer;

  J: Integer absolute I;

begin

end.


「Invalid typecast」エラーメッセージ
「Invalid typecast」

参照	例	コンパイルエラーメッセージ

説明

このエラーメッセージは規則で認められていない型キャストについて表示されます。

以下の種類の型キャストは認められています。

順序型またはポインタ型 → 別の順序型またはポインタ型

文字型，文字列型，文字または PChar の配列型 → 文字列型

順序型，実数型，文字列型，バリアント型 → バリアント型

バリアント型 → 順序型，実数型，文字列型，バリアント型

変数参照 → 同じサイズの任意の型

実数型から整数型へのキャストは標準関数の Trunc と Round で実行できます。そのほかにも Ord や Chr のような変換関数があります。


例

{ C のように浮動小数点定数は整数にキャストできない }

program Produce;

begin

  Writeln( Integer(Pi) );

end.

{ Pascal では浮動小数点値を整数に変換する関数を使用する }

program Solve;

begin

  Writeln( Trunc(Pi) );

end.


参照

型キャスト


「User break - compilation aborted」メッセージ
「User break - compilation aborted」

コンパイルエラーメッセージ

説明

このメッセージは現在使われていません。


「Assignment to typed constant '<name>`」警告メッセージ
「Assignment to typed constant '<name>'」

コンパイルエラーメッセージ

説明

この警告メッセージは現在使われていません。


「Segment/Offset pairs not supported in Borland 32-bit Pascal」エラーメッセージ
「Segment/Offset pairs not supported in Borland 32-bit Pascal」

例	コンパイルエラーメッセージ

説明

32 ビットコードでは 16 ビットコードで使っていたセグメント／オフセットのアドレス指定を使いません。16 ビットバージョンの Borland Pascal ではセグメントとオフセットの対が絶対変数の宣言に使われ，Ptr 標準関数への引数としても使われていました。

32 ビットのプロテクトモードプログラムでは絶対アドレスを使ってはいけません。そのかわりに適切な Win32 API 関数を呼び出してください。


例

program Produce;

var

  VideoMode: Integer absolute $0040:$0049;

begin

  Writeln( Byte(Ptr($0040,$0049)^) );

end.

program Solve;

{ コンパイルできるが実行できない。絶対アドレスは使えない }

var

  VideoMode: Integer absolute $0040*16+$0049;

begin

  Writeln( Byte(Ptr($0040*16+$0049)^) );

end.


実行時エラー

実行時エラーでは次の形式でエラーメッセージが表示され，プログラムが終了します。

Run-time error nnn at xxxxxxxx

nnn は実行時エラー番号，xxxxxxxx は実行時エラーアドレスです。

SysUtils ユニットを使った Delphi アプリケーションでは，ほとんどの実行時エラーが例外へ変換されるので，アプリケーションを終了させずにエラーを解決できます。これを例外処理といいます。

実行時エラーは以下の 3 つのカテゴリに分類できます。

入出力エラー (エラー番号 100～149 )

致命的エラー (エラー番号 200～255 )

オペレーティングシステムエラー

入出力エラー

入出力エラーが起きると，その文が {$I+} 状態でコンパイルされている場合はプログラムが終了します。{$I-} 状態ではプログラムの実行が続行され，IOResult 関数によってエラーが報告されます。

番号	エラー	説明

100	ディスク読み出しエラー	型付きファイルに対する Read でファイルの終わりを越えて読み出そうとした場合に表示される

101	ディスク書き込みエラー	CloseFile，Write，Writeln，Flush のいずれかでディスクがいっぱいになった場合に表示される

102	ファイルが割り当てられていません	Reset，Rewrite，Append，Rename，Erase のいずれかで AssignFile (または Assign) の呼び出しによってファイル変数へ名前が代入されていない場合に表示される

103	ファイルが開いていません	CloseFile，Read，Write，Seek，Eof，FilePos，FileSize，Flush，BlockRead，BlockWrite のいずれかでファイルが開いていない場合に表示される

104	ファイルが入力用に開いていません	テキストファイルに対する Read，Readln，Eof，Eoln，SeekEof，SeekEoln のいずれかでファイルが入力用に開いていない場合に表示される

105	ファイルが出力用に開いていません	テキストファイルに対する Write と Writeln で Console アプリケーションを生成しなかった場合に表示される

106	数値形式が無効です	Read または Readln でテキストファイルから読み出した数値が正しい数値形式でない場合に表示される

致命的エラー

致命的エラーが起きると，プログラムはすぐに終了します。

SysUtils ユニットを使ったアプリケーションでは，致命的エラーは例外へ変換されます。個々のエラーを生成するエラー条件についての詳細は，対応する例外の説明を参照してください。

番号	エラーメッセージ	例外

200	ゼロによる除算	EDivByZero

201	範囲検査エラー	ERangeError

202	スタックオーバーフロー	EStackOverflow

203	ヒープオーバーフローエラー	EOutOfMemory

204	無効なポインタ操作	EInvalidPointer

205	浮動小数点オーバーフロー	EOverflow

206	浮動小数点アンダーフロー	EUnderflow

207	無効な浮動小数点演算	EInvalidOp

215	算術演算オーバーフローエラー	EIntOverflow

216	アクセス違反	EAccessViolation

217	〔Ctrl〕+〔C〕	EControlC

218	特権命令	EPrivilege

219	無効な型キャスト	EInvalidCast

220	無効なバリアント型キャスト	EVariantError

221	無効なバリアント操作	EVariantError

222	バリアントメソッド呼び出し	EVariantError
ディスパッチャがありません

223	バリアント配列を作成できません	EVariantError

224	バリアントに配列が入っていません	EVariantError

225	バリアント配列境界エラー	EVariantError

226	TLS 初期化エラー

オペレーティングシステムエラー

入出力エラーと致命的エラー以外のすべてのエラーは，Win32 のエラー関数である GetLastError で返されるエラーコードによって報告されます。エラーコードの値はオペレーティングシステムによって異なりますが，Win32 のマニュアルでそれらの値の一覧を参照できます。