我会尽量让我的示例代码非常简单明了,但当我在现场输入时可能会出现错误。
我有一个名为 Phone 的类。
class Phone
{
public:
Phone(std::string manufacturer, std::string model, std::vector<Feature> features);
private:
std::vector<Features> features;
std::string model;
std::string manufacturer;
};
我有一个名为 Feature 的结构。
struct Feature
{
Feature(std::string feature, std::string category);
std::string feature;
std::string category;
};
如您所见,手机有一个功能列表( vector ):即。蓝牙、GPS、 radio 等,其中有一个类别:网络、导航、多媒体。
现在有关手机和功能的信息存储在 sqlite3 数据库中。 我有一个辅助函数,它将从数据库中检索特定的电话型号并返回一个填充的电话对象。 我还有一个接收电话对象并将电话写入数据库的函数。
问题是我需要为客户提供某种方法来遍历电话功能列表。对于初学者来说,数据库助手需要了解这些特性,以便将它们写入数据库。其次,客户端可能需要从数据库中检索电话,然后向用户显示功能列表。
一种解决方案是在Phone类中添加以下函数
std::vector<Feature>::iterator begin()
std::vector<Feature>::iterator end()
这对我来说不是一个理想的解决方案,因为客户端代码看起来不直观 - 看起来好像客户端正在迭代手机,而实际上是在迭代功能。
另一种解决方案在 http://accu.org/index.php/journals/1527 的一篇文章中进行了讨论。其中讨论了使用名为“memberspaces”的技术将迭代器暴露给客户端代码。这会产生更具可读性的客户端代码,但在我看来,实现有点困惑。
迭代器问题是否有更好的解决方案,或者是否有更适合我使用的设计模式。
如有任何反馈,我们将不胜感激。
最佳答案
在你的情况下,我会先选择更好的名字:
typedef std::vector<Feature> Features;
Features::iterator features_begin();
Features::iterator features_end();
Features::const_iterator features_begin() const;
Features::const_iterator features_end() const;
例子:
1)
// Note: you'll need to define an operator<< for Feature
// can be used with std::algorithms
std::copy( phone.features_begin(), phone.features_end(),
std::ostream_iterator<Feature>( std::cout, "\n\r" ) );
2)
// Note: shamelessly borrowed from http://www.boost.org/doc/libs/1_44_0/doc/html/foreach/extensibility.html
// add overloads of range_begin() and range_end() for Phone::Features
inline Phone::Features::iterator range_begin( Phone& phone ){
return phone.features_begin();
}
inline Phone::Features::iterator range_end( Phone& phone ){
return phone.features_end();
}
namespace boost{
// specialize range_mutable_iterator and range_const_iterator in namespace boost
template<>
struct range_mutable_iterator< Phone >{
typedef Phone::Features::iterator type;
};
template<>
struct range_const_iterator< Phone >{
typedef Phone::Features::const_iterator type;
};
}
...
// can be used with BOOST_FOREACH
BOOST_FOREACH( Feature x, phone ){
std::cout << x << std::endl;
}
附言鉴于 Jonannes 的建议和 boost::range
使用的命名约定,名称现在是 features_xxx()
而不是 xxx_features()
(特别是因为在这种情况下,它们确实更有意义)。
关于C++ 组合与迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3640563/