返回对类的引用

returning reference to class

本文关键字:引用 返回      更新时间:2023-10-16

我有这样的代码:

#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("hellon");
   };
   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;
}

这是可行的,但我想将getIterator()方法"推"到AbstractList类中。要做到这一点,需要能够做到以下几点:

/* non const */
AbstractIterator &it = list.getIterator();
it.do_something();

这有可能在没有动态分配的情况下以某种方式实现吗?

也许这个

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("hellon");
    }
    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;
}

顺便说一句。重要的是要记住迭代器的有效性(修改列表、虚拟析构函数等),这个例子非常基本:)

这是写得很快的

  • 迭代器的无效函数应该是私有的,可以这样做,但会使源代码复杂化
  • 注意,iterface方法是由template方法调用的-好习惯

来源:

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 cleanedn");}
    virtual bool moveNext() override
    {
        if( !isValid() )
        {
            return false;
        }
        //do ...... iterate ... whatever
        return true;
    }
    virtual void do_something() override
    {
        printf("hellon");
    }
};
class List : public AbstractList{
public:
    ~List()
    {
        printf("List cleanedn");
    }
    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;
}

这更不像

另一种解决方案可能是:

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() ); }
};

我不确定所有的参数/返回类型都是正确的,但我希望这个想法是清楚的。

PS当然,如果你想在容器中保留迭代器的所有权,你可以使用std::shared_ptr,也可以在Iterator中保留std::weak_ptr,并且你不必显式地实现invalidate(),这将是自动魔术。

我想你的意思是对抽象类类型对象的非常数引用(与Java相比,C++没有接口,它们只是纯粹的抽象类)。

要返回引用,对象必须在某个地方保持活动状态。因此,如果您的AbstractList是一个接口(仅限抽象方法),我将不知道如何做到这一点。