2008-09-29 42 views
132

Tôi đang cố gắng tìm hiểu C++ để tha thứ cho tôi nếu câu hỏi này chứng tỏ sự thiếu kiến ​​thức cơ bản, bạn thấy đấy, thực tế là, tôi thiếu kiến ​​thức cơ bản.Tạo Iterator riêng của tôi

Tôi muốn một số trợ giúp tìm cách tạo trình lặp cho lớp tôi đã tạo.

Tôi có lớp 'Hình dạng' có vùng chứa điểm. Tôi có lớp 'Mảnh' tham chiếu Hình dạng và xác định vị trí cho Hình dạng. Mảnh không có Hình dạng nó chỉ tham chiếu Hình dạng.

Tôi muốn nó có vẻ như Piece là một vùng chứa các điểm giống như của Hình dạng mà nó tham chiếu nhưng với độ lệch của vị trí của mảnh được thêm vào.

Tôi muốn có thể lặp qua các điểm của Mảnh giống như khi Mảnh là một vùng chứa. Tôi đã thực hiện một chút đọc xung quanh và không tìm thấy bất cứ điều gì đã giúp tôi. Tôi sẽ rất biết ơn đối với bất kỳ con trỏ nào.

+6

Đăng mã mẫu sẽ giúp mô tả những gì bạn đang làm tốt hơn chỉ là văn bản tiếng Anh đơn giản. –

+3

Tạo các trình vòng lặp tùy chỉnh có thể là _not_ một mức tối thiểu cơ bản, trung bình. – ldog

Trả lời

41

Bạn nên sử dụng Boost.Iterators. Nó chứa một số mẫu và khái niệm để triển khai các trình lặp và bộ điều hợp mới cho các trình vòng lặp hiện có. Tôi đã viết an article about this very topic; nó nằm trong tạp chí ACCU tháng 12 năm 2008. Nó thảo luận về một giải pháp thanh lịch (IMO) cho chính xác vấn đề của bạn: phơi bày các bộ sưu tập thành viên từ một đối tượng, sử dụng Boost.Iterators.

Nếu bạn muốn sử dụng chỉ stl, Josuttis book có chương về triển khai trình lặp vòng STL của riêng bạn.

+2

Chỉ là một nhận xét nhỏ: Cuốn sách nói về Thư viện chuẩn C++, không phải là STL - đây là những khác nhau, nhưng bị lẫn lộn rất nhiều (tôi cũng/cũng có tội) – CppChris

59

/EDIT: Tôi thấy, trình lặp của riêng thực sự là cần thiết ở đây (tôi đã đọc sai câu hỏi trước). Tuy nhiên, tôi cho phép mã bên dưới đứng vì nó có thể hữu ích trong các trường hợp tương tự.


Trình vòng lặp của riêng có thực sự cần thiết ở đây không? Có lẽ đó là đủ để chuyển tiếp tất cả các định nghĩa cần thiết để container giữ điểm thực tế:

// Your class `Piece` 
class Piece { 
private: 
    Shape m_shape; 

public: 

    typedef std::vector<Point>::iterator iterator; 
    typedef std::vector<Point>::const_iterator const_iterator; 

    iterator begin() { return m_shape.container.begin(); } 

    const_iterator begin() const { return m_shape.container.begin(); } 

    iterator end() { return m_shape.container.end(); } 

    const_iterator end() const { return m_shape.const_container.end(); } 
} 

này là giả sử bạn đang sử dụng một vector nội bộ nhưng loại có thể dễ dàng được điều chỉnh.

+0

có lẽ anh ta muốn sử dụng thuật toán STL hoặc các tính năng chức năng chống lại lớp học của mình ... – gbjbaanb

+2

Câu hỏi ban đầu thực sự nói rằng trình lặp của vùng chứa mảnh cần sửa đổi các giá trị khi trả về chúng. Điều đó sẽ yêu cầu một trình lặp riêng biệt, mặc dù nó có lẽ nên được thừa kế hoặc thu được chủ yếu từ bản gốc. – workmad3

