先頭に付けられた二重コロン「::」の意味は何ですか?


410

私は変更する必要があるクラスのコードのこの行を見つけました:

::Configuration * tmpCo = m_configurationDB;//pointer to current db

そして、クラス名の前に付けられた二重コロンが正確に何を意味するのかわかりません。それがなければ私は読むでしょう:tmpCoクラスのオブジェクトへのポインターとしての宣言Configuration...

私も見つけました:

typedef ::config::set ConfigSet;

7
答えだとは思わないで、コメントします:en.wikipedia.org/wiki/Scope_resolution_operator。このコンテキストでは、ネイキッド::はグローバル/匿名の名前空間から変数を参照することを意味します。
wkl 2010年

回答:


490

これにより、現在の名前空間から開始するのではなく、グローバル名前空間から解決が行われることが保証されます。たとえば、次のように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


2組のダブルコロンを配置する理由は何ですか?これには:::Configuration::doStuff(...)
Azurespot 2017年

@NoniA。ダブルコロンの2番目のセットが何をしているのですか?
FCo

1
@WyattAnderson、最初のセットはありません。::中間の2つの用語は、名前空間またはクラスとそのメンバーを指すと理解しています。しかし、最初のものはどうですか?
Azurespot 2017年

6
@AzurespotそれはOPが尋ねるものです、それはこの投稿が答える質問です。グローバル名前空間の識別子を使用するようにします。もう一度例を見てください
hungryWolf

193

::オペレータは、スコープ解決演算子と呼ばれ、それがスコープを解決するだけで、あることありませんさ。したがって、型名の前にこれを付けることで、型のグローバル名前空間を調べるようコンパイラーに指示します。

例:

int count = 0;

int main(void) {
  int count = 0;
  ::count = 1;  // set global count to 1
  count = 2;    // set local count to 2
  return 0;
}

122

すでに多くの合理的な答えがあります。一部の読者に役立つ可能性のある類推を入れます。 実行したいプログラムのパスを検索するとき::、ファイルシステムのディレクトリ区切り文字 ' /'のように機能します。考慮してください:

/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(例えばプログラマは自分のコードでは完全に別の何かのために使用する場合がありますことを、mergeincludesfillgenerateexchangequeuetouppermax)。2つの無関係な非標準ライブラリは、作成者が一般に互いに気づいていないか、あまり気付いていないため、同じ識別子を使用する可能性がはるかに高くなります。そして、C ++標準ライブラリを含むライブラリは、時間の経過とともにシンボルを変更します。これはすべて、古いコードを再コンパイルするとき、特にusing namespaces が頻繁に使用されているときにあいまいさを作成する可能性があります。このスペースで実行できる最悪のことは、using namespace■ヘッダー内のヘッダーのスコープをエスケープします。これにより、直接または間接的な大量のクライアントコードが、使用する名前空間とあいまいさの管理方法について独自の決定を下すことができなくなります。

したがって、リーディング::はC ++プログラマーのツールボックスの1つのツールであり、既知の衝突を明確に解消し、将来のあいまいさの可能性を排除します。


8
類推の場合は+1。類推は、十分なIMOを教育ツールとして使用されていません。
Trevor Boyd Smith

38

::スコープ解決演算子です。何かのスコープを指定するために使用されます。

たとえば、::他のすべての名前空間の外側にあるのは、単独でのグローバルスコープです。

some::thing 次のいずれかの方法で解釈できます。

  • someある名前空間(グローバルスコープに、または現在のものよりも外側の範囲)とthingなるタイプ関数オブジェクト、またはネストされたネームスペース
  • someあるクラス現在のスコープで利用可能でthingあるメンバオブジェクト関数またはタイプsomeクラス。
  • クラスメンバ関数にsomeすることができる基本型電流タイプ(又は電流タイプ自体)のとthing、このクラスの一員であり、タイプ機能又はオブジェクト

のように、スコープをネストすることもできsome::thing::badます。ここで、各名前はタイプ、オブジェクト、またはネームスペースにすることができます。さらに、最後の1つbadは関数にすることもできます。関数は内部スコープ内で何も公開できないため、他のユーザーはできませんでした。

したがって、例に戻ると::thing、グローバルスコープ内の何か、タイプ、関数、オブジェクト、またはネームスペースのみにすることができます。

それを使用する方法は、それがグローバルスコープの型であることを示唆しています(ポインター宣言で使用されています)。

この回答が完全で正しいため、スコープの解決を理解するのに役立つことを願っています。


2
このコードを考えてみましょう@obounaim liveworkspace.org/code/3Wabw0$5 class some { protected: int thing; }; class some_ext : public some { float thing; void action(){ some::thing = 42; thing = 666; } }; ここでは、someの基底クラスであるsome_extとあなたが書くときsome::thingsome_extのメンバ関数に、それは意味thingの基本型にオブジェクトをsome。なければsome::thing単独の手段thing最も近い範囲では、それがありますsome_ext::thing。より明確ですか?
Klaim 2013

17

:: 何か(変数、関数、クラス、typedefなど...)を名前空間またはクラスにリンクするために使用されます。

以前::に左側がない場合は、グローバル名前空間を使用しているという事実が強調されます。

例えば:

::doMyGlobalFunction();


10

スコープ解決演算子と呼ばれます。非表示のグローバル名は、スコープ解決演算子::を使用して参照できます

int x;
void f2()
{
   int x = 1; // hide global x
   ::x = 2; // assign to global x
   x = 2; // assign to local x
   // ...
}

10

(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_counerBendすることはできません。したがって、それm_counterが0のままであることを確認したい場合は、をチェックTwistする必要がありますが、チェックする必要はありませんBend

したがって、これをより明確にするためthis->TwistTwist、メンバー関数であるリーダーを示すために書き込むか、無料であること::Bendを示すために書き込むことBendができます。または両方。これは、リファクタリングを実行または計画している場合に非常に役立ちます。


5

:: 名前空間を定義する演算子です。

たとえばusing namespace std;、コードで言及せずにcoutを使用したい場合は、次のように記述します。

std::cout << "test";

名前空間が言及されていない場合、クラスはグローバル名前空間に属していると言われます。


1

"::"はスコープ解決演算子を表します。同じ名前の関数/メソッドは、2つの異なるクラスで定義できます。特定のクラスのメソッドにアクセスするには、スコープ解決演算子を使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.