可以/我应该从STL迭代器继承来实现我自己的迭代器类吗?如果不是,为什么不呢?
答案 0 :(得分:8)
如果你的意思是std::iterator
:是的,那就是它的用途。
如果你的意思是:no,因为没有STL迭代器有virtual
个析构函数。它们不是为了继承,而从它们继承的类可能无法正常清理。
答案 1 :(得分:5)
如果你在谈论std::iterator
模板,那么你应该,但我希望你明白它没有任何功能,只是一堆typedef。这个决定的优点是你的迭代器可以被送到iterator_traits
模板。
另一方面,如果您正在谈论某些特定的STL迭代器,如vector<T>::iterator
或其他,那么答案就是响亮的 NO 。更不用说其他一切了,你不确定它实际上是一个类(例如同一个vector<T>::iterator
可以只是被定义为T*
)
答案 2 :(得分:5)
由于可能遇到的潜在问题,没有人不应该这样做。可能最好使用 组合 而不是 继承 与STL迭代器。
由于缺少虚拟析构函数而导致未定义的行为:
STL容器&amp;迭代器并不意味着充当基类,因为它们没有虚拟析构函数。
对于没有将虚拟析构函数用作Base类的类,在通过指向基类的指针(delete,delete []等)解除分配时会出现问题。由于类没有虚拟析构函数,因此无法正确清理它们并导致未定义的行为。
有人可能会争辩说,不需要以多态方式删除迭代器。因此从STL迭代器派生出来并没有错,可能还有其他一些问题,如:
可能根本无法继承:
标准容器中的所有迭代器类型都是 实现已定义
例如:std::vector<T>::iterator
可能只是T*
。在这种情况下,您根本无法继承它。
C ++标准没有要求说std::vector<T>::iterator
没有
使用继承抑制技术来防止派生。因此,如果从STL迭代器派生,则依赖于STL的一个特性,该特性恰好允许派生。这使得这种实现 非便携式 。
如果没有正确实施,则会出现多种行为:
考虑您从vector迭代器类派生,如:
class yourIterator : std::vector<T>::iterator { ... };
可能有一个函数在向量迭代器上运行,
例如:
void doSomething(std::vector<T>::iterator to, std::vector<T>::iterator from);
由于yourIterator
是std::vector<T>::iterator
,您可以在容器类上调用doSomething()
,但是您将面临Object Slicing
的丑陋问题。 doSomething()
必须以适当的模板方式实现,以避免。{1}}
问题
使用标准库算法时遇到的问题:
考虑您正在使用矢量迭代器的派生,然后使用标准库算法,如std::transform()
对于Ex:
yourIterator a;
yourIterator b;
...
std::transform( a++, b--, ... );
后缀operator ++
返回std::vector<T>::iterator
而不是a
yourIterator
导致选择了错误的模板。
因此,继承STL迭代器确实是可能的,但如果你准备好挖掘所有这些和许多其他潜在的问题并解决它们,我个人不会给它时间和努力。