为什么using指令在全局范围和本地范围内表现不同?

Amr*_*rit 11 c++ namespaces

当我编写以下代码时,它会被编译并正确执行:

#include <iostream>
using namespace std;

namespace first
{
  int x = 5;
  int y = 10;
}

namespace second
{
  double x = 3.1416;
  double y = 2.7183;
}

int main () {
  using namespace first; //using derective
  using second::y;
  cout << x << endl;
  cout << y << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是如果我使用main函数之外的指令编写如下,

using namespace first; //using derective
using second::y;
int main () {
  cout << x << endl;
  cout << y << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

它给出了这个编译错误:

g++     namespace03.cpp   -o namespace03
namespace03.cpp: In function ‘int main()’:
namespace03.cpp:20:11: error: reference to ‘y’ is ambiguous
namespace03.cpp:13:10: error: candidates are: double second::y
namespace03.cpp:7:7: error:                 int first::y
make: *** [namespace03] Error 1
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释为什么使用指令在内部main和外部使用时表现不同main

Jes*_*ood 10

使用声明就是声明.using second::y;main 的内部类似于声明y该范围中的变量,该变量隐藏y全局命名空间范围中的任何其他s.using second::y;在全局范围内使用时,您没有隐藏任何名称,因为两者y都在同一范围内.

想象一下你的第一个例子如下(请参阅下面的评论以获得解释):

namespace first
{
  int x = 5;
  int y = 10;
}

int main () {
  using namespace first; // This makes first::y visible hereafter
  int y = 20; // This hides first::y (similar to using second::y)
  cout << x << endl;
  cout << y << endl; // Prints 20 
}
Run Code Online (Sandbox Code Playgroud)

但是,第二个例子是:

namespace first
{
  int x = 5;
  int y = 10;
}
using namespace first; // This makes first::y visible in global scope
int y = 20; // This is global ::y
int main () {
  cout << x << endl;
  cout << y << endl; // Error! Do you mean ::y or first::y?
}
Run Code Online (Sandbox Code Playgroud)

  • @user2235938:有两个“y”声明,但 using 声明在 main 内部声明“second::y”,而“first::y”在全局命名空间范围内声明。由于“second::y”是在 main 内部声明的,因此它隐藏了“first::y”。你熟悉姓名隐藏吗? (2认同)

Ale*_*Dan 6

using-declaration和using-directive有两个主要区别.

第一个区别:(明显的区别).

namespace first{

int x=1;
int y=2;
}
using first::x; //using declaration
Run Code Online (Sandbox Code Playgroud)

这将允许您使用x不带名称空间名称的变量作为显式限定符,并注意这不包括y.

namespace first{
int x=1;
int y=2;
}
using namespace first;// using directive
Run Code Online (Sandbox Code Playgroud)

这将允许您使用名称空间内的所有变量,first而不使用namespace-name作为显式限定符.


第二个区别:(这是你不明白的).

我将向您解释为什么当您在main函数中使用using-directive和using-declaration时都没有错误,但是当您尝试在全局命名空间中使用它们时,您会收到编译时错误.

假设我们在全局命名空间中定义了两个命名空间,如下所示:

namespace first
{
  int x = 5;
  int y = 10;
}

namespace second
{
  double x = 3.1416;
  double y = 2.7183;
}
Run Code Online (Sandbox Code Playgroud)


例1:

int main () {    
using namespace first;
using second::y;
  cout << x << endl; // this will output first::x;
  cout << y << endl; // this will output second::y;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

原因是using-directive using second::y会使你的变量y看起来像是使用它的范围的局部变量using-directive,在这种情况下它在main函数中使用.而using声明using namespace first将使得在此命名空间内定义的变量first看起来像全局变量,并且这仅在使用using-directive的范围内有效,在这种情况下它位于main函数内部.

因此,如果您应用上述内容,您将知道如果您执行了类似的操作:

示例2:

 using namespace first;
 using second::y;

 int main () {    
  cout << x << endl; 
  cout << y << endl; // two definitions of y. first::y and second::y 
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

你会得到一个错误,因为这两个first::ysecond::y的行为就好像他们在全局命名空间中定义,所以你将最终打破了一个确定指标规则.