C ++:使用声明和指令的顺序是否会影响选择?

问题描述 投票:3回答:2

下面是示例代码

#include <iostream>
using namespace std;


namespace A {
    void f() { cout << "a" << endl; }
}
namespace B {
    void f() { cout << "b" << endl; }
}
namespace C {
    using namespace A;
    using namespace B;
    using A::f;
}
namespace D {
    using A::f;
    using namespace A;
    using namespace B;
}
int main()
{
    C::f();
    D::f();
}

当我在Visual Studio 2015中尝试时,这会打印“a”两次,这种行为是由标准定义还是特定于此实现?

c++ using
2个回答
4
投票

它由标准定义(这样的事情总是如此)。要意识到的关键是,你的各种using namespace线对你的程序没有任何影响。

using namespace Foo是一个“using指令”,它影响名称查找,该查找由作用域内的代码执行。也就是说,如果你的namespace C {}块中的一些后来的函数试图找到一个名为foo的对象,那么AB将成为编译器搜索找到foo的地方之一。相反,如果后面的代码引用C::foo,它将不会改变编译器的外观。单个块中两个连续using namespaces的顺序并不重要,因为每个块都具有完全效果,直到块结束。

你能在fC找到D的原因是“使用声明”using A::f。与using-directive不同,using声明具有将名称注入作用域的效果,这样其他代码可以将名称称为在该作用域内。


4
投票

来自cppreference.com的以下两段应该解释这种行为:

using-directive [using namespace A;]不会在其出现的声明区域中添加任何名称(与using-declaration [using A::f;]不同),因此不会阻止声明相同的名称。

出于非限定查找的目的,using-directives是可传递的:如果一个scope包含一个指定namespace-name的using-directive,它本身包含某些namespace-name-2的using-directive,那么效果就好像using指令来自第二个命名空间出现在第一个。这些传递命名空间发生的顺序不会影响名称查找。

简单地说:using A::f;就像你在这个命名空间中声明了这个函数一样。 using namespace A;只会导致typename查找行为,就像你的情况下当前命名空间(CD)是A中的命名空间一样。

这与如何相似

namespace A {
    void f() { cout << "a" << endl; }

    namespace B {
        void f() { cout << "b" << endl; }
    }
}

namespace A {
    namespace B {
        void f() { cout << "b" << endl; }
    }

    void f() { cout << "a" << endl; }
}

是等价的。

© www.soinside.com 2019 - 2024. All rights reserved.