最好的办法是抽象化,不再使用原始函数指针。通常有两种方法:
第一个是使用std::bind
+ std::function
(或他们的boost::
旧编译器上的对应项缺乏std::
or std::tr1::
实现):
#include <functional>
#include <vector>
#include <string>
class GroceryStorage {
public:
void sendGroceryItemsToGUI(std::function<void(std::string const&)> const& itemAdder) {
for (groceryItems_t::const_iterator iter = groceryItems.begin(), iter_end = groceryItems.end(); iter != iter_end; ++iter)
itemAdder(*iter);
}
private:
typedef std::vector<std::string> groceryItems_t;
groceryItems_t groceryItems;
};
class GroceryListDisplay {
public:
void repopulateFromModel(GroceryStorage* const gs_) {
gs = gs_;
clearList();
gs_->sendGroceryItemsToGUI(std::bind(&GroceryListDisplay::addItemToList, this, std::placeholders::_1));
}
void addItemToList(std::string const&);
void clearList();
private:
GroceryStorage* gs;
};
(请注意,我已经改变了addItemToList
采取std::string
by const&
因为通过一个std::string
by value 在 99% 的情况下都是愚蠢的,但这并不是严格必要的步骤。)
第二个是要使sendGroceryItemsToGUI
一个函数模板而不是采用std::function
:
#include <functional>
#include <vector>
#include <string>
class GroceryStorage {
public:
template<typename F>
void sendGroceryItemsToGUI(F const& itemAdder) {
for (groceryItems_t::const_iterator iter = groceryItems.begin(), iter_end = groceryItems.end(); iter != iter_end; ++iter)
itemAdder(*iter);
}
private:
typedef std::vector<std::string> groceryItems_t;
groceryItems_t groceryItems;
};
class GroceryListDisplay {
public:
void repopulateFromModel(GroceryStorage* const gs_) {
gs = gs_;
clearList();
gs_->sendGroceryItemsToGUI(std::bind(&GroceryListDisplay::addItemToList, this, std::placeholders::_1));
}
void addItemToList(std::string const&);
void clearList();
private:
GroceryStorage* gs;
};
后一种方法将always更有效,但有时不切实际/不合需要,因为函数模板必须始终在头文件中定义。