您可以为迭代器创建一个接口,例如:
template <class T>
class ContainerIterator {
public:
virtual ~ContainerIterator() = default;
virtual T& operator*() = 0;
virtual ContainerIterator<T>& operator++() = 0;
virtual bool operator!=(const ContainerIterator<T>&) const = 0;
virtual ContainerIterator<T>* copy() = 0;
};
并通过模板为所有类型的迭代器实现接口,如:
template <class T, class I>
class ContainerIteratorImpl: public ContainerIterator<T>{
public:
I it;
ContainerIteratorImpl(const I &_it):it(_it) {}
T& operator*()
{
return *it;
}
ContainerIterator<T>& operator++()
{
++it;
return *this;
}
bool operator!=(const ContainerIterator<T> &rhs) const
{
return it != dynamic_cast<const ContainerIteratorImpl<T,I>&>(rhs).it;
}
ContainerIteratorImpl<T,I>* copy()
{
return new ContainerIteratorImpl<T,I>(it);
}
};
但是如果直接使用ContainerIteratorlike:
ContainerIterator<double> it = data.begin();
编译会输出类似error: cannot declare variable ‘it’ to be of abstract type的错误,因为基类ContainerIterator<double>是一个抽象类,即它没有实现,所以我们不能有它的实例。
这是 C++ 变量存储值而不是引用的结果。所以在 C++ 中,我们不能将派生类的实例存储在基类的变量中。例如
Base base = Derived(); // base is a variable
程序调用了Base的拷贝构造函数,而base不是Derived的实例。
但是如果我们使用像这样的指针
Derived derived();
Base *base = &derived; // base is a pointer
base 指向Derived 的一个实例。
所以我们需要为ContainerIterator 创建一个包装器,让我们可以创建一个对象来处理不同的迭代器,例如:
template <class T>
class Iterator {
public:
ContainerIterator<T> *pit;
Iterator():pit(0) {}
Iterator(const Iterator &x):pit(x.pit->copy()) {}
template <class I>
Iterator(const I &it):pit(new ContainerIteratorImpl<T,I>(it)){}
~Iterator()
{
delete pit;
}
T& operator*()
{
return **pit;
}
Iterator& operator++()
{
++*pit;
return *this;
}
bool operator!=(const Iterator &rhs) const
{
return *pit != *rhs.pit;
}
Iterator& operator=(const Iterator &rhs)
{
delete pit;
pit = rhs.pit->copy();
return *this;
}
};
最后,Interator 可以包含不同类型的迭代器。所以你可以在基类中声明begin()和end(),并在派生类中实现:
class AbstractDataSource
{
public:
virtual ~AbstractDataSource() = default;
virtual Iterator<double> begin() = 0;
virtual Iterator<double> end() = 0;
};
class FileDataSource : public AbstractDataSource
{
public:
std::vector<double> data;
FileDataSource(const std::vector<double> &_data):data(_data) {}
Iterator<double> begin()
{
return Iterator<double>(data.begin());
}
Iterator<double> end()
{
return Iterator<double>(data.end());
}
};
class RealtimeDataSource : public AbstractDataSource
{
public:
std::deque<double> data;
RealtimeDataSource(const std::deque<double> &_data):data(_data) {}
Iterator<double> begin()
{
return Iterator<double>(data.begin());
}
Iterator<double> end()
{
return Iterator<double>(data.end());
}
};
演示:
#include <cstdio>
#include <vector>
#include <deque>
template <class T>
class ContainerIterator {
public:
virtual ~ContainerIterator() = default;
virtual T& operator*() = 0;
virtual ContainerIterator<T>& operator++() = 0;
virtual bool operator!=(const ContainerIterator<T>&) const = 0;
virtual ContainerIterator<T>* copy() = 0;
};
template <class T, class I>
class ContainerIteratorImpl: public ContainerIterator<T>{
public:
I it;
ContainerIteratorImpl(const I &_it):it(_it) {}
T& operator*()
{
return *it;
}
ContainerIterator<T>& operator++()
{
++it;
return *this;
}
bool operator!=(const ContainerIterator<T> &rhs) const
{
return it != dynamic_cast<const ContainerIteratorImpl<T,I>&>(rhs).it;
}
ContainerIteratorImpl<T,I>* copy()
{
return new ContainerIteratorImpl<T,I>(it);
}
};
template <class T>
class Iterator {
public:
ContainerIterator<T> *pit;
Iterator():pit(0) {}
Iterator(const Iterator &x):pit(x.pit->copy()) {}
template <class I>
Iterator(const I &it):pit(new ContainerIteratorImpl<T,I>(it)){}
~Iterator()
{
delete pit;
}
T& operator*()
{
return **pit;
}
Iterator& operator++()
{
++*pit;
return *this;
}
bool operator!=(const Iterator &rhs) const
{
return *pit != *rhs.pit;
}
Iterator& operator=(const Iterator &rhs)
{
delete pit;
pit = rhs.pit->copy();
return *this;
}
};
class AbstractDataSource
{
public:
virtual ~AbstractDataSource() = default;
virtual Iterator<double> begin() = 0;
virtual Iterator<double> end() = 0;
};
class FileDataSource : public AbstractDataSource
{
public:
std::vector<double> data;
FileDataSource(const std::vector<double> &_data):data(_data) {}
Iterator<double> begin()
{
return Iterator<double>(data.begin());
}
Iterator<double> end()
{
return Iterator<double>(data.end());
}
};
class RealtimeDataSource : public AbstractDataSource
{
public:
std::deque<double> data;
RealtimeDataSource(const std::deque<double> &_data):data(_data) {}
Iterator<double> begin()
{
return Iterator<double>(data.begin());
}
Iterator<double> end()
{
return Iterator<double>(data.end());
}
};
int main(int argc, char *argv[])
{
AbstractDataSource *fds = new FileDataSource({1,2,3});
AbstractDataSource *rds = new RealtimeDataSource({4,5,6});
Iterator<double> it;
for(it = fds->begin(); it != fds->end(); ++it)
{
printf("%f\n",*it);
}
for(it = rds->begin(); it != rds->end(); ++it)
{
printf("%f\n",*it);
}
delete fds;
delete rds;
return 0;
}
输出:
1.000000
2.000000
3.000000
4.000000
5.000000
6.000000