views:

1378

answers:

6

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.

+4  A: 

I'm not convinced that the benefit is worth the readability impact. I generally consider something that's private to be "hidden enough."

Greg D
+1  A: 

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
}
anon
+3  A: 

1) There is a drawback in the form of an added restriction on binary organization. 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. 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. 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. 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.

Thomas L Holaday
Keep in mind that that was in the 90s and that compilers have advanced to the point where things like VC++'s "whole program optimization" work well enough that that kind of refactoring is a waste of programmer time.
Steve M
Has Walter Bright said that this kind of refactoring is now a waste of time? One of the questions at that session, addressing maintainability concerns, was "who but you will be able to do such things when you retire?" to which Walter replied words to the effect of "When I retire, compilers will get slower."
Thomas L Holaday
+1  A: 

I guess it boils down to whether these variables have some actual meaning in the context of the class (e.g., 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.

Ari
+1  A: 

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. 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. 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.

caspin
A: 

I agree partly with Greg, in that unnamed namespace members aren't any more encapsulated than private data. 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. 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.

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.

Peter Ruderman