사용 된 컨테이너를 노출시키지 않고 반복자를 노출하려면 어떻게해야합니까?
-
03-07-2019 - |
문제
나는 한동안 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
의견에 제안 된 바와 같이