This question already has answers here:
How to initialize private static members in C++?
(18 answers)
Closed 6 years ago.
I have a simple class which will be useful for me with generating random numbers using default_random_engine.
Random.h:
#include <random>
using namespace std;
class Random
{
public:
Random();
~Random() {}
private:
static default_random_engine _engine;
};
Random.cpp:
#include "Random.h"
Random::Random()
{
_engine = default_random_engine{}; //Will this be initialized every time I create an object of type Random?
}
Will _engine be initialized every time I create an object of type Random?
I just want it to stay like it is after the first initialization because I was told I can use the same engine multiple times.
Will _engine be initialized every time I create an object of type Random?
Yes.
I just want it to stay like it is after the first initialization
In which case, you should define it like so:
#include "Random.h"
std::default_random_engine Random::_engine;
Without this, even your original version won't compile (as you've not defined the static member).
The link #NathanOliver provided in my question helped me understand, which is to make a global variable of that type in the source file:
#include "random.h"
default_random_engine Question::_engine = default_random_engine{};
Random::Random() { }
Related
This question already has answers here:
Iterate through Struct and Class Members [duplicate]
(6 answers)
Closed 2 years ago.
I am currently writing a ROS 2 node to pass values from a PLC through ROS to a visualization:
PLC System --> ROS --> Visualization
Since ROS should only pass on the data, I want to be able to configure the interface here with as little effort as possible. The idea, which can be implemented best with ROS, would be a config-file(.msg file), in which the designation of the variables and their type is entered. Everything else is then derived from this.
The problem I inevitably run into with this: In ROS data are passed on over so-called messages. These messages are defined via structs and are automatically generated from my config-file. To assign values to the variables from the struct, I don't want to address every single one hardcoded in the program, but rather iterate through the struct using the known names.
TLNR: Can variables be addressed with variable variable names?
I know that the whole thing sounds a bit confusing. I hope the following example will clarify what I mean:
#include <vector>
#include <string>
struct MsgFile
{
int someVariable;
int someOtherVariable;
};
using namespace std;
class Example
{
public:
vector<string> variableNames{"someVariable", "someOtherVariable"};
MsgFile message;
void WriteVariables()
{
for (auto const &varName : variableNames)
{
message."varName" = 0; //<-- pseudo code of what I'm thinking of
}
}
};
Regards
Tillman
You cannot use variable names like that. There are no variable names at runtime. If you want a mapping between names (strings) and variables, you need to add that yourself.
If your "variables" are of same type, eg int, you can use a map:
#include <vector>
#include <string>
#include <unordered_map>
using MsgFile = std::unordered_map<std::string,int>;
struct Example {
std::vector<std::string> variableNames{"someVariable", "someOtherVariable"};
MsgFile message;
void WriteVariables() {
for (auto const &varName : variableNames) {
message[varName] = 0; // add an entry { varName, 0 } to the map
// (or updates then entry for key==varName when it already existed)
}
}
};
If you only need the string representation to access it (but not for printing etc) you can consider to use an enum as key instead. At least I'd define some constants like const std::string some_variable{"some_variable"}, to avoid typos going unnoticed (perhaps the variableNames is supposed to be const (and static?)).
As far as I know there is no standard way to do this, I would choose another way to store the data ( I mean not in struct ), but if you are adamant here is an answered question:
Get list of C structure members
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.
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.
This question already has an answer here:
c++ calling non-default constructor as member [duplicate]
(1 answer)
Closed 9 years ago.
I am currently looking into new c++11 random library. For simplification, I created following class
class my_rand {
private:
std::mt19937_64 eng;
public:
my_rand() {
std::array<int, std::mt19937::state_size> seed_data;
std::random_device rd;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(rd));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
this->eng.seed(seq);
};
unsigned long long operator() () {
return this->eng();
};
};
so that I can just do my_rand rand; once and then repeatedly call rand() to generate random numbers.
However, now I want to use std::uniform_int_distribution to set bound to numbers I get. It seams obvious to specify bounds while creating the object, so that invocations stay the same. The problem is, if I add private member (something like std::uniform_int_distribution<long long> uid;) then later in constructor I will not be able to set bounds because uid will already be initialized. I could not find method of std::uniform_int_distribution which allowed to set limits after it is created.
I may well be missing some point here, so thanks in advance for any help.
Use initializer lists to construct member variables or base classes. (See here for more info)
my_rand(...arguments...) : uid(...arguments...) //<-- Initializer list
{
//...stuff...
} //<-- No semicolon after function definition.
If that doesn't suit your needs, you can always go like this:
myVar = int(27);
For example:
//Initial construction:
std::uniform_int_distribution<> testA(1, 6);
//Re-assignment by copy-construction (move-construction actually)
//and a temporary object.
testA = std::uniform_int_distribution<>(5, 10);