Frage

Ich habe ein Problem mit dem Speichern der Vorlagenklasse in der Basis von zwei Objekten.

Angenommen, ich habe eine verallgemeinerte Klasse mit dem Namen ObjectManager definiert als:

template<typename T>
class ObjectManager
{}

Und ich habe eine Basisklasse wie:

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

Jetzt deklariere ich zwei weitere gefahrene Klassen von MediaSample, sagen wir:

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

Mein Problem ist die Art von Manager, eingabeparameter von MediaSample Klasse.

Welcher Typ muss anstelle des Fragezeichens gesetzt werden?Audio, Video oder was?)

zur weiteren Verdeutlichung habe ich die vollständige Quelle von ObjectManager gepostet beachten Sie, dass der Objektmanager eine Abfrage von Medienbeispielobjekten ist und das Medienbeispiel Audio oder Video sein kann

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)
{

}

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

klassen-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;
};
War es hilfreich?

Lösung

Es kann ziemlich schwierig werden, Kompilierungszeit (Vorlagen) und Laufzeitpolymorphismus (Vererbung) zu mischen.Was Sie tun können:

a) Machen Sie die Basisklasse zu einer Vorlage

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

class AudioSample : public MediaSample<AudioSample>

In diesem Fall AudioSample und VideoSample wird keine gemeinsame Basisklasse haben, was möglicherweise nicht das ist, was Sie wollen.Alternativ können Sie

b) Geben Sie ObjectManager eine Nicht-Template-Basisklasse (eine Schnittstelle)

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>()){}

Beachten Sie auch, dass, wenn Ihr MediaSample konstruktor akzeptiert einen Zeiger auf neu konstruierte ObjectManager und Sie kopieren das vermutlich in das Mitgliedsobjekt, Sie müssen daran denken, den Zeiger zu löschen, sonst wird er auslaufen.Sie sollten stattdessen wahrscheinlich nach Wert übergeben.

Andere Tipps

Wie wäre es, MediaSample zu einer Vorlage zu machen:

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

Auf diese Weise können Sie verschiedene Arten von MediaSample ohne abgeleitete Klassen AudioSample und VideoSample .

In diesem Fall MediaSamplemuss eine Vorlage sein

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

und XxxSample muss vom Spezialisierten erben MediaSample

class AudioSample : public MediaSample<AudioSample>
{
public:
    AudioSample() : MediaSample(new ObjectManager<AudioSample>()){}
    ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top