Call a method of a static member for initialization in C++ - c++

I have a class that has a static member object. Initializing that static object means setting some of its parameter to a specific value; but this is done by a function from that object. i do not know how to do it if it is static. Any help?
To be more specific I have a static boost logger object per class. It has a ClasName attribute and setting this to the name_of_the_class value is done by add_attribute("ClassName", boost::log::attributes::constant<std::string>("MyClass")) function. What is the best way to initialize the static logger? I have done:
typedef boost::log::sources::severity_logger< severity_levels > BoostLogger;
class MyClass
{
private:
static BoostLogger m_logger;
public:
MyClass()
{
MyClass::m_logger.add_attribute("ClassName", boost::log::attributes::constant<std::string>("MyClass"));
}
}
BoostLogger MyClass::m_logger; // And here I cannot call the add_attribute() function
I know that this is done every time I instantiate the class, so: What is the best way to do it?

You can initialise the logger once e.g. with a static variable in your constructor:
MyClass()
{
static bool logger_initialised = false;
if (!logger_initialised)
{
MyClass::m_logger.add_attribute("ClassName", boost::log::attributes::constant<std::string>("MyClass"));
logger_initialised = true;
}
}
Note that this is not thread-safe. But if you do not use threads, it will work and the logger will be initialised one time but only if you instantiate MyClass.

if BoostLogger doesn't provide the constructor to add_attribute you may create your own function for that, something like:
class MyClass
{
private:
static BoostLogger m_logger;
};
BoostLogger CreateBoostLoggerWithClassName(const std::string& className)
{
BoostLogger logger;
logger.add_attribute(
"ClassName",
boost::log::attributes::constant<std::string>(className));
return logger;
}
BoostLogger MyClass::m_logger = CreateBoostLoggerWithClassName("MyClass");

First of all look at the BOOST_LOG_GLOBAL_LOGGER
Here is corrected version of your code.
MyClass.h:
class MyClass
{
private:
static BoostLogger m_logger; /* This is declaration, not definition.
You need also define the member somewhere */
public:
MyClass() /* So far as this is constructor, it may be called more than once,
I think adding new static function will be better */
{
// MyClass::m_logger.add_attribute("ClassName", boost::log::attributes::constant<std::string>("MyClass"));
// AddAttribute("ClassName"); Uncomment this line if you're really need to add attribute in constructor
}
static void AddAttribute(std::string name) /* this function has been added as advice,
if you're going add attributes as you
did in question,
remove function, and uncomment first line in the constructor */
{
MyClass::m_logger.add_attribute(name, boost::log::attributes::constant<std::string>("MyClass"));
}
}
MyClass.cpp:
BoostLogger MyClass::m_logger = BoostLogger(); // This is definition of static member item

Instead of an add_attribute call, make it so that you can fully initialise BoostLogger with its constructor. Then simply provide the necessary argument when you define it.

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.

class inheritance call a different constructor

hei i have a c++03 class with a simple constructor that take an integer. And a derived class with serialization methods that should take a filename as a constructor, load the integer from it, and then call the first constructor.
class A {
public:
A(int foo);
}
and a derived class:
class XmlableA : public A {
public:
XmlableA(int foo);
XmlableA(string xmlfilename) {
//load foo from xml
// call A::A(foo)
}
}
i tried some different solution but every time i get
no matching function for call to ‘A::A()’
Almost all answers are same, so I would suggest a different solution, which I would prefer personally.
Define a static member function Create as:
class XmlableA : public A {
public:
XmlableA(int foo);
//static member function
static XmlableA Create(string const & xmlfilename)
{
//load foo from xml
int foo = /*load from file*/;
return XmlableA(foo);
}
};
Usage:
XmlableA xmlable = XmlableA::Create(xmlFile);
Initialize it, like so:
XmlableA(int foo) : A(foo) {}
You may also consider:
private:
static int LoadXML(const string& xmlfilename) {
int ret = ...; << load here
return ret;
}
public:
XmlableA(string xmlfilename) : A(LoadXML(xmlfilename)) {
}
In C++ the Base class is constructed BEFORE the Child class, so you will not be able to do this. You could make a Factory that takes a filename and creates an object based on what is in that file.
Example:
class XmltableAFactory {
public:
static XmltableAFactory build(string xmlfilename) {
// read int foo from xmlfilename
return XmltableAFactory(foo);
}
};
And then call it like so:
XmltableA myObj = XmltableAFactory::build(filename);
There are a few things to note.
This means that you will not need the string xmlfilename cosntructor in the XmltableA class because as discussed above, you cannot know foo before the base class's constructor is called.
You can either choose to return from the factory by value or by pointer. The compiler might optimize the return by value because you are creating the object and returning it on the same line. However, return by pointer is usually known to be faster, but you'll have to create a new object and then make sure to delete it when you're done with it.
If you don't want to muck about with memory, take a look at boost's auto_ptr and shared_ptr.
If you want to do something before the call to A::A(int), you end up having to hack, something like
int XmlableA::f(string filename) { /* load foo from xml */; return foo; }
XmlableA(string xmlfilename) : A(f(filename)) {}
OK, so the first one is easy:
XmlableA::XmlableA(int foo) : A(foo)
{
}
The second one requires doing something like
XmlableA(string xmlfilename) : A(fooFromXML(xmlfilename))
{
}
which we can implement as
class XmlableA : public A
{
static int fooFromXML(string filename);
public:
// ...
Note that fooFromXML, which loads the XML file and returns the integer you need, must be static, because when we call it we don't yet have an XmlableA instance to invoke it on.
For multiple arguments (and as a general design), the factory is probably best: if you're wedded to the constructor model and don't care about efficiency, you can do:
class XmlableA : public A
{
static int intFromXML(char const *varname, string const &filename);
public:
XmlableA(string const &xmlfilename)
: A(intFromXML("foo", xmlfilename), intFromXML("bar", xmlfilename))
{
}
if you're concerned about parsing the XML file repeatedly, and don't care about re-entrancy, you can "memoize" xFromXML by having it cache state in a static member.
If your class A does not have a default constructor you have to explicitly call a constructor in the initialization list of your derived class. XmlableA(string fn) : A(readIntegerFromFile(fn)) {}.
However, you should think about "outsourcing" the serialization into a separate class. E.g. what would happen if you have an object of type A and now you want to serialize it? You couldn't because you can only serialize a XmlableA. Furthermore, what would happen if your client decides that he no longer wants a XML serialization but Yaml or some proprietary format? You would have to change all your code.

C++ Initialize class static data member

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