クラスメンバー関数が同じ名前の空き機能をシャドウする理由
-
12-12-2019 - |
質問
最近私の注意にやって来たそのメンバー関数完全 shadow クラスの内側に同じ名前のフリー機能。そして完全に私は同じ名前のすべての空き関数がすべての過負荷解像度では考慮されないことを意味します。私はそれがこのようなもので行われている理由を理解することができます:
void f();
struct S
{
void f();
void g()
{
f(); // calls S::f instead of ::f
}
};
.
関数が同一の署名を持つ場合、可変スコープが同じように機能するのは自然です。しかし、なぜこのような署名が異なる署名が異なる不可能な通話を禁止する理由:
void f();
struct S
{
void f(int x);
void g()
{
f(); // fails to compile attempting to call S::f, which has wrong signature
}
};
.
shadowed free関数をクラスの内側から尋ねる方法を尋ねていません。私が知りたいことはこのデザインの背後にある根拠です。
解決
未修正名検索の場合、一度に1つのスコープだけが検討され、その範囲内の検索が結果を生じさせない場合は、次の高いスコープが検索されます。あなたの場合は、S
のスコープだけが検索されます。
しかし、なぜ無料の関数がこのような署名が異なるかどうかを禁止する理由:
問題は、名検索がその名前ではなく、識別子という名前では関係ありません。それはあなたが関数を呼びたいという事実を完全に忘れています、それはただ識別子を見るだけです。auto x = f;
を使用しているだけで、同じ名前の検索が発生し、そのように考えている場合は、非常に限られた範囲のみを検索するのが望ましい理由は非常に良い理由があります。他に何もユーザーを驚かせるだけです。
他のヒント
特別な、非常に驚くべきこと、規則がある(しかし、それはあなたの例には適用されません)クラスメンバ名が名前検索で見つかると、名前空間スコープは検索されません:
#include <string>
struct C {
std::string s;
explicit C (std::string);
void swap (C& rhs) {
swap (s, rhs.s); // error: swap is C::swap
}
};
void swap (C& lhs, C& rhs) {
swap (lhs.s, rhs.s); // std::swap(string,string)
}
.
imo、これは狂気です。
しかし、なぜ無料の関数がこのような署名が異なるかどうかを禁止する理由:
名前検索は解決方法を過負荷にする前に行われます。
- ルックアップがあいまいな場合は、過負荷解像度は行われません。
- 名前検索で実行可能な機能が見つからない場合は、他のラウンドのルックアップが試行されません。
ルールは、オーバーロードと名前検索の間の「フィードバック」なしで十分複素です。複雑化ではなく、単純化(メンバーを削除し、その名前空間スコープ名ルールを削除し、あいまいな名前のルックアップの削除など)を提案します。
私は権威のある回答を提供することはできません(たぶん何人かのDesign and Evolution of C++
からの引用を記憶するか、実際にはその時点で委員会に覚えています)が、あなたが示すように私の最初の推測は正確に失敗するでしょう。特定の時間に範囲内のもの数があることを忘れるのは簡単です。さらに、過負荷解像度は非常に複雑になる可能性があり、デフォルトの引数と変換があります。だから私はむしろほとんどの限られた範囲を持っているので、常に呼ばれているのは常に何を確信しているのか確実なものです。