Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
255 views
in Technique[技术] by (71.8m points)

c++ - Iterator for custom container with derived classes

I've a custom container which is implemented in two different ways, but with a single interface. some thing like this.

    class Vector 
    {
       virtual Iterator begin() = 0;
       virtual Iterator end () = 0 ;

    ... // some more functions.
    } ;

    class VectorImplA : public Vector
    {
       Iterator begin() { return m_data.begin() ; }
       Iterator end () { return m_data.end() ; }
    private:
       SomeFloatContainer m_data ;
    } ;

    class VectorImplB : public Vector
    {
       Iterator begin() { return m_data.end() ; }
       Iterator end() ; { return m_data.end() ; }


    private:
        std::vector <float> m_data ;

    } ;

What I need is a unified interface to Iterator, so that I'can use it in base class. Any Ideas ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I've run into exactly this problem myself before. While there are ways to solve your problem, you most likely should let go of the idea of a vector base class. What you probably should do instead, is mimic the way the c++ STL container are designed.

The STL consists of concepts rather than base classes. An std::vector is a model of the Container concept, but does not inherit from a Container base class. A concept is a set of requirements that any model of the concept should adhere to. See this page for the requirements for Container for example.

The requirements for Container state for example that you should typedef the type of the contents of the container as value_type, and typedef iterators as iterator and const_iterator. Furthermore, you should define begin() and end() functions returning iterators, and so on.

You'll then need to change functions that operate on your Vector base class to instead operate on any class that adheres to the requirements imposed by the concept. This can be done by making the functions templated. You don't necessarily have to stick to the concepts used by the STL, you might as well cook up your own. Sticking to the concepts as they are defined in the STL has the additional benefit that the STL algorithms (std::sort for example) can operate on your containers.

Quick example:

class VectorImplA
{
public:
    typedef VectorImplAIterator iterator;

    iterator begin();
    iterator end();
};

class VectorImplB
{
public:
    typedef VectorImplBIterator iterator;

    iterator begin();
    iterator end();
};

template <typename VectorConcept>
void doSomeOperations(VectorConcept &container)
{
    VectorConcept::iterator it;
    it = container.begin();
}

int main()
{
    VectorImplA vecA;
    VectorImplB vecB;
    doSomeOperations(vecA); // Compiles!
    doSomeOperations(vecB); // Compiles as well!
}

As a bonus, to answer the original question, consider the following design (I wouldn't go this way though!):

struct IteratorBase
{
    virtual void next() = 0;
};

struct IteratorA : IteratorBase
{
    void next() {};
};

struct IteratorB : IteratorBase
{
    void next() {};
};

class Iterator
{
    IteratorBase *d_base;
public:
    void next() { d_base->next(); }
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...