TITLE: discussion of singletons (Newsgroups: comp.lang.c++.moderated, 8 Mar 97) [ Although it is not mentioned by name, this is really a discussion of the singleton design pattern. You can find more of this under the design section at http://www.ses.com/~clarke/TableOfContents.html -adc ] UNKNOWN: > Hi, what I would like to know is, is it acceptable to have a public > static function to initialize a "class variable" (i.e. a static > member variable), such as the following: > > class A { > static int blah; > public: > static void init_class(int foo) { blah = foo; } > } > > This strikes as unsatisfactory since it doesn't force the user of > the class to initialize the static member at runtime, which is what > I would like. Is there a standard method for achieving this? MEYERS: Scott Meyers Initialization of statics has been addressed by several authors (see below), but this is a form of the problem I've never actually seen before. That's because most treatments of static initialization focus on the *timing* of initialization, and they assume that no outside information is necessary for the initialization process itself. In this case, a::blah can't be initialized until foo has been provided by some outside agent (via A::init_class). In other words, it's not enough to ensure that blah is "constructed" prior to use, it's also important to ensure that blah isn't used until foo has been provided and blah has taken on that value. That's a harder problem than most authors address (including me). You can initialize a static at runtime with a function, as shown below, but I think your point is that you don't really know foo until after "main" starts, so the code below is too simple for your problem: // A.CPP int A::blah = initialize_blah(); // MAIN.CPP int initialize_blah() {return foo;}; Note that this fails to prevent other translation units (e.g., B.CPP) from accessing A::blah before initialize_blah has been called. That's the problem most authors try to tackle. See below. If you want to force a later setting of blah, then I don't think you have much choice but to make blah into a function. This is better encapsulation, anyway: // untested code class A { public: static int blah() { if (!mblahinit) throw some_exception; else return mblah; } static void init_class(int foo) { mblah = foo; mblahinit = TRUE; } private: static int mblah; static bool mblahinit; } int A::mblah = 0; bool A::mblahinit = FALSE; For what it's worth, most programmers adopting this type of approach make mblah into a pointer and use a value of 0 (null pointer) to indicate that mblah hasn't yet been initialized. This makes it possible to eliminate mblahinit, though it also makes it tougher to determine how and when to delete mblah. Where it's applicable, I prefer the approach I describe in Item 26 of More Effective C++, which moves mblah out of A and into A::blah. This works for any type T where the necessary constructor arguments are available during compilation, so kindly allow me to generalize the type of mblah: class A { public: static T& blah(); // note the reference return type private: ... // mblah and mblahinit are no longer here }; T& A::blah() { static T blahValue ( /* ctor arguments */ ); return blahValue; } Here blahValue is initialized if and only if blah is called, so unneeded statics are never constructed. However, because blahValue is inside A::blah, there's no way to write an analogue to init_class. If you need init_class-like capability, you're better off with the design Steve described. There are some subtle points with initializing statics, when you want statics in different compilation units to depend on each other. This is somewhat rare, but tough to track down. Scott Meyers makes passing reference to this issue in "More Effective C++", item 26, but if he does a third book, I would like to see more detail about this problem. I've found it hard to track down information about lazy instantiation of statics, and I've checked a few different sources. I describe a complete approach in Item 47 of Effective C++, but recent clarifications to and interpretations of the soon-to-be C++ standard lead to the conclusion that my approach (often called the "nifty counter" approach after its name in the ARM) can't be guaranteed to never fail. Sigh. For my money, the best treatment of this problem is found in Martin Carroll's and Margaret Ellis' "Designing and Coding Reusable C++"; they weigh the advantages and disadvantages to something like four different approaches (including the ones described above) to this problem. You can also read about this problem in Murray's "C++ Strategies and Tactics" and in Gamma et al's "Design Patterns" (look under "Singleton"). Like all good C++ books, the above are all from Addison-Wesley :-) If you're determined to stray to other publishers, the long-awaited and recently-released "Industrial Strength C++" by Henricson and Nyquist contains a treatment of this topic. None of these treatments offers a foolproof solution. For what it's worth, the standardization committee struggled to come up with a way to solve the problem of initialization order of static objects in different translation units, and they ultimately gave up -- they were unable to find a way that always worked (especially in conjunction with template-generated static objects). It's a hard problem.