16

我偶尔会有带有私有静态数据成员的类。我目前正在争论是否应该将这些替换为实现文件中未命名命名空间中的静态变量。除了不能在内联方法中使用这些变量之外,还有其他缺点吗?我看到的优点是对班级的用户完全隐藏了它们。

4

6 回答 6

4

我不相信好处值得可读性影响。我通常认为私密的东西“足够隐蔽”。

于 2009-05-13T13:17:18.113 回答
4

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

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

于 2009-05-13T13:27:44.510 回答
2

我不同意其他答案。尽可能远离类定义。

Scott Meyers 的 Effective C++ 第 3 版中,他建议优先使用非友元函数而不是类方法。通过这种方式,类定义尽可能小,私有数据在尽可能少的地方被访问(封装)。

遵循这一原则进一步导致了pimpl 成语。但是,需要平衡。确保您的代码是可维护的。盲目地,遵循此规则会导致您将所有私有方法文件设为本地文件,并将所需的成员作为参数传入。这将改善封装,但会破坏可维护性。

尽管如此,文件本地对象很难进行单元测试。通过一些巧妙的黑客攻击,您可以在单元测试期间访问私有成员。访问文件本地对象有点复杂

于 2009-05-14T02:12:30.343 回答
1

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

考虑如下类:

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

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

我也强烈反对未命名的命名空间在某种程度上比静态数据成员更不可读或更难维护的概念。从标题中删除不相关的信息只会使其更简洁。

于 2010-06-26T01:16:16.453 回答
1

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

根据您要对它们执行的操作,您可以考虑在静态成员函数中将它们设为静态变量:

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


// cpp file
void A :: func() {
    static int avar = 0;
    // do something with avar
}
于 2009-05-13T13:19:51.510 回答
1

我想这归结为这些变量在类的上下文中是否具有某些实际含义(例如,指向所有对象使用的一些公共内存的指针)或者只是一些您需要在方法之间传递的临时数据,而不是混乱与类。在后一种情况下,我肯定会使用未命名的命名空间。在前者中,我会说这是个人品味的问题。

于 2009-05-13T13:28:54.617 回答