我暴露了太多的迭代器吗?

时间:2011-03-11 13:49:17

标签: c++ iterator

我的班级可以有孩子,所以我需要公开迭代器。 render类需要反向迭代它们,这就是我有反向迭代器的原因。但是有没有办法减少这些因为它似乎很多:

std::vector<AguiWidget*>::iterator          getChildBeginIterator();
std::vector<AguiWidget*>::reverse_iterator  getChildRBeginIterator();
std::vector<AguiWidget*>::iterator          getChildEndIterator();
std::vector<AguiWidget*>::reverse_iterator  getChildREndIterator();

std::vector<AguiWidget*>::const_iterator            getChildBeginIterator() const;
std::vector<AguiWidget*>::const_reverse_iterator    getChildRBeginIterator() const;
std::vector<AguiWidget*>::const_iterator            getChildEndIterator() const;
std::vector<AguiWidget*>::const_reverse_iterator    getChildREndIterator() const;

std::vector<AguiWidget*>::iterator          getPrivateChildBeginIterator();
std::vector<AguiWidget*>::reverse_iterator  getPrivateChildRBeginIterator();
std::vector<AguiWidget*>::iterator          getPrivateChildEndIterator();
std::vector<AguiWidget*>::reverse_iterator  getPrivateChildREndIterator();

std::vector<AguiWidget*>::const_iterator            getPrivateChildBeginIterator() const;
std::vector<AguiWidget*>::const_reverse_iterator    getPrvateChildRBeginIterator() const;
std::vector<AguiWidget*>::const_iterator            getPrivateChildEndIterator() const;
std::vector<AguiWidget*>::const_reverse_iterator    getPrivateChildREndIterator() const;

由于

7 个答案:

答案 0 :(得分:13)

那些对我来说很好看。或者,如果不知道你究竟在做什么,我就无法准确评论。但有一点你可以肯定做任何事情:你为什么不使用typedef?如果您使用typedef,您也可以在课外使用它,意味着在客户端代码中,您将使用该类!

例如,

class sample
{
public:

  //make these typedef public so you use it from outside!
  typedef std::vector<AguiWidget*>::iterator  iterator ;
  typedef std::vector<AguiWidget*>::reverse_iterator reverse_iterator;
  typedef std::vector<AguiWidget*>::const_iterator const_iterator;
  typedef std::vector<AguiWidget*>::const_reverse_iterator const_reverse_iterator;

  iterator           child_begin();
  reverse_iterator   child_rbegin();
  iterator           child_end();
  reverse_iterator   child_rend();

  const_iterator            child_begin() const;
  const_reverse_iterator    child_rbegin() const;
  const_iterator            child_end() const;
  const_reverse_iterator    child_rend() const;
};

//Usage
sample s;
sample::iterator it= s.child_begin(); 
//see this ^^^^^^^^ how we use the typedef here!

这看起来更好!基本上typedef封装了实现,因为它可以帮助您隐藏类的实现细节;例如,您在课堂上使用的容器std::vectorstd::list或什么?再次查看上面的 Usage 插图;只是通过查看它你不能说容器类型,可以吗?

另请注意,我也更改了功能名称。我觉得这很好。毕竟,STL仅使用beginend而不是beginIteratorendIterator。然而,小写是我的口味,你可能仍然更喜欢大写的一致性!

在我看来,const函数没有多大意义,如果你想公开只读迭代器,你可能想要以下一组函数!

const_iterator            readonly_child_begin();
const_reverse_iterator    readonly_child_rbegin();
const_iterator            readonly_child_end();
const_reverse_iterator    readonly_child_rend();


//Usage
sample s;
sample::const_iterator cit= s.readonly_child_begin(); 
//see this ^^^^^^^^ how we use the typedef here!

答案 1 :(得分:2)

没有固定答案,但问自己以下问题:

  • 您打算使用每个迭代器吗?
  • 你需要孩子和私人孩子之间的区别吗?
  • 你需要揭露一个叫做私人孩子的东西吗?
  • 索引不会比迭代更方便吗?

否则,这似乎完全没问题;迭代器可能需要类中的大量代码,但使用起来很方便。 (您应该看到我的多态XQuery支持XML集合的迭代器,它包含来自第三方库的几个不同的非STL兼容迭代器......)

一些评论者提出的typedef建议是一个好主意,因为它提供了更好的封装,即使编译器没有强制执行封装。

答案 2 :(得分:2)

将此接口切成两半的简单方法是使用范围而不是begin()/ end()对。例如,请参阅Boost的iterator_range。或者您可以返回对容器的引用,但是您可以只获取const_iterator或者您可以让外部修改您可能不需要的容器。

请注意,矢量迭代器是双向的,因此您可以再次使用一半的方法,而不会暴露较少的功能。如果您确实需要使用++而不是--,则可以使用外观,例如Boost的reverse_iterator

请注意,这些内容(范围和reverse_iterator外观)在概念上都很简单,您可以自己轻松地构建它们(尽管正确可能需要大量工作)。

无论哪种方式,4种功能而非16种声音对我来说都是非常合理的。

答案 3 :(得分:1)

您可以通过mixin界面实现此目的:

template<int Tag> class IteratorRange {
  private:
    std::vector<AguiWidget*>& range;
  public:
    IteratorRange(std::vector<AguiWidget*>& range) : range(range) {}

    typedef std::vector<AguiWidget*>::iterator  iterator ;
    typedef std::vector<AguiWidget*>::reverse_iterator reverse_iterator;
    typedef std::vector<AguiWidget*>::const_iterator const_iterator;
    typedef std::vector<AguiWidget*>::const_reverse_iterator const_reverse_iterator;

    iterator           begin();
    reverse_iterator   rbegin();
    iterator           end();
    reverse_iterator   rend();
};

enum { PublicChild, PrivateChild };
class MyClass : public IteratorRange<PublicChild>, private IteratorRange<PrivateChild> {
  MyClass() : IteratorRange<PublicChild>( ??? ), IteratorRange<PrivateChild>( ??? ) { }
  typedef IteratorRange<PublicChild> Public; // For MyClass::Public::begin etc
};

答案 4 :(得分:0)

根据您对这些迭代器的操作,您可以公开某种访问者函数:

template<class UnaryFunction>
void visit(UnaryFunction & f) {
    // apply function to each element in vector
}

您可以根据需要调整该签名,但这可能会使界面更加纤薄。

答案 5 :(得分:0)

是的,主要是。标准库容器也这样做。欢迎来到C ++!

但是,我会重新考虑“私人”的。我甚至不能说出它们应该是什么,但它不可能是好的。

我还会添加一些带有typedef关键字的成员类型别名,以使返回类型更加封装。

答案 6 :(得分:-1)

您已经公开了std :: vector :: iterator,这意味着您已经公开了许多实现细节。

返回const std :: vector&amp;,const引用可以减少大部分接口并提供更多功能。否则,将来你可能需要添加类似getChildSize(),getXXXSize()等的东西。