代码之家  ›  专栏  ›  技术社区  ›  lovespring

如何将成员函数传递给函数指针?

  •  10
  • lovespring  · 技术社区  · 14 年前
    class Child;
    class Parent
    {
    public:
      void (*funcPointer)();
      void (*funcPointer2)(Parent* _this);
      void (Child::*funcPointer3)();
    };
    
    class Child: public Parent
    {
    public:
      void TestFunc(){
    
      }
      void Do(){
        Parent p;
        p.funcPointer=TestFunc; // error, '=': cannot convert from 'void (__thiscall Child::* )(void)' to 'void (__cdecl *)(void)'
        p.funcPointer2=TestFunc; // error too, '=': cannot convert from 'void (__thiscall Child::* )(void)' to 'void (__cdecl *)(Parent *)'
        p.funcPointer3=TestFunc; //this works
        p.funcPointer3=&Child::TestFunc; // this works too.
        p.funcPointer3();    // error, term does not evaluate to a function taking 0 arguments
      }
    };
    

    如何将成员函数传递给函数指针,然后如何调用该函数指针?

    3 回复  |  直到 8 年前
        1
  •  8
  •   Philipp    14 年前

    不能。您要么将指针传递给静态方法,要么父对象也必须接受指向该对象的指针。

    你可能想看看 boost::bind boost::function 为此:

    #include <boost/bind.hpp>
    #include <boost/function.hpp>
    struct Y
    {
        void say(void) { std::cout << "hallo!";}
    
        boost::function<void()> getFunc() { return boost::bind(&Y::say, this); }
    };
    
    struct X
    {
        //non-boost:
        void (Y::*func)();
        Y* objectY;
        void callFunc() { (objectY->*func)(); }
    
        //boost version:
        boost::function<void()> f;
    
    };
    
    
    X x;
    Y y;
    x.f = boost::bind(&Y::say, boost::ref(y));
    x.f = y.getFunc();
    x.f();
    x.func = &Y::say;
    x.objectY = &y; 
    x.callFunc();
    
        2
  •  3
  •   CB Bailey    14 年前

    作为对上次编辑的响应,若要形成指向成员的指针,必须使用 & classkey:: . 对于普通函数,没有等价于函数名到指针到函数的隐式转换。

    // not valid:
    p.funcPointer3=TestFunc;
    
    // valid:
    p.funcPointer3 = &Child::TestFunc;
    

    要通过指向成员的指针访问成员,必须使用 .* ->* 接线员。

    例如。

    (this->*p.funcPointer3)();
    
        3
  •  1
  •   Jonathan Mee    8 年前

    我们可以完成你的三个任务 funcPointer* 在C++ 11中的问世 bind Lambda Functions . 让我们先讨论每个人,然后讨论他们在做什么:

    1. funcPointer 试图调用 Child 方法 没有 接受 儿童 对象,所以 儿童 必须保存对象。子对象可以通过指针保存: bind(&Child::TestFunc, this) 或者在C++ 14中,可以通过值保存: [arg = *this]() mutable { arg.TestFunc(); }
    2. funcPointer2 试图调用 儿童 方法与 Parent* . 我们可以这样做: [](Parent* arg){ static_cast<Child*>(arg)->TestFunc(); } 当然这不会比 (new Parent)->TestFunc() 所以我们假设 母公司* 实际上是 Child* ,如果你愿意 Parent Polymorphic Type 您可以在调用lambda之前进行验证:
    [](Parent* arg) {
        assert(dynamic_cast<Child*>(arg) != nullptr);
    
        static_cast<Child*>(arg)->TestFunc();
    }
    
    1. funcPointer3 试图存储指向 儿童 方法,你已经有了这个效果。你只需要使用 儿童 对象来调用它,例如: (this->*p.funcPointer3)() . 但你必须指定 函数指针3 这样地: funcPointer3 = &Child::TestFunc ,因为如果您尝试这样做: funcPointer3 = &TestFunc 您将得到错误:

    “&”:对绑定成员函数表达式的非法操作

    接下来,函数指针或成员函数指针不能用于引用 Closure Type ,因此我们需要将函数指针转换为 function 物体。( 函数指针3 只是一个成员函数指针,所以不需要转换它,但是我将转换它来演示 功能 对象 可以 包含成员函数指针,它简化了对以下对象的调用: p.funcPointer(this) ):

    class Parent {
    public:
        function<void()> funcPointer;
        function<void(Parent*)> funcPointer2;
        function<void(Child*)> funcPointer3;
    };
    

    现在我们已经适应了 起源 我们可以很容易地分配,如 , ,和 :

    void Child::Do() {
        Parent p;
    
        p.funcPointer = bind(&Child::TestFunc, this);
        p.funcPointer2 = [](Parent* arg) { static_cast<Child*>(arg)->TestFunc(); };
        p.funcPointer3 = &Child::TestFunc;
        p.funcPointer();
        p.funcPointer2(this);
        p.funcPointer3(this);
    }
    

    你可能知道这一点,只是在测试,但我们可以同样容易地使用 起源 那个 儿童 继承自,因为我们可以创建一个新的 起源 对象 Child::Do . 我要把它转换成一个例子: http://ideone.com/yD7Rom