2016-02-27 96 views
0

class Foo我有两种方法,assign_handler()call_handler()从另一种方法调用成员方法指针

实际处理程序代码位于main.cpp,即do_this()do_this()使用在main.cpp的一些全局变量,

我觉得富都必须有一个函数指针将在assign_handler()这是我做过什么来分配的成员。不过,我在调用assign_handler()时遇到问题,即从call_handler()调用do_this()

注意:call_handler()本身是由Foo中的sigaction调用的。

编辑:我试着按照评论中的建议产生一个MCVE。我用gedit来创建文件并在命令行中使用g ++进行编译。代码起作用。但是在我的Eclipse项目中,我收到了代码的内联注释中显示的错误。

MCVE:

//Foo.h 
class Foo{ 
public: 
    void (*funptr)(void); 
    void call_handler(); 
    void assign_handler (void(*func1)(void)); 
    Foo(){}; 

}; 
//Foo.cpp 
#include "Foo.h" 
void Foo::assign_handler(void(*func1)(void)){ 
    funptr = func1; 
} 
void Foo::call_handler(){ 
    funptr();//error: invalid use of member Foo::funptr in static member function; from this location 
    //or 
    //this->funptr();//error: 'this' is unavailable for static member functions 
} 
//main.cpp 
#include <iostream> 
#include "Foo.h" 
using namespace std; 
void do_this(void); 
int main(void){ 
    Foo foo; 
    foo.assign_handler(do_this); 

    foo.call_handler(); //this won't be called explicitly, it is assigned as a handler for a sigaction 
    int x; 
    cin>>x; 
} 

void do_this(void){ 
    cout<<"done"<<endl; 
} 
+1

发布[最小,完整和可验证示例](http:// stackoverflow。com/help/mcve)你的代码 – Thomas

+0

我假设'call_handler'是一个静态成员函数,而不是你的例子中的常规成员? – villintehaspam

+0

@villintehaspam我刚刚意识到我在类定义中留下了static关键字。删除关键字可消除错误。我会先忽略静态关键字在代码中的重要性,然后再忽略它。谢谢。 –

回答

2

我会分我分两部分回答。首先我会试着回答你的问题,然后我会试着告诉你你究竟想要做什么。

你的问题是如何分配一个函数指针到一个成员变量,然后从一个静态成员函数调用它。由于函数指针是类的成员,因此您还需要一个指向该类的指针以调用函数指针。实现此目的的一种方法是向类中添加一个静态成员,该静态成员包含指向您的类的(单个)实例的指针。既然你表示你将使用这个作为信号处理器,你不会想要使用多个处理器。

所以,这样的事情:

//Foo.h 
class Foo{ 
public: 
    static void call_handler(); 
    void assign_handler (void(*func1)(void)); 

    Foo() {  
     ms_instance = this; 
    }; 

private: 
    void (*funptr)(void); 
    static Foo *ms_instance; 
}; 

//Foo.cpp 
#include "Foo.h" 
void Foo::assign_handler(void(*func1)(void)){ 
    funptr = func1; 
} 
void Foo::call_handler(){ 
    ms_instance->funptr(); 
} 

一个更普遍的方法是将存储函数对象:

//Foo.h 
#include <functional> 
#include <utility> 

class Foo{ 
public: 
    static void call_handler(); 

    template<typename func> 
    void assign_handler (func&& handler) 
    { 
     m_handler = std::forward(handler); 
    } 

    Foo() { 
     ms_instance = this; 
    }; 

private: 
    std::function<void(void)> m_handler; 
    static Foo *ms_instance; 
}; 

//Foo.cpp 
#include "Foo.h" 

void Foo::call_handler(){ 
    ms_instance->m_handler(); 
} 

这样,您就可以将许多不同的东西,处理程序:

// Function pointers 
foo.assign_handler(do_this); 

// Lambdas 
foo.assign_handler([]() { /* do something */ }); 

// Binds - you should probably prefer lambdas... 
foo.assign_handler(std::bind(&MyClass::member_func, &myObj)); 

现在你想要什么想要当你要处理信号时要做的更复杂一点。请记住,信号处理程序只能调用某些函数(async-signal-safe functions) - 否则事情可能会变得很糟糕。因此,你应该执行一个常见的技巧叫做自我管道技巧。本质上你应该有一个接收信号的信号处理程序,但只在管道上调用write,信号编号​​作为要发送的数据。然后你的代码中有另一个地方在管道上调用select,然后在read上读取信号编号。然后你调用适当的处理函数,然后允许你做任何你喜欢的事情。

这样的一个例子是在这里:http://man7.org/tlpi/code/online/book/altio/self_pipe.c.html

知道它可以稍微棘手的一个跨平台的方式这一权利,特别是多线程的。

相关问题