代码之家  ›  专栏  ›  技术社区  ›  Alex B

如何在C++中与派生类型匹配的元素创建迭代器?

  •  3
  • Alex B  · 技术社区  · 15 年前

    我想要一个C++中的迭代器,它只能对特定类型的元素进行迭代。在下面的示例中,我只想迭代属于子类型实例的元素。

    vector<Type*> the_vector;
    the_vector.push_back(new Type(1));
    the_vector.push_back(new SubType(2)); //SubType derives from Type
    the_vector.push_back(new Type(3));
    the_vector.push_back(new SubType(4)); 
    
    vector<Type*>::iterator the_iterator; //***This line needs to change***
    
    the_iterator = the_vector.begin();
    while( the_iterator != the_vector.end() ) {
        SubType* item = (SubType*)*the_iterator;
        //only SubType(2) and SubType(4) should be in this loop.
        ++the_iterator;
    }
    

    如何在C++中创建这个迭代器?

    5 回复  |  直到 15 年前
        1
  •  9
  •   Jem    15 年前

    必须使用动态强制转换。

    the_iterator = the_vector.begin();
    while( the_iterator != the_vector.end() ) {
        SubType* item = dynamic_cast<SubType*>(*the_iterator);
        if( item != 0 )
           ... 
    
        //only SubType(2) and SubType(4) should be in this loop.
        ++the_iterator;
    }
    
        2
  •  12
  •   Sanjaya R    15 年前
        3
  •  4
  •   Mykola Golubyev    15 年前

    解决方案,无助力。但是,如果您可以访问Boost库,请按照建议使用过滤器迭代器。

    template <typename TCollection, typename T>
    class Iterator
    {
    public:
        typedef typename TCollection::iterator iterator;
        typedef typename TCollection::value_type value_type;
    
        Iterator(const TCollection& collection,
                 iterator it):
            collection_(collection),
            it_(it)
        {
            moveToNextAppropriatePosition(it_);
        }
        bool operator != ( const Iterator& rhs )
        {
            return rhs.it_ != it_;
        }
        Iterator& operator++()
        {
            ++it_;
            moveToNextAppropriatePosition(it_);
            return *this;
        }
        Iterator& operator++(int);
        Iterator& operator--();
        Iterator& operator--(int);
        value_type& operator*()
        {
            return *it_;
        }
        value_type* operator->()
        {
            return &it_;
        }
    private:
        const TCollection& collection_;
        iterator it_;
        void moveToNextAppropriatePosition(iterator& it)
        {
            while ( dynamic_cast<T*>(*it) == NULL && it != collection_.end() ) 
                ++it;
        }
    };
    
    class A
    {
    public:
        A(){}
        virtual ~A(){}
        virtual void action()
        {
            std::cout << "A";
        }
    };
    class B: public A
    {
    public:
        virtual void action()
        {
            std::cout << "B";
        }
    };
    int main()
    {
        typedef std::vector< A* > Collection;
        Collection c;
        c.push_back( new A );
        c.push_back( new B );
        c.push_back( new A );
    
        typedef Iterator<Collection, B> CollectionIterator;
        CollectionIterator begin(c, c.begin());
        CollectionIterator end(c, c.end());
    
        std::for_each( begin, end, std::mem_fun(&A::action) );
    }
    
        4
  •  2
  •   Rick Copeland    15 年前

    正如paintballbob在注释中所说,您应该创建自己的迭代器类,可能继承自 vector<Type*>::iterator . 尤其是,您需要实现或重写 operator++() operator++(int) 要确保跳过非子类型对象(可以使用 dynamic_cast<SubType*>() 检查每个项目)。对于在这个O'Reilly网络中实现自己的容器和迭代器有一个很好的概述 article .

        5
  •  2
  •   Johannes Schaub - litb    15 年前

    另一种方法是使用boost迭代器。这次,使用 std::remove_copy_if :

    std::remove_copy_if(v.begin(), v.end(), 
        boost::make_function_output_iterator(boost::bind(&someFunction, _1)),
        !boost::lambda::ll_dynamic_cast<SubType*>(boost::lambda::_1));
    

    它将调用一个函数(在本例中 someFunction . 但它可以是任何Boost::Bind可以为指向 SubType .