回答:
これにより、現在の名前空間から開始するのではなく、グローバル名前空間から解決が行われることが保証されます。たとえば、次のように2つの異なるクラスが呼び出さConfiguration
れた場合:
class Configuration; // class 1, in global namespace
namespace MyApp
{
class Configuration; // class 2, different from class 1
function blah()
{
// resolves to MyApp::Configuration, class 2
Configuration::doStuff(...)
// resolves to top-level Configuration, class 1
::Configuration::doStuff(...)
}
}
この場合、名前が別の名前空間内の新しい定義によって破壊される可能性があるため、基本的にはグローバル名前空間までトラバースできますMyApp
。
::Configuration::doStuff(...)
::
中間の2つの用語は、名前空間またはクラスとそのメンバーを指すと理解しています。しかし、最初のものはどうですか?
すでに多くの合理的な答えがあります。一部の読者に役立つ可能性のある類推を入れます。 実行したいプログラムのパスを検索するとき::
、ファイルシステムのディレクトリ区切り文字 ' /
'のように機能します。考慮してください:
/path/to/executable
これは非常に明示的です。有効なPATHに関係なく、ファイルシステムツリーのその正確な場所にある実行可能ファイルのみがこの仕様に一致できます。同様に...
::std::cout
... C ++名前空間の「ツリー」でも同様に明示的です。
そのような絶対パスと対照的な、あなたは良いUNIXシェル(例えば構成することができますzshのを解決するための)相対的な現在のディレクトリまたはあなたの内の任意の要素の下にパスがPATH
そうならば、環境変数PATH=/usr/bin:/usr/local/bin
、そしてあなたは「中」だった/tmp
、その後、...
X11/xterm
... /tmp/X11/xterm
見つかった場合、それ以外の場合、それ以外は正常に実行され/usr/bin/X11/xterm
ます/usr/local/bin/X11/xterm
。同様に、という名前空間にX
いて、「using namespace Y
」が有効だったとします。
std::cout
...のいずれかで見つけることができ::X::std::cout
、::std::cout
、::Y::std::cout
に起因して、そしておそらく他の場所引数依存のルックアップ(ADL、別名ケーニッヒのルックアップ)。つまり、::std::cout
どのオブジェクトを意味するのかがはっきりしているだけですが、幸いなことに、「std
」という名前の独自のクラス/構造体や名前空間を作成する人はいないcout
ので、実際には、「」だけを使用しても問題ありませんstd::cout
。
注目すべき違い:
1)シェルは、の順序を使用して最初の一致を使用する傾向がありPATH
ますが、C ++では、あいまいな場合にコンパイラエラーが発生します。
ほとんどのUNIXシェルだけで、あなたが入れた場合にそれを行う一方、2)C ++では、いずれかの主要なスコープのない名前は、現在の名前空間に一致させることができます.
でPATH
。
3)C ++は常にグローバル名前空間を検索します(/
暗黙的にyour を持っているようなものPATH
)。
絶対的な::abc::def::...
「パス」を使用すると、使用している他の名前空間から一部を分離するのに役立つ場合がありますが、ライブラリのクライアントコードが使用している一部のライブラリやコンテンツを制御することはできません。一方で、シンボルの既存の「絶対」位置とより密接に結合し、名前空間での暗黙的なマッチングの利点を見逃します。結合が少なく、名前空間間のコードの移動が容易で、より簡潔で読みやすいソースコードです。 。
多くのことと同様に、それはバランスをとる行為です。下のC ++標準プット識別子の多くをstd::
それはより少ない「ユニーク」ですcout
(例えばプログラマは自分のコードでは完全に別の何かのために使用する場合がありますことを、merge
、includes
、fill
、generate
、exchange
、queue
、toupper
、max
)。2つの無関係な非標準ライブラリは、作成者が一般に互いに気づいていないか、あまり気付いていないため、同じ識別子を使用する可能性がはるかに高くなります。そして、C ++標準ライブラリを含むライブラリは、時間の経過とともにシンボルを変更します。これはすべて、古いコードを再コンパイルするとき、特にusing namespace
s が頻繁に使用されているときにあいまいさを作成する可能性があります。このスペースで実行できる最悪のことは、using namespace
■ヘッダー内のヘッダーのスコープをエスケープします。これにより、直接または間接的な大量のクライアントコードが、使用する名前空間とあいまいさの管理方法について独自の決定を下すことができなくなります。
したがって、リーディング::
はC ++プログラマーのツールボックスの1つのツールであり、既知の衝突を明確に解消し、将来のあいまいさの可能性を排除します。
::
スコープ解決演算子です。何かのスコープを指定するために使用されます。
たとえば、::
他のすべての名前空間の外側にあるのは、単独でのグローバルスコープです。
some::thing
次のいずれかの方法で解釈できます。
some
ある名前空間(グローバルスコープに、または現在のものよりも外側の範囲)とthing
なるタイプ、関数、オブジェクト、またはネストされたネームスペース。some
あるクラス現在のスコープで利用可能でthing
あるメンバオブジェクト、関数またはタイプのsome
クラス。some
することができる基本型電流タイプ(又は電流タイプ自体)のとthing
、このクラスの一員であり、タイプ、機能又はオブジェクト。のように、スコープをネストすることもできsome::thing::bad
ます。ここで、各名前はタイプ、オブジェクト、またはネームスペースにすることができます。さらに、最後の1つbad
は関数にすることもできます。関数は内部スコープ内で何も公開できないため、他のユーザーはできませんでした。
したがって、例に戻ると::thing
、グローバルスコープ内の何か、タイプ、関数、オブジェクト、またはネームスペースのみにすることができます。
それを使用する方法は、それがグローバルスコープの型であることを示唆しています(ポインター宣言で使用されています)。
この回答が完全で正しいため、スコープの解決を理解するのに役立つことを願っています。
class some { protected: int thing; }; class some_ext : public some { float thing; void action(){ some::thing = 42; thing = 666; } };
ここでは、some
の基底クラスであるsome_ext
とあなたが書くときsome::thing
some_extのメンバ関数に、それは意味thing
の基本型にオブジェクトをsome
。なければsome::
、thing
単独の手段thing
最も近い範囲では、それがありますsome_ext::thing
。より明確ですか?
::
何か(変数、関数、クラス、typedefなど...)を名前空間またはクラスにリンクするために使用されます。
以前::
に左側がない場合は、グローバル名前空間を使用しているという事実が強調されます。
例えば:
::doMyGlobalFunction();
(OPは既に問題を解決しているので、この回答は主にグーグル向けです。)付加された意味::
-スコープ再解決演算子-は他の回答で説明されていますが、人々がそれを使用している理由を追加したいと思います。
意味は、「他のものではなく、グローバル名前空間から名前を取得する」です。しかし、なぜこれを明示的に綴る必要があるのでしょうか?
使用例-名前空間の衝突
グローバル名前空間とローカル/ネストされた名前空間に同じ名前がある場合、ローカルの名前空間が使用されます。したがって、グローバルなものが必要な場合は、先頭にを付け::
ます。このケースは@Wyatt Andersonの回答で説明されています。彼の例をご覧ください。
使用例-非メンバー機能を強調する
メンバー関数(メソッド)を記述しているとき、他のメンバー関数への呼び出しと非メンバー(無料)関数への呼び出しは似ています。
class A {
void DoSomething() {
m_counter=0;
...
Twist(data);
...
Bend(data);
...
if(m_counter>0) exit(0);
}
int m_couner;
...
}
しかし、それが起こるかもしれないTwist
クラスの姉妹メンバ関数でA
、かつBend
自由な機能です。つまり、Twist
使用して変更することができるm_couner
とBend
することはできません。したがって、それm_counter
が0のままであることを確認したい場合は、をチェックTwist
する必要がありますが、チェックする必要はありませんBend
。
したがって、これをより明確にするためthis->Twist
にTwist
、メンバー関数であるリーダーを示すために書き込むか、無料であること::Bend
を示すために書き込むことBend
ができます。または両方。これは、リファクタリングを実行または計画している場合に非常に役立ちます。
::
名前空間を定義する演算子です。
たとえばusing namespace std;
、コードで言及せずにcoutを使用したい場合は、次のように記述します。
std::cout << "test";
名前空間が言及されていない場合、クラスはグローバル名前空間に属していると言われます。
"::"はスコープ解決演算子を表します。同じ名前の関数/メソッドは、2つの異なるクラスで定義できます。特定のクラスのメソッドにアクセスするには、スコープ解決演算子を使用します。
::
はグローバル/匿名の名前空間から変数を参照することを意味します。