假設我正在開發一個購物清單管理器。我有一個帶有GroceryListDisplay
的窗口,它是一個顯示購物清單上的商品的控件。雜貨數據由程序的模型組件存儲在GroceryStorage
類中。使用指向非靜態成員函數的指針實現回調
要將保存的文件加載到我的程序中,我的程序的模型組件必須用從該文件導入的數據重新填充。 View組件需要被通知這個新的數據,否則GUI將不會被更新,並且用戶不能看到導入的數據。
這裏是我提出的概念,以促進這一點。
/* A View class that represents a GUI control that displays the grocery list */
class GroceryListDisplay {
public:
void repopulateFromModel(GroceryStorage* gs) {
this->gs = gs;
/* Delete every list entry that was loaded into GUI */
this->clearList();
/* Import grocery list from the Model */
void (*itemAdder)(std::string) = addItemToList;
this->gs->sendGroceryItemsToGUI(addItemToList);
}
void addItemToList(std::string);
void clearList();
private:
GroceryStorage* gs;
}
/* A Model class that stores the grocery list */
class GroceryStorage {
public:
void sendGroceryItemsToGUI(void (*itemAdder)(std::string)) {
/* Sends all stored items to the GUI */
for (int i = 0; i < (int)this->groceryItems.size(); ++i)
itemAdder(this->groceryItems[i]);
}
private:
std::vector<std::string> groceryItems;
}
當用戶指示GUI導入某個文件時,View將調用Model中從該給定文件加載數據的函數。然後,調用repopulateFromModel
函數以使GUI保持最新。
我在使用GroceryStorage::sendGroceryItemsToGUI
中的回調函數指針時遇到了麻煩,因爲否則模型將不得不知道它應該調用哪個函數,這違反了模型/視圖原理。
這段代碼有一個大問題。如果我在現實生活中的情況下使用這個概念,我得到的是說類似
error: argument of type ‘void (GroceryListDisplay::)(std::string)’ does not match ‘void (*)(std::string)’
東西是編譯器要我硬編碼類從哪個函數指針起源名的編譯器錯誤?我不能這樣做,因爲這意味着模型知道哪個View類負責處理回調,而這又是一個Model/View違規。
我誤解了函數指針是如何工作的嗎?
檢查[this](http://www.newty.de/fpt/fpt.html)。 – tjameson 2011-04-05 18:42:51
指向成員函數的指針與指向非成員函數的指針完全不同。調用函數的代碼如何知道它屬於哪個視圖? – 2011-04-05 18:45:41
請參閱[這個答案](http://stackoverflow.com/questions/5499155/c-member-function-pointer/5499169#5499169)我的。 – Xeo 2011-04-05 18:48:16