Использование :: 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
Другие виды использования могут быть: Определение функции извне класса, доступ к статической переменной внутри класса или использование множественного наследования.