Path: utzoo!attcan!uunet!taumet!steve From: steve@taumet.com (Stephen Clamage) Newsgroups: comp.lang.c++ Subject: Re: Are global class objects special? Message-ID: <463@taumet.com> Date: 27 Sep 90 16:34:58 GMT References: <26729@mimsy.umd.edu> Organization: Taumetric Corporation, San Diego Lines: 126 wilson@brillig.cs.umd.edu writes: >Am I right that there is no way to vary a parameter to >a constructor for a class object having global scope >without recompilation? I would like to vary the seed >to an object which is a random number generator used by >several different objects (which is why it is global). >Currently the seed must be hard coded since my tests show >that the constructor is invoked before main is executed. >I am using g++, the GNU C++ compiler. >For that matter, is there anything special about having a global >class object? I have code which runs properly when class objects >are declared within main, but when I move them up above main >the code crashes from within the constructor for the first object. >Actually the code crashes after trying to free up heap space used >for constructing a char* within the constructor. There is a slightly ugly but very portable technique to handle global objects, which are slightly special. It is used in the iostreams library to get the standard streams initialized at the right time. NOTE: The word "static" has two meanings in C and C++: It means having the lifetime of the program (non-auto), and it also means not externally declared/defined (non-extern). We need to use the word in both meanings here. I will qualify the word each time. Within a compilation unit, static (non-auto) objects are created in the order they are declared in the text, and destroyed in the reverse order. There is no portable way to guarantee the order of initialization of objects in different compilation units within a program. (Another poster mentioned that initialization occurs in the order in which the modules are linked. This may be true on some systems, but is by no means guaranteed.) So we define an initializer class and a static (non-extern) instance of the class in the class header which is included in every compilation unit which needs to know about the class. The class constructor has a "one-time switch" to insure the body is executed only once. file "myclass.h" ================ class myclass { .... }; class myclass_init { static int count; public: myclass_init(); ~myclass_init(); }; static myclass_init mi; ================ file "myclass.c" ================ #include "myclass.h" ... // myclass member functions myclass_init::count = 0; // static member initialization // this constructor will be executed before any other constructors in // any modules which include "myclass.h" myclass_init::myclass_init() { if( ++count == 1 ) { // one-time processing here } } // this destructor will be executed after all other destructors in // any modules which include "myclass.h" myclass_init::~myclass_init() { if( count-- == 1 ) { // one-time processing here } } ================ ================ A similar technique can be used to get exactly one object of a given type statically constructed conceptually before main begins. file "myclass.h" ================ class myclass { ... public: myclass(); }; class myclass_init { public: myclass_init(); }; static myclass_init mi; extern myclass *my; // we want exactly one of these statically constructed ================ file "myclass.c" ================ #include ... // myclass member functions myclass my = 0; // defining instance of mi set to 0 myclass_init::myclass_init() { if( ! my ) { my = new myclass(); // gets constructed exactly once ... // other processing } } ================ ================ As long as myclass.h is included in a file before any reference to anything which depends on what it does, the static construction will have occurred first. -- Steve Clamage, TauMetric Corp, steve@taumet.com