2010-12-22 52 views
16

我一直在长时间使用static关键字来定义内部链接。后来,我转向使用匿名命名空间封装本地事物的C++风格。匿名命名空间:他们真的很棒吗?

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

一个常见的问题是,我有这样的模式:

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

要查看某个函数内部或外部的联系,我现在必须滚动了很多,而不是旧的C风格,我可以检查前面的功能/对象是否有static

我知道有一些事情匿名命名空间可以做到这一点static不能隐藏typedefs - 但个人而言,我并不是真的对此非常感兴趣。

你对此有何看法?匿名命名空间的胜利是否值得降低可读性?或者我都出错了?

+3

命名空间范围内的`static`函数已被弃用,这是不使用它们的充分理由。 anon命名空间中的函数具有`static`的所有优点,除了它们具有外部链接。后者我认为已经由编译器处理,从导出的部分中删除匿名命名空间中定义的名称。 – 2010-12-22 21:58:04

+11

@实际上,静态函数永远不会被弃用。弃用仅针对* objects *。但是,在n3225中已经取消了弃用:在C++ 0x中,不再推荐使用它来为对象或函数提供内部链接。另一个区别是未命名的名称空间会保留外部链接:未命名的名称空间及其内容将在C++ 0x中获得内部链接。所以在static-way和namespace-way之间似乎没有任何区别,除了namespace-way将允许诸如`namespace {int a; } int a;`。 – 2010-12-22 22:09:27

回答

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

一位不愿具名的命名空间是不会让一个类声明污染在全球范围内的唯一的事。在.cpp文件中定义类时非常有用。

2

除了由史蒂夫注意到了非常有效的点我看在匿名的命名空间,使他们优于静态功能等非常重要的方面: 局部性,易于重构和信息隐藏

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

那么选择你有:

  1. 立即作出了新的(也许是私有)类:

    这需要相当大量的输入可能是矫枉过正和-lets面对它 - 每个人 有时是懒惰或匆忙。

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

    两个需要编辑的头文件和CPP文件,如果你这样做 正常,所以还是有点负担可能中断您的 工作流程更并且生成不必要的代码 混乱您的头文件,可能需要前向声明或 甚至在您的头文件中包含更多内容。

  3. 匿名命名空间:

    你不需要 成员访问,并提供一个目的的辅助功能 - >把它放在那里,靠近写这个 功能类的方法,其中将使用它。这是由我的首选大 :它很快,它不会混乱头文件。这个命名空间清楚地表明:除了这个cpp以外,这个命令不会被其他任何东西使用。没有 的朋友会使用它,并且没有图书馆用户会知道它的存在。你几乎不会更明显,通常这种范例会导致更清洁的功能设计,这是很少的输入参数,只有一个 输出被修改。此外,您还有功能位置:定义在主要使用 之前。虽然这可能是一个缺点,但我发现在浏览大类的 实现时非常有帮助。另一个优点是跨越几个 函数的常量,但对图书馆用户来说并不是很有趣。将它们放在 命名空间中,最好与使用它们的函数相同。如果后来变为 ,则需要常量和其他函数,将整个变换为一个类,它已经整齐地打包了。

声明:许多人可能会争辩说,使用pimpl是远远更清洁。这只是我个人的意见。

相关问题