كيفية استخدام قالب فئة في الفئة الأساسية من اثنين من كائنات مختلفة

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

سؤال

لدي مشكلة مع تخزين قوالب فئة في قاعدة اثنين من الكائنات.

أقول لقد المعمم الدرجة اسمه ObjectManager النحو التالي:

template<typename T>
class ObjectManager
{}

و لدي قاعدة الطبقة مثل:

class MediaSample
{
public:
    MediaSample(ObjectManager<?>* manager){}
private:
    ObjectManager<?> mMediaSampleManager;
}

الآن أعلن آخر اثنين دريفيد فئة من MediaSample, يقول:

class AudioSample : public MediaSample
{
public:
    AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}
    //...
}
public class VideoSample : public MediaSample
{
public:
    VideoSample() : MediaSample(new ObjectManager<VideoSample>())
    //...
}

مشكلتي هي نوع من مدير, معلمة الإدخال MediaSample فئة.

أي نوع يجب أن يكون بدلا من علامة استفهام الشخصية ؟ (الصوت والفيديو أو ماذا؟)

لمزيد من التوضيح نشرت لي مصدر كاملة من ObjectManager علما بأن مدير كائن هو الاستطلاع من وسائل الإعلام عينة الكائنات وسائل الإعلام يمكن أن تكون العينة الصوت أو الفيديو

class BaseMediaSampleManager
{
public:
    ~BaseMediaSampleManager(){}

    virtual INT initialize(INT objectCount) = 0;

protected:
private:
};

template<typename T>
class MediaSamppleManager : public BaseMediaSampleMnager //(based on user2079303 advise)
{
protected:
    MediaSamppleManager(void);

    MediaSamppleManager(const MediaSamppleManager& manager);

    MediaSamppleManager& operator = (const MediaSamppleManager& rhs);

public: 

    virtual ~MediaSamppleManager(void);

    static MediaSamppleManager<T>* instance();

    INT initialize(INT objectCount);

    // take existing object from object pool and return that object
    INT aquireObject(T** object);

    // take back in use object to object pool
    INT release(T* object);

private:
    std::list<T*> mPooledSamples;
    INT32 mPooledObjectCount;
    INT32 mInUseObjects;
    Mutex mPooledSamplesMutex;
    static Mutex mSampleManagerObjectMutex;
    static MediaSamppleManager<T>* mSampleManagerObject;
};

template<typename T>
Mutex MediaSamppleManager<T>::mSampleManagerObjectMutex;

template<typename T>
MediaSamppleManager<T>* MediaSamppleManager<T>::mSampleManagerObject = NULL;

template<typename T>
MediaSamppleManager<T>* MediaSamppleManager<T>::instance()
{
    if (mSampleManagerObject == NULL)
    {
        ScopedLock<Mutex> guard(mSampleManagerObjectMutex);
        if (mSampleManagerObject == NULL)
        {
            MediaSamppleManager<T>* temp = new MediaSamppleManager<T>();
            mSampleManagerObject = temp;
        }
    }
    return mSampleManagerObject;
}

template<typename T>
MediaSamppleManager<T>& MediaSamppleManager<T>::operator=(const MediaSamppleManager<T>& rhs)
{

}

template<typename T>
MediaSamppleManager<T>::MediaSamppleManager(const MediaSamppleManager<T>& manager)
{

}

template<typename T>
INT MediaSamppleManager<T>::release(T* object)
{
    ScopedLock<Mutex> guard(mPooledSamplesMutex);
    mPooledSamples.push_back(object);
    mInUseObjects--;
}

template<typename T>
INT MediaSamppleManager<T>::aquireObject(T** object)
{
    ScopedLock<Mutex> guard(mPooledSamplesMutex);
    if (mInUseObjects == mPooledObjectCount)
    {
        // do we need waiting until new sample become available? or 
        // is it required to create new sample when no free sample exist in pool? 
        return 2;
    } 
    else
    {
        T* temp = 0;
        temp = mPooledSamples.front();
        *object = temp;
        mPooledSamples.pop_front();
        mInUseObjects++;
    }
    return 1;
}

