Private static class members

U

Urs Thuermann

Is it wise to use private static class members in a header file? Say
I have a class that wants to keep a list of pointers to all created
objects:

---- foo.h ----
class Foo {
public:
Foo();
~Foo();
private:
static std::list<Foo *> all_foos;
};
---- foo.cc ---
std::list<Foo *> Foo::all_foos;

Foo::Foo() {
...;
all_foos.push_back(this);
}
Foo::~Foo() {
all_foos.remove(this);
...
}
---------------

Having this in a header file exposes implementation details to the
user and causes unnecessary recompilation of all files using this
header when I change (say I rename) that private static member.

As long as I have no inline member functions using the list, I would
tend to move the list `all_foos' from the class by removing it from
foo.h completely and removing the Foo:: in foo.cc and making it static
there, i.e. in foo.cc

static std::list<Foo *> all_foos;

OTOH, this means that `all_foos' is no longer part of the class and
may be accessilbe by other non-member and non-friend functions in
foo.cc.

I'd like to hear some thoughts on this.

urs
 
J

Juha Nieminen

Urs Thuermann said:
static std::list<Foo *> all_foos;

The more recommended idiom is to use a nameless namespace instead of the
'static' keyword, but that works as well.
OTOH, this means that `all_foos' is no longer part of the class and
may be accessilbe by other non-member and non-friend functions in
foo.cc.

That file should contain the implementation of the class, so it shouldn't
be a problem. Any ancillary functions inside that file are part of the
implementation of the class (even if they are not declared as members of
the class). You shouldn't implement any non-related functions there.

I see no problem.
 
V

Victor Bazarov

The more recommended idiom is to use a nameless namespace instead of the
'static' keyword, but that works as well.

Did you miss the fact that 'all_foos' is a data member of a class?
That file should contain the implementation of the class, so it shouldn't
be a problem. Any ancillary functions inside that file are part of the
implementation of the class (even if they are not declared as members of
the class). You shouldn't implement any non-related functions there.

I see no problem.

V
 
J

Juha Nieminen

Victor Bazarov said:
Did you miss the fact that 'all_foos' is a data member of a class?

Did you miss the fact that the original poster wanted to remove the
static data member from the class and put it in the compilation unit
instead?
 
J

Jorgen Grahn

Is it wise to use private static class members in a header file? Say
I have a class that wants to keep a list of pointers to all created
objects:

---- foo.h ----
class Foo {
public:
Foo();
~Foo();
private:
static std::list<Foo *> all_foos;
};
---- foo.cc ---
std::list<Foo *> Foo::all_foos;

Foo::Foo() {
...;
all_foos.push_back(this);
}
Foo::~Foo() {
all_foos.remove(this);
...
}

Not really. Depending on what you mean, the answer is either (a) "no,
all_foos is private" or (b) "no more than all the other private stuff
in Foo which is also listed there".
and causes unnecessary recompilation of all files using this
header when I change (say I rename) that private static member.

That is probably very rare, and has a small impact when it happens.
As long as I have no inline member functions using the list, I would
tend to move the list `all_foos' from the class by removing it from
foo.h completely and removing the Foo:: in foo.cc and making it static
there, i.e. in foo.cc

static std::list<Foo *> all_foos;

OTOH, this means that `all_foos' is no longer part of the class and
may be accessilbe by other non-member and non-friend functions in
foo.cc.

I can see myself doing it either way. But remember: it's a fact of
life that the declaration of a class Foo contains private stuff that a
user of Foo is not/should not be interested in. It's nice if you can
minimize it to make the header file more readable, but you can't
eliminate it.

/Jorgen
 
V

Victor Bazarov

Did you miss the fact that the original poster wanted to remove the
static data member from the class and put it in the compilation unit
instead?

Right. There were two lines with that code, and I was sure you were
quoting the first one. My mistake.

As for the unnamed namespace, I don't agree. All names in it have
external linkage, and I for one don't see the reason to have more
exported symbols when they can't be accessed from outside anyway. I
vote for static.

V
 
P

Paul Brettschneider

Victor said:
As for the unnamed namespace, I don't agree. All names in it have
external linkage, and I for one don't see the reason to have more
exported symbols when they can't be accessed from outside anyway. I
vote for static.

What's the reason for that design decision (to make them external, but
inaccessible)? It seems so pointless to polute the symbol tables.
 
I

Ian Collins

Is it wise to use private static class members in a header file? Say
I have a class that wants to keep a list of pointers to all created
objects:

---- foo.h ----
class Foo {
public:
Foo();
~Foo();
private:
static std::list<Foo *> all_foos;
};
---- foo.cc ---
std::list<Foo *> Foo::all_foos;

Foo::Foo() {
...;
all_foos.push_back(this);
}
Foo::~Foo() {
all_foos.remove(this);
...
}
---------------

Having this in a header file exposes implementation details to the
user and causes unnecessary recompilation of all files using this
header when I change (say I rename) that private static member.

As long as I have no inline member functions using the list, I would
tend to move the list `all_foos' from the class by removing it from
foo.h completely and removing the Foo:: in foo.cc and making it static
there, i.e. in foo.cc

static std::list<Foo *> all_foos;

OTOH, this means that `all_foos' is no longer part of the class and
may be accessilbe by other non-member and non-friend functions in
foo.cc.

I find myself doing this fairly often. If the types and instances
aren't exposed by the classes public interface, I tend to place them all
in the unnamed namespace (I use this rather than static because I group
all local classes, type names and variables together).

One example I have is a name service information cache. The cache
comprises a number of maps and sets which are private to the implementation.

An alternative approach if the are private types is to place them in
their own headers, which facilitates unit testing.
 
R

red floyd

What's the reason for that design decision (to make them external, but
inaccessible)? It seems so pointless to polute the symbol tables.

ObDisclaimer: IANASCM (I am not a Standard Committee Member), but my
guess
is that it was for templates. IIRC, a template parameter must have
external
linkage.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top