前方宣言
プログラミングにおいて、前方宣言(ぜんぽうせんげん)とはプログラマが完全な定義を与えていない変数または関数の宣言のことである。
int elements[];
void foo(int);
C言語では、上の二つの行はそれぞれ 配列 と 一つの引数の関数 の前方宣言を表す (また後者は関数プロトタイプでもある)。コンパイラはこれらの宣言を処理した後、プログラマに残りの部分でelementsとfooの実体の使用を許可する。しかしいくつかの場合、プログラマは宣言した実体のための定義を提供しなければならないだろう:
int elements[10];
void foo(int x) { printf("%d\n", x); }
Pascalや他のヴィルトの言語では、前方宣言は使う前にすべての実体を宣言しなければならないという一般的規則である。C言語でも同じ一般的規則が適用されるが、未宣言の関数のための例外がある。その結果、C言語では(賢明ではないが)相互再帰の関数ペアを実行することが可能である:
int first(int x)
{
if (x == 0) return 1;
return second(x-1);
}
int second(int x)
{
if (x == 0) return 0;
return first(x-1);
}
Pascalで同様の実装をする場合、firstがsecondを呼び出す前にsecondの前方宣言が必要である。前方宣言がなければ、コンパイラは識別子 secondが宣言されないで使われたというエラーメッセージを表示するであろう。
前方参照[編集]
前方参照という用語は時々前方宣言の類義語として使われている。[1] しかしながらこの用語はその定義よりもむしろ、宣言する前に実体を実際に利用することを言及するのに使われている。この定義は上記のコードにおけるfirstのsecondへの参照が前方参照ということである。[2][3] したがって私達は、Pascalでは前方宣言が必須であるので、前方参照が禁止されていると言うであろう。
C++での(正しい)前方参照の例:
class C {
public:
void mutator(int x) { myValue = x; }
int accessor() const { return myValue; }
private:
int myValue;
};
例えば、myValueの宣言前にmyValueへの二つの参照があるとする。C++では一般的に前方参照を禁止しているが、上記コードはクラスメンバの例外として許されている。コンパイラは、メンバ変数 myValueの型を知らないとメンバ関数 accessorをコンパイルできないので、myValueの宣言を処理するまでaccessorの定義を覚えておく。
前方参照を可能にすると、コンパイラの複雑さやメモリの必要量が激しく増し、一般的にはコンパイラのワンパスでの実行を難しくする。