使用命名空间不适用于定义?

时间:2013-07-22 14:48:03

标签: c++ namespaces

我无法理解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的引用含糊不清。 那是为什么?

2 个答案:

答案 0 :(得分:6)

有一个简单的原因,为什么这不能按预期的方式运作:

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语句用于为 lookup 引入范围的内容(通常但不一定是命名空间)。声明

const int x = 10;
除了检测ODR违规外,

通常不会首先要求查找。

答案 1 :(得分:1)

声明/定义中标识符的名称查找与使用中的名称查找的工作方式不同。特别是,它不关心使用语句。这有一个非常简单的原因:如果它不同,它将导致各种令人讨厌的惊喜。考虑一下:

// sneakattack.h
namespace sneakattack { void foo(); }
using namespace sneakattack;

// somefile.cpp
#include "sneakattack.h"
void foo() { std::cout << "Hello\n"; }

// otherfile.cpp
void foo();
int main() { foo(); }

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