The static function needed to work with members of the C ++ class

I need to make some kind of bridge between the two pieces of software, but I ran into a problem that I don’t know how to deal with. I hope someone will have interesting and (preferably) working suggestions.

Here is the background: I have a C ++ software package. I have to replace some function inside this class with another function, which is normal. The problem is that the new function calls another function, which must be static, but must deal with class members. This is the second feature that makes me crazy.

If the function is not static, I get the following error:

error: argument of type 'void (MyClass::)(…)' does not match 'void (*)(…)' 

If I set it to static, I get either the following error:

 error: cannot call member function 'void MyClass::MyFunction(const double *)' without object 

or

 error: 'this' is unavailable for static member functions 

depending on whether or not I use the keyword "this" ("Function ()" or "this-> Function ()").

And finally, the class object requires some arguments that I cannot pass to the static function (I cannot change the prototype of the static function), which prevents me from creating a new instance inside the static function itself.

How do you feel about such a case with minimal rewriting?

Edit: Well, here is a simplified example of what I should do, hoping this is clear and correct:

 // This function is called by another class on an instance of MyClass MyClass::BigFunction() { … // Call of a function from an external piece of code, // which prototype I cannot change XFunction(fcn, some more args); … } // This function has to be static and I cannot change its prototype, // for it to be passed to XFunction. XFunction makes iterations on it // changing parameters (likelihood maximization) which do not appear // on this sample void MyClass::fcn(some args, typeN& result) { // doesn't work because fcn is static result = SomeComputation(); // doesn't work, for the same reason result = this->SomeComputation(); // doesn't work either, because MyClass has many parameters // which have to be set MyClass *tmp = new MyClass(); result = tmp->SomeComputation(); } 
+4
source share
4 answers

Following the spencercw suggestion below the original question, I tried the "static member variable that you set to point to this " (a global variable would be complex and dangerous in the context of a software package).

In fact, I realized that something similar was already implemented in the code (which I did not write):

 static void* currentObject; 

So I just used it since

 ((MyClass*)currentObject)->SomeComputation(); 

It works, thanks !!!

+1
source

Pointers to non-static member functions are a little tricky to handle. The simplest workaround would be to simply add an opaque pointer argument to your function, which can then be drawn as a pointer to 'this', and then do what you need.

Here is a very simple example:

 void doSomething(int (*callback)(void *usrPtr), void *usrPtr) { // Do stuff... int value = callback(usrPtr); cout << value << "\n"; } class MyClass { public: void things() { value_ = 42; doSomething(myCallback, this); } private: int value_; static int myCallback(void *usrPtr) { MyClass *parent = static_cast<MyClass *>(usrPtr); return parent->value_; } }; int main() { MyClass object; object.things(); return 0; } 

In this example, myCallback() can access the private value_ through an opaque pointer.

If you want to use a more C ++-like approach, you can explore the use of Boost.Function and Boost.Bind, which allow you to pass non-static member functions as callbacks:

 void doSomething(boost::function<int ()> callback) { // Do stuff... int value = callback(); cout << value << "\n"; } class MyClass { public: void things() { value_ = 42; doSomething(boost::bind(&MyClass::myCallback, this)); } private: int value_; int myCallback() { return value_; } }; int main() { MyClass object; object.things(); return 0; } 

If you really cannot change the function prototype, you can use a global pointer, but this opens up all kinds of problems if you ever have more than one instance of your class. This is just bad practice.

 class MyClass; static MyClass *myClass; void doSomething(int (*callback)()) { // Do stuff... int value = callback(); cout << value << "\n"; } class MyClass { public: void things() { value_ = 42; myClass = this; doSomething(myCallback); } private: int value_; static int myCallback() { return myClass->value_; } }; int main() { MyClass object; object.things(); return 0; } 
+2
source

The non-reentrant and non-thread-safe path is to pass the address "this" using a global variable.

0
source

You can move result = SomeComputation(); from your static function and put it in a BigFunction right before calling the static function.

0
source

Source: https://habr.com/ru/post/1398214/


All Articles