Hanna Khalil
Hanna Khalil

Reputation: 1055

Abstract Iterator Class in c++

After writing AVL tree class I would like to write 3 kinds of iterators for the tree: preOrder, inOrder, postOrder. I thought that a very rational way is to do so through abstract class iterator and so the 3 iterator classes inheret from it. but problem arise when I want write the declaration of postfix ++ operator. I thought in some options: 1. iterator& operator++(int) problem: postfix iterator can't return refernce to the object. 2. iterator operator++(int) problem: class iterator is abstract and therefor can't return by value.

So what is the right way to do that? Thank you

Upvotes: 1

Views: 548

Answers (1)

Steve Jessop
Steve Jessop

Reputation: 279285

Postfix increment must return by value, and must return the same type as the object. It's unsuited to dynamic polymorphism.

What you do depends why you are using a base class in the first place:

1) you want polymorphic iterators, and you expect a user will have a reference-to-base. This is not the normal way to use iterators in C++, and it doesn't work well[*]. The normal way to write code that might accept different types of iterators is to write a function template with the iterator type as a template parameter. You should either change the design (so that users always know which kind of iterator they have) or define a wrapper class that can hold any of the three kinds of iterators, then it can have a postfix increment that returns an instance of the wrapper. From the user's POV there is one iterator type with three modes (preorder, inorder, postorder iteration). If you want to implement that internally using dynamic polymorphism then that's your business.

2) there's some code you want to share between the iterators, and a base class is a convenient way to share code. Then do not make postfix increment a function in the base class.

[*] why do certain operators not work well with dynamic polymorphism in C++? Because C++ uses value semantics. Operators like postfix increment, addition, and others that return by value inherently create a new object. The calling code needs to have space on the stack for that new object (well, a copy of it), so it needs to know the dynamic type. Other languages get around this because object types aren't stored on the stack -- they're allocated "elsewhere" (the heap). The calling code doesn't need to know the size or the dynamic type because it only accesses them by reference.

Upvotes: 9

Related Questions