Использование :: in С++

Я изучаю C++, и я никогда не могу сказать, когда мне нужно использовать ::. Я знаю, что мне нужно использовать std:: перед cout и cin. Означает ли это, что внутри файла iostream разработчики, которые его создали, создали пространство имен std и помещают функции cin и cout в пространство имен std? Когда я создал новый класс, который не находится в том же файле, что и main() по какой-то причине я должен добавить ::.

Например, если я создаю class под названием A, почему мне нужно поставить A:: перед функцией, которую я создаю, хотя я не помещал ее в имя? Например, void A::printStuff(){}. Если я создаю функцию в main, почему мне не нужно ставить main::printStuf{}?

Я знаю, что мой вопрос, вероятно, запутан, но может ли кто-нибудь мне помочь?

Ответ 1

Вы почти правы насчет cout и cin. Это объекты (не функции), определенные внутри пространства имен 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;
}

:: известен как оператор разрешения области. Имена cout и cin определены в std, поэтому мы должны определить их имена с помощью std::.

Классы ведут себя немного как пространства имен, поскольку имена, объявленные внутри класса, принадлежат классу. Например:

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

Конструктор с именем foo является членом класса с именем foo. Они имеют одно и то же имя, потому что его конструктор. Функциональная bar также является членом foo.

Поскольку они являются членами foo, ссылаясь на них извне класса, мы должны квалифицировать их имена. В конце концов, они принадлежат к этому классу. Поэтому, если вы собираетесь определить конструктор и bar вне класса, вам нужно сделать это так:

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

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

Это происходит потому, что они определяются вне класса. Если вы не поставили foo:: qualification на имена, вы бы определили некоторые новые функции в глобальной области, а не как члены foo. Например, это совершенно другой bar:

void bar()
{
  // Implement different bar
}

Это позволило иметь то же имя, что и функция класса foo потому что она в другой области. Этот bar находится в глобальном масштабе, тогда как другой bar принадлежит классу foo.

Ответ 2

:: называется оператором разрешения области видимости. Можно использовать так:

:: идентификатор
имя-класса :: идентификатор
пространство имен :: идентификатор

Вы можете прочитать об этом здесь
https://docs.microsoft.com/en-us/cpp/cpp/scope-resolution-operator?view=vs-2017

Ответ 3

:: используются для областей разыменования.

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)
}

unrelated: cout и cin - это не функции, а экземпляры объектов потока.

EDIT исправлено, поскольку Keine Lust предложил

Ответ 4

посмотрите на это информативно [Квалифицированные идентификаторы

Квалифицированное id-выражение является неквалифицированным id-выражением, предваряемым оператором разрешения области :: и, необязательно, последовательностью перечислений (поскольку С++ 11) или именами пространства имен или выражениями decltype (поскольку С++ 11) разделены по операторам с разрешающей способностью. Например, выражение std :: string :: npos является выражением, которое называет статический член npos в строке класса в пространстве имен std. Выражение :: tolower называет функцию tolower в глобальном пространстве имен. Выражение :: std :: cout определяет глобальную переменную cout в пространстве имен std, которая является пространством имен верхнего уровня. Выражение boost :: signals2 :: connection обозначает тип соединения, объявленного в сигнале пространства имен 2, который объявляется в пространстве имен.

Шаблон ключевого слова может появляться в квалифицированных идентификаторах по мере необходимости для устранения неоднозначности зависимых имен шаблонов] 1

Ответ 5

Одно использование для "Unary Scope Resolution Operator" или "Colon Colon Operator" - для локального и глобального выбора переменных одинаковых имен:

    #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

Другие виды использования могут быть: Определение функции извне класса, доступ к статической переменной внутри класса или использование множественного наследования.