簡體   English   中英

將成員函數指針作為參數發送到另一個成員函數中

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

我想發送一個成員函數作為參數,但它不會編譯。 為什么代碼不起作用? 這就是我寫的。 如果我通過一個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();

}

這里編譯輸出(我的程序名是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 ==========

std::function<void(void)>是可以被調用的東西,沒有任何參數,也沒有任何進一步的上下文。

goo:func2然而, goo:func2是一個非靜態成員函數。 它不能被稱為; 它需要一個goo實例 就好像它有一個不可見的參數: void func2(goo* const this) 這是有道理的,因為func2可能需要一些其他非靜態goo成員來完成它的工作。

你有幾個選擇:

  • 使用lambda來捕獲this ,即: auto const fp = [this] { func2(); }; auto const fp = [this] { func2(); }; 記住,這等於auto const fp = [this] { this->func2(); }; auto const fp = [this] { this->func2(); };
  • 如果func2不需要goo任何非靜態成員,那么使該函數為static
  • 使用std::bind

成員函數指針不能包裝到std::function<void(void)>因為成員函數有一個隱式參數:指針this 但是你定義的函數包裝器只需要使用nullary callables。

解決方案1:將函數包裝器更改為std::function<void(goo*)> 這將要求您修改global_func以傳遞參數。

解決方案2:使用std::bind生成一個仿函數,其中隱式指針綁定到某個實例。

這是因為成員函數沒有匹配的簽名。 它還包含隱含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工作,因為它可以捕獲this

靜態函數也可以工作,因為它沒有隱式的this參數。

基本上你需要一個代表你調用函數的實例,所以在你的情況下this似乎是合理的。

成員函數將隱式this參數作為其第一個參數。

goo::func2(void)

實際上是

goo::func2(goo* const this);

你可以做以下兩件事之一:

更改global_func的簽名以接受std::function<void(goo*)>

使用std::bind綁定this參數。

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

您需要將func2設為靜態類成員函數,或者在將其轉換為std::function時將其綁定this std::function

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

更多 - 您的代碼中還有一些其他不尋常的結構。 雖然它們有效,但它們並不是很好的C ++實踐:

void func2(void)

這是C Style,在C ++中你只需編寫void func2() 也:

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

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

因為非靜態成員函數不是函數。 在通常的實現中,它包括一個指向它所作用的對象的隱藏指針( this )。

只有靜態方法可以與函數一樣使用。

暫無
暫無

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

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