web-dev-qa-db-ja.com

C ++で::を使用する

私はC++を学んでおり、いつ::を使用する必要があるかわかりません。 coutcinの前にstd::を使用する必要があることは知っています。これは、iostreamファイルの内部で、それを作成した開発者がstdという名前空間を作成し、関数cinおよびcoutstdという名前空間に入れたことを意味しますか?何らかの理由でmain()と同じファイルにない新しいクラスを作成したとき、::を追加する必要があります。

たとえば、classと呼ばれるAを作成する場合、なぜ名前空間に入れなかったとしても、作成する関数の前にA::を配置する必要があるのはなぜですか?たとえばvoid A::printStuff(){}mainに関数を作成する場合、なぜmain::printStuf{}を配置する必要がないのですか?

私の質問はおそらく紛らわしいことを知っていますが、誰かが私を助けることができますか?

36
foobar5512

coutcinについてはほぼ正しいです。これらは、std名前空間内で定義されたオブジェクト(関数ではない)です。 C++標準で定義されている宣言は次のとおりです。

ヘッダー<iostream>概要

#include <ios>
#include <streambuf>
#include <istream>
#include <ostream>

namespace std {
  extern istream cin;
  extern ostream cout;
  extern ostream cerr;
  extern ostream clog;

  extern wistream wcin;
  extern wostream wcout;
  extern wostream wcerr;
  extern wostream wclog;
}

::は、スコープ解決演算子として知られています。名前coutcinstd内で定義されているため、std::で名前を修飾する必要があります。

クラスは、クラス内で宣言された名前がクラスに属するという点で、名前空間のように動作します。例えば:

class foo
{
  public:
    foo();
    void bar();
};

fooという名前のコンストラクターは、fooという名前のクラスのメンバーです。それらはコンストラクタなので同じ名前を持っています。関数barfooのメンバーです。

これらはfooのメンバーであるため、クラス外からそれらを参照する場合、名前を修飾する必要があります。結局のところ、彼らはそのクラスに属します。したがって、コンストラクターとbarをクラス外で定義する場合は、次のようにする必要があります。

foo::foo()
{
  // Implement the constructor
}

void foo::bar()
{
  // Implement bar
}

これは、それらが定義されているためです外部クラス。名前にfoo::修飾子を付けなかった場合、fooのメンバーとしてではなく、グローバルスコープでいくつかの新しい関数を定義することになります。たとえば、これはまったく異なるbar

void bar()
{
  // Implement different bar
}

スコープが異なるため、fooクラスの関数と同じ名前を使用できます。このbarはグローバルスコープにありますが、他のbarfooクラスに属していました。

52

::は、スコープの逆参照に使用されます。

const int x = 5;

namespace foo {
  const int x = 0;
}

int bar() {
  int x = 1;
  return x;
}

struct Meh {
  static const int x = 2;
}

int main() {
  std::cout << x; // => 5
  {
    int x = 4;
    std::cout << x; // => 4
    std::cout << ::x; // => 5, this one looks for x outside the current scope
  }
  std::cout << Meh::x; // => 2, use the definition of x inside the scope of Meh
  std::cout << foo::x; // => 0, use the definition of x inside foo
  std::cout << bar(); // => 1, use the definition of x inside bar (returned by bar)
}

無関係:coutとcinは関数ではなく、ストリームオブジェクトのインスタンスです。

[〜#〜] edit [〜#〜]として修正Keine Lust提案

17
scones

::はスコープ解決演算子と呼ばれます。次のように使用できます。

::identifier
クラス名::identifier
namespace::identifier

こちらについて読むことができます
https://docs.Microsoft.com/en-us/cpp/cpp/scope-resolution-operator?view=vs-2017

16
Johnny Mnemonic

「単項スコープ解決演算子」または「コロンコロン演算子」の使用法の1つは、同じ名前のローカルおよびグローバル変数の選択です。

    #include <iostream>
    using namespace std;

    int variable = 20;

    int main()
    {
    float variable = 30;

    cout << "This is local to the main function: " << variable << endl;
    cout << "This is global to the main function: " << ::variable << endl;

    return 0;
    }

結果の出力は次のようになります。

これはメイン関数にローカルです:30

これはメイン関数全体に適用されます:20

他の用途としては、クラスの外部から関数を定義すること、クラス内の静的変数にアクセスすること、または多重継承を使用することがあります。

4
TrevorLee

それは有益であると考えてください[修飾された識別子

修飾されたid-expressionは、スコープ解決演算子::、およびオプションで列挙シーケンス(C++ 11以降)、クラス名または名前空間名、またはdecltype式(C++ 11以降)で区切られた非修飾id-expressionです。スコープ解決演算子によって。たとえば、式std :: string :: nposは、名前空間stdのクラス文字列の静的メンバーnposに名前を付ける式です。式:: tolowerは、グローバル名前空間で関数tolowerに名前を付けます。式:: std :: coutは、トップレベル名前空間である名前空間stdのグローバル変数coutに名前を付けます。式boost :: signals2 :: connectionは、名前空間boost2で宣言されている名前空間Signals2で宣言されているタイプ接続を指定します。

キーワードテンプレートは、依存するテンプレート名を明確にするために必要に応じて修飾識別子に表示される場合があります] 1

0
vincent87