簡體   English   中英

從另一個方法調用成員方法指針

[英]Invoking a member method pointer from another method

class Foo我有兩種方法, assign_handler()call_handler()

實際的處理程序代碼在main.cpp ,該代碼為do_this() do_this()使用main.cpp的一些全局變量,

我認為Foo必須具有一個函數指針作為成員,這將在我做的assign_handler()分配。 但是我在調​​用assign_handler()遇到麻煩,即調用do_this() ,即調用do_this() call_handler()

注意: call_handler()本身是由Foosigaction調用的。

編輯:我嘗試按照注釋中的建議生成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;
}

我將答案分為兩部分。 首先,我將嘗試回答您的問題,然后嘗試告訴您您實際要做什么。

您的問題是如何將函數指針分配給成員變量,然后從靜態成員函數中調用它。 由於函數指針是該類的成員,因此您還需要一個指向該類的指針才能調用該函數指針。 實現此目的的一種方法是向您的類中添加一個靜態成員,該成員包含指向您的類(單個)實例的指針。 由於您已指示將其用作信號處理程序,因此無論如何您都不想使用多個處理程序。

因此,如下所示:

//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));

現在,當您要處理信號時,您真正想做的事情要復雜一些。 請記住,信號處理程序只能調用某些函數( 異步信號安全函數 ),否則可能會變得很丑陋。 因此,您應該執行一個常見的技巧,即自管技巧。 本質上,您應該有一個接收信號的信號處理程序,但只能在管道上以信號號作為要發送的數據調用write 然后,您在代碼中還有另一個地方需要調用管道上的select ,然后read以讀取信號編號。 然后,您調用適當的處理程序函數,然后該函數便可以執行您喜歡的任何事情。

例如: http//man7.org/tlpi/code/online/book/altio/self_pipe.c.html

請注意,以跨平台的方式實現此目標可能會有些棘手,尤其是在多線程的情況下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM