두 개의 다른 객체의 기본 클래스에서 템플릿 클래스를 사용하는 방법
-
21-12-2019 - |
문제
두 객체의 바닥에 템플릿 클래스를 저장하는 데 문제가 있습니다.
는 다음과 같이 정의 된 ObjectManager라는 일반화 된 클래스를 가지고 있습니다.
template<typename T>
class ObjectManager
{}
.
와 같은 기본 클래스가 있습니다.
class MediaSample
{
public:
MediaSample(ObjectManager<?>* manager){}
private:
ObjectManager<?> mMediaSampleManager;
}
.
이제는 MediaSample에서 또 다른 두 개의 드라이 클래스를 선언합니다. say :
class AudioSample : public MediaSample
{
public:
AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}
//...
}
public class VideoSample : public MediaSample
{
public:
VideoSample() : MediaSample(new ObjectManager<VideoSample>())
//...
}
.
내 문제는 관리자 의 유형, MediaSample
클래스의 입력 매개 변수입니다.
물음표 문자 대신 유형이 아닌 유형이어야합니까?(오디오, 비디오 또는 무엇?)
더 명확한 설명을 보려면 ObjectManager의 완전한 소스를 게시했습니다. Object Manager는 미디어 샘플 개체의 폴링이며 미디어 샘플은 오디오 또는 비디오 일 수 있습니다
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;
};
. 해결책
컴파일 시간 (템플릿) 및 런타임 다형성 (상속)을 혼합하기가 꽤 어려울 수 있습니다.당신이 할 수있는 일 :
a) 기본 클래스를 템플릿으로 만드십시오
template <class T>
class MediaSample {
ObjectManager<T> mMediaSampleManager;
};
class AudioSample : public MediaSample<AudioSample>
.
이 경우 AudioSample
및 VideoSample
에는 공통 기본 클래스가 없으므로 원하는 것이 아닐 수도 있습니다.또는
b) 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;
};
.
이렇게하면 파생 된 클래스 Audiosample과 VideosAmple이없는 in needs 없이는 서로 다른 종류의 MediaSample을 가질 수 있습니다.
In this case MediaSample
needs to be a template
template<typename T>
class MediaSample
{
public:
MediaSample(ObjectManager<T>* manager): mMediaSampleManager(manager) {}
private:
ObjectManager<T>* mMediaSampleManager;
}
and XxxSample
has to inherit from the specialized MediaSample
class AudioSample : public MediaSample<AudioSample>
{
public:
AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}
...
}