抽象容器类和子元素可以迭代吗?

时间:2017-08-29 01:16:23

标签: c++ inheritance interface iterator

我创建了一个带有以下基本功能的抽象容器类

class AbstractInventory
{
private:
    string name;
public:
    AbstracInventory(string name);
    virtual ~AbstractInventory();
    virtual size_t size() const = 0;
    virtual Stack* stackAt(size_t index) const = 0;
    virtual Stack* &stackAt(size_t index) = 0;
    Stack* operator[](int index) const { return(stackAt(index)); }
    Stack* &operator[](int index) { return(stackAt(index)); }
};

作为一个例子,这可以是派生类之一

class BasicInventory : public AbstractInventory
{
private:
    vector<Stack*> content;
public:
    BasicInventory(string name, int size, bool sorting = false, ItemFilter* f=nullptr);

    size_t size() const override { return(content.size()); }
    Stack* stackAt(size_t index) const override { return(content[index]);     }
    Stack*& stackAt(size_t index) override { return(content[index]); }
};

现在我的问题是如果它可以使抽象接口和它的子迭代像向量或列表那样在foreach循环中使用它

1 个答案:

答案 0 :(得分:2)

您可以创建自己的迭代器,例如:

struct Stack {};

class AbstractInventory;

class AbstractInventoryIterator
{
public:
    using difference_type =  std::ptrdiff_t;
    using value_type = Stack*;
    using pointer = Stack**;
    using reference = Stack*&;
    using iterator_category = std::random_access_iterator_tag;

    AbstractInventoryIterator(AbstractInventory* inv, std::size_t index) : inv(inv), index(index) {}

    AbstractInventoryIterator(const AbstractInventoryIterator&) = default;
    AbstractInventoryIterator& operator =(const AbstractInventoryIterator&) = default;

    bool operator == (const AbstractInventoryIterator& rhs) const { return std::tie(inv, index) == std::tie(rhs.inv, rhs.index); }
    bool operator != (const AbstractInventoryIterator& rhs) const { return !(*this == rhs); }

    reference operator*() const;
    pointer operator->() const { return &operator*(); }

    AbstractInventoryIterator& operator ++() { ++index; return *this; }
    AbstractInventoryIterator& operator --() { --index; return *this; }

    AbstractInventoryIterator operator ++(int) { auto next(*this); ++*this; return next; }
    AbstractInventoryIterator operator --(int) { auto prev(*this); --*this; return prev; }

    AbstractInventoryIterator& operator += (difference_type n) { index += n; return *this; }
    AbstractInventoryIterator& operator -= (difference_type n) { index -= n; return *this; }

    AbstractInventoryIterator operator + (difference_type n) const { auto res(*this); res += n; return res; }
    AbstractInventoryIterator operator - (difference_type n) const { auto res(*this); res -= n; return res; }

    friend AbstractInventoryIterator operator + (difference_type n, AbstractInventoryIterator it) { return it + n; }
    difference_type operator - (const AbstractInventoryIterator& it) const { return index - it.index; }

    reference operator [](difference_type n) const;

    bool operator < (const AbstractInventoryIterator& rhs) const { return rhs - *this > 0; }
    bool operator > (const AbstractInventoryIterator& rhs) const { return rhs < *this; }
    bool operator <= (const AbstractInventoryIterator& rhs) const { return !(rhs < *this); }
    bool operator >= (const AbstractInventoryIterator& rhs) const { return !(*this < rhs); }

private:
    AbstractInventory* inv = nullptr;
    int index = 0;
};

class AbstractInventory
{
private:
    std::string name;
public:
    AbstractInventory(std::string name) : name(name) {}
    virtual ~AbstractInventory() = default;
    virtual std::size_t size() const = 0;
    virtual Stack* stackAt(std::size_t index) const = 0;
    virtual Stack* &stackAt(std::size_t index) = 0;
    Stack* operator[](int index) const { return(stackAt(index)); }
    Stack* &operator[](int index) { return(stackAt(index)); }

    AbstractInventoryIterator begin() { return {this, 0}; }
    AbstractInventoryIterator end() { return {this, size()};}
};


auto AbstractInventoryIterator::operator*() const
-> AbstractInventoryIterator::reference 
{ return inv->stackAt(index); }

auto AbstractInventoryIterator::operator [](difference_type n) const
-> AbstractInventoryIterator::reference
{ return inv->stackAt(index + n); }

等同于const_iterator