2011-11-27 3 views
4

Я видел оба подхода в коде. Не могли бы вы объяснить, в чем разница между ними? Как я думаю, это связано с тем, как поиск пространства имен выполняется с помощью C++, можете ли вы предоставить некоторую информацию об этом, или, возможно, ссылку на хороший документ? Благодарю.В чем разница между написанием «:: namespace :: identifier» и «namespace :: identifier»?

+5

Это как разница между '/ usr/bin/rm' и' usr/bin/rm'; или между 'Windows \ calc.exe' и' C: \ Windows \ calc.exe'. –

+0

@KerrekSB хорошая аналогия –

+0

Не правда ли? Если я объявляю пространство имен и использую идентификатор «std :: cout», он все равно будет работать, однако в моем собственном пространстве имен не существует «std» пространства имен. –

ответ

5

Это действительно не имеет значения, по крайней мере, не большую часть времени.

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

В формате identifier1::identifier2 мы вместо этого рассмотрим текущий scope for identifier1. Если мы его не найдем, будет поиск объекта родителя, и так далее, пока мы его не найдем. Затем мы ищем identifier2 в пределах того объема, который мы только что нашли.

В случае, если вы уже находитесь в глобальном масштабе, это не имеет значения. Но эта история меняется, когда вы работаете в пространстве имен или классах, в которых есть другие пространства имен или классы.

+0

Отлично, спасибо. –

12

Пример:

#include <cstdio> 

namespace x { 
    const int i = 1; 
} 

namespace y { 
    namespace x { 
     const int i = 2; 
    } 

    void func() 
    { 
     std::printf("x::i = %d\n", x::i); 
     std::printf("::x::i = %d\n", ::x::i); 
    } 
} 

int main() 
{ 
    y::func(); 
    return 0; 
} 

Выход:

 
x::i = 2 
::x::i = 1 

Объяснение:

  • Когда вы ссылаетесь на язя ntifier, как x::i, используемое определение является «самым близким» x::i. Внутри ::y::func определение ::y::x::i ближе, чем определение ::x::i. Напротив, нет такой функции ::y::std::printf, поэтому вместо этого используется ::std::printf.

  • При обращении к идентификатору, как ::x::i, нет никакой возможности двусмысленности: он ищет пространство имена верхнего уровня с именем x, затем находит i внутри.

Таким образом, используя :: в начале позволяет пишется полное имя глобальной что-то. Это также позволяет различать локальные и глобальные переменные.

Пример 2:

#include <cstdio> 
const int x = 5; 
int main() 
{ 
    const int x = 7; 
    std::printf("x = %d\n", x); 
    std::printf("::x = %d\n", ::x); 
    return 0; 
} 

Выход:

 
x = 7 
::x = 5 
+0

Почему «std: : printf "работает тогда, внутри пространства имен" y "? В пространстве имен «y» нет пространства имен «std». Не могли бы вы также объяснить этот бит? –

+1

@drandrestor: Это похоже на переменную область видимости - если компилятор не находит имя на текущем уровне, он «выскакивает» на один уровень и ищет его там. В этом случае пространство имен 'std' не существует в' y', поэтому компилятор затем проверяет глобальное пространство имен и находит его там. –

+1

Ха, 9 против 1 и 1 приняты ... –