C ++では、ときに、同じ名前の二つの変数は、同じスコープ内に見ることができますか?
-
12-09-2019 - |
質問
このコードは、私が悪い習慣として扱われ、再定義や変数をマスキングについて、コンパイラから警告を引き出すべきだと思う何かを示します:
#include <iostream>
int *a;
int* f()
{
int *a = new int;
return a;
}
int main()
{
std::cout << a << std::endl << f() << std::endl;
return 0;
}
その出力(Gでコンパイル++)
0
0x602010
私は、カップルの参照(Stroustrup氏との完全なC ++リファレンス)を見てきましたし、いつ、なぜこれが許可されているについては何も見つけることができません。でも、私はそれが単一のローカルスコープ内ではありませんことを知っています。
いつ、なぜこれが許可されていますか?この構造のための良好な使用はありますか?どのように私は、G ++はそれについて私に警告する得ることができますか?他のコンパイラはそれについて甲高い音ですか?
解決
これは許可されています。基本的に、あなただけが実際に使用してグローバル名を気にする必要があります。
とし、あなたの例では、f()
が最初に定義されていました。その後、いくつかの他の開発者がグローバル宣言を追加しました。名前、仕事に使用f()
を追加することで、まだ動作します。オーバーライドがエラーだった場合、この関数は、突然それが新しく追加されたグローバル変数とは全く何もしていなくても、作業を停止します。
他のヒント
これが許可されている理由として:これは完全に有効です。
。 あなたは、F()関数内にある場合は、は、ローカルスコープを定義しています。ローカルスコープはそう
あなたが「」変数「皮革」グローバルint *a;
を定義し、グローバルスコープを上書きします これは完全に有効ですが、私はあなたがパラメータをシャドウするとき-Wall
であなただけの警告を受けると思います。
あなたはをシャドー警告をしたい場合は任意のの変数の型は、あなたがこれを使用することができ、g++
マニュアルページから:
-Wshadow
Warn whenever a local variable shadows another local variable,
parameter or global variable or whenever a built-in function is
shadowed.
-Wshadow
は、デフォルトで-Wall
に含まれていないことに注意します。
言語の多くは、この種のものを許可する。
通常、(すべての言語に関連して)ほとんどのローカルに定義された変数は、あなたがあまりにも言及しているものです。 20+言語の私は、これは非常に一般的です使用しています。
また、ほとんどの言語は、明示的に外側のスコープのいずれかを参照することができます。
例えば、C ++は、::演算子でグローバルスコープで変数を指定することができalowsます。
#include <iostream>
int a = 5;
int main()
{
int a = 6;
std::cout << a << "\n" << ::a << "\n";
// Local
// global
}
これが許可されたときに答えるために:任意の2つの入れ子スコープで基本的に
たとえばます:
void foo() {
int a;
{
int a;
}
}
class Base {
int a;
};
class Derived: public Base {
int a; // Yes, the name Base::a is visible in the scope of Derived, even if private
};
class Foo() {
int a;
Foo(int a) : a(a) { } // Works OK
};
using std::swap;
void swap(MyClass& lhs, MyClass& rhs);
// Not strictly a variable, but name lookup in C++ happens before determining
// what the name means.
さて、答えは明らかに同じスコープ内で単一の名前を持つ2つの「もの」を有する一般的に許可されていることでなければなりません。名前の最大1つは実際にあるので、これは可能であるの定義されたのその範囲内。他の人は単にの表示のその範囲内だろう。名前解決のルールは、複数の候補がある場合、選択された名前を決定します。
あなたは本当に、コンパイラは選択肢の間で選ぶすべてのケースのために警告を与えたくありません。それはオーバーロードして、いくつかのスマートなテンプレートコードなどの罪のないものに、あなたにwarnignsのトンを提供します。
、これは完全に合法であり、コンパイラにあいまいでます。
しかし、それは混乱や見つけにくいバグを引き起こす可能性を秘めているプログラミング言語の多くの機能の一つです。それは明瞭にするために、これらの変数のそれぞれに異なる名前を付けるために些細なことですので、私はいつもそうすることをお勧めしたい。