3

我会尽量保持我的示例代码非常简单,但是当我在现场输入时它可能会出现错误。

我有一个名为 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;
};

如您所见,电话具有功能列表(矢量):即。蓝牙、GPS、收音机等,其中有一个类别:网络、导航、多媒体。

现在有关电话和功能的信息存储在 sqlite3 数据库中。我有一个辅助函数,它将从数据库中检索特定的电话模型并返回一个填充的电话对象。我还有一个函数,它接收一个电话对象并将电话写入数据库。

问题是我需要为客户提供一些迭代电话功能列表的方法。对于初学者,数据库助手需要了解这些特性,以便将它们写入数据库。其次,客户端可能需要从数据库中检索电话,然后向用户显示功能列表。

一种解决方案是在类 Phone 中添加以下函数

std::vector<Feature>::iterator begin()
std::vector<Feature>::iterator end()

这对我来说不是一个理想的解决方案,因为客户端代码看起来不直观 - 它看起来好像客户端正在迭代电话,而实际上他们正在迭代功能。

另一种解决方案在http://accu.org/index.php/journals/1527的一篇文章中进行了讨论,该文章讨论了使用名为“memberspaces”的技术将迭代器公开给客户端代码。这将导致客户端代码更具可读性,但在我看来,实现有点混乱。

迭代器问题是否有更好的解决方案,或者我可以使用更合适的设计模式。

任何反馈将不胜感激。

4

2 回答 2

1

在你的情况下,我会先选择更好的名字:

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;
}

PS 鉴于 Jonannes 的建议和名称使用的命名约定,boost::range现在features_xxx()不是xxx_features()(特别是因为它们在这种情况下确实更有意义)。

于 2010-09-04T01:46:30.340 回答
1

如果客户端代码要使用 BOOST_FOREACH,为什么不直接添加方法

const std::vector<Feature>& getFeatures() const;

电话?

于 2010-09-05T07:09:13.457 回答