【问题标题】:How to hide my inner collection but allow the user iterate over him ?如何隐藏我的内部集合但允许用户遍历他?
【发布时间】:2014-05-22 08:07:28
【问题描述】:

我有很多类在 list<cats> 里面,我想允许使用我的类的用户迭代我拥有的猫,所以我通过编写以下函数让他们访问 const 迭代器:

list<cats>::const_iterator GetIterator()
{
    //return the iterator
}

现在我想更改类的实现并使用向量而不是列表,所以我需要返回向量的常量迭代器。

问题是每个使用我的班级的人现在都需要将他们的代码从list&lt;cats&gt;::const_iterator 更改为vector&lt;cat&gt;::const_iterator

如果所有迭代器都从“前向迭代器”继承,那将非常有用。

我的主要问题是如何解决这个问题,我不想从集合中继承。

另一个非常相关的问题是为什么 STL 的设计者选择不从另一个继承迭代器? (例如随机访问迭代器可以继承前向迭代器,他拥有它的所有功能)

在我提出问题之前,我进行了相当广泛的搜索,但找不到解决方案。 我发现最接近我的问题的是这个,但这不完全是我的问题。 Give access to encapsulated container

【问题讨论】:

  • 您可以使用typedef 隐藏类型:类似于typedef list&lt;cats&gt;::const_iterator cats_const_iterator;
  • 请注意,要拥有一个多态 forward_iterator 基类,您需要所有相关的成员函数都是 virtual 并且您必须将迭代器分配在某个长期存在的地方(很可能:动态)并返回一个指向它的指针。
  • 最简单的解决方案是永远不要写单词 type::iterator。 :) 改用auto it = getIterator ();
  • 我认为您的解决方案之一是实现一些提供迭代功能的外观类。在该类中使用的迭代器类型将被封装。

标签: c++ stl


【解决方案1】:

从你的类中公开一个迭代器类型,例如:

class a
{
  vector<int> g;
public:
  typdef vector<int>::const_iterator const_iterator;

  const_iterator begin() const
  { return g.begin(); }

  : // etc

};

【讨论】:

    【解决方案2】:

    如果用户可以重新编译你可以使用的代码

    typedef list<cats> CatList;
    

    在您的包含文件中。然后,如果要更改容器,请将其更改为

    typedef vector<cats> CatList;
    

    用户会使用例如

    CatList::iterator it;
    

    但这不是一个好的做法;不同容器的迭代器可能看起来相同但行为不同,例如从向量中删除项目会使所有迭代器无效,但在列表上执行相同操作只会影响已删除项目的迭代器。如果有一天您想使用std::map&lt;some_key,cats&gt;,请不要提及该案例。

    【讨论】:

      【解决方案3】:

      我同意 Nim 的回答,并希望提供我所遵循的风格,我认为这会使维护变得更容易,因为现在更改底层容器类型对你的类的用户来说根本不需要做任何工作,而在维护你的类时你几乎不需要做任何工作。

      class A
      {
        // change only this to change the underlying container:
        // Don't Repeat Yourself!
      
        using container_t = std::vector<int>;               
      
      
      
      
      public:
      
        // constructor from a copy of a container
        A(container_t source) 
        : _myContainer { std::move(source) } 
        {}
      
        // this derived type is part of the public interface
        using const_iterator_t = container_t::const_iterator; 
      
        // following your function naming style...
        const_iterator_t GetIterator() const { return /* some iterator of _myContainer */; }
        const_iterator_t GetEnd() const { return std::end(_myContainer); }
      
      
      private:
        container_t _myContainer;
      };
      

      【讨论】:

        猜你喜欢
        • 2020-05-14
        • 1970-01-01
        • 1970-01-01
        • 2019-12-04
        • 2016-05-10
        • 1970-01-01
        • 2014-07-21
        • 1970-01-01
        • 2012-09-21
        相关资源
        最近更新 更多