容器类内部的类迭代器

问题描述 投票:0回答:2

我需要构建一个内部类迭代器来处理容器类FigureOfCircles

#define T Circle
    class FigureOfCircles {
private:
    Circle* c;
    int size;
public:
    class Iterator {
    protected:
        T* t;
    public:
        explicit Iterator (T* t1 = 0) : t(t1) { }
        Iterator (const Iterator& x) : t(x.t)  {}
        T& operator*() const { return *t; }
        T* operator->() const { return t; }

        Circle& operator[](const std::size_t& n) { return t[n]; }
        Iterator& operator++() { ++t; return *this; }
        Iterator operator++(int) { return Iterator(t++); }

        Iterator& operator--() { --t; return *this; }
        Iterator operator--(int) { return Iterator(t--); }

        Iterator operator- (int n) { return Iterator(t - n); }
        Iterator operator+ (int n) { return Iterator(t - n); }

        Iterator& operator-= (int n) { t -= n; return *this; }
        Iterator& operator+= (int n) { t += n; return *this; }

        bool operator== (const Iterator& x) const { return t == x.t; }
        bool operator!= (const Iterator& x) const { return t != x.t; }
        bool operator<= (const Iterator& x) const { return t <= x.t; }
        bool operator> (const Iterator& x) const { return t > x.t; }
        bool operator>= (const Iterator& x) const { return t >= x.t; }
        bool operator< (const Iterator& x) const { return t < x.t; }
        friend int operator- (const Iterator& x, const Iterator& y) { return x.t - y.t; }

        Iterator& operator= (const Iterator& x) {
            if (t == x.t) exit(-6);
            t = x.t;
            return *this;
        }
    };

    FigureOfCircles (int sz) : size(sz) {
        c = new T[size];
        for (Iterator i = begin(); i != end(); ++i) *i = input();
    }
    FigureOfCircles(const FigureOfCircles& f) {
        size = f.size;
        c = new T[size];
        for (Iterator i = begin(); i != end(); ++i) *i = f.c[i - begin()];
    }
    ~FigureOfCircles() { if (c) delete[] c; }

    Circle input() {
        int size = 1;
        Point* arr = new Point[size];
        float r, x1, y1;
        cout << endl << "Введiть к-сть точок, радiус i координати центру: ";
        cin >> size >> r >> x1 >> y1;
        for (int i = 0; i < size; i++) {
            Point tmp;
            cin >> tmp;
            if (tmp.GetX() == x1 && tmp.GetY() == y1) exit(-7);
            if (pow(tmp.GetX() - x1, 2) + pow(tmp.GetY() - y1, 2) != r * r) exit(-8);
            arr[i] = tmp;
        }
        return Circle(size, r, arr, x1, y1);        
    }

    Iterator begin() { return Iterator(c); }
    Iterator end() { return Iterator(c+size); }
};

但是我不知道T应该是什么类型,以便可以使用迭代器对象?如果是int,那怎么办

Iterator begin() { return Iterator(c); }
Iterator end() { return Iterator(c+size); }

注意:

FigureOfCircles (int sz) : size(sz) {
    c = new T[size];
    for (int i = 0; i < size; i++)
        c[i].input();
    for (Iterator i = begin(); i != end(); ++i) {
        *i = T(i-begin());
    }
}

...

 int main () {
    //...
    FigureOfCircles f(2);
    FigureOfCircles::Iterator i;
    for (i = f.begin(); i != f.end(); i++) cout << *i << endl;
    }
c++
2个回答
1
投票

您有一个由Circle指向的c个数组。迭代器应指向此数组的元素。最简单的解决方案是使用普通指针。也就是说,迭代器中的T应该只是Circle

如果要使用int(应为std::ptrdiff_t),则迭代器还应保留指向第一个元素的指针。在这个特定示例中,我看不出这样做的理由。

[operator-应该返回指针之间的差,std::ptrdiff_t,而不是Circle

friend std::ptrdiff_t operator-(Iterator x, Iterator y) { 
    return x.t - y.t;
}

按值取Iterator。它只是一个指针,您不需要通过const-ref接收它(实际上是将一个指针指向一个指针)。

一旦有了迭代器,就可以使用标准库算法进行复制:代替

for (Iterator i = begin(); i != end(); ++i) *i = f.c[i - begin()];

您可以写

std::copy(f.begin(), f.end(), begin());

我建议您使用std::vector<Circle>而不是Circle*。然后,您就可以借用其迭代器:

class FigureOfCircles {
private:
    std::vector<Circle> c;
public:
    std::vector<Circle>::iterator begin() {
        c.begin();
    }

    std::vector<Circle>::iterator end() {
        c.end();
    }
};

这还将使您不必编写副本构造函数和析构函数。


1
投票

虽然@Evg的答案是有效的,但从您的问题尚不清楚,为什么还要编写自己的迭代器。如果不是使用一对指针+长度成员,而是使用std::vectorstd::array-甚至是std::span,而忽略了从何处获取缓冲区,则可以使用这些类各自的迭代器代替实现自己的。

[仅当您在FigureOfCircles类中有某些特殊行为时-例如跳过元素,非标准的迭代顺序等-确实需要自定义迭代器。

PS-命名有点尴尬。如果一个图形只能有圆,则只需调用类Figure。如果有圆形以外的图形,请尝试:template <typename Element> class Figure { ... },然后将使用Figure<Circle>

© www.soinside.com 2019 - 2024. All rights reserved.