stl容器的抽象包装?

时间:2011-03-16 17:53:58

标签: c++ stl containers

我想将一些对象公开为具有stl样式操作可能性的抽象容器(for_each循环,迭代器)并隐藏容器实现细节。

性能问题无关紧要(复制“通用”迭代器时虚拟调用甚至内存分配都可以接受)。

我将编写一个带有纯虚函数的抽象容器接口(+容器上的“通用”迭代器)和一个用于stl顺序容器的实现适配器。

但也许有用于此目的的有用现有库?

或者这完全是一个坏主意?

5 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

如果您的“对象”不是STL对象而是自定义对象,我认为这是个好主意。

正如您在http://www.sgi.com/tech/stl/Vector.html上看到的那样,vector“是”RandomAccessContainer的模型“。大多数Boost包使用类似的概念(术语realy是“概念”)

在C ++中,你有两种可能性:

  • 您建议的抽象类(接口)
  • 模板

使用模板,您可以执行以下操作:

doSomething < AnythingThatIsIterable >(AnythingThatIsIterable i){
    for (AnythingThatIsIterable::itertaor it = i.begin(); it != i.end(); ++i){
        it->foo()
    }
}
  • 任何提供迭代器,开始和结束的类都可以工作:std :: vector,也可以是你自己的对象。
  • 这些对象不必从任何接口继承,因此std :: vector 工作。

答案 2 :(得分:1)

Here is我的Java样式的前向迭代器包装器实现了一个。它很丑。提升部分是可选的,可能会被重构。

答案 3 :(得分:0)

对于“暴露C ++类以使类的用户不必在我的类实现更改时重新编译程序”的问题的最通用解决方案是pImpl模式。有关详细信息:http://en.wikipedia.org/wiki/Opaque_pointer

答案 4 :(得分:0)

我完全理解用户的问题。他/她想要一个自定义容器类,向用户公开类似STL的接口。标准STL容器在某种程度上是不够的,因此它们不是合适的选择。

例如,我有一个名为IDataline的'Dataline'的接口类。 IDataLine接口的实现在构造时采用分隔字符串,对其进行解析并公开字段列表。通过具有forward_iterator_tag语义的const_iterator。 没有STL容器可以开箱即用。

此外,我的客户端类希望能够遍历两个数据行字段并逐字段地比较它们。

我已经定义了IDataline接口,如下所示:

 1 class IDataline
 2 {
 3 public:
 4    class const_iterator 
 5    {
 6      public: 
 7           virtual const_iterator& operator=(const const_iterator& rhs) =0;
 8           virtual bool operator==(const const_iterator& rhs) =0;
 9           virtual bool operator!=(const const_iterator& rhs) =0;
10           virtual const_iterator& operator++() =0;
11           virtual const_iterator  operator++(int) =0;
12           virtual const Field& operator*() =0;
13           virtual const Field* operator->() =0;
14           virtual const Field& operator[](size_t idx) =0;
15           virtual size_t offset() =0;
16    }; 
17
18    virtual const_iterator begin() =0;
19    virtual const_iterator end() = 0;
20 };

问题可以在第11,18和19行看到 - 我们需要能够返回一个const_iterator,它需要一个复制构造函数,但由于它是虚拟的,所以既没有默认也没有复制构造函数(对于接口类型)和编译器(正确)balks。

你可能会说我可以将begin()和end()定义为:

virtual const_iterator& begin() = 0;
virtual const_iterator& end() = 0;

然后,我可以在专用主机中创建两个专用迭代器实例并返回引用(或指向那些喜欢它们的指针),以使其适合我的情况。

问题是这样的实现不能满足前向迭代器的所有要求,并且会破坏依赖于前向迭代器语义的更一般的用例。

经过一番思考(以及同事咨询),我发现有两种方法可以解决这个问题:

  1. 您的寄宿家庭类必须完全抽象吗?如果您可以将抽象最小化到您需要改变的行为,那么您的可实例化主机可以嵌入一个具体的迭代器(因为类本身的实例可以实例化)并且您拥有所需的内容。

  2. 上面的
  3. Eduardo Leon 表明迭代器本身可以使用pimpl(指向实现的指针)成语来包装。虽然有很多材料可以完整地描述这种技术, Basilev ,在 Leon的建议中的评论中表明他不相信pimpl成语会起作用。我的同事向我提供了一种尝试的技术,因此我将研究一个经过测试的样本。如果它有效,我会分享它。如果没有,我会详细说明样本中获得的经验,并等待更有知识的人来判断pimpl是否适用于这种情况。