Reputation: 10539
I have code like this:
#include <stdio.h>
class AbstractIterator{
virtual void do_something() = 0;
};
class AbstractList{};
class Iterator : public AbstractIterator{
public:
Iterator(const AbstractList & list) : list(list){};
virtual void do_something() override{
printf("hello\n");
};
const AbstractList & list;
};
class List : public AbstractList{
public:
Iterator getIterator(){
return Iterator(*this);
}
};
int main(int argc, char** argv){
List list;
Iterator it = list.getIterator();
it.do_something();
return 0;
}
This works, but I want to "push" getIterator() method to AbstractList class. To do so, need to be able to do following:
/* non const */
AbstractIterator &it = list.getIterator();
it.do_something();
Is this possible to be done somehow without dynamic allocation?
Upvotes: 0
Views: 99
Reputation: 44238
Another solution could be:
class AbstractIteratorImpl{
public:
virtual void do_something() = 0;
};
class Iterator {
pibluc:
void do_something() { impl->do_something(); }
friend class AbstractList;
private:
Iterator( std::unique_ptr<AbstractIteratorImpl> &limpl ) : impl( limpl ){}
std::unique_ptr<AbstractIteratorImpl> impl;
}
class AbstractList
{
virtual std::unique_ptr<AbstractIteratorImpl> getIteratorImpl() = 0;
public:
Iterator getIterator() { return Iterator( getIteratorImpl() ); }
};
I am not sure all argument/return types are correct, but I hope idea is clear.
PS Of course if you want to keep ownership of the iterator in the container you can use std::shared_ptr
plus you may keep std::weak_ptr
in Iterator
and you would not have to implement invalidate()
explicitly, that would be automagic.
Upvotes: 2
Reputation: 1427
Maybe this
class AbstractIterator{
public:
virtual void do_something() = 0;
};
class AbstractList
{
public:
virtual AbstractIterator* getIterator() = 0;
};
class Iterator : public AbstractIterator{
public:
Iterator(AbstractList& list) : list(list){}
const Iterator operator=( const Iterator& other )
{
list = other.list;
return *this;
}
virtual void do_something() override{
printf("hello\n");
}
AbstractList& list;
};
class List : public AbstractList{
Iterator iterator;
public:
List() : iterator( *this ) {}
AbstractIterator* getIterator() override
{
iterator = Iterator( *this );
return &iterator;
}
};
int main(int argc, char *argv[])
{
List list;
AbstractIterator* it = list.getIterator();
it->do_something();
return 0;
}
BTW. It is important to remember about iterator validness ( modification of lists, virtual destructors etc ), this example is very basic :)
This is written very fast
Source:
class AbstractList;
class AbstractIterator{
public:
AbstractIterator( AbstractList* list ) : list( list ), valid( true ) {}
virtual bool moveNext() = 0;
void doSomething()
{
if( isValid() )
{
do_something();
}
}
bool isValid() { return valid && 0 != list; }
void invalidate()
{
valid = false;
}
protected:
AbstractList* list;
private:
virtual void do_something() = 0;
bool valid;
};
class AbstractList
{
public:
virtual ~AbstractList()
{
for( std::shared_ptr< AbstractIterator > it : iterators )
{
it->invalidate();
}
iterators.clear();
}
std::shared_ptr< AbstractIterator > iterator()
{
std::shared_ptr< AbstractIterator > it = getIterator();
iterators.push_back( it );
return it;
}
private:
virtual std::shared_ptr< AbstractIterator > getIterator() = 0;
private:
std::list< std::shared_ptr< AbstractIterator > > iterators;
};
class Iterator : public AbstractIterator{
public:
Iterator( AbstractList* list ) : AbstractIterator(list){}
~Iterator() {printf("Iterator cleaned\n");}
virtual bool moveNext() override
{
if( !isValid() )
{
return false;
}
//do ...... iterate ... whatever
return true;
}
virtual void do_something() override
{
printf("hello\n");
}
};
class List : public AbstractList{
public:
~List()
{
printf("List cleaned\n");
}
List() {}
private:
std::shared_ptr< AbstractIterator > getIterator() override
{
std::shared_ptr< AbstractIterator > iterator( new Iterator( this ) );
return iterator;
}
};
int main(int argc, char *argv[])
{
List* list = new List();
std::shared_ptr< AbstractIterator > it = list->iterator();
it->doSomething();
if( it->isValid() )
{
std::cout << "It valid" << std::endl;
}
delete list;
if( !it->isValid() )
{
std::cout << "It !valid" << std::endl;
}
return 0;
}
This is more less how should look like
Upvotes: 6
Reputation: 122133
I guess what you mean is a non const reference to an object of abstract class type (in contrast to Java, C++ does not have interfaces, they are just pure abstract classes).
To return a reference, the object has to be kept alive somewhere. Thus, if your AbstractList
is an interface (abstract methods only) I would not know how to do it.
Upvotes: 1