匿名命名空间:它们真的那么棒吗?

时间:2010-12-22 21:39:53

标签: c++ static namespaces

我长期使用static关键字来定义内部链接。后来,我转而采用C ++方式在匿名命名空间中包装本地事物。

但是,现在当我使用匿名命名空间多年时,我开始认为static关键字更容易使用!

一个常见问题是我有这种模式:

namespace {
    // ...five pages of code...
}  // namespace

要查看某个函数是否具有内部或外部链接,我现在必须滚动很多,而不是旧的C样式,我可以检查函数/对象是否在其前面有static

我知道匿名命名空间有些事情static不能 - 隐藏typedef - 但不管怎样我个人对此并不是很感兴趣。

你对此有何看法?匿名命名空间的胜利是否很好,它保证了可读性的降低?或者我都错了?

3 个答案:

答案 0 :(得分:20)

如果命名空间中的代码太长,那么就没有什么可以阻止你这样做了:

namespace {
    int foo(char* x) {
        return x[0] + x[1];
    }
}

namespace {
    int bar(char *x, char *y) {
        return foo(x) + foo(y);
    }
}

在C ++ 03中,使用未命名的命名空间的实际优势恰恰在于内容具有外部链接(但在TU之外仍然不可见,因为无法引用它们)。模板参数不能具有内部链接:

namespace {
    int foo(const char* x) {
        return x[0] + x[1];
    }
}

static int foo2(const char *x) {
    return x[0] + x[1];
}

template <int (*F)(const char*)>
void baz(const char *p) {
    F(p);
}

int main() {
    baz<foo>("ab");   // OK
    baz<foo2>("ab");  // not valid
}

答案 1 :(得分:2)

除了Steve提到的非常有效的观点之外,我还看到匿名命名空间中的其他非常重要的方面使它们优于静态函数: 地点,易于重构和信息隐藏

假设您有一个或两个类函数需要其他几个非常具体但不使用类成员的辅助函数。如果你坚持使用Robert C. Martin(函数应该很小并且服务于一个明确定义的目的),你会经常发现大函数可以重构为较小的函数,尽管这些较小的函数在开始时可能只用于以前的大函数。

那么你有什么选择:

  1. 立即制作一个新的(可能是私人的)课程:

    这需要相当多的打字可能是矫枉过正的 - 小伙子面对它 - 每个人 有时是懒惰或匆忙。

  2. 生成私有静态函数或非成员函数:

    如果你这样做,都需要编辑头文件和cpp文件 正确的,所以仍然有一点负担可能会打断你的 超出必要的工作流程并生成不必要的代码 你的头文件混乱,可能需要前进声明或 甚至还包括你的标题。

  3. 匿名命名空间:

    你有一个不需要的辅助功​​能 会员访问并服务于一个目的 - &gt;把它放在那里写下来 函数接近将使用它的类方法。这很大 我喜欢的一个:它很快,它不会使头文件混乱。 命名空间明确指出:除了这个cpp之外,其他任何东西都不使用它。没有 朋友会使用它,没有图书馆用户会知道它的存在。您 几乎不可能更明显,这种范式往往会导致 清洁功能设计,输入参数少,只有一个 输出已修改。你还有函数局部性:在初级之前定义 使用。虽然这可能是一个缺点,但我觉得在浏览时非常有用 大类的实现。另一个优点是跨越几个常数 函数但对库用户来说并不是很有趣。把它们放进去 命名空间,与使用它们的函数最相同。如果它转 以后你需要其他地方的常量和函数,转换 整个上课,它已经整齐地包装好了。

  4. 免责声明:很多人可能会争辩说使用pimpl更加清晰。这只是我个人的意见。

答案 2 :(得分:1)

匿名命名空间是唯一不允许类声明污染全局范围的东西。在.cpp文件中定义类时非常有用。