답변:
이렇게하면 현재있는 네임 스페이스에서 시작하는 대신 전역 네임 스페이스에서 확인이 수행됩니다. 예를 들어, 두 개의 다른 클래스가있는 경우 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
.
::Configuration::doStuff(...)
::
두 용어 사이가 네임 스페이스 또는 클래스와 그 멤버를 의미 한다고 생각 합니다. 그러나 첫 번째는 어떻습니까?
이미 합리적인 답변이 많이 있습니다. 일부 독자에게 도움이 될 수있는 유추를 살펴 보겠습니다. 실행하려는 프로그램의 경로를 검색 할 때 ::
파일 시스템 디렉토리 구분 기호 ' /
' 와 매우 유사합니다 . 치다:
/path/to/executable
이것은 매우 명시 적입니다. 파일 시스템 트리의 정확한 위치에있는 실행 파일 만 PATH에 관계없이이 사양과 일치 할 수 있습니다. 비슷하게...
::std::cout
... C ++ 네임 스페이스 "tree"에서 똑같이 명시 적입니다.
같은 절대 경로와 대조, 당신은 (예를 들어 좋은 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 ++은 항상 전역 네임 스페이스를 검색합니다 ( /
암시 적으로 your를 갖는 것처럼 PATH
).
절대 ::abc::def::...
"경로"를 사용하는 것은 때로는 사용중인 다른 네임 스페이스와 분리하는 데 유용 할 수 있지만, 라이브러리의 클라이언트 코드에서도 사용하는 컨텐츠 또는 다른 라이브러리의 일부를 제어 할 수는 없습니다. 반면, 기존 심볼의 "절대"위치에보다 밀접하게 연결되며, 네임 스페이스에서 암시 적 매칭의 이점을 줄입니다. 커플 링 감소, 네임 스페이스 간 코드 이동 용이성,보다 간결하고 읽기 쉬운 소스 코드 .
많은 것들과 마찬가지로 밸런싱 행위입니다. 아래 식별자의 C ++ 표준 풋 많이 std::
그 이하 "독특한"있는 cout
프로그래머가 코드에서 완전히 다른 무언가를 사용할 수있는 (예를 들어 merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). 두 개의 관련되지 않은 비표준 라이브러리는 작성자가 일반적으로 서로를 인식하지 못하거나 동일한 식별자를 사용할 가능성이 훨씬 높습니다. 그리고 C ++ 표준 라이브러리를 포함한 라이브러리는 시간이 지남에 따라 심볼을 변경합니다. 이 모든 것은 오래된 코드를 다시 컴파일 할 때, 특히 using namespace
s를 많이 사용한 경우 모호성을 만듭니다 .이 공간에서 할 수있는 최악의 일은 허용입니다.using namespace
임의로 많은 양의 직접 및 간접 클라이언트 코드가 사용할 네임 스페이스 및 모호성을 관리하는 방법에 대한 자체 결정을 내릴 수 없도록 헤더의 범위를 벗어나기 위해 헤더에 있습니다.
따라서 선행 ::
은 C ++ 프로그래머 도구 상자에 알려진 충돌을 적극적으로 명확하게하거나 미래의 모호함을 제거 할 수있는 도구 중 하나입니다.
::
범위 확인 연산자입니다. 무언가의 범위를 지정하는 데 사용됩니다.
예를 들어 ::
다른 모든 네임 스페이스 외부의 전역 범위 만 있습니다.
some::thing
다음 방법 중 하나로 해석 될 수 있습니다.
some
A는 공간 (글로벌 범위, 또는 현재 하나 이상의 외측 범위) 및 thing
A는 입력 하는 기능 , 객체 또는 중첩 된 공간 ;some
현재 범위에서 사용할 수 있는 클래스 이며 클래스thing
의 멤버 객체 , 함수 또는 유형 입니다 some
.some
될 수 기본형 전류 형 (또는 전류 타입 자체) 및 thing
그 다음,이 클래스의 하나의 부재, 인 형태 , 기능 또는 목적 .에서처럼 중첩 범위를 가질 수도 있습니다 some::thing::bad
. 여기서 각 이름은 유형, 객체 또는 네임 스페이스 일 수 있습니다. 또한 마지막 bad
것은 함수일 수 있습니다. 함수는 내부 범위 내에서 아무것도 노출시킬 수 없으므로 다른 함수는 할 수 없습니다.
따라서 예제로 돌아 가면 ::thing
전역 범위에서 유형, 함수, 객체 또는 네임 스페이스 만 될 수 있습니다.
사용하는 방식은 (포인터 선언에서 사용되는) 전역 범위의 유형임을 제안합니다.
이 답변이 스코프 해상도를 이해하는 데 도움이되도록 완전하고 정확하기를 바랍니다.
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
. 더 명확합니까?
(이 답변은 OP가 이미 문제를 해결했기 때문에 대부분 Google 직원을위한 것입니다.) prepended의 의미 ::
범위-resulution 연산자- 다른 답변에 설명되어 있지만 사람들이 왜 그것을 사용하고 있는지 추가하고 싶습니다.
"다른 이름이 아닌 전역 네임 스페이스에서 이름을 가져옵니다"라는 의미입니다. 그러나 왜 이것이 명시 적으로 철자가 필요한가?
사용 사례-네임 스페이스 충돌
글로벌 네임 스페이스와 로컬 / 중첩 네임 스페이스에서 동일한 이름을 사용하면 로컬 네임 스페이스가 사용됩니다. 따라서 전 세계를 원한다면 앞에 추가하십시오 ::
. 이 사례는 @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
0으로 유지하려면 확인 Twist
해야하지만 확인 할 필요는 없습니다 Bend
.
따라서이를보다 명확하게 this->Twist
나타 내기 위해 Twist
멤버 함수 인 독자를 보여주기 위해 쓰거나 무료 인 ::Bend
것을 나타 내기 위해 쓸 Bend
수 있습니다. 아니면 둘다. 리팩토링을 수행하거나 계획 할 때 매우 유용합니다.
::
네임 스페이스를 정의하는 연산자입니다.
예를 들어, using namespace std;
코드에서 언급하지 않고 cout을 사용하려면 다음과 같이 작성하십시오.
std::cout << "test";
네임 스페이스가 언급되지 않은 경우 클래스는 글로벌 네임 스페이스에 속한다고합니다.
::
란 글로벌 / 익명 네임 스페이스에서 변수를 참조합니다.