-
25-09-2019 - |
質問
はC ++ FAQライトから次の場合は真である:「関数名減衰関数へのポインタに」(配列名は、その最初の要素へのポインタに減衰されるように)。なぜ我々はアンパサンドを含める必要がありますか?
typedef int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = &Fred::f;
だけではなくます:
typedef int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = Fred::f;
第2のケースでフレッド:: fは関数であり、その関数へのポインタに減衰することができます。
私はこの質問は愚かなことではありません願っています。
解決
のオリジナルの答え:の
メンバ関数は、関数ではなく、メンバ関数ポインタは、関数ポインタではないからです。したがって、減衰のルールは適用されません。
また、C ++での関数の型ではなく、メンバー関数のタイプがあります。あなたは関数へのポインタが期待されている場所で関数を使用することができますが、そのようなもの、のみへのポインタメンバ関数がありませんので、あなたがメンバー関数を使用することはできませんので。あなたの例ではfが関数です。一方、フレッド:: fは...よく、何もない。
また、私は「関数の名前が崩壊することができます...」と主張します。いいえ、名前は何もできない、関数型の左辺値は、暗黙的に関数へのポインタに変換することができ、これははるかにオーバーロードの解決に関しては、
として恒等変換でありますがを私の答えを明確にするために編集:の
のC ++のすべての式は、型と値を持っています。一つのタイプの値は、時折、他の型の値に変換することができます。これらの変換は、一つの変換より良くするためになるようにランク付けされている主な機能のオーバーロードの解決のために別のもの。
コンバージョンの種類の一つは、左辺値対右辺値変換と呼ばれます。左辺値が右辺値は、この変換を必要とされているコンテキストに表示された場合に行われます。通常、この種の変換は、例えば、何もしません。
int i = 4, j = 5;
i = j;
二行目j上のは左辺値ですが、jは右辺値に変換されるように右辺値は、ここでは必要とされています。しかし、これは、観察の変換ではない、それはありますか?しかし、左辺値ツー右辺値の変換を観察することができる場合があります。 のはT Nのアレイの左辺値は型T*
値の右辺値に変換することができるされているその配列の最初のエレメントのアドレスである と < em>の値が関数のアドレスである「シグネチャSを持つ関数へのポインタ」型の右辺値「署名Sと機能」タイプの左辺値のの
私たちは関数へのポインタに機能を割り当てるとき、関数左辺値は暗黙のうちに、それのアドレスに変換されていることを意味します。
void f() {}
void (*p) () = f; //f is converted to rvalue
はfが式であり、タイプを有します。 Fのタイプはvoid()
のをmember-function
としてC ++には、このようなタイプは、ののはありません
メンバー関数ポインタ-はなく、メンバ関数自体があります。私は非静的関数について当然の話しています。静的な機能ではなく、あなたが&X::f
を書くことができ、あなたが書き込みX::f
に持っていない、つまり、通常の関数と同じように動作します
どうして? X :: fはタイプの機能を有しており、上述の変換が行われるため。 fは非静的である場合は、しかし、X :: fは型である...何?そうそう、それはタイプを持っていないので、式ではないため、値が何に変換できないことが値を持っていないんます。
引用:5.3.1節3 明示&が使用され、そのオペランドが修飾-ID括弧で囲まれていない場合メンバへのポインタのみが形成されています。 [注:「メンバーへのポインタを」暗黙の変換が存在しないため、修飾-idが括弧で囲まれている式&(修飾-ID)が、型の式を形成しないでもないが、修飾-IDを行いますタイプ「関数へのポインタ」の機能型の左辺値であるようなタイプ「のメンバ関数へのポインタ」(4.3)に非静的メンバ関数の修飾-IDから。 NORさえの範囲内で、修飾されていない-ID&メンバーへのポインタであります 修飾されていない-IDのクラス。
希望、これは明確だった...