Что означает двойное двоеточие в начале ::?

Я нашел эту строку кода в классе, который мне нужно изменить:

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

и я не знаю, что именно означает двойное двоеточие перед именем класса. Без этого я бы прочитал: объявление tmpCo как указателя на объект класса _3 _... но добавленное двойное двоеточие меня смущает.

Я также нашел:

typedef ::config::set ConfigSet;

person rmbianchi    schedule 24.11.2010    source источник
comment
Не думаю, что это ответ, поэтому я прокомментирую: en.wikipedia.org/wiki/ Scope_resolution_operator. В этом контексте голый :: означает ссылку на переменную из глобального / анонимного пространства имен.   -  person wkl    schedule 24.11.2010


Ответы (9)


Это гарантирует, что разрешение происходит из глобального пространства имен, а не начинается с пространства имен, в котором вы сейчас находитесь. Например, если у вас есть два разных класса с именем 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.

person Wyatt Anderson    schedule 24.11.2010
comment
В чем причина поставить 2 набора двойных двоеточий? В этом: ::Configuration::doStuff(...) - person Azurespot; 01.06.2017
comment
@NoniA. вы спрашиваете, что делает второй набор двойных двоеточий? - person FCo; 02.06.2017
comment
@WyattAnderson, нет 1-го сета. Думаю, я понимаю, что :: между двумя терминами относится к пространству имен или классу и его члену. А как насчет 1-го? - person Azurespot; 03.06.2017
comment
@Azurespot, вот что спрашивает OP, на этот вопрос отвечает этот пост. Он обязательно использует идентификатор из глобального пространства имен. Посмотрите на пример еще раз - person hungryWolf; 30.04.2018

Оператор :: называется оператором разрешения области видимости и делает именно это, он разрешает область видимости. Таким образом, добавляя префикс к имени типа this, он сообщает вашему компилятору искать этот тип в глобальном пространстве имен.

Пример:

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;
}
person Moo-Juice    schedule 24.11.2010

Уже много разумных ответов. Я приведу аналогию, которая может помочь некоторым читателям. :: во многом похож на разделитель каталогов файловой системы '/' при поиске программы, которую вы хотите запустить. Рассмотреть возможность:

/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 ++ выдает ошибку компилятора, когда вы неясны.

2) В C ++ имена без какой-либо ведущей области могут быть сопоставлены в текущем пространстве имен, в то время как большинство оболочек UNIX делают это только в том случае, если вы помещаете . в PATH.

3) C ++ всегда ищет в глобальном пространстве имен (например, / неявно имеет PATH).

Общее обсуждение пространств имен и явности символов

Использование абсолютных ::abc::def::... "путей" иногда может быть полезно для изоляции вас от любых других используемых вами пространств имен, которые являются частью, но на самом деле не имеют контроля над содержимым, или даже других библиотек, которые также использует клиентский код вашей библиотеки. С другой стороны, он также более тесно связывает вас с существующим «абсолютным» местоположением символа, и вы упускаете преимущества неявного сопоставления в пространствах имен: меньшее связывание, более легкая мобильность кода между пространствами имен и более сжатый, читаемый исходный код. .

Как и во многих других вещах, это баланс. Стандарт C ++ помещает в std:: множество идентификаторов, которые менее «уникальны», чем cout, которые программисты могут использовать для чего-то совершенно другого в своем коде (например, merge, includes, fill, generate, exchange, queue, toupper, max). Две несвязанные нестандартные библиотеки имеют гораздо больше шансов использовать одни и те же идентификаторы, поскольку авторы, как правило, не знают друг друга или не знают друг друга. А библиотеки, включая стандартную библиотеку C ++, со временем меняют свои символы. Все это потенциально создает двусмысленность при перекомпиляции старого кода, особенно при интенсивном использовании using namespaces: худшее, что вы можете сделать в этом пространстве, - разрешить using namespace в заголовках выйти за пределы области заголовков, так что произвольно большое количество прямых и косвенных клиентский код не может принимать собственные решения о том, какие пространства имен использовать и как управлять неоднозначностями.

Итак, ведущий :: - это один из инструментов в наборе инструментов программиста C ++ для активного устранения неоднозначности известного конфликта и / или устранения возможности неоднозначности в будущем ...

person Tony Delroy    schedule 24.11.2010
comment
+1 за хорошую аналогию. аналогии почти не используются ИМО в качестве обучающего инструмента. - person Trevor Boyd Smith; 21.09.2011

:: - оператор разрешения области видимости. Он используется для указания объема чего-либо.

Например, только :: является глобальной областью за пределами всех других пространств имен.

some::thing можно интерпретировать любым из следующих способов:

  • some - это пространство имен (в глобальной или внешней области, отличной от текущей), а thing - это тип, функция, объект или вложенное пространство имен;
  • some - это класс, доступный в текущей области, а thing - это объект-член, функция или тип some класс;
  • в функции-члене класса some может быть базовым типом текущего типа (или самого текущего типа), а thing тогда является одним членом этого класса, тип, функция или объект.

У вас также может быть вложенная область видимости, как в some::thing::bad. Здесь каждое имя может быть типом, объектом или пространством имен. Кроме того, последний, bad, также может быть функцией. Остальные не могли, поскольку функции не могут ничего раскрывать в пределах своей внутренней области видимости.

Итак, вернемся к вашему примеру, ::thing может быть только чем-то в глобальной области: типом, функцией, объектом или пространством имен.

То, как вы его используете, предполагает (используется в объявлении указателя), что это тип в глобальной области.

Я надеюсь, что этот ответ является достаточно полным и правильным, чтобы помочь вам понять разрешение области.

person Klaim    schedule 24.11.2010
comment
@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::thing в функции-члены some_ext, это означает, что объект thing относится к базовому типу some. Без some::, только thing означает thing в ближайшей области, то есть some_ext::thing. Это понятнее? - person Klaim; 05.04.2013

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

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

e.g.:

::doMyGlobalFunction();

person Stephane Rolland    schedule 24.11.2010

вызываемый им оператор разрешения области действия. На скрытое глобальное имя можно ссылаться с помощью оператора разрешения области видимости ::
Например;

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

(Этот ответ в основном для гуглеров, потому что 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 оставался равным нулю, вы должны проверить Twist, но вам не нужно проверять Bend.

Чтобы сделать это более заметным, можно написать this->Twist, чтобы показать читателю, что Twist является функцией-членом, или написать ::Bend, чтобы показать, что Bend свободен. Или оба. Это очень полезно, когда вы делаете или планируете рефакторинг.

person Steed    schedule 23.10.2013

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

Например, если вы хотите использовать cout без упоминания using namespace std; в своем коде, вы пишете это:

std::cout << "test";

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

person Vladimir Ivanov    schedule 24.11.2010

"::" представляет оператор разрешения области видимости. Функции / методы с одинаковыми именами могут быть определены в двух разных классах. Для доступа к методам определенного класса используется оператор разрешения области видимости.

person Vaman Acharya    schedule 20.02.2019