I am working on an C++ application. I have a data file in a particular
format and there are multiple clients who need to access data in this
file. All these clients are part of the same single threaded process.
I am planning to make an object which will handle this file format.
Each time a new client registers a new instance will be created and
its reference passed to the client. This instance will hold some
client specific details. I will have some static variables in the
object which will keep common information like for example the file
name
Is this the right way to solve this problem?
Also one more query. When first instance of the object are the static
variables initialized to zero as they are in global static variables?
Kaustubh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Your langauge here is pretty vague. What do you mean by client? What
are you trying to achieve?
>
> Also one more query. When first instance of the object are the static
> variables initialized to zero as they are in global static variables?
Global and static member variables are really the same. Static members
are just globals in the namespace of a class. The only difference
between global variables and and static member variables is that
static members can be private. Collectively globals, static globals,
and static member variables are refered to as static data.
Also, if you have a global or static member variable then *you* can
specify the initial value.
//C.h
class C {
static int i;
};
//C.cpp
int C::i = 0;
You can either initialize them with constants, functions,
constructors, whatever. However, as a rule of thumb it's best to only
use constants. That's because constant initialization (say with 0)
doesn't require any code to be executed. The initial value of C::i in
the example above is a part of the programs image on disk, and it is
read into memory with the rest of your program code.
On the other hand if you do this:
int C::i = f(); // for some function f()
The f function will be executed as part of program initialization
before main is executed. The problem is that the order of
initilization of static data in different translation units (different
C++ files) is undefined, and you can run into dependency bugs than
will change from compile to compile.
Actually, it is a good policy to not use any non-constant static data
if possible because mutable static data introduces all kinds of
multithreading synchronization problems, and also hinders unit
testing. If you do use static data, remember to give it a constant
initilizer.
It sounds OK, but I would skip the static variables. If you need
multiple file_accessor objects to share common data, you can also have a
file_accessor_factory type that holds the shared data. You can use
multiple, simultaneous instances of file_accessor_factory if you ever
need to access multiple, simultaneous files. Any time you use static
member variables, you're effectively hard-coding the number 1.
> Also one more query. When first instance of the object are the static
> variables initialized to zero as they are in global static variables?
Yes, all statically allocated variables (including class members) are
zero-initialized.
> Hello Group,
>
> I am working on an C++ application. I have a data file in a particular
> format and there are multiple clients who need to access data in this
> file. All these clients are part of the same single threaded process.
>
> I am planning to make an object which will handle this file format.
> Each time a new client registers a new instance will be created and
> its reference passed to the client. This instance will hold some
> client specific details. I will have some static variables in the
> object which will keep common information like for example the file
> name
>
> Is this the right way to solve this problem?
It is not the solution I would choose, but there are multiple ways to
skin a cat.
I would probably use a design similar to this:
class ClientData {};
class Format : boost::noncopyable {
private:
Format(std::string file_name);
public:
static Format& Instance(const std::string& file = "default_name.ext")
{
static std::map<std::string, Format> instances;
std::map<std::string, Format>::iterator it = instances.find(file);
if (it == instances.end())
{
it = instances.insert(make_pair(file, Format(file))).second;
}
return it->second;
}
ClientData addClient();
void doSomething(ClientData&);
};
void client1()
{
ClientData data = Format::Instance().addClient;
Format::Instance().doSomething(data);
}
/* For convenience, you could add a wrapper class: */
class Wrapper {
public:
Wrapper(const std::string& file = "default_name.ext") :
format(Format::Instance(file)), client(format.addClient()) {}
doSomething()
{
format.doSomething(client);
}
private:
Format& format;
ClientData client;
};
void client2()
{
Wrapper fileFormat("alternative_file");
fileFormat.doSomething();
}
>
> Also one more query. When first instance of the object are the static
> variables initialized to zero as they are in global static variables?
Class-static variables are treated identically to global (file/namespace
scope) variables: on program startup, their memory is first initialised
to zero, and afterward the initialisation according to their definition
is executed.
This all happens before the variable can be referenced the first time.
>
> Kaustubh
>
>
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
This confusion is an unfortunate side effect of using imprecise terms,
such as "global", "static", "local", etc. when they're not what's really
meant. When those terms are used, the concepts of "scope" and "storage
duration" are often mixed up.
"Scope" talks about portions of the program text where a name is valid,
and there are {local, function prototype, function, namespace, class}
scopes (3.3). "Storage duration" talks about the lifetime of an object
storage, and there are {static, automatic, dynamic} storage durations
(3.7). (As far as I understand, the "local scope" is roughly what the
C Language calls "block scope", and the "namespace scope" is a slight
generalization of what the C Language calls "file scope".)
A "global variable" has a namespace scope and a static storage duration,
and a typical "local variable" has a local scope and an automatic
storage duration. However, declaring a "local variable" with "static"
gives it a static storage duration; its scope remains local.
If you associate the term "global" with the static storage duration and
"local" with the automatic storage duration, you'll have some trouble
categorizing this beast properly. :)
int global; // namespace scope, static storage duration
void foo()
{
int local; // local scope, automatic s.d.
static int static_local; // local scope, static s.d.
new int; // (the anonymous obj.) dynamic s.d.
}
Note that, on the other hand, the "static" applied to a "global variable"
(a deprecated feature, anyway) does not affect its scope nor its storage
duration, but gives it an internal linkage. I feel this makes the biggest
inconsistency among the various meanings of "static".
static int static_global; // namespace scope, static s.d.
// but the linkage is internal
A class member has a class scope. A non-static data member may have
any storage duration, depending on how the object that contains the
non-static data member is created. However, a static data member always
has a static storage duration.
struct X
{
int non_static_class; // class scope
static int static_class; // class scope
};
int X::static_class; // static storage duration;
// a separate definition is necessary
X global; // global.non_static_class has static s.d.
void f()
{
X local; // local.non_static_class has automatic s.d.
X* dynamic = // dynamic.non_static_class has dynamic s.d.
new X;
}
An astute reader may have recognized that the two concepts apply to
two different kinds of things: the scope is about names, and the storage
duration is about objects. Often you have a name for an object and vice
versa, but not always, so the distinction can be important.
--
Seungbeom Kim