[英]Passing a member function as an argument to a constructor
我有一個按鈕課。 我希望按鈕類的構造函數采用按下按鈕時將調用的函數。 如果按鈕類僅從一個類中獲取函數,這將很容易,但是按鈕的構造函數獲取函數的目的是,無論在哪個類中創建按鈕,都將能夠在其中存儲指向函數的指針。創建它的類。
為了顯示:
struct Button {
Button(void (*functionPtr)()) {
// Store the function pointer to be called later
}
};
struct SomeClass {
void LoadFile();
SomeClass() {
Button* temp1 = new Button(&LoadFile); // ???
}
};
struct AnotherClass {
void SaveFile();
SomeClass() {
Button* temp2 = new Button(&SaveFile); // ???
}
};
我該如何工作?
盡管看起來很相似,但指向函數的指針和指向成員的函數實際上是完全不同的野獸。
void (*functionPtr)()
是指向不帶任何參數並返回void的函數的指針。 &AnotherClass::SaveFile
是一個指向AnotherClass
成員函數的AnotherClass
...其類型為void (AnotherClass::*)()
。 請注意,類名是類型的一部分,因此您不能簡單地將指向成員函數的指針存儲到任意類。 此外,要調用指向成員函數的指針,您需要一個實例指針-您必須以某種方式存儲該指針,但是它們也將具有不同的類型!
在C ++ 11中,您可以做的是使用類型擦除:
std::function<void()> callback;
並為其分配任意可調用項:
template <typename F>
Button(F cb)
: callback(cb)
{ }
然后可以使用std::bind
創建一個按鈕:
Button* temp1 = new Button(std::bind(&OtherClass::LoadFile, this));
Button* temp2 = new Button(std::bind(&AnotherClass::SaveFile, this));
現在, temp1->callback()
實際上將在與其一起構造的OtherClass
實例上調用LoadFile()
。 這就是你想要的。 而且,我們仍然可以使用自由功能:
void whatever();
Button* temp3 = new Button(whatever);
插入有關使用原始指針和new
的常見警告,並優先使用unique_ptr
。
您實際上沒有指向成員函數的指針,因為它沒有意義,而沒有隱藏在其上調用對象的this
指針。
您可以嘗試解決一些常見的問題。
C
方式:
除函數指針外,還存儲一個void*
。 然后將void*
int傳遞給回調。 這不太“安全”,但在C語言中很常見。
OOP方法1:
子類Button
並在基類上具有虛函數,例如onPress
,可以在子類中實現。
OOP方法2:
具有獨立於您的自定義類實現的Button
的回調接口。
編輯:或使用lambdas如注釋中所述。 我仍在用現代方式重新學習C ++。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.