nsundare@copper.ucs.indiana.edu (Neelakantan Sundaresan) (03/05/91)
I am trying to solve the problem of initializing the static(shared) data area of a class type. Basically I would like this initializtion and any other house keeping stuff done, when the first object instance of that class is 'construct'ed. Is there a neat way to achieve this? What I have been doing is define a global variable of that class, whose constructor is different from any others for that class (in the sense of number or types of parameters it takes) and in the code for this constructor do the initialization. I guess this is not a very clean way to do it, Is there a better way to solve this.... Thanks for any ideas, Neel Sundaresan (A C++ novice)
wlp@calmasd.Prime.COM (Walter L. Peterson, Jr.) (03/08/91)
In article <1991Mar4.224519.6434@bronze.ucs.indiana.edu> nsundare@copper.ucs.indiana.edu (Neelakantan Sundaresan) writes: > >I am trying to solve the problem of initializing the static(shared) data >area of a class type. Basically I would like this initializtion and any >other house keeping stuff done, when the first object instance of that >class is 'construct'ed. Is there a neat way to achieve this? > There is no "neat" way to do this. There is, however, "A" way to do this. What you need to do is create yet another class, not a special constuctor. If your class is called Foo, lets call this new class Foo_Starter: // declare clas Foo here class Foo { static whatever; }; class Foo_Starter { static count; public: Foo_Starter() { if (count++ == 0) { whatever = 33; // initialize Foo's static data members } } ~Foo_Starter() { if (--count ==0) { // clean up Foo's statics ( if necessary ) } } }; static Foo_Starter startfoo; Put these declarations and definitions in the same header file. When that header file's code is encountered for the first time during execution, the static instance of Foo_Starter will be constructed. The static data member count in Foo_Starter will have been initialized to zero. By the language definition of C++ statics, unlike all other type of objects, ARE initialized to zero. The constructor will test count before incrementing it and if it is zero, will initialize the statics for your class Foo. Since the value of count is now incremented, any further encounters with this header code will not cause re-initialization of Foo's statics. The destructor can do any clean up that might be necessary. It is important to note that the point in the Foo_Starter constructor where it initializes the static is NOT where the static is defined. The static MUST still be defined in some file that will occur once and ONLY once in a program; that is to say in a .c file. So, if this header file is called Foo.h and Foo's member functions are defined in a file called Foo.c, you will need to define the statics at file-scope level in Foo.c. Please note that this "fix" prevents you from declaring either an extern or static to be a const or a *const since the initialization will not be able to take place at the same point as definition. All of this folderol is necessary because C++ does not specify any order to the initialization of objects with external linkage. Some hack (er.. trick, er.... technique) like this is absolutely essential if you are going to declare any instances of Foo at file-scope level and if the construction of those instances relies on the existance of some meaningfull data existing in the statics. Refer to section 3.4 of the ARM for a more detailed explaination/excuse of this stuff. It is to be hoped that X3J16 will take some positive action with regard to the order of initialization of object with external linkage so that hacks like this will not be needed in the future. -- "Exploring the consensual hallucination of cyberspace" Walter L. Peterson, Jr. Internet : wlp@calmasd.Prime.COM CompuServe : 70441,3177 "The opinions expressed here are my own."
jeffw@sparc27.tamu.EDU (Jeffrey A Waller) (03/08/91)
In article <2390@calmasd.Prime.COM>, wlp@calmasd.Prime.COM (Walter L. Peterson, Jr.) writes: |> In article <1991Mar4.224519.6434@bronze.ucs.indiana.edu> nsundare@copper.ucs.indiana.edu (Neelakantan Sundaresan) writes: |> > |> >I am trying to solve the problem of initializing the static(shared) data |> >area of a class type. Basically I would like this initializtion and any |> >other house keeping stuff done, when the first object instance of that |> >class is 'construct'ed. Is there a neat way to achieve this? |> > |> |> There is no "neat" way to do this. There is, however, "A" way to do |> this. What you need to do is create yet another class. I would only agree if this data area included static class members which required dynamic initialization. Otherwise leave everything in the class: class Foo { private: static int count; . . . void initialize_static_stuff(); public: Foo() { if(!count++) initialize_static_stuff(); . . . } }; Obviously, there are restrictions, though it works with what I find to be the most common sort of initialization -- calling malloc and/or new. -Jeff
wlp@calmasd.Prime.COM (Walter L. Peterson, Jr.) (03/13/91)
In article <13174@helios.TAMU.EDU|> jeffw@sparc27.tamu.EDU (Jeffrey A Waller) writes: |>I would only agree if this data area included static class members which required |>dynamic initialization. Otherwise leave everything in the class: |> |>class Foo |>{ private: |> |> static int count; |> . |> . |> . |> void initialize_static_stuff(); |> |> public: |> |> Foo() |> { if(!count++) initialize_static_stuff(); |> . |> . |> . |> } |>}; |> |>Obviously, there are restrictions, though it works with what I find to be the |>most common sort of initialization -- calling malloc and/or new. |> It is true that static data members that do not require dynamic initialization do not need the technique from the ARM, however, they do not need this also dont, in general, need this technique either. They frequently can just be initialized where they are declared in the class. In any case there is one problem with the implementation shown above. That is a problem with efficiency. In the example above, the test of count will be made every time an instance of Foo is created, even though it is only needed when the first instance is created. The example in my article, ( which was shamelessly cribbed from the ARM ) will be executed exactly once upon the comming into scope of each translation unit which included the header file. If Foo is a class that might have many instances created, such as a 2D or 3D point class in a CAD system, this efficiency issue can be significant. Also, it is always possible to find specific solutions to specific problems that are "better" for that particular problem than more general solutions. The solution from the ARM which I wrote about is a very general solution, that will work in virutally all cases. Finally: The exact technique used to hack arround this problem in C++ is not and should not be the real issue. The real issue is that the current lack of definition of the order of initialization of externally linked objects is not an acceptable state of afairs and a proper solution to this problem must be addressed by X3J16. -- "Exploring the consensual hallucination of cyberspace" Walter L. Peterson, Jr. Internet : wlp@calmasd.Prime.COM CompuServe : 70441,3177 "The opinions expressed here are my own."