كيف يمكنني كشف التكرارات دون الكشف عن الحاوية المستخدمة؟

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

هل أحاول شيئًا لا يمثل مشكلة؟هل يجب عليّ فقط كتابة def std::vector< T >::iterator؟آمل أن أعتمد فقط على المكرر، وليس على حاوية التنفيذ ...

هل كانت مفيدة؟

المحلول

ويمكنك العثور على المادة التالية مثيرة للاهتمام لأنه يتناول بالضبط المشكلة التي قد نشرت: على التوتر بين البرمجة الشيئية والجنيسة في C ++ وما المحو نوع يمكن القيام به حيال ذلك

نصائح أخرى

ولقد فعلت قبل التالية بحيث حصلت على مكرر التي كانت مستقلة عن الحاوية. قد يكون هذا مبالغة منذ أن ويمكن أيضا أن تستخدم لAPI حيث يمر الطالب في 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 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 هنا: وثائق المحكمة الخاصة بلبنان بشأن المتجهات

يحرر:تمت إضافة typename كما هو مقترح في التعليقات

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top