Thật khó để có đa hình động với các trình lặp vòng kiểu C++. operator++(int)
trả về theo giá trị, mà afaik là không thể nhận được: bạn không thể có hàm thành viên ảo trả về *this
theo giá trị mà không bị cắt.
Nếu có thể, tôi khuyên bạn nên sử dụng các mẫu như những người khác nói.
Tuy nhiên nếu bạn làm cần đa hình năng động, ví dụ bởi vì bạn không thể phơi bày việc thực hiện add_all_msgs làm mẫu sẽ làm gì, sau đó tôi nghĩ rằng bạn có thể giả vờ là Java, như thế này:
struct MessageIterator {
virtual Message &get() = 0;
virtual void next() = 0;
// add more functions if you need more than a Forward Iterator.
virtual ~MessageIterator() { }; // Not currently needed, but best be safe
};
// implementation elsewhere. Uses get() and next() instead of * and ++
void add_all_msgs(MessageIterator &it);
template <typename T>
struct Adaptor : public MessageIterator {
typename T::iterator wrapped;
Adaptor(typename T::iterator w) : wrapped(w) { }
virtual Message &get() {
return *wrapped;
}
virtual void next() {
++wrapped;
}
};
int main() {
std::deque<Message> v;
Adaptor<std::deque<Message> > a(v.begin());
add_all_msgs(a);
}
Tôi đã kiểm tra rằng biên dịch này, nhưng tôi đã không kiểm tra nó và tôi chưa bao giờ sử dụng thiết kế này trước đây. Tôi cũng không làm phiền với const-ness - trong thực tế bạn có thể muốn có một const Message &get() const
. Và tại thời điểm bộ điều hợp không có cách nào để biết khi nào nên dừng lại, nhưng sau đó cũng không phải mã bạn bắt đầu, vì vậy tôi cũng đã bỏ qua điều đó. Về cơ bản, bạn cần có hàm hasNext
so sánh wrapped
với trình lặp kết thúc được cung cấp cho hàm tạo.
Bạn có thể làm điều gì đó với chức năng mẫu và tham chiếu const để khách hàng không phải biết hoặc khai báo loại Bộ điều hợp khó chịu đó.
[Chỉnh sửa: suy nghĩ về điều đó, có lẽ tốt hơn là nên có một mẫu hàm add_all_msgs
sơ khai, bao bọc thông số của nó trong Bộ điều hợp và sau đó gọi real_add_all_msgs
. Điều này hoàn toàn ẩn bộ điều hợp từ phía máy khách.]
Nguồn
2009-07-09 15:27:43
Công ước sẽ lấy vòng lặp theo giá trị thay vì tham chiếu.Bên cạnh đó iterators thường là "nhỏ" anyway, lý do cho điều này (afaik) là để cho phép người gọi để vượt qua một tạm thời, chẳng hạn như một giá trị trả về từ std :: back_inserter. C++ 0x giúp với điều này trong ít nhất hai cách tôi có thể nghĩ đến. –
Heh, hoặc giá trị trả về từ "bắt đầu" đến để suy nghĩ về nó. Mã "sử dụng" ở trên không biên dịch: "khởi tạo không hợp lệ tham chiếu không const của loại 'blah' từ tạm thời kiểu 'blah'". –
OP rõ ràng đã nói: "miễn là người lặp lại đang lặp lại Thông báo". Giải pháp này, và hầu hết những người khác, hoàn toàn bỏ qua yêu cầu này. –