كيفية استخدام قالب فئة في الفئة الأساسية من اثنين من كائنات مختلفة
-
21-12-2019 - |
سؤال
لدي مشكلة مع تخزين قوالب فئة في قاعدة اثنين من الكائنات.
أقول لقد المعمم الدرجة اسمه 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>()){}
...
}