7

次の2つの関数は同じタイプとシグネチャを持っていることに注意してください。

void foo1(int t) {} // foo1 has type 'void(*)(int)', and signature '(*)(int)'
void foo2(const int t) {} // Also type 'void(*)(int)', signature '(*)(int)'

(これconstは関数型または関数シグネチャの一部ではありません)。同様に、戻り型の修飾子(constまたはvolatile)は、関数型または関数シグネチャに影響を与えません。

ただし、関数定義自体(図には示されていません)では、名前付き変数はの修飾をt維持します。constfoo2

関数の戻り型が関数シグネチャの一部と見なされない理由(過負荷の解決に使用される)について説明するStackOverflowの質問がたくさんあります。

constただし、引数修飾子(またはvolatile)が関数の型または署名の一部ではない理由を尋ねるStackOverflowの質問は見つかりません。また、C ++ 11標準ドキュメントを直接調べたところ、解明するのが難しいことがわかりました。

引数修飾子(つまり、constおよびvolatile)が関数の型または署名の一部ではないという事実の背後にある理論的根拠は何ですか?

補遺明確にするために、以下のR.MartinhoFernandesの回答から、C ++(私は思う)では引数修飾子トップレベルのconst修飾子でvolatileある場合にのみ関数の型/署名の一部として無視されることを明確にする必要があります-以下の回答を参照してください。

4

1 に答える 1

12

引数修飾子 (つまり、const と volatile) が関数の型またはシグネチャの一部ではないという事実の背後にある理論的根拠は何ですか?

void foo(int)発信者の観点からは、 と の間に違いはありませんvoid foo(int const)。修飾子に関係なく、渡されたものは変更されません。関数はコピーを取得します。

実装者の観点から見ると、唯一の違いは、では本体でvoid foo(int x)変更x(つまり、ローカル コピー) を実行できますが、 では変更できないことxですvoid foo(int const x)

C++ は、これら 2 つの観点を認識しています。呼び出し元の視点は、2 つの宣言void foo(int);を行いvoid foo(int const);、同じ関数を宣言することによって認識されます。実装者の視点は、関数を次のように宣言できるようにすることで認められますが、誤って引数に代入しないようにするかvoid foo(int x);のように定義できます。void foo(int const x) { /*...*/ }

これはトップレベルconstにのみ適用されることに注意してください。つまりconst、型全体に適用されます。int const&orのようなものint const*では、修飾子は「(const (int)) へのポインター」のように型の一部にのみ適用されるため、トップレベルではありませんconst。ただしint *constconst「const ((int) へのポインター)」のように型全体に適用されます。

于 2012-12-04T16:12:58.783 に答える