Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/246.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 允许访问封装的容器 X类{ 公众: typedef std::列表容器; // (1) 常量容器&GetElements()常量; // (2) 容器::迭代器元素begin(); 容器::迭代器ElementEnd(); // (3) CustomIterator GetElementIterator(); 私人: 集装箱m_集装箱; };_C++_Stl_Iterator - Fatal编程技术网

C++ 允许访问封装的容器 X类{ 公众: typedef std::列表容器; // (1) 常量容器&GetElements()常量; // (2) 容器::迭代器元素begin(); 容器::迭代器ElementEnd(); // (3) CustomIterator GetElementIterator(); 私人: 集装箱m_集装箱; };

C++ 允许访问封装的容器 X类{ 公众: typedef std::列表容器; // (1) 常量容器&GetElements()常量; // (2) 容器::迭代器元素begin(); 容器::迭代器ElementEnd(); // (3) CustomIterator GetElementIterator(); 私人: 集装箱m_集装箱; };,c++,stl,iterator,C++,Stl,Iterator,我正在寻找一种一致且干净的方法,为调用方提供用于封装容器的迭代器。我想出了上面源代码中标记的三个想法 提供size()、begin()和end(),所有这些都非常适合读取访问。但是,由于返回的容器引用是常量,因此只能使用常量迭代器。返回引用非常量是错误的,因为可以修改容器本身(例如clear()) 提供对元素的非常量访问,但是我们通常需要自己的size()方法(如GetElementCount())iterator::distance(),但对于某些容器来说,这可能是低效的(在这些容器中,ope

我正在寻找一种一致且干净的方法,为调用方提供用于封装容器的迭代器。我想出了上面源代码中标记的三个想法

  • 提供size()、begin()和end(),所有这些都非常适合读取访问。但是,由于返回的
    容器
    引用是常量,因此只能使用
    常量迭代器
    。返回引用非常量是错误的,因为可以修改容器本身(例如
    clear()
  • 提供对元素的非常量访问,但是我们通常需要自己的
    size()
    方法(如
    GetElementCount()
    )<可以使用code>iterator::distance(),但对于某些容器来说,这可能是低效的(在这些容器中,
    operator++
    /
    --
    被重复调用以计算距离)
  • 提供一个自定义迭代器,其中包含
    next()
    等方法。仍然需要一个自己的
    size()
    方法

  • 我敢打赌有更好的解决方案,所以如果你知道,我很高兴看到它们。

    我想不出更干净的方法;您可以考虑轻量级(4)解决方案,以

    进行访问。
    class X {
      public:
        typedef std::list<int> Container;
    
        // (1)
        const Container& GetElements() const;
    
        // (2)
        Container::iterator ElementBegin();
        Container::iterator ElementEnd();
    
        // (3)
        CustomIterator GetElementIterator();
    
      private:
        Container m_container;
    };
    

    我更喜欢(3)因为容器类型是完全封装的,即您的类型不一定需要包含,并且您可以更改容器类型,而无需根据模块重新编译。

    当然,最简单的是:

    const Container& container() const { return m_container; }
    

    2和3真的不是截然不同的选项。然而,3作为书面形式是非常无用的。没有STL算法将使用
    CustomIterator::next
    。对于STL兼容性,您可以编写:

    Container::const_iterator ElementBegin() const;
    Container::const_iterator ElementEnd() const;
    int size() const;
    
    给标准的
    操作符+++
    操作符*

    混合使用(2)和(3)可能就是我要做的:

    // mix of 2 and 3
    CustomIterator begin();
    CustomIterator end();
    
    X类{
    公众:
    typedef std::list ElementContainer;
    typedef ElementContainer::size_type ElementSizeType;
    类型定义元素容器::迭代器元素迭代器;
    类型定义元素容器::常量迭代器常量迭代器;
    ElementIterator elementBegin(){返回m_容器。begin();}
    ElementIterator elementEnd(){return m_container.end();}
    ConstElementIterator elementBegin()const{return m_container.begin();}
    ConstElementIterator elementEnd()const{return m_container.end();}
    ElementSizeType elementSize()常量{return m_container.size();}
    私人:
    元素容器m_容器;
    };
    

    它仍然为编写自定义迭代器留出了空间(通过更改
    typedef
    s),但只要容器提供的迭代器正常,就可以使用它们。

    我将使用这些名称:
    迭代器
    常量迭代器
    开始
    结束
    cbegin
    cend
    size()

    class X {
      public :
        typedef std::list<int> ElementContainer;
        typedef ElementContainer::size_type ElementSizeType;
        typedef ElementContainer::iterator ElementIterator;
        typedef ElementContainer::const_iterator ConstElementIterator;
    
        ElementIterator elementBegin() { return m_container.begin(); }
        ElementIterator elementEnd() { return m_container.end(); }
    
        ConstElementIterator elementBegin() const { return m_container.begin(); }
        ConstElementIterator elementEnd() const { return m_container.end(); }
    
        ElementSizeType elementSize() const { return m_container.size(); }
    
      private :
        ElementContainer m_container;
    };
    

    如果您可以使用Boost,则有一个库供您使用: 具体来看迭代器外观和迭代器适配器

    下面是一个示例,它提供了一个std::vector holder,以及与STL兼容的迭代器。您可以通过添加其他方法来扩展它,如操作符[]、size()、push_back()等

    模板 类向量保持器 { 公众: 类型定义T值_类型

    公众: 向量持有者() :m_值() { }

    公众: typedef typename std::vector::iterator vector\u iterator; typedef typename std::vector::const_迭代器vector_const_迭代器

    const_iterator cbegin() const { return m_container.cbegin(); }
    const_iterator cend() const { return m_container.cend(); }
    
    类迭代器:公共boost::迭代器适配器 { 公众: 迭代器() :迭代器::迭代器适配器 { } 迭代器(常量向量迭代器&it) :迭代器::迭代器适配器(it) { } 私人: 朋友类boost::迭代器\u核心\u访问; }; 类常量迭代器:公共boost::迭代器适配器 { 公众: 常量迭代器() :常量迭代器::迭代器适配器 { } 常量迭代器(常量向量常量迭代器&it) :常量迭代器::迭代器适配器(it) { } 常量迭代器(常量迭代器&it) :const_iterator::iterator_adaptor_Uit(it.base()) { } 私人: 朋友类boost::迭代器\u核心\u访问; }; 迭代器begin() { 返回迭代器(m_values.begin()); } 迭代器结束() { 返回迭代器(m_values.end()); } 常量迭代器begin()常量 { 返回常量迭代器(m_values.begin()); } 常量迭代器end()常量 { 返回常量迭代器(m_values.end()); }受保护: std::向量m_值;};
    如果您想从容器中公开几乎所有内容,为什么不从它继承,而不是封装它?@Sander De Dyker:因为我不想以任何方式扩展容器(无论如何,STL containere不是要派生的)。一个类中甚至可能有多个容器,比如
    X
    one就是一个例子。在一般情况下,这的确不是一个好主意。但在特定情况下,它可能是有用的(假设您知道自己在做什么)。这似乎是一个没有实际意义的观点,因为它不适用于这里。您的第四个建议正是我的第一个建议,但是它只允许访问常量元素。第三种解决方案也是我最初的想法,但我仍然想知道是否我不能用STL迭代器完成它,因为它们已经存在了。:-)当然可以,但请记住,它不仅是开始和结束,还有rbegin、rend和反向迭代器。当然,这个类不仅仅由容器和访问方法组成,这是完全无用的。可能有装载例程或其他有用的方法在容器上运行。@这不是您在问题中所写的。很抱歉,不清楚。但很明显,这个类只包含一个con
    class X 
    {
      public :
    
        typedef std::list<int>::iterator iterator;
        typedef std::list<int>::const_iterator const_iterator ;
    
        iterator begin() { return m_container.begin(); }
        iterator end() { return m_container.end(); }
    
        const_iterator cbegin() const { return m_container.begin(); }
        const_iterator cend() const { return m_container.end(); }
    
        size_t size() const { return m_container.size(); }
    
      private :
        std::list<int> m_container;
    };
    
    const_iterator cbegin() const { return m_container.cbegin(); }
    const_iterator cend() const { return m_container.cend(); }
    
    class iterator : public boost::iterator_adaptor<iterator, vector_iterator>
    {
    public:
        iterator()
            : iterator::iterator_adaptor_()
        {
        }
    
        iterator(const vector_iterator& it)
            : iterator::iterator_adaptor_(it)
        {
        }
    
    private:
        friend class boost::iterator_core_access;
    };
    
    class const_iterator : public boost::iterator_adaptor<const_iterator, vector_const_iterator>
    {
    public:
        const_iterator()
            : const_iterator::iterator_adaptor_()
        {
        }
    
        const_iterator(const vector_const_iterator& it)
            : const_iterator::iterator_adaptor_(it)
        {
        }
    
        const_iterator(const iterator& it)
            : const_iterator::iterator_adaptor_(it.base())
        {
        }
    private:
        friend class boost::iterator_core_access;
    };
    
    
    iterator begin()
    {
        return iterator(m_values.begin());
    }
    
    iterator end()
    {
        return iterator(m_values.end());
    }
    
    const_iterator begin() const
    {
        return const_iterator(m_values.begin());
    }
    
    const_iterator end() const
    {
        return const_iterator(m_values.end());
    }protected:
    std::vector<T> m_values;};