简体   繁体   English

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

[英]static class data vs. anonymous namespaces in C++

I occasionally have classes with private static data members. 我偶尔会有私有静态数据成员的类。 I'm currently debating if I should replace these with static variables in an unnamed namespace in the implementation file. 我目前正在讨论是否应该在实现文件中的未命名命名空间中用静态变量替换它们。 Other that not being able to use these variables in inline methods, are there any other drawbacks? 其他无法在内联方法中使用这些变量的其他缺点是什么? The advantage that I see is that is hides them completely from the users of the class. 我看到的优点是它完全隐藏了类的用户。

I'm not convinced that the benefit is worth the readability impact. 我不相信这种好处值得对可读性产生影响。 I generally consider something that's private to be "hidden enough." 我一般认为私有的东西“足够隐蔽”。

1) There is a drawback in the form of an added restriction on binary organization. 1)对二进制组织的附加限制形式存在缺陷。 In a presentation at a C++ conference in the 1990s, Walter Bright reported achieving significant performance increases by organizing his code so that functions that called each other were in the same compilation unit. 在20世纪90年代的C ++会议上的演示中,Walter Bright报告说通过组织他的代码来实现显着的性能提升,以便相互调用的函数位于同一个编译单元中。 For example, if during execution Class1::method1 made far more calls to Class2 methods than to other Class1::methods, defining Class1::method1 in class2.cpp meant that Class1::method1 would be on the same code page as the methods it was calling, and thus less likely to be delayed by a page fault. 例如,如果在执行期间Class1 :: method1对Class2方法的调用远多于对其他Class1 ::方法的调用,则在class2.cpp中定义Class1 :: method1意味着Class1 :: method1将与方法位于同一代码页上它正在调用,因此不太可能被页面错误延迟。 This kind of refactoring is easier to undertake with class statics than with file statics. 使用类静态比使用文件静态更容易进行这种重构。

2) One of the arguments against introducing the namespace keyword was "You can do the same thing with a class," and you will see class and struct being used as a poor-man's namespace in sources from the pre-namespace era. 2) 反对引入namespace关键字的一个论点是“你可以用类做同样的事情”,你会看到类和结构在前命名空间时代的源代码中被用作穷人的命名空间。 The convincing counter-argument was because namespaces are re-openable, and any function anywhere can make itself part of a namespace or access a foreign namespace, then there were things you could do with a namespace that you could not do with a class. 令人信服的反驳是因为命名空间被重新打开的,任何功能都可以随时随地进行本身就是一个命名空间的一部分,或者访问国外命名空间,那么有些事情,你可以用一个命名空间,你不能用一个类做做。 This has bearing on your question because it suggests that the language committee was thinking of namespace scope as very much like class scope; 这与您的问题有关,因为它表明语言委员会认为命名空间范围与类范围非常相似; this reduces the chance that there is some subtle linguistic trap in using an anonymous namespace instead of a class static. 这减少了使用匿名命名空间而不是静态类时存在一些微妙的语言陷阱的可能性。

I disagree with the other answers. 我不同意其他答案。 Keep as much out of the class definition as possible. 保持尽可能多的类定义。

In Scott Meyers' Effective C++ 3rd edition he recommends preferring non-friend functions to class methods. Scott Meyers的Effective C ++第3版中,他建议使用非友元函数来进行类方法。 In this way the class definition is as small as possible, the private data is accessed in as few places as possible (encapsulated). 通过这种方式,类定义尽可能小,私有数据在尽可能少的地方访问(封装)。

Following this principle further leads to the pimpl idiom . 遵循这一原则进一步导致了pimpl成语 However, balance is needed. 但是,需要平衡。 Make sure your code is maintainable. 确保您的代码可维护。 Blindly, following this rule would lead you to make all your private methods file local and just pass in the needed members as parameters. 盲目地,遵循这个规则将导致您将所有私有方法文件设置为本地,并且只需将所需成员作为参数传递。 This would improve encapsulation, but destroy maintainability. 这将改善封装,但会破坏可维护性。

All that said, file local objects are very hard to unit test. 总而言之,文件本地对象很难进行单元测试。 With some clever hacking you can access private members during unit tests. 通过一些聪明的黑客攻击,您可以在单元测试期间访问私人成员。 Accessing file local objects is a bit more involved . 访问本地文件的对象是多一点参与

I agree partly with Greg, in that unnamed namespace members aren't any more encapsulated than private data. 我部分同意Greg,因为未命名的命名空间成员不再是私有数据封装。 The point of encapsulation, after all, is to hide implementation details from other modules, not from other programmers. 毕竟,封装的目的是隐藏其他模块的实现细节,而不是其他程序员。 Nevertheless, I do think there are some cases where this is a useful technique. 尽管如此,我认为在某些情况下这是一种有用的技术。

Consider a class like the following: 考虑如下类:

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

In this case, any module that wants to use Foo must also know the definition of Bar even though that definition is of no relevance what-so-ever. 在这种情况下,任何想要使用Foo的模块也必须知道Bar的定义,即使该定义与以往无关。 These sort of header dependencies lead to more frequent and lengthier rebuilds. 这些类型的头依赖性导致更频繁和更长的重建。 Moving the definition of helper to an unnamed namespace in Foo.cpp is a great way to break that dependency. 将帮助程序的定义移动到Foo.cpp中的未命名的命名空间是打破该依赖关系的好方法。

I also disagree strongly with the notion that unnamed namespaces are somehow less readable or less maintainable than static data members. 我也强烈反对这样一种观念,即未命名的命名空间在某种程度上比静态数据成员更不易读或更难维护。 Stripping irrelevant information from your header only makes it more concise. 从标题中删除不相关的信息只会使其更简洁。

It not only hides them from users of the class, it hides them from you! 它不仅隐藏了类的用户,还隐藏了它们! If these variables are part of the class, they should be associated with the class in some way. 如果这些变量是类的一部分,它们应该以某种方式与类相关联。

Depending on what you are going to do with them, you could consider making them static variables inside static member functions: 根据您要对它们执行的操作,您可以考虑将它们作为静态成员函数中的静态变量:

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


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

I guess it boils down to whether these variables have some actual meaning in the context of the class (eg, pointer to some common memory used by all objects) or just some temporary data you need to pass around between methods and would rather not clutter the class with. 我想这可以归结为这些变量在类的上下文中是否具有某些实际意义(例如,指向所有对象使用的一些常见内存的指针),或者只是需要在方法之间传递的一些临时数据而不是混乱上课。 In the latter case I would definitely go with the unnamed namespace. 在后一种情况下,我肯定会使用未命名的命名空间。 In the former, I'd say it's a matter of personal taste. 在前者中,我会说这是个人品味的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM