Reputation: 363
I have the following classes: // the concreteIterator.h
template<class Item>
class concreteForwardItr : public iterator<Item>
{
public:
concreteForwardItr(){}
concreteForwardItr( List<Item> *theList){
// this->iterator();
targetList = theList;
currentPos = 0;
}
void first(){
currentPos = 0;
}
Item CurrentItem() const {
// return targetList->
if(!IsDone())
{
return targetList->get(currentPos);
}
private:
List<Item>* targetList;
//keep track of current position
long currentPos;
}
//iterator.h
template <class Item>
class iterator{
public:
virtual void first() =0;
virtual Item CurrentItem() = 0;
}
but the compiler complains: undefined reference to 'iterator::iterator()'
But I don't even call that function. I know the compiler will generate a default one for the list class. Does anyone see what the problem is?
Upvotes: 1
Views: 86
Reputation: 39151
First, let's put this in the right order:
template <class Item>
class iterator{
public:
virtual void first() = 0;
virtual Item CurrentItem() = 0;
}
template<class Item>
class concreteForwardItr : public iterator<Item>
{
public:
concreteForwardItr(){}
concreteForwardItr( List<Item> *theList){
// this->iterator();
targetList = theList;
currentPos = 0;
}
void first(){
currentPos = 0;
}
Item CurrentItem() const {
// return targetList->
if(!IsDone()) // what is `IsDone`?
{
return targetList->get(currentPos);
}
// where's the closing brace?
private:
List<Item>* targetList;
//keep track of current position
long currentPos;
}
One problem with this is that concreteForwardItr::CurrentItem
does not override iterator::CurrentItem
, because the former is const
but not the latter. You should always use the "keyword" override
when you want to override a virtual function (if your compiler supports it):
Item CurrentItem() const override
{ /* ... */ }
This would have produced a compiler error along the lines of error: function does not override any base class virtual function.
To make concreteForwardItr::CurrentItem
override iterator::CurrentItem
adjust the const-qualification of either one. Which one you should adjust is a design decision; if the interface declares that member function as const
, the implementation cannot change that.
I've commented on two other possible problems in the first code block. Note that in the source file (.cpp), the class template iterator
should occur before concreteForwardItr
("the right order").
You might want to consider renaming this class, as it fulfils the C++ concept of a range rather than that of a C++ iterator.
Virtual functions typically have a runtime overhead, and iterators/ranges are often used in loops. That might be one of the reasons why the Standard Library (and boost ranges IIRC) don't use a class hierarchy design for their own iterator/range classes, but rather unrelated classes fulfilling some abstract concepts, combined with generic algorithms. The algorithms are also decoupled from the class design of the iterator, they only require the concept.
Upvotes: 2