简体   繁体   English

将成员函数指针作为参数发送到另一个成员函数中

[英]Send member function pointer as parameter within another member function

I want to send a member function as a parameter, but it won't compile. 我想发送一个成员函数作为参数,但它不会编译。 Why doesn't the code work? 为什么代码不起作用? Here what I have written. 这就是我写的。 If I pass a lambda instead it works though. 如果我通过一个lambda而不是它有效。

void global_func(std::function<void(void)>f)
{
    f();
}

class goo
{
public:
    goo() { }

    void func1()
    {
        std::function<void(void)> fp = &goo::func2;  // get a pointer to the function func2 . Error here or next line

        global_func( fp);
    }

    void func2(void)
    {

    }

};


void main()
{
    goo g1;
    g1.func1();

}

Here the compiler output ( my program name is tryvector.cpp) 这里编译输出(我的程序名是tryvector.cpp)

1>------ Build started: Project: TryVector, Configuration: Debug Win32 ------
1>  TryVector.cpp
1>e:\program files\microsoft visual studio 12.0\vc\include\functional(506): error C2664: 'void std::_Func_class<_Ret,>::_Set(std::_Func_base<_Ret,> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,> *'
1>          with
1>          [
1>              _Ret=void
1>          ]
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>          e:\program files\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Fret(__thiscall goo::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Fret=void
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Fty=void (__thiscall goo::* const &)(void)
1>          ]
1>          e:\program files\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Fret(__thiscall goo::* const &)(void),_Alloc>(_Fty,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Fret=void
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Fty=void (__thiscall goo::* const &)(void)
1>          ]
1>          e:\program files\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Fret,goo,,std::allocator<std::_Func_class<_Ret,>>>(_Fret (__thiscall goo::* const )(void),_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Fret=void
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>          ]
1>          e:\program files\microsoft visual studio 12.0\vc\include\functional(442) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Fret,goo,,std::allocator<std::_Func_class<_Ret,>>>(_Fret (__thiscall goo::* const )(void),_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Fret=void
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>          ]
1>          e:\program files\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<void,goo,>(_Fret (__thiscall goo::* const )(void))' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Fret=void
1>          ]
1>          e:\program files\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<void,goo,>(_Fret (__thiscall goo::* const )(void))' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Fret=void
1>          ]
1>          d:\vc++ my files\tryvector\tryvector\tryvector.cpp(42) : see reference to function template instantiation 'std::function<void (void)>::function<void(__thiscall goo::* )(void)>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=void (__thiscall goo::* )(void)
1>          ]
1>          d:\vc++ my files\tryvector\tryvector\tryvector.cpp(42) : see reference to function template instantiation 'std::function<void (void)>::function<void(__thiscall goo::* )(void)>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=void (__thiscall goo::* )(void)
1>          ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

A std::function<void(void)> is something which can just be called, without any parameters and without any further context. std::function<void(void)>是可以被调用的东西,没有任何参数,也没有任何进一步的上下文。

goo:func2 , however, is a non-static member function. goo:func2然而, goo:func2是一个非静态成员函数。 It cannot just be called; 它不能被称为; it needs a goo instance . 它需要一个goo实例 It's as if it had an invisible parameter: void func2(goo* const this) . 就好像它有一个不可见的参数: void func2(goo* const this) And that makes sense, because func2 probably needs some other non-static goo members to do its job. 这是有道理的,因为func2可能需要一些其他非静态goo成员来完成它的工作。

You have several options: 你有几个选择:

  • Use a lambda to capture this , ie: auto const fp = [this] { func2(); }; 使用lambda来捕获this ,即: auto const fp = [this] { func2(); }; auto const fp = [this] { func2(); }; . Remember, this is equal to auto const fp = [this] { this->func2(); }; 记住,这等于auto const fp = [this] { this->func2(); }; auto const fp = [this] { this->func2(); }; .
  • If func2 doesn't need any non-static members of goo , then make the function static . 如果func2不需要goo任何非静态成员,那么使该函数为static
  • Use std::bind . 使用std::bind

A member function pointer cannot be wrapped into a std::function<void(void)> because the member function has an implicit argument: The pointer this . 成员函数指针不能包装到std::function<void(void)>因为成员函数有一个隐式参数:指针this But the function wrapper you have defined only takes nullary callables. 但是你定义的函数包装器只需要使用nullary callables。

Solution 1: Change the function wrapper to std::function<void(goo*)> . 解决方案1:将函数包装器更改为std::function<void(goo*)> This will require you to modify global_func as well to pass the argument. 这将要求您修改global_func以传递参数。

Solution 2: Use std::bind to generate a functor where the implicit pointer is bound to some instance. 解决方案2:使用std::bind生成一个仿函数,其中隐式指针绑定到某个实例。

It's because the member function does not have a matching signature. 这是因为成员函数没有匹配的签名。 It also contains implicit this . 它还包含隐含this You can make your example by binding the member function and this : 您可以通过绑定的成员函数,使您的例子this

#include <functional>

void global_func(std::function<void(void)>f)
{
    f();
}

class goo
{
public:
    goo() { }
    void func1()
    {
        std::function<void(void)> fp = std::bind(&goo::func2, this);
        global_func( fp);
    }

    void func2(void) { }
};

int main()
{
    goo g1;
    g1.func1();
}

Lambda works, because it can capture this . Lambda工作,因为它可以捕获this

Static function also would work, because it doesn't have implicit this parameter. 静态函数也可以工作,因为它没有隐式的this参数。

Basically you need an instance on which behalf you call the functions, so in your case this seems reasonable. 基本上你需要一个代表你调用函数的实例,所以在你的情况下this似乎是合理的。

Member functions have an implicit this parameter as their first parameter. 成员函数将隐式this参数作为其第一个参数。

goo::func2(void)

is actually 实际上是

goo::func2(goo* const this);

You can do one of two things: 你可以做以下两件事之一:

Change the signature of global_func to accept a type of std::function<void(goo*)> 更改global_func的签名以接受std::function<void(goo*)>

Use std::bind to bind the this parameter. 使用std::bind绑定this参数。

std::function<void(void)> fp = std::bind(&goo::func2, this);
global_func(fp);

Your need either to make func2 a static class member function, or bind it to this when you convert it to a std::function : 您需要将func2设为静态类成员函数,或者在将其转换为std::function时将其绑定this std::function

 std::function<void()> fp = std::bind(&goo::func2, this);

Some more -- There are a few other unusual constructs in your code. 更多 - 您的代码中还有一些其他不寻常的结构。 Although they work, but they are not good C++ practice: 虽然它们有效,但它们并不是很好的C ++实践:

void func2(void)

this is C Style, in C++ you just write void func2() . 这是C Style,在C ++中你只需编写void func2() Also: 也:

void global_func(std::function<void()>f) // <-- not void(void)

Finally, int main() not void main() 最后, int main()不是void main()

Because a non static member function is not a function. 因为非静态成员函数不是函数。 In common implementations, it includes a hidden pointer to the object on which it acts ( this ). 在通常的实现中,它包括一个指向它所作用的对象的隐藏指针( this )。

Only static methods can be used the same as functions. 只有静态方法可以与函数一样使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM