Вопрос про область видимости и работу оператора

Рейтинг: 1Ответов: 1Опубликовано: 03.04.2023
using namespace std;

int main(){
int b=0;
//bool b;// error
int cin;
cin>>cin;
cout<<cin;}

1 Вопрос: почему если мы подключили пространство имен, не возникает конфликта имен в int cin,ведь по идее cin уже определена где-то сверху с др типом? и почему как-то странно работает оператор >> ?

void operator>>(int& b, int& c) {
    b=c;
}

2 Вопрос: почему нельзя так перегрузить оператор?

Ответы

▲ 2Принят

Стандарт про 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 ;

можно подменить на другое исполнение?