簡體   English   中英

C ++將函數作為多態類型的參數傳遞

[英]C++ passing function as argument with polymorphic type

我有功能

void addOnHover(std::function<void(Button&, HoverState)>& func);
void addOnHover(void(*fptr)(Button&, HoverState));

Button繼承了ButtonBase ,它是接口類,我想傳遞

void hoverOver(game::ButtonBase& button, game::HoverState state)
{
    static int i = 0;
    if (state == game::HoverState::STATE_ENTER)
        std::cout << "entered " <<    button.getLabel().getText().getString().toAnsiString() << " " << ++i << "\n";
    else if (state == game::HoverState::STATE_LEAVE)
        std::cout << "left " << button.getLabel().getText().getString().toAnsiString() << " " << ++i << "\n";
    else
        std::cout << "inside " << button.getLabel().getText().getString().toAnsiString() << " " << ++i << "\n";
}

假設bButton類型

但是如果我這樣做b.addOnHover(hoverOver); 它不會編譯(某些時髦的編譯器錯誤,與此類人員一樣)。

如果我執行b.addOnHover(std::function<void(game::Button&, game::HoverState)>(hoverOver);或者將hoverOver從將game::ButtonBase&更改為game::ButtonBase&可以使其工作game::Button& ,但是我想知道如果沒有這種冗長(std :: function ...)並將參數保留為game::ButtonBase& ,是否可以完成game::ButtonBase&因為將來可能會有更多的Button類

根據Bolov的要求,這是傳遞hoverOver時的編譯器錯誤

1>Source.cpp(58): error C2664: 'void game::Button::addOnHover(std::function<_Fty> &)' : cannot convert parameter 1 from 'void (__cdecl *)(game::ButtonBase &,game::HoverState)' to 'std::function<_Fty> &'
1>          with
1>          [
1>              _Fty=void (game::Button &,game::HoverState)
1>          ]

編輯:

一種可能的解決方案,甚至還很冗長,是添加

template <class T, class C, class Q>
std::function<void(T&, C)> wrap(Q ptr)
{
    return std::function<void(T&, C)>(ptr);
}

並調用b.addOnHover(game::wrap<game::Button, game::HoverState>(hoverOver);但我不確定它是否能正常運行

您遇到的一個問題是,不能將非常量左值引用綁定到右值。

使

void addOnHover(const std::function<void(Button&, HoverState)>& func);

或(最好):

void addOnHover(std::function<void(Button&, HoverState)> func);

在您的版本中,參數func是一個非常量左值,當您這樣調用它時, b.addOnHover(hoverOver) hoverOver是一個函數指針,因此會創建一個類型為std::func (rvalue)的臨時對象,該對象為我已經說過,不能綁定到非常量左值引用。

順便說一句,當我看到錯誤消息時我發現了這一點,因此嘗試解決錯誤很重要。

我可以看到兩個潛在的問題。

1)'參數'(即Button)的類型void addOnHover(std::function<void(Button&, HoverState)>& func); 比您在void hoverOver(game::ButtonBase& button, game::HoverState state)...ButtonBase賦予的值更具體void hoverOver(game::ButtonBase& button, game::HoverState state)...

就像您要為父類分配一個ptr,給子類分配一個ptr。

如果使用普通值,則ButtonBase&參數應接受Button& ,但不能接受。 換句話說,我認為您應該

void addOnHover(std::function<void(ButtonBase&, HoverState)>& func);

void hoverOver(game::Button& button, game::HoverState state)... (或void hoverOver(game::ButtonBase& button, game::HoverState state)...

2)即使類型匹配, std::function也不會自動接受來自相同類型的函數指針或lambda的轉換。 使用std::function很痛苦,就像在c ++ 11中一樣。 您需要先將函數分配給std::function對象,或者像您那樣調用構造函數。 不幸的是,這不同於可以讓std::string接受const char*

我猜你的std::function用法或包裝器是類型轉換。 所以編譯器接受它,因為您明確告訴編譯器強制轉換應該可以。 這並不意味着類型實際上是兼容的。

關於第二個問題,我問了一個相關的問題,關於如何讓std::function接受相應類型的函數(普通,lambda等): 如何使帶有function <>參數的C ++ 11函數自動接受lambda 我最大的答案是我不應該使用std::function或期望以這種方式使用它。

暫無
暫無

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

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