【问题标题】:Static function needing to deal with members of a C++ class需要处理 C++ 类成员的静态函数
【发布时间】:2012-03-14 20:20:49
【问题描述】:

我必须在两个软件之间架起某种桥梁,但我遇到了一个我不知道如何处理的问题。希望有人会提出有趣且(最好)可行的建议。

这是背景:我有一个 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 指针,所以你不能做 this-> 。您需要将它应该处理的对象作为参数传递给函数。
  • this 在静态上下文中无效,因为没有类实例。
  • 代码很复杂,所以我没有贴出来,我会尝试写一些在“代码模式”下说明问题的东西(不知道需要多长时间)。
  • @SkippyleGrandGourou 由于您无法更改函数原型,因此您必须在调用函数之前使用全局指针或静态成员变量,将其设置为指向this。但是,如果您有多个类的实例,这将无法正常工作。看我的回答。

标签: c++ class static


【解决方案1】:

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

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

static void*          currentObject;

所以我只是用它,因为

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

确实有效,谢谢!!!

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我认为你仍然这样做。因为您通过引用将结果发送到静态函数。
    • 我想确实可以使用结果参数作为输入,我没有这样想。但请记住,这是一个简化的示例。实际上它在我的情况下不起作用,因为我在 SomeComputation 函数中包含的一件事是更新对象的许多值。
    【解决方案3】:

    指向非静态成员函数的指针有点难以处理。最简单的解决方法是向函数添加一个不透明的指针参数,然后您可以将其转换为指向“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;
    }
    

    【讨论】:

      【解决方案4】:

      不可重入和非线程安全的方式是使用全局变量传递“this”地址。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-02
        • 1970-01-01
        相关资源
        最近更新 更多