1

阅读The C++ Programming Language 第 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: 变量

巴兹: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.

4

3 回答 3

2
// I thought that the following line would resolve the name clash
using foo::var;   

好吧,它确实解决了当前命名空间的名称冲突,即baz.

如果搬进quxbaz,那就更喜欢了foo::var

但是对于::qux(在任何命名空间之外),没有理由更喜欢baz::var(的别名foo::var)而不是bar::varor foo::var,因为它们都在当前命名空间搜索路径中。

即使只using namespace baz;在全球范围内看到。

于 2018-02-07T23:17:03.580 回答
2
using foo::var;

上面的行基本上什么都不做,只是让你的函数调用更加模棱两可。第一个using namespace foo使命名空间中的任何内容都foo可以在没有foo::(So var) 的情况下使用。下一行对 namespace 做同样的事情bar。最后一行,如上所示,告诉编译器专门删除foo::var baz 内部的命名空间限定符。因此,在您的 if 语句中,编译器有 3 个候选者可供选择,并且不能选择一个。GCC 7.2 给出的确切错误是:

prog.cc:在函数'void qux(int)'中:

prog.cc:24:14:错误:如果(n == var){ 对“var”的引用不明确

prog.cc:4:9:注意:候选人是:int foo::var int var = 0;

prog.cc:9:9: 注意: int bar::var int var = 1;

prog.cc:4:9: 注意: int foo::var int var = 0;

现场观看

为避免这种歧义,最好避免此类语句,using namespace a;而是完全限定所有名称。

于 2018-02-07T22:46:59.590 回答
0

所以问题是当你使用可以来自两个命名空间的变量名时。当您在特定级别有多个候选人时,那就是模棱两可了。你有foo::varand bar::var,你做 using namespace foo; using namespace bar;

现在当编译器看到 var 时,他不知道var你要使用哪个。如果你真的想使用 that using namespace,那么你需要为这些变量做一个例外并说出你的意思:

if (n == foo::var) 
{
    std::cout << "baz: var " << std::endl;
} 
else if(n == bar::var) 
{
    std::cout << "baz: " << n << std::endl;
}
于 2018-02-07T22:48:01.177 回答