This question already has answers here:
Defining static members in C++
(6 answers)
Closed 7 years ago.
I need a class with static std::vector<int> simples (first N simple numbers). I created it in static method __init__, which is called before any instance of MyClass is created:
class MyClass
{
public:
MyClass()
{
/* I need to use MyClass::simples here */
printf("%d\n", (int)MyClass::simples.size());
/* But I get the error here :( */
}
static void __init__(int N)
{
simples.push_back(2);
/* ...
here I compute first N simple numbers and fill
MyClass::simples with them
*/
}
private:
static std::vector<int> simples;
};
int main()
{
MyClass::__init__(1000);
MyClass var;
return 0;
}
But when I tried to use this vector in construction, I get undefined reference to 'MyClass::simples' error. How to solve my problem?
When defining a static member in C++, you need to write it two times: first in class definition as you did:
static std::vector<int> simples;
And then outside (preferably in an external .cpp file):
std::vector<int> MyClass::simples;
If you know about C language, this can help you: static members in C++ are comparable from global variables in C: defined as a prototype in .h file included whenever you need it, and value initialized in one .c/.cpp file.
You have to define the static data member outside the class
std::vector<int> MyClass::simples;
Within the class definition it is only declared.
Related
This question already has answers here:
Unresolved external symbol on static class members
(6 answers)
Closed 7 years ago.
I'm currently designing some code on QT that is built across multiple source. I want to create an array in one source and be able to access it in another source.
Currently in my Header I have class
Array_Class : public QString
{
public:
static QString Data_Array [2];
};
I don't think I need a constructor as I'm going to "populate" the array before I read it.
currently in my source.cpp I have
Array_Class::Data_Array[0]= "foo";
Array_Class::Data_Array[1]= "bar";
however this gives me the error message undefined reference to "Array_Class::Data_Array". What am I missing? thanks
So far, you have only declared your array:
Array_Class : public QString
{
public:
static QString Data_Array [2]; // -> only a declaration!
};
In order to use it, you must now define it. To do this, you need to place somewhere in your .cpp:
QString Array_Class::Data_Array [2];
This question already has answers here:
How to initialize private static members in C++?
(18 answers)
Closed 8 years ago.
I have a class like this:
class example {
public:
static void setStaticVar() { example::var = 1; };
private:
static int var;
};
But it gives me linker errors and I have no idea why.
I want to store some data in the variable that is the same for every instance. That's why I want to use a static variable instead of an instance variable (with an instance variable I would store the same data in every single instance of the class which is a waste of memory).
How do I do this?
In the source file
int example::var = 0;
You need to initialize the variable once. In one .cpp, outside of any functions, you have to initialize the variable:
int example::var = 0;
You must initialize it out of the class definition.
Try this.
class example { ... };
// initialize it to avoid linker errors
int example::var = 1;
This question already has answers here:
Static variable for object count in c++ classes?
(3 answers)
Closed 3 months ago.
I would like to achieve a functionality where I can know how much object where created using a specific class.
I have tried the following:
myClass.h
class myClass {
private:
static int internalCounter;
int id;
public:
myClass(): id(internalCounter) {internalCounter++;}
}
The problem is that C++ doesn't allow this, and I'm not sure how to workaround this.
I have seen similar question in SA in which answer suggested something like:
myClass::internalCounter = 0;
But I don't think this right on the syntax level.
C++ does allow this. But the static variable needs a definition, and it sounds like that's missing. You'll need to put this in a source file (not the header)
int myClass::internalCounter = 0;
The = 0 is optional, since static variables are zero-initialised by default, but you might prefer to be explicit.
You need to define your static variable as
int myClass::internalCounter = 0;
in an implementation file.
The other suggestion you saw was almost right. You need something like this:
int myClass::internalCounter = 0;
But it needs to go in a source file (*.cpp) rather than a header. That line is necessary because the declaration on its own (in the header file) would never be instantiated otherwise. Resolving it in a source file means it will get picked up and instantiated within a specific translation unit.
You must define your static variable:
int myClass::internalCounter=0;
in your implementation file, its always best to read your compiler/linker output, in case of g++ it is:
main.cpp:(.text.startup+0x2): undefined reference to `myClass::internalCounter'
undefined reference means it was not defined, this is a hint on what you must fix in your code
I will suggest that, as you need to put your counter into a source file anyway, you take the definition of it out of the class and just put it into the anonymous namespace area. That takes some of the implementation detail of your class out of your header file.
If you are working in C++11 use atomic_int rather than int.
Use post-increment operator to make the action properly atomic.
myClass.h
class myClass
{
private:
int id;
public:
myClass();
// etc
};
myClass.cpp
#include <atomic>
#include "myClass.h"
namespace {
static std::atomic_int internalCounter;
}
myClass::myClass()
: id( internalCounter++ )
{
}
the operator++ post-increment on atomic_int is, at the name suggests, atomic, so it will be thread-safe.
I have the following problem (just learning OOP style C++): I have 3 classes:
app
objectManager
object
The app class sets up startup variables and creates an instance of objectManager. It tells objectManager to load values from different files and to precalculate some data in a vector what will be required for each object.
My problem is the following: I would like to use a precalculated vector accessable for each object. I don't understand how can I possibly access this variable from the objects, as they know absolutely nothing about the manager's instance.
I've read about singletons but I have no idea how should I implement it.
I've read about static data members but AFAIK it seems that I still have to somehow connect to the objectManager instance, so it doesn't help me.
I've tried global variables (I know...), but ended up with compiling errors.
I've tried to put static variables outside of a class definition in objectManager.h (is it a global case?), and I ended up with something strange:
I can access the variables from all parts of the program what includes objectManager.h, but it's value is different/uninitialized in different classes.
objectManager.h
#pragma once
#include "Object.h"
static int xxxtest;
class objectManager
{
objectManager.cpp
xxxtest = 123456;
cout << xxxtest << endl;
-> 123456
while in object.cpp or app.cpp (after)
cout << xxxtest << endl;
-> 0
Can you explain to me what is happening here?
Can you recommend me a simple and clean way of organizing such a program, while making a precalculated variable accessable to other parts of the program?
Static class variables are in fact the solution.
Static variables in classes need to be declared in the CPP file, right after the include.
Header:
class Class {
static int staticVariable;
static void staticFunction();
//...
};
CPP:
int Class::staticVariable = 5;
Do that, and all Object instances have access to the static variable (if it's private) and all members of the entire Program can access it (if it's public) by stating:
int Value = Class::staticVariable;
I hope this helps shed some light.
Ah yeah, I used the code from http://de.wikibooks.org/wiki/C++-Programmierung:_Statische_Elemente_in_Klassen (Page is in German) as Reference.
To get back to your problem, that would mean:
Header:
class objectManager {
static std::vector<double> Precompiled;
};
CPP:
std::vector<double> Precompiled; //Initialized automatically.
Since you only intend to create one objectManager, it is a candidate for a singleton or a regular global. As a global, you could define a header file like this:
// in object_manager.hpp
class App;
class ObjectManager;
class ObjectManagerImpl;
ObjectManager & objectManager ();
class ObjectManager {
friend ObjectManager & objectManager ();
friend class App;
std::unique_ptr<ObjectManagerImpl> impl_;
ObjectManager ();
void read_files (std::string file1, std::string file2);
public:
std::vector<int> & precomputed ();
//...
};
And in your source file, you could have something like:
// in object_manager.cpp
class ObjectManagerImpl {
friend class ObjectManager;
std::vector<int> precomputed_;
//...
};
ObjectManager::ObjectManager () : impl_(new ObjectManagerImpl) {}
void ObjectManager::read_files (std::string file1, std::string file2) {
//...
}
std::vector<int> & ObjectManager::precomputed () {
return impl_->precomputed_;
}
//...
ObjectManager & objectManager () {
static ObjectManager instance;
return instance;
}
Now, in the source file of your object, you would include the header file for objectManager, and access the vector through the accessor.
// in object.cpp
//...
std::vector<int> &precomputed = objectManager().precomputed();
Hi i have a class tools which has static variable std::vector m_tools.
Can i insert the values into the static variable from Global scope of other classes defined in other files.
Example:
tools.h File
class Tools
{
public:
static std::vector<std::vector> m_tools;
void print()
{
for(int i=0 i< m_tools.size() ; i++)
std::cout<<"Tools initialized :"<< m_tools[i];
}
}
tools.cpp File
std::vector<std::vector> Tools::m_tools; //Definition
Using register class constructor for inserting the new string into static variable.
class Register
{
public:
Register(std::string str)
{
Tools::m_tools.pushback(str);
}
};
Different class which inserts the string to static variable in static variable
first_tool.cpp
//Global scope declare global register variable
Register a("first_tool");
////////
second_tool.cpp
//Global scope declare global register variable
Register a("second_tool");
Main.cpp
void main()
{
Tools abc;
abc.print();
}
Will this work?
In the above example on only one string is getting inserted in to the static list. Problem look like "in Global scope it tries to insert the element before the definition is done"
Please let me know is there any way to set the static definiton priority? Or is there any alternative way of doing the same.
You are likely, here, to encounter the issue referred to as Initialization Order Fiasco.
The problem is that the initialization order of globals (and static class variables are globals) is well-defined within a same translation unit (roughly, think .cpp) but is completely undefined across translation units. Therefore, there is no guarantee that the vector be initialized when you try to push items in there.
Your solution here ? Use local static variables:
class Tools
{
public:
static std::vector<std::string>& AccessTools()
{
static std::vector<std::string> Tools; // local static
return Tools;
}
private:
};
class Register
{
public:
Register(std::string str)
{
Tools::AccessTools().push_back(str);
}
};
It is guaranteed to be initialized upon first access... though it's not (and cannot be) thread safe; if you are in a multithreading situation, you need to call Tools::AccessTools in main before launching the other threads to guarantee the initialization.
The initialization order of static global variables in different compilation units is not defined in C++ - this is why you have a problem.
A workaround may be to call a static function which contains the first static variable as local. This way you can force it to be initialized before it is used:
// tools.h
class Tools
{
public:
static std::vector<std::vector>& getTools();
...
};
// tools.cpp
std::vector<std::vector>& Tools::getTools() {
static std::vector<std::vector> tools;
return tools;
}
...
class Register
{
public:
Register(std::string str)
{
Tools::getTools().pushback(str);
}
};
The initialization of statics is not specified by C++. C++ FAQ Lite call it the "static initialization order fiasco"
my2c