C++ Initialize class static data member - c++

I have a class which has a number of static function to perform some calculation. However, before the calculation, I need to pass in a data to initialize some of the static data members. Currently I have an init(data) function and a clearResource() function which should be called before and after the use of the class. Is there a better way of doing that?
For example:
classA(){
static int a;
static init(int b) {
a = b;
}
static functionA(){
//perform something based on value of a;
switch(a){
}
}
}
int main(){
classA::init(5);
classA::functionA();
}
Thanks

Avoid using static member functions : have your constructor initialize the data and the destructor clear the resources (see RAII). If the existing class cannot be changed, implement a helper class which calls init from its constructor and clearResource from its destructor.

You can use this kind of design
class A()
{
public:
static int a;
static void functionA(int arg = A::a)
{
if(A::a != arg)
A::a = arg;
...
}
};
int A::a = 0;
int main()
{
A::functionA();
}

You should apply the RAII concept: see this and this questions.

Make the member functions and data non-static, initialize in a constructor and free resources in the destructor. This will guarantee the correct sequence of calls: initialize - perform operations - free resources in the client code.

I'd avoid using static members in this case.
This is your problem. You have a class that does processing on some data. That data, for whatever reason, needs to be shared across all instances of this processing class. Ok then, we have a non-static solution!
class Data : boost::noncopyable
{
public:
Data()
{
// initialise all of our data.
}; // eo ctor
}; // eo class Data
Where you instantiate this class is up to you. It could be a member of an application class that is run at start up, or part of some root. It just needs to be accessible and does not need to be static nor a singleton.
class DataProcessor
{
private:
Data& m_Data;
public:
DataProcessor(Data& _data) : m_Data(_data)
{
}; // eo ctor
}; // eo class DataProcessor

Related

Is there a way to get class object in static function other than passing it as parameter?

Is there a way to get the class object in a class static function other than passing it as function argument? I cannot pass it as argument or make my class singleton.
class test{
public:
int i=10;
test(){}
Static test_static_method(){
// somehow get an object of the class to call class member.
std::cout << classObj->i << "\n";
}
};
I am trying to pass the static function to a C-API that takes in void(*)(). But I need class instance in my function to access the class data. Any help is appreciated.
If you're not going to have too many instances of your class, you can use preallocated "callback pool" -- pre-created functions that you allocate as needed for the callbacks:
#define REP10(P, M) M(P##0) M(P##1) M(P##2) M(P##3) M(P##4) M(P##5) M(P##6) M(P##7) M(P##8) M(P##9)
#define REP100(M) REP10(,M) REP10(1,M) REP10(2,M) REP10(3,M) REP10(4,M) REP10(5,M) REP10(6,M) REP10(7,M) REP10(8,M) REP10(9,M)
typedef void (*callback_fn_t)(void); // or whatever signature you need
class myclass {
static struct callback_t {
callback_t *next;
callback_fn_t callback;
myclass *obj;
} callback_table[100];
callback_t *my_callback;
static callback_t *freelist;
#define CB_FUNC_DECL(M) static void cbfunc##M() { callback_table[M].obj->callback(); }
REP100(CB_FUNC_DECL)
public:
callback_fn_t get_callback() {
if (!my_callback) {
if (!freelist) return nullptr;
my_callback = freelist;
freelist = my_callback->next;
my_callback->obj = this; }
return my_callback->callback;
}
void callback() {
/* this non-static method is called by the callback */
}
myclass() : my_callback(nullptr) { }
myclass(const myclass &a) : my_callback(nullptr) {
// need to manually define copy
}
~myclass() {
if (my_callback) {
my_callback->obj = nullptr;
my_callback->next = freelist;
freelist = my_callback; }
}
};
#define CB_TABLE_INIT(M) { M ? myclass::callback_table+M-1 : 0, myclass::cbfunc##M },
myclass::callback_t myclass::callback_table[100] = { REP100(CB_TABLE_INIT) };
myclass::callback_t *myclass::freelist = &myclass::callback_table[99];
Now if you want to use one of these objects as a callback, you call get_callback to get the function pointer you give to the C library, and it will call the callback method in your class on that object.
** I offer here an addition of a singleton solution although you said you can't, for future readers of this topic, who might see it helpful. Pay attention to the other solution.
The answer to your question is "No" for a reason. Objects are unique, and any object of the same class can (and usually will) contains a different data. When you are talking about static function/members of a class, different objects of the same class, will always contain the exact same data in those static functions/members.
However, if from some reason (probably an architecture bug), you don't care which object you will access using your static function, you can either make your class a singleton (which means that you'll always have only one instance of your class, and you'll always know which object data you'll use), or define an object instance static pointer in your class. Something like that:
class test {
public:
int i = 10;
test *class_obj;
test() {
class_obj = this; // The last object that created
}
Static test_static_method() {
// somehow get an object of the class to call class member.
std::cout << class_obj->i << "\n";
}
};
Read about:
Singleton
C++ Singleton
Static members in C++

