从3.4.1 / 14开始:
如果命名空间的变量成员定义在范围之外 它的命名空间然后出现在定义中的任何名称 成员(在声明者身份之后)被查找,就像定义一样 该成员发生在其名称空间中。
如果该名称被视为成员名称的定义,那么宣言的意义何在?
以下示例为什么会起作用:
namespace N
{
extern int j;
}
int i = 2;
int N::j = i; //N::j=2
int N::j=i
实际出现在命名空间范围内。因此,对于非限定名称查找,声明int i=2
不可见。 为什么要发布此声明?
答案 0 :(得分:3)
你的问题:
int N::j=i
实际出现在命名空间范围内。因此,对于非限定名称查找,声明int i=2
不可见。为什么要发现这个声明?
答案:
由于
i
命名空间中找不到N
,因此会在全局命名空间中查找它。如果i
命名空间中有N
,则会用于初始化N::j
。
希望以下计划澄清您的疑问。
#include <iostream>
namespace N
{
extern int j;
extern int k;
int x = 3;
}
int x = 2;
int y = 10;
int N::j = x; // N::x is used to initialize N::j
int N::k = y; // ::y is used to initialize N::k
int main()
{
std::cout << N::j << std::endl;
std::cout << N::k << std::endl;
}
输出:
3 10
更新,以回应OP的评论
标准的含义是:
namespace N
{
extern int j;
}
int x = 2;
int N::j = x;
相当于:
namespace N
{
extern int j;
}
int x = 2;
namespace N
{
int j = x;
}
查找x
的逻辑是相同的。如果在同一名称空间N
中找到它,则使用它。如果在命名空间x
中找不到N
,则会在封闭的命名空间中向外搜索它。
答案 1 :(得分:1)
您似乎对名称查找在基本级别上的工作方式感到困惑。也许一个简单的例子可以帮助:
#include <iostream>
void print(std::string const & s) { std::cout << "Boo: " << s << "\n"; }
namespace Foo
{
std::string message = "Foo";
void action() { print(message); }
}
int main() { Foo::action(); }
显然,print
的定义中可以看到名称Foo::action
。包含名称空间的名称在包含的名称空间中可见。这没什么不寻常的。
您所引用的规则以及R Sahu已经很好地证明了这一点的一点是,您可以将变量的定义放在其声明的其他位置,在这种情况下,初始化程序中出现的任何名称都会在声明变量的名称空间。这是另一个例子:
namespace Foo
{
namespace Bar { int a = 10; }
int b = 20;
extern int c;
}
namespace Bar { int a = -20; }
int b = 5;
int Foo::c = Bar::a + b; // uses Foo::Bar::a and Foo::b, NOT ::Bar::a or ::b
int main() { return Foo::c; } // returns 30