web-dev-qa-db-ja.com

関数宣言と署名の違いは何ですか?

CまたはC++では、関数宣言と関数シグネチャの違いは何ですか?

関数の宣言については知っていますが、関数のシグネチャはまったく新しいものです。関数シグネチャの概念を持つことのポイントは何ですか?実際に使用されている2つの概念は何ですか?

ありがとう!

40
Tim

関数宣言は、関数のプロトタイプです(または、その時点でコンパイラーによってプロトタイプが表示されていない場合は、関数定義から取得できます)-戻り値の型、関数の名前、パラメーターの型(オプションでC)。

関数シグネチャは、コンパイラがオーバーロード解決を実行するために使用する関数宣言の一部です。複数の関数が同じ名前を持っている可能性があるため(つまり、それらはオーバーロードされている)、コンパイラーは、関数呼び出しが解決すべき特定の名前を持ついくつかの可能な関数のどれを決定する方法を必要とします。シグネチャは、そのオーバーロードの解決においてコンパイラが考慮するものです。具体的には、この規格では「署名」を次のように定義しています。

オーバーロードの解決に関与する関数に関する情報:そのパラメーターのタイプ、および関数がクラスメンバーの場合は、関数自体のcv修飾子(メンバー関数が宣言されているクラスの場合)。

戻り値の型は関数シグネチャの一部ではないことに注意してください。標準が脚注で述べているように、「関数のシグネチャには戻り値の型は含まれていません。これはオーバーロードの解決に関与しないためです」。

43
Michael Burr

この規格では、宣言と定義という2つの用語が定義されています。定義は暫定的な宣言です。ただし、C99およびC++ 03標準の定義は少し異なります。

C++ 0xドラフトから:

付録C

8.3.5変更:C++では、空のパラメーターリストで宣言された関数は引数を取りません。 Cでは、空のパラメーターリストは、関数の引数の数と型が不明であることを意味します。 "

定義

1.3.11署名

関数の名前とparameter-type-list(8.3.5)、およびそれがメンバーとなっているクラス、概念、概念マップ、または名前空間。関数または関数テンプレートがクラスメンバーである場合、そのシグネチャには、関数または関数テンプレート自体のcv-qualifiers(存在する場合)およびref-qualifier(存在する場合)がさらに含まれます。制約付きメンバー(9.2)の署名には、そのテンプレート要件が含まれています。関数テンプレートのシグネチャには、戻り値の型、テンプレートパラメータリスト、およびテンプレート要件(存在する場合)がさらに含まれます。関数テンプレート特殊化のシグネチャには、それが特殊化されているテンプレートのシグネチャとそのテンプレート引数(明示的に指定されているか推測されているかに関係なく)が含まれています。 [注:署名は、名前のマングリングとリンクの基礎として使用されます。—エンドノート]

6
dirkgently

関数のシグネチャには、関数の戻り値の型またはリンケージ型は含まれません。

わかりました Wikipedia 含まれている戻り値の型について私と意見が異なります。ただし、関数呼び出しがシグニチャーと一致するかどうかを判別するときに、コンパイラーは戻り値の型を使用しないことを知っています。この前のStackOverflowの質問は同意するようです: 戻り値の型は関数のシグネチャの一部ですか?

3
Mark Ransom

標準によると、トップレベルのconstとvolatile on volatileは署名の一部ではないことにも注意してください。しかし、一部のコンパイラはこれを間違っています。

例えば.

void f(const int, const char* const);

と同じ署名があります

void f(int, const char*);
1
Ben Voigt