Create a static initialise class in c++

I want to have a class that is used for a one off initialization like so:
class Initialise
{
public:
Initialise()
{
m_name = "Jimmy";
}
~Initialise(){}
private:
std::string m_name;
};
class SomeClass
{
static Initialise staticStuff; // constructor runs once, single instance
};
int main()
{
SomeClass testl;
return 0;
}
When I run the above I find that the constructor of the 'Initialise' class never gets hit in the debugger. Why is this?
You didn't define staticStuff, you only declared it.
You have to declare it outside of the class like so :
Initialise SomeClass::staticStuff;
Here is a live example.
Moreover, like pointed by Borgleader, you should consider using a member initializer list to improve your code.

Can initialization of a template class member be delegated to client?

I have faced with the following problem: how to initialize static Proxy which holds object that is provided as template parameter.
Here is my code snippet which shows the situation:
template<class SharedState>
class TToolbar : public ImplCustomToolBar
{
public:
virtual const ICustomToolbarsSharedState* const GetSharedState() const { return &sharedState_.Get();}
private:
// intent: static constructor for static SharedState initialization
class SharedStateHolder
{
public:
SharedStateHolder()
{
ToolbarsSharedState_.Initialize();
}
const SharedState& Get() const { return ToolbarsSharedState_;}
private:
SharedState ToolbarsSharedState_;
};
static SharedStateHolder sharedState_;
};
// I need TToolbar::SharedStateHolder sharedState_;
As it is unknown what template parameter will be provided, I can't use explicit specialization of template for the static member initialization.
So the only solution I found: clients of TToolbar should do initialization themselfs. But I think that it is error prone solution.
Question: what weaknesses are in my solution and what is the proper way of dealing with such situation?
You can use a static local variable of a member function:
template<class SharedState>
class TToolbar : public ImplCustomToolBar
{
virtual const ICustomToolbarsSharedState* const GetSharedState() const
{
static SharedStateHolder sharedState_;
return &sharedState_.Get();
}
};
The compiler is responsible for ensuring that the static is unique.
Or, if one wants to get rid of that Holder class:
template<class SharedState>
class TToolbar : public ImplCustomToolBar
{
virtual const ICustomToolbarsSharedState* const GetSharedState() const
{
static SharedState sharedState_;
static bool initialized = false;
if (!initialized)
{
sharedState_.Initialize();
initalized = true;
}
return &sharedState_;
}
};
One way to solve your problem is to delegate the construction of TToolBar to a factory, which knows about that shared state (basically, that's what SharedStateHolder does), and pass it to a protected constructor of TToolBar, which only that factory may use, by being friend with TToolBar. Objects needing such toolbar would have to go through the factory to get one.
template<typename SharedState>
class TToolBar {
friend class TToolBarFactory;
// ...
protected:
TToolBar(SharedState *shared){
// ...
}
// all other constructor also protected
};
class TToolBarFactory{
public:
TToolBarFactory();
TToolBar<SharedStateImpl> *makeToolBar();
// other toolbar pseudo constructors
};
Now SharedState construction is delegated to a dedicated class, which should be a singleton to ensure that toolbars all carry the same state.
Alternatively, since the SharedState instance is static, you can simply make a static method to set that variable once for all, and have the factory call it when it is instantiated. Then you would not need to pass it to TToolBar constructor (like I did above), and allow other objects to create them directly.
We may consider TToolBarFactory as a constructor for the TToolBar class, rather than its instances.
Note that this problem is orthogonal to the fact that TToolBar is parameterized on SharedState: you could make the factory directly provide specialized instances of TToolBar (like I did), or generalize it to a template, with a constructor a la std::vector::emplace, which is templated on the contained data constructor parameters.
template <typename SharedState>
class TToolBarFactory {
public:
template <class... args>
TToolBarFactory(Args...args){
TToolBar<SharedState>::setSharedState(new SharedState(args...));
// remaining factory init code.
}
// this could also be a variadic templated function
TToolBar<SharedState> *makeToolBar(){
return new TToolBar<SharedState>();
}
};
// example
class SharedStateImpl {
public:
SharedStateImpl(int i, float f){}
};
// the factory instance
TToolBarFactory<SharedStateImpl> factory(42,3.14);
int main(){
TToolBar<SharedStateImpl> *toobar = factory.makeToolBar();
}
If I understood your problem, it is really about having SharedState constructed outside TToolBar, because.you don't want that class to make any assumpions about SharedState constructors. My solution is a bit heavy weight. You could definitely do the same by simply making SharedStateHolder a template parameter of TToolBar, and keep all the initialization details there.

Is the typical C++ implementation of Factory class flawed?

I have the need to implement factory class in C++, but when I was thinking about that, I found one big problem that I couldn't solve, and I found out, that all factory implementation examples around are flawed in the same way. I'm probably the one who is wrong, but please tell me why.
So here is simple "typical" factory implementation, it allows me to register new objects without changing the Factory class.
//fruit.h
class Fruit
{
protected :
int count;
public :
Fruit(int count) : count(count) {}
virtual void show() = 0;
};
// factory.h
/** singleton factory */
class Factory
{
typedef Fruit* (*FruitCreateFunction)(int);
static Factory* factory;
std::map<std::string, FruitCreateFunction> registeredFruits;
public :
static Factory& instance()
{
if (factory == NULL)
factory = new Factory();
return *factory;
}
bool registerFruit(const std::string& name, Fruit* (createFunction)(int))
{
registeredFruits.insert(std::make_pair(name, createFunction));
return true;
}
Fruit* createFruit(const std::string& name, int count)
{
return registeredFruits[name](count);
}
};
//factory.cpp
Factory* Factory::factory = NULL;
//apple.h
class Apple : public Fruit
{
static Fruit* create(int count) { return new Apple(count); }
Apple(int count) : Fruit(count) {}
virtual void show() { printf("%d nice apples\n", count); };
static bool registered;
};
// apple.cpp
bool Apple::registered = Factory::instance().registerFruit("apple", Apple::create);
//banana.h
class Banana : public Fruit
{
static Fruit* create(int count) { return new Banana(count); }
Banana(int count) : Fruit(count) {}
virtual void show() { printf("%d nice bananas\n", count); };
static bool registered;
};
// banana.cpp
bool Banana::registered = Factory::instance().registerFruit("banana", Banana::create);
// main.cpp
int main(void)
{
std::vector<Fruit*> fruits;
fruits.push_back(Factory::instance().createFruit("apple", 10));
fruits.push_back(Factory::instance().createFruit("banana", 7));
fruits.push_back(Factory::instance().createFruit("apple", 6));
for (size_t i = 0; i < fruits.size(); i++)
{
fruits[i]->show();
delete fruits[i];
}
return 0;
}
Ok, this code looks fancy and it works, but here comes the but:
The C++ standard doesn't allow me to define the order in which global (static) variables will be defined.
I have 3 static variables here
Apple::registered;
Banana::registered;
Factory::factory;
The Factory::factory pointer needs to be defined to NULL before the Apple(or Banana)::registered variable, or the Factory::instance method will work with uninitialized value, and behave unpredictably.
So, what am I not getting here? Is the code really working only by an accident? If so, how should I solve the issue?
All global POD data is guaranteed to be initialized to a constant value before any initializers run.
So at the start of your program, before any of the register calls are made and before main is run, the pointer is NULL and all of the bools are false, automatically. Then the initializers run, including your register calls.
Edit: Specifically, from the standard (3.6.2.2: Initialization of non-local objects):
Together, zero-initialization and
constant initialization are called
static initialization; all other
initialization is dynamic
initialization. Static initialization
shall be performed before any dynamic
initialization takes place.
All static variables are initialized before the program begins to run. They are set at compile time and baked right into the executable.
The only issue arises when one static variable depends on another:
In a.hpp:
static int a = 1;
in b.hpp:
extern int a;
static int b = a;
The order in which static variables are initialized is not well defined, so b may or may not be 1 in this example. As long as your variables don't depend on each other, you're fine. Furthermore, is you don't give an initial value, static members are set to zero by default.
I've tended to see the 'instance' method of Factory implemented as follows:
static Factory& instance()
{
static Factory *factory = new Factory();
return *factory;
}
However, the point is that all access to the instance runs through the static instance method. The calls to register the two fruit classes for example use Factory::instance() to obtain the singleton which will guarantee that the initializer for Factory::factory has executed. In my posted alternative implementation the static initialization only occurs the first time the method is called.
The possible issues with Apple::registered and Banana::registered depend on where they might be used from. In the posted code they aren't used at all. If used only within apple.cpp and banana.cpp respectively then there is no issue with order of initialization.

C++ Class Delegation Constructor Problems

Thank you for reading.
The to delegate Class is called Sensor. It need a reference to be set in the Constructor like:
class Sensor { Sensor(other *ref);}
I have a Class testFactory. If i now type
class testFactor{
...stuff...
private:
Sensor mySensor;}
I get ALL the Problems. It cannot alloc an abstract Object. Or it cannot declare the variable, or does not know the Type of the variable.
Even taking Sensor out of the header into the cpp with as a static variable does not help.
Only if i change the Sensor Constructor to a void/non Constructor i dont get ANY Problems.
But then i have to use a setRed Function in the Sensor and this could lead to more problems.
Hope you can help me with: declaring a Variable with holds an Class with an non Void Constructor
You need to initialise the Sensor instance correctly - for example:
class TestFactor {
public:
TestFactor() : mySensor( 0 ) {}
private:
Sensor mySensor;
};
It works fine for me using c++. Perhaps you didn't declare the construction of Sensor in the initialisation list for Fac?
class Sensor {
public:
Sensor(int *a)
{
}
};
int b;
class Fac {
public:
Fac():
sensor(&b)
{}
private:
Sensor sensor;
};
main()
{
Fac a;
return 0;
}
One thing that I can see is that your constructor for Sensor is private (try changing class to struct or putting public: before constructor or declaring the frienship between Sensor and containing class). And you should either have a default constructor in addition to it or provide the parameter when instantiating it in containing class.
But you obviously need to be more specific to get more specific answers.
If you have classes with non-default constructors the compiler wont generate a default constructor for it. You also cannot instantiate classes which have only private constructors.
You can either provide a public default constructor, use a pointer to the instance or simply initialize the member via a public constructor:
class testFactor {
Sensor mySensor;
public:
testFactor() : mySensor(0) {}
};
One more point: If sensor is an abstract class, you cannot create an instance of it.
Most factory patterns have an abstract base classes an return pointers of the base class that point to allocated derived objects.
class Sensor
{
virtual std::string get_sensor_name(void) const = 0;
};
class Fire_Sensor
: public Sensor
{
std::string get_sensor_name(void) const
{ return "Fire Sensor";}
};
Sensor *
Sensor_Factory::create_sensor(std::string name)
{
if (name == "Fire Sensor")
{
return new Fire_Sensor;
}
return NULL;
}
Also look up reference slicing.