I'm using my own REGISTER_OBJECT() macro to create a factory full of classes.
It works as expected, except for the initialization of my static std::map variable. If I don't initialize the static std::map in a .cpp file, I'll of course get a unresolved external symbol. But the problem is, I must initialize in the .cpp file that is called first at run time. Otherwise, REGISTER_OBJECT() will get called before the std::map initializer.
//std::map MUST be initialized in the .cpp file the compiler calls first.
std::map<std::string, MyFactory*> Factory::factories; //global init
REGISTER_OBJECT(MyClass);
If I place the std::map initializer in the .cpp file I prefer, REGISTER_OBJECT will be called up to a few times, the std::map will fill accordingly, but then the std::map line hits and the variable is reset.
How on earth can I make sure std::map is initialized before any calls to REGISTER_OBJECT without putting it in another .cpp file. Thanks :)
SOLUTION
//Factory.cpp
std::map<std::string, MyFactory*>* Factory::factories = NULL;
void Factory::Register(const std::string& name, MyFactory* _class)
{
if(!factories){ factories = new std::map<std::string, MyFactory*>(); }
(*factories)[name] = _class;
}
You could make your factories variable a pointer (initialized to null), and then have your REGISTER_OBJECT macro lazy instantiate it, i.e., set it to new std::map... if it's null.
This article on (essentially) merging a singleton pattern into the class kept my static variable from being created twice (https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use-members)
The basic gist is replace
class MyClass {
// static member gets initialized twice
static inline int someNumber = randomInt();
}
... with ...
class MyClass {
// singleton like pattern keeps someNumber from being initialized more than once
static inline int& someNumber() {
static int* singletonHack = randomInt();
return &singletonHack;
}
}
Then access it like this MyClass::someNumber()
Related
I'm trying to implement a factory pattern like this.
The problem right now is that the program terminates with a segfault in the register function because the map is not initialized yet.
// initialise the registered names map
std::map<std::string, factoryMethod> SourceFactory::registeredClasses_ = { };
bool SourceFactory::Register(std::string name, factoryMethod createMethod) {
// registeredClasses_ = { }; // This prevents the segfault but does not work for obvious reasons
auto temp = std::make_pair(name.c_str(), createMethod);
std::pair<std::map<std::string, factoryMethod>::iterator, bool> registeredPair =
SourceFactory::registeredClasses_.insert(temp);
return registeredPair.second;
}
Why is it possible for Register() to be called before the initialization of the map? I tried initializing the map in the header file but then I get the linker error
multiple definition of SourceFactory::registeredClasses_
A solution would be to set a static bool isInitialized=false and then initialize the map accordingly. But I hope this can be avoided.
It's possible when Register is called from a different translation unit before the registry has been initialised.
Unfortunately, adding a static flag would not solve anything because that would not be initialised either.
A convenient solution is to add a level of indirection:
// static
std::map<std::string, factoryMethod>& SourceFactory::registry()
{
static std::map<std::string, factoryMethod> registeredClasses;
return registeredClasses;
}
bool SourceFactory::Register(const std::string& name, factoryMethod createMethod) {
auto temp = std::make_pair(name, createMethod);
return registry().insert(temp).second;
}
This is a common problem known as the static initialisation order fiasco.
Objects with static storage duration at namespace scope are constructed in-order within a translation unit, but you don't know whether those in other translation units may undergo initialisation first.
Instead of having your container at namespace scope, make it function static (perhaps returned from a new GetRegistry() function?) so that it is constructed on first use. That could be use from main, use from initialisation of another static-duration "thing" (which is presumably where your Register call is coming from), use from the moon…
This is also why the proper way to write a singleton is to have a GetInstance() function that declares (staticly!) the instance within the function's scope.
A solution would be to set a static bool isInitialized=false and then initialize the map accordingly. But I hope this can be avoided.
Nope. Not only would you then have the same problem with the isInitialized flag, but there's nothing you can "do" with that information. You can't "initialize" something other than in an initializer, and the whole problem is that the initializer hasn't been used yet. You could assign to the map, but that would have undefined behaviour because you'd be assigning to something that doesn't exist yet… and then it would be initialized later anyway!
So I have experience using programming languages and just switched over to C++. Now I have created a few working applications but I always stumble upon the same problem. I don't exactly know what everything is called in the code. You have a class which obvious to see since the has written class before it. And you also have some sort of functions attached to the class are these called instances? And is the class the object it referring to by for example class::function.
But my main question was how can I access the variables from another function within the same class file. I have included an example below explaining what I want to achieve. I already tried a lot of things and googled a lot. I tried code pasting code creating setting and getting functions, calling the class to get and set the variable but I can't get it to work. I've spend a lot of time fixing this very basic problem. Could someone explain me what is called what in this code (Class,Object,Instance). And explain me the most efficient way to receive data from another function in the same .cpp file.
Thanks
load_data.h
#pragma once
class load_data
{
public:
static int data[13];
load_data();
static void test2();
};
load_data.cpp
#include "load_data.h"
#include "abc.h"
load_data::load_data()
{
int data[3]; // Initializing the array
data[0] = abc::LoadImage("textures/1.png");
data[1] = abc::LoadImage("textures/2.png");
data[2] = abc::LoadImage("textures/3.png");
}
void load_data::test2()
{
abc::CreateSprite(1, data[0]);
abc::SetSpritePosition(1, 0, 0);
abc::SetSpriteScale(1, 3, 3);
// Now I get an error saying it has no data. Which however is set in
// load_data(). But since each function gets its own variables this one will be empty.
abc::CreateSprite(2, data[1]);
abc::SetSpritePosition(2, 64, 64);
abc::SetSpriteScale(2, 3, 3);
abc::CreateSprite(3, data[2]);
abc::SetSpritePosition(3, 128, 128);
abc::SetSpriteScale(3, 3, 3);
}
Change your load_data() constructor to the following (currently, your creating a new data[] variable that is locally scoped to your load_data() constructor, which gets initialized instead of your object's data[] (gets "eclipsed"). Your subsequent call to test2() fails when it accesses data[] because the other, local data[] was initialized instead. Also, fyi, the local data[] is destroyed when load_data() returns (because it is an auto/stack variable that falls out of scope).
load_data::load_data()
{
//int data[3]; // Initializing the array
data[0] = abc::LoadImage("textures/1.png");
data[1] = abc::LoadImage("textures/2.png");
data[2] = abc::LoadImage("textures/3.png");
}
you also have some sort of functions attached to the class are these
called instances?
An object is an instance of a class. A class defines the object type, which consists of state variables, and operations for them (known as "member functions" or "methods").
An object's methods are called through a handle to the instance. IE, an instantiated variable:
load_data ld = new load_data();
ld.test2();
And is the class the object it referring to by for example
class::function.
This notation is for explicitly qualifying a method name. It helps resolve naming conflicts and should only be used when needed (otherwise it is implicit).
But my main question was how can I access the variables from another
function within the same class file.
...
But since each function gets its own variables this one will be empty
All functions of a class share the class'es (member) variables. An given instance of the class has the only copy of those member variables (ie, their specific values/memory to that instance), so all method calls through a specific instance variable (say ld) of load_data will refer to the same data[] array (so load_data ld1, ld2 would each have their own copies). Functions can, and usually do, declare their own variables to help assist in computing the task they perform (bools, counters, etc...). These such variables, as mentioned before, are scoped to that function, meaning they're no longer allocated and get destroyed when the function returns (they are auto-variables).
And you also have some sort of functions attached to the class are
these called instances?
No. the functions inside of the class are called "class member function" or just "member functions". An instance is a copy of that object (read class) in memory. So in short:
class A {
public:
void fun (void); ///< This is a class member function
};
void main (int argc, char *argv[]) {
A a; ///< a is an instance of object A
}
And is the class the object it referring to by for example
class::function.
The class defines the object. In the above snipped, A is an object.
But my main question was how can I access the variables from another
function within the same class file.
You need to do some reading on variable scope. In your above example the data array is local to the constructor. It doesn't exist within the object, only within that function. So as soon as the constructor finishes, the variable goes out of scope and is lost. In order to keep it in the object's scope you would need to declare it within the object.
class load_object {
public:
// The same
private:
int load[3];
};
Cheers
I have read that constructors can inizialize only non static attribute. I have written a small code to check that and Im wondering now because the compiler dosnt show any error??? So Can I initialize static attribute and non static attribute in the constructor or not? this is my code! Thank you very much!
class NixIs {
int var;
static int global;
public:
NixIs(int val = 0)
{
global = val;
}
I think you mean "field" instead of "attribute"
Your code is valid C++ but it does not initialize the static field global, as it's an instance constructor.
If you want to initialize NixIs::global with a trivial constant value (known at compile-time) you can specify it inline in the header:
NixIs.h:
class NixIs {
static int global = 0;
}
If you have a non-constant initial value (such as a parameterless free-function result) then the static field initializer needs to be in a code-file (instead of a header). You need to specify the static field in addition to its type and the initial value of the static field:
NixIs.h:
class NixIs {
static int global;
}
NixIs.cpp:
int NixIs::global = nonTrivialValue;
If you want to initialize multiple static fields in a particular order or with function-result values you'll need to use a hack because C++ does not have static constructors. See here: Static constructor in c++
Initializing an attribute in a constructor is usually done using the initializer list. For instance, you could initialize the non-static attribute in your class like this:
NixIs( int init_val) : val(init_val) {
// do stuff
}
I think that is what you meant. Trying to initialize a static class member like this would be an error. However, all class methods including constructors and destructors can access static members. In your example, 'global' would simply be overwritten with each new instance that is created.
NixIs first(1); // first.global is now 1
NixIs second(2); // first.global is now also 2 (same as second.global)
I need to instantiate many objects from a class, but each one of them needs to be aware of a certain value X that is common for every object of this class, like a global parameter. This is necessary for my constructors to work properly in my objects.
Is there a way to do that without passing the value as a constructor parameter? What I wanna do is use the same variable in all objects so I don't waste RAM.
*in my real situation it's not just an X value, is a 1024-dimmension int vector.
What you want is a static member. "When a data member is declared as static, only one copy of the data is maintained for all objects of the class". e.g.
class myClass {
public:
static int x;
};
I assume you mean that you want a vector of size 1024 as the shared variable across all your classes. You could do this:
class MyClass {
static std::vector<int> s_my_vector;
}
This code would go into your header file. In your cpp file, you'd have to initialize the std::vector. However, I do not recommend this. Class static variables that require constructor calls (i.e. not primitives or POD types) have a lot of gotchas that I'm not planning to go into. I will offer a better solution however:
class MyClass {
static std::vector<int> & GetMyVector()
{
static std::vector<int> my_vector;
static bool initialized = MyVectorInit(my_vector);
return my_vector;
}
static bool MyVectorInit(std::vector<int> & v)
{
v.resize(1024);
...
}
public:
MyClass() {
std::vector<int> & v = GetMyVector();
...
}
static void EarlyVectorInit()
{
GetMyVector();
}
}
In this case, the static local variable ensures that there will only be one copy of my_vector, and you can get a reference to it by calling GetMyVector. Furthermore, the static bool initialized is guaranteed to only be created once, which means that MyVectorInit will only be called once. You can use this method in case you need to populate your vector in some non-trivial way that can't be done in the constructor.
The way I've written it, your vector will be created automatically the first time you need to use it, which is fairly convenient. If you want to manually trigger creation for some reason, call EarlyVectorInit().
I came across the following structure in a C++ library:
In myClass.h
class myClass {
public:
static myClass* Instance();
.
.
private:
static myClass* _instance;
.
.
};
and in myClass.cpp
myClass* myClass::_instance = NULL;
// followed by the all other functions..
myClass::myClass() {
.
.
}
myClass* myClass::Instance() {
if (_instance == NULL) {
.
.
}
.
.
}
So what is the use of making the _instance to be NULL pointer outside any function? And when is this line of code executed?
Thank you.
Edit:
Adding the main function. And the instance function in myClass.cpp that checks for the value of the pointer. Still don't understand when the pointer get set to NULL though.
int _tmain(int argc, T_CHAR* argv[]) {
myClass* instance = myClass::Instance();
.
.
.
return 0;
}
So what is the use of making the _instance to be NULL pointer outside any function?
Static data members usually have to be defined, in the namespace containing their class, in one source file; they are subject to the One Definition Rule, and so must have exactly one definition in any program that uses them. This is that definition.
Initialising it with NULL makes sure it's initially null, so that the Instance() function can determine whether the instance has been created yet. This isn't strictly necesssary since, like all static variables, it will be zero-initialised whether or not you explicitly provide an initialiser.
And when is this line of code executed?
During static initialisation, before any other code in the program; since it's a trivial type with a constant initialiser.
I have stumbled upon something like this once. It was something similar to singleton. The reason (as explained by the person doing it) was that he specifically wanted to initialize instance at the first getInstance() function call and he wanted to make sure that the _instance pointer will be at first initialized to NULL (and not some garbage from memory) so that the check
if (_instance == NULL)
in the function works properly.
I am not sure this is the case here, but it's possible.
myClass* myClass::_instance = NULL;
the code attempts to initialize the static member variable.
It's an initialisation, ensuring that the pointer starts life with the value NULL from the very beginning of the program.1
It gives the pointer an invalid, but recognisable and testable value before some useful pointer value is assigned to it later on during the program. This way, you can safely test the pointer to see whether it was yet given said useful value.
In this case, since you are showing a singleton, "later" means "when an instance of myClass is first requested" using some myClass::getInstancePlease() function that you have not shown.
It is more common to implement a singleton with a function-static instance, rather than a class-static pointer to some [probably dynamically-allocated] instance.
1 As an object with static storage duration, it would do so anyway; therefore, this initialisation is actually completely pointless beyond documenting programmers' intent.
Static keyword means it is being shared by all the objects that will be instantiated by the class. Hence you need to initialize it outside any function.Static states that it is a class variable shared between all the instance of the class. It is opposite to instance variables, which each instance has its own copy. To access a class variable, there are two ways. 1) a_class::static_variable 2) a_class a; a.static_variable. The initialization must go in the source file (.cpp) rather than in the header.
Because it is a static variable the compiler needs to create only one copy of it. If you don't, you get a link error. If that is in a header you will get a copy in every file that includes the header, so get multiply defined symbol errors from the linker.
Static data members are not part of objects of a given class type; they are separate objects. As a result, the declaration of a static data member is not considered a definition. The data member is declared in class scope, but definition is performed at file scope.