Static object of class? - c++

I am actually not really aware if you can declare a class and then use a static instance it among several objects of the same class. More specifically:
class State {
public:
State();
static CustomNumberDist normal_dist;
private:
int id;
};
So every instance of State should contain the same instance of CustomNumberDist. I compiles but I am wondering if it is valid or I may run into problems later on.

The declaration (header file i.e. .h) that you have given is perfectly valid.
However in the definition (.cpp file) you need
State::CustomNumberDist normal_dist;
As memory will be required for the static object when you get to the linking stage.

it is not valid. It should be like :
class X
{
public:
int normalValue = 5; //NSDMI
static int i;
};
int X::i = 0;
i needs a place in the memory. In the memory which is not involved with a concrete object .
More information can be find here:
Static Data Member Initialization

Related

Static Variables in code

After a bit of research I'm surprised to say I have not found a question like this anyway I'm just wondering why I can't assign a value to a static variable?
note I am not using any headers I'm just creating a class in one cpp file(I know not good practice) here is the error I get
main.cpp|17|error: ISO C++ forbids in-class initialization of non-const static member 'Rabbit::now'|
In Java this wouldn't be a problem
thanks
class Rabbit
{
public:
string name;
string color;
int age;
bool friendly;
int happiness;
static time_t now = 4;
const int currentID;
};
I'm just wondering why I can't assign a value to a static variable?
You most certainly can assign any value you'd like to a static variable. You just do not assign it within the class definition itself. The reason for this is that you cannot initialize a static variable more than once! If you were allowed to initialize it inside the class definition, that would be problematic.
I am not using any headers I'm just creating a class in one cpp file (I know not good practice)
Right. Well if you were using headers you'd see why static variable initialization inside the class definition would be problematic. Each translation unit where the header is included would be trying to initialize the static variable, which cannot happen hence the error you're seeing.
If you are asking how you would do this in c++, then
//.h
class Rabbit
{
public:
static int now;
};
//.cpp
int Rabbit::now = 4;

Static initialization order in class heirarchy

