Стандарт про using namespace :
A using-directive specifies that the names in the nominated namespace
can be used in the scope in which the using-directive appears after
the using-directive. During unqualified name lookup (3.4.1), the names
appear as if they were declared in the nearest enclosing namespace
which contains both the using-directive and the nominated namespace. [
Note: In this context, “contains” means “contains directly or
indirectly”. — end note ]
Директива using указывает, что имена в указанном пространстве имен могут использоваться в области, в которой директива using появляется после директивы using. Во время поиска по неквалифицированным именам (3.4.1) имена отображаются так, как если бы они были объявлены в ближайшем охватывающем пространстве имен, которое содержит как директиву using, так и назначенное пространство имен. [Примечание: В данном контексте “содержит” означает “содержит прямо или косвенно”. — заключительная
записка ]
Про охватывающее пространство, пример с тремя отделами, локальная , охватывающая и именное :
namespace My {
int glob = 88 ;
}
using namespace My ;
char const * glob = "glob" ;
# include <iostream>
int main(){
double glob = 7.77 ;
std :: cout << "glob = " << glob << std :: endl ;
std :: cout << "::glob = " << ::glob << std :: endl ;
std :: cout << "My::glob = " << My::glob << std :: endl ;
}
glob = 7.77
::glob = glob
My::glob = 88
Выведется значение локальной переменной 7.77
так как она имеет бо'льший приоритет над охватывающим пространством (глобальными переменными и именным пространством). При добавлении ::
выводится глобальная переменная. И при добавлении My::
конечно выводится переменная из My
. Глобальные переменные и переменные из пространства My
имеют одинаковые права.
Удаляем глобальную переменную.
namespace My {
int glob = 88 ;
}
using namespace My ;
# include <iostream>
int main(){
double glob = 7.77 ;
std :: cout << "glob = " << glob << std :: endl ;
std :: cout << "::glob = " << ::glob << std :: endl ;
std :: cout << "My::glob = " << My::glob << std :: endl ;
}
glob = 7.77
::glob = 88
My::glob = 88
при ::
выводится значение переменной из именного пространства, так как такая запись означает использование внешнего пространства и мы указали её использовать.
Удаляем локальную переменную.
namespace My {
int glob = 88 ;
}
using namespace My ;
# include <iostream>
int main(){
std :: cout << "glob = " << glob << std :: endl ;
std :: cout << "::glob = " << ::glob << std :: endl ;
std :: cout << "My::glob = " << My::glob << std :: endl ;
}
glob = 88
::glob = 88
My::glob = 88
При отсутствии конкурентов, локальных и глобальных переменных выводится значение из пространства имен My
в любой записи.
При присутствии только глобальных переменных и использовании пространства имён происходит конфликт имён и остаётся прямое указание из какого пространства нужно брать переменную.
namespace My {
int glob = 88 ;
}
using namespace My ;
char const * glob = "glob" ;
# include <iostream>
int main(){
// error: reference to 'glob' is ambiguous
// std :: cout << "glob = " << glob << std :: endl ;
std :: cout << "::glob = " << ::glob << std :: endl ;
std :: cout << "My::glob = " << My::glob << std :: endl ;
}
::glob = glob
My::glob = 88
почему если мы подключили пространство имен, не возникает конфликта имен в int cin
Ваша переменная cin объявлена в локальном пространстве имён. Директива using namespace добавляет в охватывающее пространство. А локальное пространство имеет приоритет над охватывающем.
почему как-то странно работает оператор >>
Локальная переменная cin имеет тип int, потому-что локальные переменные имеют приоритет на охватывающими. . Ничего странного, так как целое число при бинарном сдвиге возвращает новое целое число, которое вы благополучно игнорируете.
Чтобы выделить переменную из охватывающего пространства можно использовать ::, тогда ::cin будет тип потока, а cin локальная переменная.
:: cin >> cin ;
почему нельзя так перегрузить оператор
error: 'void operator<<(int&, int)' must have an argument of class or enumerated type
Ошибка говорит, что тип должен быть классом или перечислением. Всё дело в том, что встроенный тип int уже вшит в язык очень жёстко и новые определения операторов могут быть созданы только над новыми типами. Каким образом обычный оператор бинарного сдвига
int x = 7 << 2 ;
// x == 28 ;
можно подменить на другое исполнение?