【问题标题】:Hiding the STL container implementation by returning an iterator通过返回一个迭代器隐藏 STL 容器实现
【发布时间】:2012-04-06 18:35:36
【问题描述】:

我想要做的是返回一个 ForwardIterator(甚至是一对开始和结束迭代器),以便可以对客户端类隐藏底层实现。 我找不到任何这样的例子。

如果底层实现是vector,那么迭代器就是vector::iterator。即使你模板化了输出,这似乎也行不通。

【问题讨论】:

  • “似乎不起作用”是什么意思?请更准确。
  • 你能显示一些代码吗?很难从你的描述中猜出什么问题

标签: c++ stl iterator


【解决方案1】:

您不能同时按原样返回一个对象并期望调用者不知道它的类型。 “隐藏”任何对象的真实类型的典型方法是将其隐藏在接口后面。

例如,你可能想要这样写:

template<typename T>
class Cursor
{
public:
    typedef T value_type;
    virtual ~Cursor () {}
    virtual bool has_result () = 0;
    virtual value_type get_result () = 0;
};

// implements cursor interface for any sequence
// described as a pair of forward iterators.
template<typename I>
class ForwardSequenceCursor :
    public Cursor<std::iterator_traits<I>::value_type>
{
    I myCurrent;
    const I myEnd;
public:
     ForwardSequenceCursor(I begin, I end)
         : myCurrent(current), myEnd(end)
     {}
     virtual bool has_result () {
         return myCurrent != myEnd;
     }
     virtual value_type get_result () {
         return *myCurrent++;
     }
};

然后,您可以将任何正向序列返回为:

class Foo
{
    std::vector<int> myValues;
public:
    std::unique_ptr< Cursor<int> > values () {
        return std::unique_ptr< Cursor<int> >(
            new ForwardSequenceCursor<vector<int>::const_iterator>(
                myValues.begin(), myValues.end()
            )
        );
    }
};

然后像这样使用它:

std::unique_ptr< Cursor<int> > cursor = foo.values();
while (cursor->has_result()) {
    std::cout << cursor->get_result() << std::endl;
}

【讨论】:

    【解决方案2】:
    【解决方案3】:

    你不能直接做你想做的事,因为正如其他人提到的,如果你的客户要获得一个返回值,它需要知道那个返回值是什么。

    解决它的一种方法是执行以下操作:

    template<typename Collection> class MyClass
    {
        typedef Collection::iterator ReturnIt;
        typedef std::pair<ReturnIt, ReturnIt> IteratorPair;
        ReturnIt foo();
        IteratorPair bar();
    };
    

    现在,这并没有让我们从客户端看到容器类型中解放出来,但是接口没有绑定到容器类型。

    【讨论】:

      【解决方案4】:

      ForwardIterator 是一个概念,而不是一个类型。您需要声明您的函数以返回一个类型。

      【讨论】:

        【解决方案5】:

        没有“ForwardIterator”类型的基类,正常的 STL 方法是在你的类中有一个实际迭代器类型的 typedef,以便客户端代码可以像这样使用它:

        MyClass::iterator it = myclass.begin();

        隐藏起来不是很好,但仍然可以让您稍后更改实现,而无需更改客户端代码。

        【讨论】:

          猜你喜欢
          • 2021-12-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-12
          • 1970-01-01
          • 2013-04-16
          • 2010-12-19
          相关资源
          最近更新 更多