C ++ STL似乎不经常使用纯粹的抽象基类(也就是接口)。我知道大多数事情都可以通过STL算法或聪明的模板元编程来实现。
但是,对于某些用例(例如,在API中,如果我不想具体说明我获得的容器类型,只是它包含的元素),则以下形式的接口将是很好:
template<typename T> struct forward_iterable {
struct iterator {
typedef T value_type;
typedef T& reference;
typedef T* pointer;
virtual reference operator*() const = 0;
virtual pointer operator->() const = 0;
virtual bool operator==(const iterator&) const = 0;
virtual bool operator!=(const iterator&) const = 0;
virtual operator const_iterator() const = 0;
virtual iterator& operator++() = 0;
virtual iterator operator++(int) = 0;
};
struct const_iterator { ... }; // similar, but with const references
virtual iterator begin() = 0;
virtual const_iterator begin() const = 0;
virtual iterator end() = 0;
virtual const_iterator end() const = 0;
};
如果STL容器将此类实现为非虚函数,我认为这不会影响性能(如果我直接使用容器而不是通过此接口)。那么为什么STL中的“接口”如此之少呢?或者我只是用“Java”术语思考太多了?
答案 0 :(得分:6)
STL(它是标准库的一个子集)根本不使用OOP(如在运行时多态性中),这是设计使然。
根据您的设计,按值返回迭代器是否存在问题(协方差对值类型不起作用)?也就是说,整个事件不可避免地要依赖静态成员(可以通过引用返回)还是依赖于堆分配的迭代器?后者在非垃圾收集语言中看起来相当尴尬。
你所描述的(在值类型上模板化的迭代器)可以使用一种名为type-erasure的技术来实现(你可以在那里找到any_iterator
实现)就像boost function
和{{ 1}}类型。
基本理念是:
any
它可能比那更复杂(例如需要对描述和实施迭代器类别做些什么?,如何比较两个any_iterators工作(double dispatch / RTTI?))。
答案 1 :(得分:2)
你在STL中没有看到很多“接口”式抽象基类的原因是因为它在很大程度上依赖于C ++模板。当你使用C ++模板时,几乎任何类,无论它的父级是什么,只要它支持模板试图使用的所有方法,它都会做。
有一种隐含的界面,但实际上写出来是无关紧要的。在我自己的编码中,我倾向于写一个,只是为了方便用户,但这不是STL作者如何滚动。
答案 2 :(得分:0)
STL结构未定义继承。为子类化任何stl集合做一个好的案例并不容易。考虑到这一点,stl不会让你“支付”可能与正常类继承相关的任何费用。如果要使用虚拟方法,则优化程序无法对它们进行内联。
此外,STL希望与那些无法从顶级抽象基类继承的东西兼容,比如数组。