"Victor Bazarov" <v.********@comAcast.net> wrote in message news:<HmYJb.731281$HS4.5490555@attbi_s01>...
"jose luis fernandez diaz" <jo**********************@yahoo.es> wrote... Christof Krueger <ne**@pop2wap.net> wrote in message
news:<bt*************@news.t-online.com>... >>Put them all in one special compilation unit, "external data".
>
>
> Can you give me an example ?. How can I be sure in the example below
> that y is always 1 ?
>
>
>>Victor
Within one compilation unit initialisation takes place in the order as
written in the file.
So put all your global variables in one cpp-file (or whatever extension
you prefer)
// globals.cpp
int x = 1;
int y = x;
<EOF>
// foo.cpp
extern int x;
...
// bar.cpp
extern int y;
...
This way initialisation takes place in globals.cpp in a well defined
order. Your foo.cpp and bar.cpp files can then use the globals by
declaring them with the extern keyword.
Ok, but what if I design a library. How can I force their users to
initialize the library global variables before their first use ?
// library.C
int x = 1;
// foo1.C
extern int x;
int y = x;
You cannot force the users of your library to do anything. And,
to be entirely frank, it's not a good idea to try. Develop your
library with this thought in mind: the users of it are not dumber
than you, but they may need a bit of guidance from you. So, do
supply your library with a good document describing some features
of your library that are not obvious, or are not features of the
language.
If a C++ programmer does not know that objects with static storage
duration are initialised in unspecified order if they are in two
different compilation units, it's NOT your problem. Besides, the
static objects are really best avoided in any C++ program, just
for that unspecifiedness of the order of their initialisation.
As to the particular question about how to make 'y' to always be
the same as 'x', initialise them _BOTH_ from a function:
// library.C
int x = functionThatReturnsXValue();
int functionThatReturnsXValue() {
return 1;
}
// foo1.C
int y = functionThatReturnsXValue();
And don't let them see the actual 'x'.
Victor
I am agree with you and thank your hints, but sometimes it is necesary
to use global variables. Stroustup in his book gives an example in
21.5.2 section (Closing of Streams):
". . . how an implementation can ensure that the predefined streams
cout, cin, cerr and clog are cleated before their first use and closed
(only) after their last use . . ."
"The fundamental idea is to define a helper class that is a counter
that keeps track of how many timesn <iostream> has been included in a
separately compiled source file:
class ios_base::Init {
static int count;
public:
Init();
~Init();
};
namespace { ios_base::Init __ioinit; } // in <iostream>, one copy in
each file
// #including <iostream>
int ios_base::Init::count=0; // in some .C file
Each translation unit declares its own object called __ioinit:
ios_base::Init::Init() { if (count++==0) { /* initialize cout, cin,
etc. */}
ios_base::Init::~Init(){ if (count--==0) { //clean up cout, cerr . . .
*/ }
This is a general technique for dealing with libraries that require
initialization an cleanup of global objects . . ."
What do you think about this technique ? Do you know another better or
similar ?
One can write code like this:
ostream my_cout=cout;
#include <iostream>
but he is a fool if do it.
I think that the best is follow your hints whenever possible and like
last resource use a trick similar to the above. What do you think ?
Regards,
Jose Luis