I've recently become painfully aware of the Static Initialization Order Fiasco. I am wondering though if the rule that "initialization order is undefined across translation units" still holds for static members in a parent class which are needed by static members in a child class.
For example, say we have (excluding, for brevity, all the # guards and includes)
// a.h
class A {
static int count;
static int register_subclass();
};
// a.cpp
int A::count = 0;
int A::register_subclass() {
return count ++;
}
And then a sub-classes of A,
// b.h
class B : public A {
static int id;
};
// b.cpp
int B::id = A::register_subclass();
There are two translation units here with static objects in one depending on static objects in the other on initialization... it seems like it may be an instance of the static initialization order fiasco.
My question is: is it actually safe?
That is, am I guaranteed that there is no chance that B::id will contain junk copied from A::count before the latter is initialized? From my own tests, A always seems to get initialized first, but I'm not sure how to introduce noise in the initialization order to increase the probability of failing if the behavior is undefined.
Generally, it is not safe to rely on the static initialization order of a base class and derived class. There is no guarantee that the static initialization of A will happen before B. That is the definition of the static initialization order fiasco.
You could use the construct on first use idiom:
// a.h
class A {
private:
static int& count();
protected:
static int register_subclass();
};
// a.cpp
int& A::count() {
static int count = 0;
return count;
}
int A::register_subclass() {
return count()++;
}
// b.h
class B : public A {
public:
static int id;
};
// b.cpp
int B::id = A::register_subclass();
Live demo.
Update: However, saying that, bogdan pointed out in comments
according to [3.6.2] in the Standard, the order of initialization in this specific example is guaranteed. It has nothing to do with inheritance, but with the fact that the initialization of A::count is constant initialization, which is guaranteed to be done before dynamic initialization, which is what B::id uses.
But unless you have a complete grasp of such intracaccies I recommend you use the construct on first use idiom.
And it is ok in this case but be careful of functions like A::register_subclass in a multi-threaded context. If multiple threads call it simultaneously anything could happen.
I am wondering though if the rule that "initialization order is undefined across translation units" still holds for static members in a parent class which are needed by static members in a child class.
Yes, it does.
The only way that static data members relate to inheritance hierarchies (or, really, their encapsulating classes at all) is in their fully qualified names; their definition and initialisation is completely unaware/uncaring of this.

Private static declaration and subsequent initialization

A .cpp file has a bunch of class definitions . One class has a private static member as follows:
class SomeClass:public SomeParentClass
{
private:
static int count;
};
and right after the class is defined, the count attribute to initialized to zero as follows:
int SomeClass::count = 0;
Coming from the Java/C# world I am having trouble understanding at which point is count initialized to zero? Is it when the SomeClass is instantiated? Also, the class definition has the count type to be int, why does the SomeClass::count has to have an int in front of it?
And my last question is, since the count attribute is private shouldn't its visibility be restricted when it is initialized outside the class definition?
Thanks
Static members of the class are initialized in arbitrary order upon your program's start-up
The static int count; in the class is a declaration of your static variable, while int SomeClass::count = 0; is its definition. All definitions in C++ require to specify a type.
The fact that the definition of the count appears to have occurred in the file scope, the actual scope of the SomeClass::count remains private, as declared.
Is it when the SomeClass is instantiated?
No, you can access it via SomeClass::count (assuming the function has rights to SomeClass's private members) before any instantiations. It's fully usable before you start making objects.
Why does the SomeClass::count has to have an int in front of it?
Well, because it's an int. Think of when you make function prototypes and definitions:
int func (int);
int func (int i) {return 1;} //you still need the int and (int i) here
func {return 1;} //NOT VALID - this is what count would be without int
Since the count attribute is private shouldn't its visibility be
restricted when it is initialized outside the class definition?
Static variable definition is an exception to access specifiers when defined in the normal manner, according to this answer.
The class static variable will behave as if it is initialized to 0 when the program starts. It is independent of class instantiation.
The C++ language requires a type before an identifier in a declaration.
The C++ syntax to initialize a class static variable makes it look like a global, but access to the variable is enforced during compilation.

static constant members for array size

MyClass.h
class MyClass
{
public:
static const int cTotalCars;
private:
int m_Cars[cTotalCars];
};
MyClass.cpp
#include "MyClass.h"
const int MyClass::cTotalCars = 5;
The above code doesn't work because it will say "expected constant expression" for the m_Cars array.
class MyClass
{
public:
static const int cTotalCars = 5;
private:
int m_Cars[cTotalCars];
};
The above will work, but I am told that I should always define static members in the CPP file, outside the class definition. What can I do?
Static const members of simple type are a exception to that rule, so you latter code is correct.
This exception is a fairly modern one (from C++98, but not implemented by every compiler until a few years later) so many old-fashioned teachers are not yet aware of it. They prefer the idiom:
class MyClass
{
public:
enum { cTotalCars = 5 };
private:
int m_Cars[cTotalCars];
};
That behaves exactly the same, but makes little sense nowadays.
The above will work, but I am told that I should always define static members in the CPP file, outside the class definition. What can I do?
Well, what you have been suggested to do: define the static members in the CPP. Note that in the code above the static member is not defined even if the value is stated. The proper final code would look like:
// .h (ignoring all but the static member)
class MyClass {
static const int cTotalCars = 5; // declaration and initialization
};
// .cpp
static const int MyClass::cTotalCars; // definition (cannot have value!)
The definition in the .cpp file is what actually reserves the space for the variable when used as an lvalue. For a simple test that verifies that without that line the variable is not defined you can do:
void f( const int & x ) {}
int main() {
f( MyClass::cTotalCars );
}
Without the line in the .cpp file the code above will trigger a linker error pointing to the missing definition of MyClass::cTotalCars. The problem with the code is that it uses the static const member (by the definition of use in the standard), and that requires the member to be defined. While the case of using the constant to define the array size does not constitute use.
I would rather use a #define C_TOTAL_CARS 5, then static const int cTotalCars = C_TOTAL_CARS; and then also, int m_Cars[C_TOTAL_CARS];.
If is was a static int you would need to place it into the .cpp file. You do not need the keyword static in this instance as all you want is a constant. Just use const int cTotalCars = 5;. It is better than #define as you have type info and also it has a symbol that can be viewed in a debugger.
It just can't works if you define size of the array is set in cpp file. All class clients should know the size of class instance but they just have no idea about .cpp file because you only put #include "MyClass.h" in client-files.
In other words - your class definition is varies depending on the cpp-file which is not used while compile files that uses MyClass.

Initialize static variables in C++ class?

I have noticed that some of my functions in a class are actually not accessing the object, so I made them static. Then the compiler told me that all variables they access must also be static – well, quite understandable so far. I have a bunch of string variables such as
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
and so on in the class. I have then made them all static const because they never change. However, my program only compiles if I move them out of the class: Otherwise, MSVC++2010 complains "Only static constant integral variables may be initialized within a class".
Well that's unfortunate. Is there a workaround? I would like to leave them inside the class they belong to.
They can't be initialised inside the class, but they can be initialised outside the class, in a source file:
// inside the class
class Thing {
static string RE_ANY;
static string RE_ANY_RELUCTANT;
};
// in the source file
string Thing::RE_ANY = "([^\\n]*)";
string Thing::RE_ANY_RELUCTANT = "([^\\n]*?)";
Update
I've just noticed the first line of your question - you don't want to make those functions static, you want to make them const. Making them static means that they are no longer associated with an object (so they can't access any non-static members), and making the data static means it will be shared with all objects of this type. This may well not be what you want. Making them const simply means that they can't modify any members, but can still access them.
Mike Seymour has given you the right answer, but to add...
C++ lets you declare and define in your class body only static const integral types, as the compiler tells. So you can actually do:
class Foo
{
static const int someInt = 1;
static const short someShort = 2;
// etc.
};
And you can't do that with any other type, in that cases you should define them in your .cpp file.
Some answers including even the accepted answer seem to be a little misleading.
You don't have to
Always assign a value to static objects when initializing because that's optional.
Create another .cpp file for initializing since it can be done in the same header file.
You can even initialize a static object in the same class scope just like a normal variable using the inline keyword.
Initialize with no values in the same file
#include <string>
class A
{
static std::string str;
static int x;
};
std::string A::str;
int A::x;
Initialize with values in the same file
#include <string>
class A
{
static std::string str;
static int x;
};
std::string A::str = "SO!";
int A::x = 900;
Initialize in the same class scope using the inline keyword
#include <string>
class A
{
static inline std::string str = "SO!";
static inline int x = 900;
};
Since C++11 it can be done inside a class with constexpr.
class stat {
public:
// init inside class
static constexpr double inlineStaticVar = 22;
};
The variable can now be accessed with:
stat::inlineStaticVar
Static member variables must be declared in the class and then defined outside of it!
There's no workaround, just put their actual definition in a source file.
From your description it smells like you're not using static variables the right way. If they never change you should use constant variable instead, but your description is too generic to say something more.
Static member variables always hold the same value for any instance of your class: if you change a static variable of one object, it will change also for all the other objects (and in fact you can also access them without an instance of the class - ie: an object).
I feel it is worth adding that a static variable is not the same as a constant variable.
using a constant variable in a class
struct Foo{
const int a;
Foo(int b) : a(b){}
}
and we would declare it like like so
fooA = new Foo(5);
fooB = new Foo(10);
// fooA.a = 5;
// fooB.a = 10;
For a static variable
struct Bar{
static int a;
Foo(int b){
a = b;
}
}
Bar::a = 0; // set value for a
which is used like so
barA = new Bar(5);
barB = new Bar(10);
// barA.a = 10;
// barB.a = 10;
// Bar::a = 10;
You see what happens here. The constant variable, which is instanced along with each instance of Foo, as Foo is instanced has a separate value for each instance of Foo, and it can't be changed by Foo at all.
Where as with Bar, their is only one value for Bar::a no matter how many instances of Bar are made. They all share this value, you can also access it with their being any instances of Bar. The static variable also abides rules for public/private, so you could make it that only instances of Bar can read the value of Bar::a;
Just to add on top of the other answers. In order to initialize a complex static member, you can do it as follows:
Declare your static member as usual.
// myClass.h
class myClass
{
static complexClass s_complex;
//...
};
Make a small function to initialize your class if it's not trivial to do so. This will be called just the one time the static member is initialized. (Note that the copy constructor of complexClass will be used, so it should be well defined).
//class.cpp
#include myClass.h
complexClass initFunction()
{
complexClass c;
c.add(...);
c.compute(...);
c.sort(...);
// Etc.
return c;
}
complexClass myClass::s_complex = initFunction();
If your goal is to initialize the static variable in your header file (instead of a *.cpp file, which you may want if you are sticking to a "header only" idiom), then you can work around the initialization problem by using a template. Templated static variables can be initialized in a header, without causing multiple symbols to be defined.
See here for an example:
Static member initialization in a class template
Optionally, move all your constants to .cpp file without declaration in .h file. Use anonymous namespace to make them invisible beyond the cpp module.
// MyClass.cpp
#include "MyClass.h"
// anonymous namespace
namespace
{
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
}
// member function (static or not)
bool MyClass::foo()
{
// logic that uses constants
return RE_ANY_RELUCTANT.size() > 0;
}