사용 된 컨테이너를 노출시키지 않고 반복자를 노출하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/156936

문제

나는 한동안 C#을 사용해 왔으며 C ++로 돌아가는 것은 두통입니다. 나는 C#에서 나와 함께 C ++로의 일부 연습을 얻으려고 노력하고 있지만 저항을 찾고 있으며 귀하의 도움을 받아들이게되어 기쁩니다.

다음과 같은 수업에 반복자를 노출하고 싶습니다.

template <class T>
class MyContainer
{
public:
    // Here is the problem:
    // typedef for MyIterator without exposing std::vector publicly?

    MyIterator Begin() { return mHiddenContainerImpl.begin(); }
    MyIterator End() { return mHiddenContainerImpl.end(); }

private:
    std::vector<T> mHiddenContainerImpl;
};

문제가 아닌 것을 시도하고 있습니까? std :: vector <t> :: iterator를 입력해야합니까? 구현 컨테이너가 아니라 반복자에 따라 바라고 있습니다 ...

도움이 되었습니까?

해결책

다음 기사가 귀하가 게시 한 문제를 정확히 다루기 때문에 흥미로운 것을 찾을 수 있습니다. C ++의 객체 지향과 일반적인 프로그래밍 사이의 장력과 유형 삭제에 대해 할 수있는 유형의 긴장

다른 팁

컨테이너와 무관 한 반복자를 얻도록 전에 다음을 수행했습니다. 발신자가 vector<T*>& 이는 모든 요소로 채워져 있어야하며 발신자는 벡터에서 직접 반복 할 수 있습니다.

template <class T>
class IterImpl
{
public:
    virtual T* next() = 0;
};

template <class T>
class Iter
{
public:
    Iter( IterImpl<T>* pImpl ):mpImpl(pImpl) {};
    Iter( Iter<T>& rIter ):mpImpl(pImpl) 
    {
        rIter.mpImpl = 0; // take ownership
    }
    ~Iter() {
        delete mpImpl; // does nothing if it is 0
    }
    T* next() {
    return mpImpl->next(); 
    }
private:
    IterImpl<T>* mpImpl; 
};

template <class C, class T>
class IterImplStl : public IterImpl<T>
{
public:
    IterImplStl( C& rC )
    :mrC( rC ),
    curr( rC.begin() )
    {}
    virtual T* next()
    {
    if ( curr == mrC.end() ) return 0;
    typename T* pResult = &*curr;
    ++curr;
    return pResult;
    }
private:
    C& mrC;
    typename C::iterator curr;
};


class Widget;

// in the base clase we do not need to include widget
class TestBase
{
public:
    virtual Iter<Widget> getIter() = 0;
};


#include <vector>

class Widget
{
public:
    int px;
    int py;
};

class Test : public TestBase
{
public:
    typedef std::vector<Widget> WidgetVec;

    virtual Iter<Widget> getIter() {
        return Iter<Widget>( new IterImplStl<WidgetVec, Widget>( mVec ) ); 
        }

    void add( int px, int py )
    {
        mVec.push_back( Widget() );
        mVec.back().px = px;
        mVec.back().py = py;
    }
private:
    WidgetVec mVec;
};


void testFn()
{
    Test t;
    t.add( 3, 4 );
    t.add( 2, 5 );

    TestBase* tB = &t;
    Iter<Widget> iter = tB->getIter();
    Widget* pW;
    while ( pW = iter.next() )
    {
        std::cout << "px: " << pW->px << " py: " << pW->py << std::endl;
    }
}

이것은 당신이 원하는 것을해야합니다.

typedef typename std::vector<T>::iterator MyIterator;

에서 가속 C ++:

다음과 같은 유형이있을 때마다 vector<T>, 이는 템플릿 매개 변수에 따라 다르며 다음과 같이 해당 유형의 멤버를 사용하려고합니다. size_type, 그 자체는 유형입니다. 전체 이름보다 우선해야합니다. typename 구현에 이름을 유형으로 취급하도록 알리기 위해.

나는 "std :: vector를 공개적으로 노출시키지 않는다"는 당신이 의미하는 바에 대해 확신이 없지만 실제로, 당신은 다음과 같이 당신의 typedef를 정의 할 수 있습니다.

typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator; // To work with constant references

사용자가 아무것도 알아 차리지 않고 나중에이 typedef를 변경할 수 있습니다 ...

그건 그렇고, 수업이 컨테이너로 행동하기를 원한다면 몇 가지 다른 유형을 노출시키는 것이 좋은 관행으로 간주됩니다.

typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::difference_type difference_type;
typedef typename std::vector<T>::pointer pointer;
typedef typename std::vector<T>::reference reference;

그리고 당신의 수업에 필요한 경우 :

 typedef typename std::vector<T>::const_pointer const_pointer;
 typedef typename std::vector<T>::const_reference const_reference;

이 모든 Typedef의 의미를 여기에 찾을 수 있습니다. 벡터에 대한 STL 문서

편집 : 추가 typename 의견에 제안 된 바와 같이

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top