簡體   English   中英

如何將函子分配給函數指針?

[英]How to assign functor to function pointer?

通常,我可以將功能對象分配給功能指針嗎? 我想做這樣的事情:

#include <iostream>

class Foo {
    int num;
public:
    Foo(int num_par) : num(num_par) {}
    void operator()(int multiplier) {
        std::cout << multiplier * num << std::endl;
    }
};

int main() {
    typedef void(*bar)(int);
    Foo f(42);
    bar b = f; // MSVC error
               // ^ C2440: 'initializing' : cannot convert from 'Foo' to 'bar'
    b(2); // wanted to print 84
}

如果這是不可能的,那么我希望有一個專門用於Windows編程的替代方法,其中我希望WindowProc包含從WinMain主體的本地數據設置的狀態信息(即,不創建全局變量)。 分配給WNDCLASSEXlpfnWndProc成員時,會發生此問題。 盡管std::function解決了上述代碼段的問題:

std::function<void(int)> sf = f;
sf(2); // prints 84

它不適用於我的WinAPI案例:

class WindowProc {
    int some_state;
public:
    void set_some_state(int par);
    LRESULT CALLBACK operator()(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
};

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow) {

    HWND hWnd;
    WNDCLASSEX wc;
    WindowProc wp;

    typedef LRESULT(CALLBACK *baz)(HWND, UINT, WPARAM, LPARAM);

    std::function<baz> std_func = wp;
    std::function<baz> std_binded_func = std::bind(&WindowProc::operator(), &wp);

    // none of these compile:
    wc.lpfnWndProc = wp;                      // #1
    wc.lpfnWndProc = wp.operator();           // #2
    wc.lpfnWndProc = &WindowProc::operator(); // #3. Wrong anyway because some_state's value is part of the instance, not the class
    wc.lpfnWndProc = std_func;                // #4. Wrong anyway because some_state's value is part of the instance, not the class
    wc.lpfnWndProc = std_binded_func;         // #5

    // do stuff...
    wp.set_some_state(some_runtime_number);
    // ...do other stuff
}

MSVC 2013錯誤:

1.)錯誤C2440: = :無法從WindowProc轉換為WNDPROC

2.)錯誤C3867: WindowProc::operator () :函數調用缺少參數列表; 使用&WindowProc::operator ()創建指向成員的指針

2續)錯誤C2440: = :無法從LRESULT (__stdcall WindowProc::* )(HWND,UINT,WPARAM,LPARAM) WNDPROC LRESULT (__stdcall WindowProc::* )(HWND,UINT,WPARAM,LPARAM)WNDPROC

3.)與“ 2續”相同。

4.)錯誤C2440: = :無法從std::function<baz>轉換為WNDPROC

5.)與4。

我如何使它工作?

通常,功能對象除要調用的功能外還包含其他上下文信息。 可以分配給函數指針的唯一函數對象是帶有空捕獲的lambda函數,但這實際上只是一個函數:

void (*bar)(int) = [](int x) { std::cout << x; }

如果要通過函數指針獲取函數對象,則需要希望函數指針具有合適的參數,用戶可以指定該參數並且可以直接傳遞該參數:

void call_function(int arg, void* user_data) {
    (*static_cast<std::function<void(int)>*>(userdata))(arg);
}
...

std::function<void(int)> function_object;
void (*bar)(int, void*) = &call_function;

bar(17, &function_object);

最合理的帶有函數指針的現代接口也帶有用戶數據指針,該數據可用於傳遞必要的上下文。 顯然,除了傳遞必要的上下文外,可能還需要以某種方式保持用作上下文的對象的生命周期。

我不是Windows程序員,但我想您嘗試使用的API實際上可以設置函數指針和指向某些用戶數據的指針。 如果沒有地方可以傳遞上下文信息,則需要以某種方式在功能指針本身中編碼必要的信息。 例如,您可以使用引用全局對象的函數指針來獲取上下文。 顯然,對於要傳遞的每個上下文,您將需要一個不同的功能。

您需要以通常的方式聲明一個指向成員函數的指針,然后調用它。 嘗試這個:

#include <iostream>

class Foo {
    int num;
public:
    Foo(int num_par) : num(num_par) {}
    void operator()(int multiplier) {
        std::cout << multiplier * num << std::endl;
    }
};

int main() {
    typedef void(Foo::*bar)(int);
    Foo f(42);
    bar b = &Foo::operator(); // no more MSVC error
                              // ^ C2440: 'initializing' : cannot convert from 'Foo' to 'bar'
    (f.*b)(2); // wanted to print 84, and it does
}

您必須通過實例進行調用,在此示例中為f

暫無
暫無

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

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