总体目标
我管理一组对象(Collection
作为Real
简单示例)。然后我在我的集合上定义了迭代器。这意味着:iterator
、、const_iterator
和reverse_iterator
。const_reverse_iterator
在这个例子中,我只关注iterator
和const_iterator
,其他两个非常相似。
之后,我想在我的集合上定义一个过滤器,它根据特定条件保留或不保留元素。例如,只保留Real
具有正值的实例。我还想仅在保留元素上迭代我的集合。
我是如何实现收藏的
对于这个例子,我在集合中的对象非常简单。目标只是拥有一个对象而不是本机类型:
struct Real
{
public:
double r;
};
然后我定义我的收藏,而不必知道里面的真实容器:
class Collection
{
public:
typedef std::vector<Real>::iterator iterator;
typedef std::vector<Real>::const_iterator const_iterator;
private:
std::vector<Real> data;
public:
Collection() : data() {}
Collection(unsigned long int n) : data(n) {}
Collection(unsigned long int n, const Real& x) : data(n,x) {}
Collection::iterator begin() { return this->data.begin(); }
Collection::iterator end() { return this->data.end(); }
Collection::const_iterator begin() const { return this->data.begin(); }
Collection::const_iterator end() const { return this->data.end(); }
};
这在这个简单的示例中运行良好:
int main()
{
Collection c(5);
double k = 1.0;
for(Collection::iterator it = c.begin(); it != c.end(); ++it)
{
it->r = k;
k *= -2.0;
}
std::cout << "print c with Collection::iterator" << std::endl;
for(Collection::iterator it = c.begin(); it != c.end(); ++it)
std::cout << it->r << std::endl;
std::cout << "print c with Collection::const_iterator" << std::endl;
for(Collection::const_iterator it = c.begin(); it != c.end(); ++it)
std::cout << it->r << std::endl;
return 0;
}
这个程序写出预期的输出:
print with Collection::iterator
1
-2
4
-8
16
print with Collection::const_iterator
1
-2
4
-8
16
我是如何实现过滤器的
现在我想创建一个抽象过滤器,有一个集合的引用或指针,有迭代器,并有一个通过过滤器接受值的抽象函数。对于这第一步,我只编写了没有迭代器的类:
class CollectionFilter
{
private:
Collection& col;
public:
CollectionFilter(Collection& c) : col(c) {}
virtual ~CollectionFilter() {}
Collection& collection() { return this->col; }
iterator begin() { /* todo */ }
iterator end() { /* todo */ }
const_iterator begin() const { /* todo */ }
const_iterator end() const { /* todo */ }
virtual bool accept(const Real& x) const = 0;
};
然后,很容易创建一个实现特定条件的新过滤器:
class CollectionFilterPositive : public CollectionFilter
{
public:
CollectionFilterPositive(Collection& c) : CollectionFilter(c) {}
virtual ~CollectionFilterPositive() {}
virtual bool accept(const Real& x) const { return x.r >= 0.0; }
};
在过滤器中实现迭代器之前,我有一些评论/问题。
- 这个过滤器适用于非常量
Collection&
,那么,真的需要begin() const
andend() const
函数吗?如果是,为什么? - 我不能在 a 上应用过滤器
const Collection&
,但它显然是我的目标所必需的。有什么好方法可以做到这一点?我是否必须将该类复制CollectionFilter
到CollectionFilterConst
具有非常相似代码的类?此外,这种解决方案对于必须从两个相似类继承的用户来说是相当混乱的。
然后,让我们看看迭代器的实现。对于这个例子,我只写了iterator
而不是const_iterator
. 我将此添加到我的课程中:
class CollectionFilter
{
public:
class iterator
{
private:
CollectionFilter* filter;
Collection::iterator iter;
public:
iterator(CollectionFilter* f, Collection::iterator i) : filter(f), iter(i) {}
iterator(const iterator& i) : filter(i.filter), iter(i.iter) {}
iterator& operator = (const iterator& i) { this->filter = i.filter; this->iter = i.iter; return *this; }
iterator& operator ++ ()
{
if(this->iter != this->filter->collection().end())
{
do
{
++this->iter;
} while(this->iter != this->filter->collection().end() && !this->filter->accept(*this->iter));
}
}
iterator operator ++ (int) { /* similar */ }
Real& operator * () { return *this->iter; }
Collection::iterator operator -> () { return this->iter; }
bool operator == (const iterator& i) const { return this->iter == i.iter; }
bool operator != (const iterator& i) const { return this->iter != i.iter; }
};
public:
iterator begin()
{
Collection::iterator it = this->col.begin();
if(!this->accept(*it)) ++it;
return CollectionFilter::iterator(this,it);
}
iterator end()
{
Collection::iterator it = this->col.end();
return CollectionFilter::iterator(this,it);
}
};
这在这个简单的例子上也很有效
int main()
{
Collection c(5);
double k = 1.0;
for(Collection::iterator it = c.begin(); it != c.end(); ++it)
{
it->r = k;
k *= -2.0;
}
std::cout << "print c with CollectionFilterPositive::iterator" << std::endl;
CollectionFilterPositive fc(c);
for(CollectionFilterPositive::iterator it = fc.begin(); it != fc.end(); ++it)
std::cout << it->r << std::endl;
return 0;
}
给出预期的输出:
print with CollectionFilterPositive::iterator
1
4
16
再次,一些问题:
- 我对这种方法完全错误吗?
- 我想我必须复制代码
CollectionFilter::iterator
来实现CollectionFilter::const_iterator
,只需进行少量修改。有没有办法避免重复这段代码(如果我计算重复的类CollectionFilterConst
和反向迭代器,写了 8 次)? - 我对我的代码的 const 正确性感到不舒服。你看到一些问题了吗?
提前致谢 !