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
容器
引用是常量,因此只能使用常量迭代器
。返回引用非常量是错误的,因为可以修改容器本身(例如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;};