when I want to have a static pointer as a member of a class I need constexprfor the initialisation with nullptr.
class Application {
private:
constexpr static Application* app = nullptr;
}
Can someone explain me why I need to do that? I cannot find the exact reason why it`s necessary that the static variable has to exist at compile time.
That's because you're initialising it inside the class definition. That's only allowed for constant integral and enumeration types (always) and for constexpr data members (since C++11). Normally, you'd initialise it where you define it (outside the class), like this:
Application.h
class Application {
private:
static Application* app;
}
Application.cpp
Application* Application::app = nullptr;
Note that you need to provide the out-of-class definition even in the constexpr case, but it must not contain an initialiser then. Still, I believe the second case is what you actually want.
If you don't want it to be constexpr (and it's not an integer) then you need to initialise it outside of the class body:
class Application
{
private:
static Application* app;
};
Application* Application::app = nullptr;
Typically, you need to initialise a static member variable outside the class declaration, unless it is const. I think this explains it better than I could.
Static variables do not need to "exist at compile time". But if you want to initialize a static variable inside the class, its value needs to be known at compile time.
However, I do not know the reason for this restriction.
Related
Code 1:
#include<iostream>
class Singleton
{
private:
static Singleton instance; //declaration of static variable
public:
static Singleton &GetInstance()
{
return instance;
}
void Hello()
{
std::cout << "Hello!";
}
};
Singleton Singleton::instance; //definition of static variable
int main()
{
Singleton::GetInstance().Hello();
}
Code 2:
#include <iostream>
class Singleton
{
public:
static Singleton &GetInstance()
{
static Singleton instance; //declaration of static variable
return instance;
}
void Hello()
{
std::cout << "Hello!";
}
};
int main()
{
Singleton::GetInstance().Hello();
}
In Code 1 we're required to define the static variable, but in Code 2, we just declared the static variable in the function Singleton::GetInstance&() and then returned it. Do the declaration and definition happen in the same line in Code 2? and why?
The static member variable instance declared inside class Singleton in Code 1 is a class variable.
This means that regardless of the state of different instances of class Singleton, the state of static variable will remain the same for all objects/instances of that particular class. Hence, it needs to be defined outside the class.
(Just like a global variable which is available to function of all scopes.). A single copy of static member variable is allocated in memory even if you don't create any instance. Their definition persists through the entire file.
In Code 2, the static variable instance is not a class variable but is simply a local variable inside a static member function. Hence there is no need for it to be defined outside since its scope is limited only to static Singleton &GetInstance() function.
For classes static variables are stored well... staticly, so they are accessible between each instance of the class. As in, the same variable is accessible between classes. See https://en.wikipedia.org/wiki/Static_variable for what they are. In functions it wont make much sense to define them static as the function has no access outside of it.
In classes you do not need to define them as static. But in this case using a Singleton it is nice as it ensures everything in the program is working with one instance, as per Singleton design. (Does not guarantee thread safety)
Also static functions simply do not need a constructor to run, so they work as simple functions. They do not guarantee that you work with the same data.
[edit: this answer predates the C++14 tag on the question; it assumes C++17 or C++20]
The assumption is wrong:
class Singleton
{
private:
static inline Singleton instance; //definition of static variable
// ^^^^^^
You just need to give the compiler a warning.
I have not found a way to initialize the class member succesfully inside the constructor and I can not figure out why.
I have a header file:
#pragma once
struct STATE_MOUSE {
bool moving;
int left_button;
int right_button;
int middle_button;
bool scroll_up;
bool scroll_down;
};
class Message {
private:
static STATE_MOUSE state_mouse;
public:
Message();
~Message();
};
Then I have a source file:
#include "message.hpp"
STATE_MOUSE Message::state_mouse = {false, 0, 0, 0, false, false};
Message::Message() {
//Would like to initialize state_mouse here somehow.
}
Message::~Message() {
}
Now to the issue. This set up seems to work. However I am used to initialize members inside a constructor and I have not found a way to do that with this static struct member.
The following method does not work, could someone explain why?
state_mouse.moving = false;
When you declare a member as static it will belong to the class with only one instance and not to the objects of the class, therefore you cannot initialize it inside the constructor. The constructor is a special member function which mainly exists to initialize the non static members of a new object.
Note that a static member is shared by all objects of the class and when an object changes it, the change can be seen from all other objects of the same class. If this is what do you want to achieve, then the method you shown is good.
Static member variables are not associated with each object of the class. It is shared by all objects.
If you declare a static variable inside the class then you should define it in the cpp file, otherwise, you can get error undefined reference.
Note that if the static member variable is of const int type (e.g. int, bool, char), you can then declare and initialize the member variable directly inside the class declaration in the header file.
I have class with static string variable m.
class turbo
{
public:
static string m;
}
if I not declare like defined below I will get error undefined reference turbo::m.
string turbo::m;
Why I should declare it twice? I don't need to declare non static variables second time. Where is logic?
To be honest, I was surprised by this too the first time,
but found the very reasonable reason for it.
while member variables are stored within the object allocated space,
static members are not placed within the object memory space (either heap or stack)
but have a private shared space. just like functions do.
Therefore, declaring the static string m within the class.
is just like saying: there is a shared definition of this somewhere
and the name is turbo::m.
Hope this clears things up.
It's the difference between declaration and definition, very much like declaring a function with a forward reference, e.g.;
int MyFuncion();
and actually defining it with its function body, e.g.,
int MyFunction()
{
return 1;
}
I know you have an object and not a function, but conceptually, the declaration/definition idea is the same.
C++ forbids the definition of non-const static data members in the body of a class ("inline definition"). It becomes more obvious if you try to use an explicit constructor: for example,
class turbo
{
public:
static string m;
static string s = string("my_str"); // doesn't work
}
Hence, when you write static string m in the body of a class, it is merely a declaration, not a definition. You will have to define it later:
static string turbo::s = string("my_str");
In your case, you are simply invoking the default constructor in the definition:
static string turbo::m; // calls the default constructor
(Like any static variable, initialization occurs at the very start of your program, before main.)
Note that the definition must also occur only once (to avoid multiple definitions), so it must not appear in a header file.
In the class definition you only declare the static variable
class turbo
{
public:
static string m;
}
but it is not yet defined. To define the corresponding object you have to write
string turbo::m;
Now it will exist regardless of whether instances of the class were created.
There is a static member in a struct, because it is needed in the destructor.
struct Form
{
// ...
~Form()
{
// access World here
}
static btDynamicsWorld *World;
};
Is there a way to initialize this static member from within another function?
void ModulePhysics::Init()
{
// ...
btDynamicsWorld *Form::World = /* ... */;
}
My current code results in those two compiler errors.
Error 1 error C2655: 'Form::World' : definition or redeclaration illegal in current scope
Error 2 error C2086: 'btDynamicsWorld *Form::World' : redefinition
No, you can't. But you can initialize it to NULL, and in the function, if it is NULL, do the real initialization.
Edit: Provide an example:
void ModulePhysics::Init()
{
// ...
if(Form::World == NULL)
{
// The real initialization
}
}
Somewhere, on file scope (in the C file, not in the header!):
btDynamicsWorld* Form::World = NULL;
No you can't.
The declaration of a static data member in the member list of a class is not a definition. You must define the static member outside of the class declaration, in namespace scope.
Here you can get a more detailed description of how and where you can initialize static class variables.
in the init() method remove the type in front of the static variable.
it should solve your issue, I hope.
1) All static class members (except integral members initialized immediately in the class definition) should also be defined outside (preferrably in a .cpp file, so that the definition is processed only once by compiler). For example:
// form.h
struct Form
{
static btDynamicsWorld *World;
};
// form.cpp
// You can initialize World here as well if you want to,
// but you don't have to, as long as it's not const.
// However, it is generally a good idea to initialize
// pointers to NULL (or nullptr in C++11).
btDynamicsWorld *Form::World;
This can only be done at global scope. If you don't do this, you will get linker errors (undefined symbol) if you try referencing this variable.
2) What you are seemingly trying to do is not "initialize", but just assign to the static member. You are doing it almost correctly, but you don't need to redeclare the type:
void ModulePhysics::Init()
{
Form::World = /* ... */;
}
3) I don't really see why do you need to make anything static to access it from the destructor. Destructor is responsible for deleting instance variables, but they are not yet deleted when the destructor's body is executing. So you may just as well use a "normal" class member, unless you are planning to share its value across different class instances.
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;
}