需要处理C++类成员的静态函数

Static function needing to deal with members of a C++ class

本文关键字:成员 静态函数 C++ 处理      更新时间:2023-10-16

我必须在两个软件之间建立某种桥梁,但我面临着一个不知道如何处理的问题。希望有人会有有趣的(最好)工作建议。

背景是这样的:我有一个C++软件套件。我必须用另一个函数替换给定类中的某个函数,这是可以的。问题是,新函数调用了另一个必须是静态的函数,但必须处理该类的成员。这是第二个让我抓狂的功能。

如果函数不是静态的,我会得到以下错误:

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

如果我将其设置为静态,我会得到以下错误之一:

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

error: ‘this’ is unavailable for static member functions

这取决于我是否使用"this"关键字("Function()"或"this->Function())。

最后,类对象需要一些参数,我无法将这些参数传递给静态函数(我无法修改静态函数原型),这使我无法在静态函数本身中创建新实例。

你会如何用最少的重写来处理这样的情况?

编辑:好的,这是一个关于我必须做的事情的简化示例,希望它是清晰正确的:

// 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();
}

指向非静态成员函数的指针处理起来有点棘手。最简单的解决方法就是在函数中添加一个不透明的指针参数,然后将其转换为指向"this"的指针,然后使用它执行所需操作。

这里有一个非常简单的例子:

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;
}

在该示例中,myCallback()可以通过不透明指针访问私有value_

如果你想要一种更像C++的方法,你可以考虑使用Boost.Function和Boost.Bind,它们允许你将非静态成员函数作为回调传递:

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;
}

如果你真的不能更改函数原型,你可以使用全局指针,但如果你的类有不止一个实例,就会出现各种问题。这只是一般不好的做法。

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;
}

根据spencercw在初始问题下面的建议,我尝试了"您设置为指向this的静态成员变量"解决方案(全局变量在软件套件的上下文中会很棘手和危险)。

事实上,我发现代码中已经实现了类似的东西(我没有写):

static void*          currentObject;

所以我只是用它,作为

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

它确实有效,谢谢!!!

非重入和非线程安全的方法是使用全局变量传递"this"地址。

您可以将result = SomeComputation();从静态函数中移出,并在调用静态函数之前将其放置在BigFunction中。