使用命名空间对定义无效

using namespace does not work for definitions?

本文关键字:定义 无效 命名空间      更新时间:2023-10-16

我在理解c++名称空间时遇到问题。考虑以下示例:

//distr.h
namespace bogus{
    extern const int x;
    extern const int y;
    double made_up_distr(unsigned param);
}

现在,如果我定义我的变量,比如下面的cpp,所有的东西都会编译好

//distr.cpp
#include "distr.h"
#include <cmath>
const int bogus::x = 10;   
const int bogus::y = 100;
double bogus::made_up_distr(unsigned param){
    auto pdf = (exp(param) / bogus::x) + bogus::y;
    return pdf;
}

但是,如果我尝试简单地引入bogus名称空间并使用

//broken distr.cpp
#include "distr.h"
#include <cmath>
using namespace bogus;
const int x = 10;
const int y = 100;
double made_up_distr(unsigned param){
    auto pdf = (exp(param) / x) + y;
    return pdf;
}

我的编译器告诉我对xy的引用是不明确的。为什么?

有一个简单的原因可以解释为什么这不能像你预期的那样工作:

namespace bogus {
    const int x;
}
namespace heinous {
    const int x;
}
using namespace bogus;
using namespace heinous;
const int x = 10;

现在,上面的x应该指bogus::xheinous::x还是新的全局::x?这将是第三个没有using语句的代码,这意味着添加using语句将以一种特别微妙的方式改变现有代码的含义。

using语句用于介绍查找的作用域(通常但不一定是命名空间)的内容。声明

const int x = 10;

通常一开始就不需要查找,除非检测到ODR违规。

声明/定义中的标识符的名称查找与使用中的名称查找不同。特别是,它不关心使用语句。原因很简单:如果情况不同,就会导致各种令人讨厌的惊喜。考虑一下:

// sneakattack.h
namespace sneakattack { void foo(); }
using namespace sneakattack;
// somefile.cpp
#include "sneakattack.h"
void foo() { std::cout << "Hellon"; }
// otherfile.cpp
void foo();
int main() { foo(); }

该程序当前有效:声明sneakattack::foo被忽略,定义::foo被正确地链接到其他文件中的使用。但是,如果名称查找的工作方式不同,某个文件会突然定义sneakattack::foo,而不是::foo,并且程序将无法链接。