命名空间的组成和选择
namespace composition and selection
阅读 C++ 编程语言第 4 版后(第 14.4.4 节 -
组合和选择)我认为下面的程序可以正确编译:
#include <iostream>
namespace foo {
int var = 0;
// more declarations
}
namespace bar {
int var = 1;
// more declarations
}
namespace baz {
// composition of namespaces foo and bar
using namespace foo;
using namespace bar;
// I thought that the following line would resolve the name clash
using foo::var;
}
using namespace baz;
void qux(int n) {
if (n == var) {
std::cout << "baz: var " << std::endl;
} else {
std::cout << "baz: " << n << std::endl;
}
}
int main() {
qux(0);
qux(1);
}
预期的输出应该是
baz: var
baz: 1
当我尝试编译上面的代码时,我收到一条错误消息,指出对 'var' 的引用不明确。使用 foo::var
消除了编译错误,但我想更好地理解这个问题。
我的代码有什么问题?
如何以命名空间 baz 包含的方式解决名称冲突 foo::var
?
谢谢!
编辑
如以下答案中所建议,将 qux
的定义移动到命名空间 baz
中使其有效。因此,以下代码按预期编译
#include <iostream>
namespace foo {
int end = 0;
}
namespace bar {
int end = 1;
}
namespace baz {
using namespace foo;
using namespace bar;
using foo::end;
void qux(int n) {
if (n == end) {
std::cout << "baz: end " << std::endl;
} else {
std::cout << "baz: " << n << std::endl;
}
}
}
int main() {
baz::qux(baz::end);
baz::qux(1);
}
还有一件事我不是很清楚。我认为添加 using namespace baz
将使 baz
中的所有内容在当前范围内也可用,而无需使用 baz::
。换句话说,我原以为由于“一切都在命名空间 baz 中工作”,所以在添加 using namespace baz
.
之后,这在当前范围内也是如此
using foo::var;
除了使您的函数调用更加模棱两可之外,上面的行基本上什么也没做。第一个 using namespace foo
使命名空间 foo
中的任何内容在没有 foo::
的情况下可用(因此 var
)。下一行对命名空间 bar
做同样的事情。最后一行,如上所示,告诉编译器专门删除 baz 中 foo::var
only 的名称空间限定符。因此,在您的 if 语句中,编译器有 3 个候选者可供选择,并且可以选择 none。 GCC 7.2 给出的确切错误是:
prog.cc: In function 'void qux(int)':
prog.cc:24:14: error: reference to 'var' is ambiguous
if (n == var) {
prog.cc:4:9: note: candidates are: int foo::var
int var = 0;
prog.cc:9:9: note: int bar::var
int var = 1;
prog.cc:4:9: note: int foo::var
int var = 0;
为避免这种歧义,最好避免使用 using namespace a;
类型的语句,而是完全限定所有名称。
所以问题是当您使用可以来自两个命名空间的变量名时。当您在特定级别有多个候选人时,那就是一个模棱两可的问题。
你有 foo::var
和 bar::var
,你使
using namespace foo;
using namespace bar;
现在,当编译器看到 var 时,他无法知道您要使用哪个 var
。
如果你真的想使用那个using namespace
,那么你需要为这些变量做一个例外并说出你的意思f.e:
if (n == foo::var)
{
std::cout << "baz: var " << std::endl;
}
else if(n == bar::var)
{
std::cout << "baz: " << n << std::endl;
}
// I thought that the following line would resolve the name clash
using foo::var;
好吧,它确实解决了当前命名空间 的名称冲突,即 baz
。
如果将 qux
移动到 baz
,它会优先选择 foo::var
。
但是对于 ::qux
(在任何命名空间之外),没有理由比 bar::var
或 [=14= 更喜欢 baz::var
(foo::var
的别名) ], 因为它们都在当前命名空间搜索路径中。
尽管在全球范围内只看到 using namespace baz;
。
阅读 C++ 编程语言第 4 版后(第 14.4.4 节 - 组合和选择)我认为下面的程序可以正确编译:
#include <iostream>
namespace foo {
int var = 0;
// more declarations
}
namespace bar {
int var = 1;
// more declarations
}
namespace baz {
// composition of namespaces foo and bar
using namespace foo;
using namespace bar;
// I thought that the following line would resolve the name clash
using foo::var;
}
using namespace baz;
void qux(int n) {
if (n == var) {
std::cout << "baz: var " << std::endl;
} else {
std::cout << "baz: " << n << std::endl;
}
}
int main() {
qux(0);
qux(1);
}
预期的输出应该是
baz: var
baz: 1
当我尝试编译上面的代码时,我收到一条错误消息,指出对 'var' 的引用不明确。使用 foo::var
消除了编译错误,但我想更好地理解这个问题。
我的代码有什么问题?
如何以命名空间 baz 包含的方式解决名称冲突 foo::var
?
谢谢!
编辑
如以下答案中所建议,将 qux
的定义移动到命名空间 baz
中使其有效。因此,以下代码按预期编译
#include <iostream>
namespace foo {
int end = 0;
}
namespace bar {
int end = 1;
}
namespace baz {
using namespace foo;
using namespace bar;
using foo::end;
void qux(int n) {
if (n == end) {
std::cout << "baz: end " << std::endl;
} else {
std::cout << "baz: " << n << std::endl;
}
}
}
int main() {
baz::qux(baz::end);
baz::qux(1);
}
还有一件事我不是很清楚。我认为添加 using namespace baz
将使 baz
中的所有内容在当前范围内也可用,而无需使用 baz::
。换句话说,我原以为由于“一切都在命名空间 baz 中工作”,所以在添加 using namespace baz
.
using foo::var;
除了使您的函数调用更加模棱两可之外,上面的行基本上什么也没做。第一个 using namespace foo
使命名空间 foo
中的任何内容在没有 foo::
的情况下可用(因此 var
)。下一行对命名空间 bar
做同样的事情。最后一行,如上所示,告诉编译器专门删除 baz 中 foo::var
only 的名称空间限定符。因此,在您的 if 语句中,编译器有 3 个候选者可供选择,并且可以选择 none。 GCC 7.2 给出的确切错误是:
prog.cc: In function 'void qux(int)':
prog.cc:24:14: error: reference to 'var' is ambiguous if (n == var) {
prog.cc:4:9: note: candidates are: int foo::var int var = 0;
prog.cc:9:9: note: int bar::var int var = 1;
prog.cc:4:9: note: int foo::var int var = 0;
为避免这种歧义,最好避免使用 using namespace a;
类型的语句,而是完全限定所有名称。
所以问题是当您使用可以来自两个命名空间的变量名时。当您在特定级别有多个候选人时,那就是一个模棱两可的问题。
你有 foo::var
和 bar::var
,你使
using namespace foo;
using namespace bar;
现在,当编译器看到 var 时,他无法知道您要使用哪个 var
。
如果你真的想使用那个using namespace
,那么你需要为这些变量做一个例外并说出你的意思f.e:
if (n == foo::var)
{
std::cout << "baz: var " << std::endl;
}
else if(n == bar::var)
{
std::cout << "baz: " << n << std::endl;
}
// I thought that the following line would resolve the name clash using foo::var;
好吧,它确实解决了当前命名空间 的名称冲突,即 baz
。
如果将 qux
移动到 baz
,它会优先选择 foo::var
。
但是对于 ::qux
(在任何命名空间之外),没有理由比 bar::var
或 [=14= 更喜欢 baz::var
(foo::var
的别名) ], 因为它们都在当前命名空间搜索路径中。
尽管在全球范围内只看到 using namespace baz;
。