operator= bei abstrakter Klasse ohne RTTI
-
Hi @all,
Ich habe eine abstrakte Basisklkasse, um alle ableitenden Klassen zu zwingen sich an eine bestimmte Schnittstelle zu halten:
ImageIoObj { ... public: virtual void Load(void) = 0; virtual void Save(void) = 0; .... };
Weiterhin einen Kontainer, der die einzelnen von ImageIoObj abgeleiteten Instanzen verwaltet:
ImageIoCont { ... public: ImageIoCont( const ImageIoCont& theIo );//hier liegt das problem private: std::list<ImageIoObj*> m_lImageLoaderObj; };
den ctor von ImageIoCont habe ich dann rotzfrech so implementiert:
ImageIoCont::ImageIoCont( const ImageIoCont& theIo ) { m_lImageLoaderObj.insert( m_lImageLoaderObj.begin(), theIo.m_lImageLoaderObj.begin(), theIo.m_lImageLoaderObj.end() ); int iSize = m_lImageLoaderObj.size(); }
Das das nicht gehen kann ist mir so schon klar, trotzdem ist danach iSzie == 3. Genau die richtige anzahl. Trotzdem schmiert
er danach ab - klar, er hat ja irgendwelchen Unsinn kopiert (auch wenn mir nicht klar ist, was er denn dann da kopiert).beholfen habe ich mir durch eine unschöne selbstgeschriebene Kopierfunktion, die die einzelnen ImageIoObj-Objeckt mittels dynamic_cast
außeinanderhält:ImageIoObject* ImageIoFactory( ImageIoObject* pObj ) { if( dynamic_cast<BitmapIO*>(pObj) ) return new BitmapIO(); if( dynamic_cast<TiffIO*>(pObj) ) return new TiffIO(); if( dynamic_cast<BTNExgenIplIO*>(pObj) ) return new BTNExgenIplIO(); assert(0); return NULL; } LoaderIterator iterBeg = pIo->m_lImageLoaderObj.begin(); while( iterBeg != pIo->m_lImageLoaderObj.end() ) { ImageIoObject* pNewIo = ImageIoFactory( *iterBeg++ ); if( pNewIo ) m_lImageLoaderObj.push_back( pNewIo ); }
kann man das irgendwie schöner lösen. Gut ich könnte einfach ImageIoObj nicht mehr abstrakt machen. Das hätte auch den Vorteil, nicht mehr dynamisch Speicher anfordern zu müssen, aber dann erzwinge ich ja nicht mehr die Einhaltung der Schnittstelle.
-
Wo kommt das m_lImageLoaderObj her?
_IoList sollte sich einfach kopieren lassen. Es werden jedoch nur die Pointer kopiert. Wenn du neue Objekte willst, wäre eine clone() Methode überlegenswert.
-
[cpp]du kannst es entweder so :
class ImageIoObj
{
public:
virtual void Load(void) = 0;
virtual void Save(void) = 0;virtual void Clone() = 0;
virtual ~ImageIoObj(){}
};struct ObjectDeleter
{
template<typename T>
void operator()(T *obj)
{
delete obj;
}
};class ImageIoCont
{typedef std::list<ImageIoObj*> Images;
class PushClone
{
public:
PushClone(Images &images)
: images(images)
{
}
void operator()(ImageIoObj *obj)
{
images.push_back(obj->Clone());
}
private:
Images &images;
};public:
ImageIoCont( const ImageIoCont& theIo )
{
std::for_each(theIo._IoList.begin(), theIo._IoList.end(), PushClone(_IoList));
}~ImageIoCont()
{
std::for_each(_IoList.begin(), _IoList.end(), ObjectDeleter());
}private:
Images _IoList;
};
[/cpp]oder einfach so machen:
#include <boost/shared_ptr.hpp> class ImageIoCont { typedef std::list<boost::shared_ptr<ImageIoObj> > Images; public: // jetzt brauchst du kein copy constructor mehr //ImageIoCont( const ImageIoCont& theIo ) //{ //} // jetzt brauchst du kein destructor mehr //~ImageIoCont() //{ //std::for_each(_IoList.begin(), _IoList.end(), ObjectDeleter()); //} private: Images _IoList; };
-
@ssm
Danke,ich sehe schon, ich werde mich wohl doch einmal eingehender mit boost beschäftigen müssen.
soltte die Clone Funktion nicht so aussehen?
virtual ImageIoObj Clone() = 0;
Der Ansatz gefällt mir als kurzfristige Lösung auch ganz gut.
m_lImageLoaderObj is logischerweise die _IoList das kommt von zusammenkopiert, konstruierten Beispielen
-> schon editiert.
_IoList sollte sich einfach kopieren lassen. Es werden jedoch nur die Pointer kopiert. Wenn du neue Objekte willst, wäre eine clone() Methode überlegenswert.
Das ist schon richtig, aber der Speicher sollte schön im Destruktor wieder freigegeben werden, und das geht so dann natürlich nicht..
-
TheBigW schrieb:
soltte die Clone Funktion nicht so aussehen?
virtual ImageIoObj Clone() = 0;
nein sie sollte so aussehen:
virtual ImageIoObj * Clone() const = 0;
und sie könnte so realiziert werden:
class BitmapIO { public: virtual ImageIoObj * Clone() const { return new BitmapIO(*this); } }; class TiffIO { public: virtual ImageIoObj * Clone() const { return new TiffIO(*this); } }; class BTNExgenIplIO { public: virtual ImageIoObj * Clone() const { return new BTNExgenIplIO(*this); } };
-
Hihi und so jagt ein vertipper den nächsten
Auf die Implementierung wäre ich eventuell gerade noch gekommen. Trotzdem Danke für die schnelle Hilfe.