2014-11-03 292 views
0

我最近决定开始使用回调函数来让我的生活变得更加简单。但是,我有一个有点问题:C++回调函数,在静态函数中调用成员变量

#include <iostream> 
#include <functional> 
#include <memory> 

class setCallback 
{ 
public: 
     setCallback() {} 
     setCallback(std::function<int()> func) : callback(func) { } 

     int call() { return callback(); } 
private: 
     std::function<int()> callback; 
}; 

class callThis 
{ 
public: 
     callThis() : number(10) {} 

     static int another() 
     { 
       return number; 
     } 
     int number; 
}; 

int main(int argc, char** argv[]) 
{ 
     std::shared_ptr<setCallback> caller; 
     std::shared_ptr<callThis> funcholder; 

     funcholder.reset(new callThis); 
     caller.reset(new setCallback(funcholder->another)); 

     std::cout << caller->call() << "\n"; 

     std::cin.get(); 
} 

正如你可以从代码中看到,我拉的功能从“callthis”变成“setCallBack”。这使我可以保留该功能以备后用,如果需要的话。然而,如果我尝试从“callthis”加载到静态函数中的成员变量,它显然不起作用(使用值)。

有没有办法解决这个问题?我想使用静态函数访问在类中找到的变量;可选地避免在传入回调时使用静态函数(但我认为这是不可能的,因为回调的方式)。

我听说过有关包装类,但我不完全知道如何去实现它。有些见解将不胜感激。

非常感谢。

编辑:

解决调用带有回调函数的变量,经B萨胡

解决呼叫使用回调未做功能函数被调用静态和保持事物合理解耦

我研究如何使用C++ 11调用非静态函数;如果有人遇到同样的问题,我认为这可能会有用。这与Sahu提出的R原理相同,然而,使用它的类型和过程最终会变得更清洁。使用std :: bind(class :: func,object)可以有效地获得相同的结果。

int main(int argc, char** argv) 
{ 
    std::function<void(void)> somefunc; 

    Functionholder func; 

    somefunc = std::bind(&Functionholder::say, &func); 
} 

信用为这个去:This beautiful person

其中在更复杂的例子使用时,其持有的函数来调用,呼叫者类将采取功能并在需要时调用它类和粘合剂/状态类(请注意,我用这对游戏UI),你真的可以得到一些合理的整洁和解耦代码去:

#include <iostream> 
#include <functional> 

class Functionholder 
{ 
public: 
    void say() { std::cout << "hello!\n"; } 
}; 

class CallbackHandler 
{ 
public: 
    CallbackHandler(){} 
    CallbackHandler(std::function<void()> call) { callback = call; } 

    void update() 
    { 
     //something happens to call this 
     callback(); 
    } 

    std::function<void()> callback; 
}; 

class TheState 
{ 
public: 
    TheState() 
    { 
     hand = CallbackHandler(std::bind(&Functionholder::say, &func)); 
    } 

    void update() { hand.update(); } 

    Functionholder func; 
    CallbackHandler hand; 
}; 

int main(int argc, char** argv) 
{ 
    TheState state; 
    state.update(); 

    std::function<void(void)> somefunc; 

    std::cin.get(); 
} 

如果您有任何改进,让我知道!

回答

1

提供使用用户指定的数据调用回调函数的功能。然后,使用回调函数中的数据。

#include <iostream> 
#include <functional> 
#include <memory> 

class setCallback 
{ 
    public: 
     setCallback() {} 
     setCallback(std::function<int(void*)> func) : callback(func) { } 

     int call(void* data) { return callback(data); } 
    private: 
     std::function<int(void*)> callback; 
}; 

class callThis 
{ 
    public: 
     callThis() : number(10) {} 

     static int another(void* data) 
     { 
     callThis* ptr = static_cast<callThis*>(data); 
     return ptr->number; 
     } 
     int number; 
}; 

// Fixed this line. You had 
// int main(int argc, char** argv[]) 
int main(int argc, char** argv) 
{ 
    std::shared_ptr<setCallback> caller; 
    std::shared_ptr<callThis> funcholder; 

    funcholder.reset(new callThis); 
    caller.reset(new setCallback(callThis::another)); 

    std::cout << caller->call(funcholder.get()) << "\n"; 

    std::cin.get(); 
} 
+0

啊哈!谢谢。我现在无法检查这个,但是,这看起来很稳固。我注意到,你将“调用这个”对象传递给“setcallback”所使用的函数,这种方法比刚刚从一开始就将对象“callthis”发送到“setcallback”有什么优势? – creativeflow 2014-11-03 22:55:42

+0

这是另一种也应该起作用的方法。在这种情况下,你必须在'setCallback'中存储一个指向数据的指针。你必须判断在哪里放置数据。如果'data'没有从'caller-> call()'的一次调用改变为下一次调用,那么最好把它放在'setCallback'中。如果它可能会改变,那么你必须在调用时提供它。 – 2014-11-03 23:03:52

+0

非常感谢,所以如果数据在运行时会发生变化,那么使用回调调用数据真的很有用吗?我应该发布另一个问题,但有没有办法从静态函数调用非静态函数?我会用同样的方法吗? – creativeflow 2014-11-04 07:44:19