假设我正在开发一个购物清单管理器。我有一个带有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