user2984297
user2984297

Reputation: 363

About template inheritence

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

Answers (1)

dyp
dyp

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

Related Questions