静态类数据与C ++中的匿名命名空间

时间:2009-05-13 13:02:04

标签: c++ namespaces static-members

我偶尔会有私有静态数据成员的类。我目前正在讨论是否应该在实现文件中的未命名命名空间中用静态变量替换它们。其他无法在内联方法中使用这些变量的其他缺点是什么?我看到的优点是它完全隐藏了类的用户。

6 个答案:

答案 0 :(得分:4)

我不相信这种好处值得对可读性产生影响。我通常会认为某些东西是“非常隐蔽的”。

答案 1 :(得分:4)

1)对二元组织的附加限制形式存在缺陷。在20世纪90年代的C ++会议上的演示中,Walter Bright报告说通过组织他的代码来实现显着的性能提升,以便相互调用的函数位于同一个编译单元中。例如,如果在执行期间Class1 :: method1对Class2方法的调用远多于对其他Class1 ::方法的调用,则在class2.cpp中定义Class1 :: method1意味着Class1 :: method1将与方法位于同一代码页上它正在调用,因此不太可能被页面错误延迟。使用类静态比使用文件静态更容易进行这种重构。

2)反对引入namespace关键字的一个参数是“你可以用类做同样的事情”,你会看到类和结构被用作穷人的命名空间来自命名空前时代的消息来源。令人信服的反驳是因为命名空间是可重新打开的,任何地方的任何函数都可以使自己成为命名空间的一部分或访问外部命名空间,然后你可以用不做一个班级。这与您的问题有关,因为它表明语言委员会认为命名空间范围与类范围非常相似;这减少了使用匿名命名空间而不是静态类时存在一些微妙的语言陷阱的可能性。

答案 2 :(得分:2)

我不同意其他答案。尽可能多地离开课堂 尽可能定义。

Scott Meyers' Effective C++ 3rd edition中,他建议更喜欢非朋友 类方法的函数。这样,类定义如下 尽可能小,私人数据在很少的地方访问 可能(封装)。

遵循这一原则进一步导致pimpl idiom。然而, 需要平衡。确保您的代码可维护。盲目, 遵循此规则将引导您创建所有私有方法 文件本地,只需传入所需的成员作为参数。这个 将改进封装,但破坏可维护性。

所有这一切,文件本地对象很难进行单元测试。同 一些聪明的黑客你可以在单元测试期间访问私人成员。 访问文件本地对象有点involved

答案 3 :(得分:1)

它不仅隐藏了班级用户,还隐藏了你!如果这些变量是类的一部分,它们应该以某种方式与类相关联。

根据你要对它们做什么,你可以考虑在静态成员函数中使它们成为静态变量:

// header file
class A {
  public:
     static void func();
};


// cpp file
void A :: func() {
    static int avar = 0;
    // do something with avar
}

答案 4 :(得分:1)

我想这可以归结为这些变量在类的上下文中是否具有某些实际意义(例如,指向所有对象使用的一些常见内存的指针)或者只是需要在方法之间传递的一些临时数据而宁愿不要把班级弄得乱七八糟。在后一种情况下,我肯定会使用未命名的命名空间。在前者中,我会说这是个人品味的问题。

答案 5 :(得分:1)

我部分同意Greg,因为未命名的命名空间成员不再是私有数据封装。毕竟,封装的目的是隐藏其他模块的实现细节,而不是其他程序员。尽管如此,我确实认为在某些情况下这是一种有用的技术。

考虑如下类:

class Foo {
public:
    ...
private:
    static Bar helper;
};

在这种情况下,任何想要使用Foo的模块也必须知道Bar的定义,即使该定义与以前无关。这些类型的头依赖性导致更频繁和更长的重建。将助手的定义移动到Foo.cpp中的未命名的命名空间是打破这种依赖的好方法。

我还强烈反对这样一种观念,即无名的命名空间在某种程度上比静态数据成员更不易读或更难维护。从标题中删除不相关的信息只会使其更简洁。