+0

@gbjbaanb: Điều tốt về mã của tôi là nó * có thể * được sử dụng bởi các thuật toán STL. –

1

Giải pháp cho vấn đề của bạn không phải là việc tạo ra các trình vòng lặp của riêng bạn, mà là việc sử dụng các container và các vòng lặp STL hiện có. Lưu trữ các điểm trong mỗi hình dạng trong một container như vector.

class Shape { 
    private: 
    vector <Point> points; 

Việc bạn làm từ đó tùy thuộc vào thiết kế của bạn. Cách tiếp cận tốt nhất là lặp qua các điểm trong các phương thức bên trong Shape.

for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i) 
    /* ... */ 

Nếu bạn cần truy cập điểm Shape bên ngoài (điều này có thể là một dấu hiệu của một thiết kế thiếu), bạn có thể tạo trong phương pháp Shape rằng sẽ trả lại chức năng truy cập iterator cho điểm (trong trường hợp đó cũng tạo ra một typedef công cộng cho các container điểm). Nhìn vào câu trả lời của Konrad Rudolph để biết chi tiết về cách tiếp cận này.

+2

Anh ấy sẽ vẫn cần tạo trình lặp của riêng mình để chuyển tiếp các yêu cầu tới Mảnh tới các Hình dạng trong Mảnh đó. Trình vòng lặp tùy chỉnh là một công cụ tuyệt vời ở đây và rất thanh lịch để sử dụng. – Roel

13

Bạn có thể đọc ddj article

Về cơ bản, kế thừa từ std :: iterator để có được hầu hết công việc thực hiện cho bạn.

19

Ở đây Designing a STL like Custom Container là một bài viết tuyệt vời giải thích một số khái niệm cơ bản về cách STL như lớp vùng chứa có thể được thiết kế cùng với lớp lặp cho nó. iterator ngược (ít khó khăn hơn) mặc dù là trái như một bài tập :-)

HTH,

0

Viết lặp tùy chỉnh trong C++ có thể khá dài dòng và phức tạp để hiểu được.

Vì tôi không thể tìm thấy cách tối thiểu để viết trình lặp vòng tùy chỉnh, tôi đã viết this template header có thể hữu ích. Ví dụ, để làm cho iterable Piece lớp:

#include <iostream> 
#include <vector> 

#include "iterator_tpl.h" 

struct Point { 
    int x; 
    int y; 
    Point() {} 
    Point(int x, int y) : x(x), y(y) {} 
    Point operator+(Point other) const { 
    other.x += x; 
    other.y += y; 
    return other; 
    } 
}; 

struct Shape { 
    std::vector<Point> vec; 
}; 

struct Piece { 
    Shape& shape; 
    Point offset; 
    Piece(Shape& shape, int x, int y) : shape(shape), offset(x,y) {} 

    struct it_state { 
    int pos; 
    inline void next(const Piece* ref) { ++pos; } 
    inline void begin(const Piece* ref) { pos = 0; } 
    inline void end(const Piece* ref) { pos = ref->shape.vec.size(); } 
    inline Point get(Piece* ref) { return ref->offset + ref->shape.vec[pos]; } 
    inline bool cmp(const it_state& s) const { return pos != s.pos; } 
    }; 
    SETUP_ITERATORS(Piece, Point, it_state); 
}; 

Sau đó, bạn sẽ có thể sử dụng nó như một STL container bình thường:

int main() { 
    Shape shape; 
    shape.vec.emplace_back(1,2); 
    shape.vec.emplace_back(2,3); 
    shape.vec.emplace_back(3,4); 

    Piece piece(shape, 1, 1); 

    for (Point p : piece) { 
    std::cout << p.x << " " << p.y << std::endl; 
    // Output: 
    // 2 3 
    // 3 4 
    // 4 5 
    } 

    return 0; 
} 

Nó cũng cho phép thêm các loại khác của vòng lặp như const_iterator hoặc reverse_const_iterator.

Tôi hy vọng điều đó sẽ hữu ích.

Các vấn đề liên quan