使用名称空间行为的基本原理 [英] Rationale behind using namespace behavior

查看:89
本文介绍了使用名称空间行为的基本原理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

引用标准:

using指令指定所提名名称空间中的名称 可以在使用指令出现在以下位置的范围内使用 使用指令.在不合格的名称查找(3.4.1)期间,名称 好像它们是在最近的封闭命名空间中声明的一样 其中包含using指令和指定的名称空间.

A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.

看下面的代码:

namespace A {

    int fn() { return 1; }

}

namespace Inner {

    int fn() { return 2; }

    namespace B {

        using namespace A;

        int z = fn();

    }

}

在这里,在我知道命名空间的确切规则之前,我曾希望在编写using namespace A时将z初始化为1,因此期望使用A::fn().但是不是这种情况,由于我引用的规则,z将被初始化为2,因为Inner::fn()被调用.

Here, before I knew the exact rules of namespaces, I had expected that z will be initialized to 1, as I written using namespace A, so expected that A::fn() will be used. But it is not the case, z will be initialized to 2, as Inner::fn() is called because of the rule I quoted.

此行为背后的原理是什么:就像在包含使用指令和指定名称空间的最近的封闭名称空间中声明它们一样?"

What is the rationale behind this behavior: "as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace"?

如果using namespace可以为该命名空间中的所有内容使用声明进行应用,那么会有什么弊端?

What would be the cons, if using namespace worked as applying using declarations for everything in that namespace?

注意:是促使我提出此问题的相关问题.

Note: this is the related issue that motivated me to ask this question.

推荐答案

名称空间系统的理想属性是我所说的增量API兼容性.也就是说,如果我将符号添加到命名空间,则任何以前运行的程序都应继续工作并表示相同的意思.

A desirable property of a namespace system is that of what I call incremental API compatibility. That is, if I add a symbol to a namespace, then any previously working program should keep working and mean the same thing.

现在,带有重载的普通C ++与增量API不兼容:

Now, plain C++ with overloads is not incrementally API compatible:

int foo(long x) { return 1; }

int main()
{
    foo(0);
}

现在,我添加了重载int foo(int x) { return 2; },程序默默地更改了含义.

Now I add the overload int foo(int x) { return 2; } and the program silently changes meaning.

无论如何,当C ++人员设计namespace系统时,他们希望在增加外部API时,以前的工作代码不应更改选择符号的名称空间.在您的示例中,先前的工作代码将类似于:

Anyway, when C++ people designed the namespace system they wanted that when incrementing an external API, previously working code should not change the namespace from where the symbol is chosen. From your example, the previous working code would be something like:

namespace A {
    //no fn here, yet    
}

namespace Inner {

    int fn() { return 2; }

    namespace B {

        using namespace A;
        int z = fn();
    }
}

并且z易于初始化为2.现在,使用名为fn的符号扩展名称空间A不会更改该工作代码的含义.

And z is easily initialized to 2. Now augmenting namespace A with a symbol named fn will not change the meaning of that working code.

相反的情况并不适用:

namespace A {
    int fn() { return 1; }
}

namespace Inner {

    // no fn here

    namespace B {

        using namespace A;
        int z = fn();
    }
}

此处z初始化为1.当然,如果将fn添加到Inner,它将改变程序的含义,但是Inner不是外部API:实际上,当最初编写Inner时,A::fn已经存在(它已经存在了)被召唤!),所以没有理由不意识到冲突.

Here z is initialized to 1. Of course, if I add fn to Inner it will change the meaning of the program, but Inner is not an external API: actually, when Inner was written initially, A::fn did already exist (it was being called!), so there is no excuse for being unaware of the clash.

想象一下这个C ++ 98程序:

Imagine this C++98 program:

#include <iostream>

namespace A {
int move = 0;
void foo()
{
    using namespace std;
    cout << move << endl;
    return 0;
}
}

int main()
{
    A::foo();
    return 0;
}

现在,如果我使用C ++ 11进行编译,则由于此using规则,一切都可以正常工作.如果using namespace std可以为该命名空间中的所有内容使用声明进行应用,则该程序将尝试打印功能std::move而不是A::move.

Now, if I compile this with C++11, everything works fine thanks to this using rule. If using namespace std worked as applying using declarations for everything in that namespace, then this program would try to print function std::move instead of A::move.

这篇关于使用名称空间行为的基本原理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