[英]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";
}
假設b
是Button
類型
但是如果我這樣做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.