【问题标题】:How to call a non static member function from a static member function without passing class instance如何在不传递类实例的情况下从静态成员函数调用非静态成员函数
【发布时间】:2011-10-17 05:19:51
【问题描述】:

我需要从同一个类的静态成员函数中调用一个非静态成员函数。 静态函数是回调。它只能接收 void 作为数据,尽管我传递了一个 char*。所以我不能直接将类实例提供给回调。我可以将结构而不是 char 传递给回调函数。任何人都可以提供例如代码以在静态成员函数中使用非静态成员函数。并且使用静态成员函数中的结构来使用类的实例来调用非静态成员函数?

【问题讨论】:

    标签: c++ class static struct


    【解决方案1】:

    通常这样的回调应该是这样的:

    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 样式转换。
    • 感谢 Henrick 成功了。我之前尝试过同样的事情,除了我要为结构创建一个指针。
    【解决方案2】:

    如果您的实例是单例(通常使用私有或受保护的构造函数和指向自身的静态指针来实现),您可以这样做,例如:

    class MyClass {
    private:
      MyClass():myInstance(0) {}
    
      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 getInstance 方法结合私有/受保护的构造函数允许您限制对单个实例的访问。
    • 您可以在第一个示例中添加不同的静态回调“myCallback”,使用 const 参数调用相同的方法 MyClass::callback。用 XMacro 定义“myCallback”会很好。
    • 您没有收到“在静态成员函数中无效使用成员'myInstance''getInstance() 错误吗?
    【解决方案3】:

    这是唯一的方法:

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

    【讨论】:

      【解决方案4】:

      我需要从静态成员调用非static 成员函数 相同class的功能。 static 函数是一个回调。它可以 只接收 void 作为数据,尽管我传递了 char*

      这表明当前的设计有缺陷或不恰当。恕我直言,您应该考虑更改设计。试想一下,如果您以某种方式使事情正常运行,但代码的可维护性和可读性又会如何。

      我建议你应该将你的回调函数更改为不同的签名并进行相应的更改。

      class A {
      //...
        static void CallBack (A *pObj)
        {
          // logic
        }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多