template<typename T>
INT MediaSamppleManager<T>::initialize(INT objectCount)
{
    if (objectCount<=0)
    {
        return -1;
    }
    mPooledObjectCount = objectCount;
    mPooledSamples.resize(objectCount);
    for (int i = 0 ; i< objectCount ; i++)
    {
        T* temp = new T(this);
        mPooledSamples.push_back(temp);
    }
    return 1;
}

template<typename T>
MediaSamppleManager<T>::~MediaSamppleManager(void)
{
    std::cout << "MediaSampleManager Destroyed \n";
}

template<typename T>
MediaSamppleManager<T>::MediaSamppleManager(void)
    :mPooledObjectCount(0)
    ,mInUseObjects(0)
{

}

فئة MediaSample :

class MediaSample
{
public:
    // create empty media sample
    MediaSample(BaseMediaSampleManager* manager);

    virtual ~MediaSample(void);

    virtual INT32 rate() = 0;

    virtual double frameSize() = 0;

    // data size of media sample
    virtual INT size();

    UINT* data();

    ULONG samplingTime();

    INT32 addRef();

    INT32 release();    

private:
    UINT8* mMediaSampleBuffer;
    // The time sample captured
    ULONG mTimestamp;
    // length of data
    INT mDataLength;

    INT mRefCount;

    BaseMediaSampleManager* mMediaSampleManager;
};

فئة AudioSample :

class PMCAPI AudioSample 
    :public MediaSample/*<AudioSample>*/
{
public:
    AudioSample(MediaSamppleManager<AudioSample>* manager);

    ~AudioSample();

    virtual INT32 rate();

    virtual double frameSize();

    virtual INT size();

protected:
private:
    // in 8,16 KHZ
    INT32 mSampleRate;
    // Mono or Stereo
    INT mChannels;
    // Used format ex: PCM,G729,G723,G711A,G711U
    INT mCodec;
    // ex : 8 bit , 16 bit
    INT mBitsPerSample;
};
هل كانت مفيدة؟

المحلول

أنه يمكن الحصول على من الصعب جدا أن تخلط وقت الترجمة (قوالب) و runtime تعدد الأشكال (الميراث).ما يمكنك القيام به:

أ) جعل قاعدة الطبقة قالب

template <class T>
class MediaSample {
    ObjectManager<T> mMediaSampleManager;
};

class AudioSample : public MediaSample<AudioSample>

في هذه الحالة AudioSample و VideoSample سوف لا يكون لديك قاعدة مشتركة الدرجة التي قد لا يكون ما تريد.يمكنك بدلا من ذلك ،

ب) إعطاء ObjectManager غير قالب قاعدة الطبقة (واجهة)

class BaseManager{
    virtual ~BaseManager(){}
    // pure virtual functions that ObjectManager implements
};

template<typename T>
class ObjectManager: public BaseManager{
    // implementation
};

class MediaSample {
    BaseManager mMediaSampleManager;
    // ...
};

class AudioSample: public MediaSample {
public:
    AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}

لاحظ أيضا أنه إذا كان الخاص بك MediaSample منشئ يقبل مؤشر إلى المشيدة حديثا ObjectManager و يفترض نسخ هذا الكائن العضو ، يجب أن نتذكر أن حذف المؤشر أو تسرب.ربما عليك أن تمر من القيمة بدلا من ذلك.

نصائح أخرى

عن كيفية صنع MediaSample قالب:

template <typename T>
class MediaSample
{
public:
    MediaSample(ObjectManager<T>* manager){}
private:
    ObjectManager<T> mMediaSampleManager;
};

بهذه الطريقة يمكنك الحصول على أنواع مختلفة من MediaSample دون المساعدة من وجود الفئات المشتقة AudioSample و VideoSample.

في هذه الحالة MediaSampleيجب أن يكون القالب

template<typename T>
class MediaSample
{
public:
    MediaSample(ObjectManager<T>* manager): mMediaSampleManager(manager) {}
private:
    ObjectManager<T>* mMediaSampleManager;
}

و XxxSample يجب أن يرث المتخصصة MediaSample

class AudioSample : public MediaSample<AudioSample>
{
public:
    AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}
    ...
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top