如何在不传递类实例的情况下从静态成员函数调用非静态成员函数

9

我需要在同一个类的静态成员函数中调用一个非静态成员函数。静态函数是一个回调函数,它只能接收void类型的数据,尽管我通过char*传递一个值。因此,我无法直接将类实例提供给回调函数。我可以传递一个结构体代替char到回调函数中。请问有没有任何示例代码可以在静态成员函数中使用结构体来调用非静态成员函数并解决这个问题?

4个回答

9

通常这样的回调会像这样:

void Callback( void* data)
{
    CMyClass *myClassInstance = static_cast<CMyClass *>(data);
    myClassInstance->MyInstanceMethod();
}

当然,你需要确保数据指向你的类的实例。例如:
CMyClass* data = new CMyClass();
FunctionCallingMyCallback( data, &Callback);
delete data;

现在,如果我理解您的意思正确,您还需要传递一个char*。 您可以将这两个内容包装在一个结构体中,并在回调函数中取消包装,如下所示:
MyStruct* data = new MyStruct();
data->PtrToMyClass = new CMyClass();
data->MyCharPtr = "test";
FunctionCallingMyCallback( data, &Callback);
delete data->PtrToMyClass;
delete data;


void Callback( void* data)
{
    MyStruct *myStructInstance = static_cast<MyStruct *>(data);
    CMyClass *myClassInstance = myStructInstance->PtrToMyClass;
    char * myData = myStructInstance->MyCharPtr;
    myClassInstance->MyInstanceMethod(myData);
}

或者,如果您可以修改CMyClass的定义,将所有必要的数据放入类成员中,这样您就可以像第一个示例中那样使用回调。

好答案 - +1 - 但是在我看来你不应该使用C风格的强制类型转换。 - sje397
谢谢Henrick,它起作用了。我之前尝试过同样的事情,唯一不同的是我没有为结构体创建指针。 - HariHaraSudhan

2
如果您的实例是单例模式(通常使用私有或受保护的构造函数和指向自身的静态指针实现),您可以执行以下操作:
class MyClass {
private:
  MyClass():myInstance(0) {}

  static MyClass *myInstance;

  void callback();
public:
  ~MyClass() {}

  static MyClass *getInstance();

  static void myCallback();    
};

MyClass *MyClass::getInstance() {
  if(!myInstance) {
    myInstance = new MyClass;
  }
  return myInsance;
}    

void MyClass::callback() {
 // non-static callback
}

void MyClass::myCallback() {
  getInstance()->callback();
}

如果您不使用单例模式,但可以将实例强制转换为void *,那么您可以改用以下方法:

void MyClass::myCallback(void *data) {
  MyClass *instance = static_cast<MyClass *>(data);
  instance->callback();
}

看起来getInstance在进入类的命名空间方面很有用。是这样吗?这是唯一的目的吗? - Jonathan
@Jonathan getInstance 方法与私有/受保护的构造函数结合使用,可以限制对单个实例的访问。 - sje397
你可以在第一个示例中添加不同的静态回调函数“myCallback<1-4>”,这些函数都调用具有const参数的MyClass :: callback方法。使用XMacro定义“myCallback<1-4>”会很好。 - Jonathan
1
你是否遇到了“在静态成员函数中无效使用成员'myInstance'”的错误? - Mich
@Mich 我认为这里myInstance也应该被设置为静态的。 - Kargath
是的,我也这么认为。@Kargath - 已编辑。 - sje397

0

这是唯一的方法:

#include <iostream>
#include <cassert>

struct A;
A *oneObj = NULL;


struct A
{
  A(){
    oneObj=this;
  }
  ~A(){
    oneObj=NULL;
  }
  void foo()
  {
  }

  static void boo()
  {
    assert( NULL != oneObj );
    oneObj->foo();
  }
};

int main()
{
  A onlyOne;
  A::boo();
}

0
我需要从同一类的静态成员函数中调用非静态成员函数。这个静态函数是一个回调函数,只能接收void类型的数据,但我会传递一个char*类型的参数。
这表明现有的设计存在缺陷或不当。在我看来,你应该考虑改变设计。想象一下,如果你设法让事情工作起来,那么代码的可维护性和可读性如何呢?
我建议你将回调函数更改为不同的签名,并进行相应的更改。
class A {
//...
  static void CallBack (A *pObj)
  {
    // logic
  }
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接