Smart Pointer



  • Hi,
    ich habe langsam die Schnauze voll von dem Ewigen freigeben von Resourcen, und daher habe ich mir gedacht, dass ich mir SmartPointer bastele 🙂
    Das habe ich jetzt so gemacht:

    #pragma once
    
    template<class C> class CSafeBase
    {
    private:	
    						CSafeBase(const CSafeBase&)
    	{
    	};
    						CSafeBase& operator=(const CSafeBase&)
    	{
    	};
    
    protected:
    	C					m_Type;
    
    public:
    	C&					Get()
    	{
    						return m_Type;
    	}
    	const C&			Get() const
    	{
    						return m_Type;
    	}
    
    						CSafeBase(C Type)
    	{
    		m_Type=Type;
    	}
    						virtual ~CSafeBase()
    	{
    	};
    };
    
    template<class C> class CSafe //DUMMY
    {
    };
    
    template<> class CSafe<SC_HANDLE> : public CSafeBase<SC_HANDLE>
    {
    public:
    						CSafe(SC_HANDLE pType) : CSafeBase(pType)
    	{
    	}
    
    						~CSafe()
    	{
    		CloseServiceHandle(m_Type);
    	}
    };
    //... weitere spezielle CSafe#s für andere Windows-Typen
    
    template<> class CSafe<void*> : public CSafeBase<void*>
    {
    private:
    	bool				m_bArray;
    
    public:
    						CSafe(void* pType, const bool& bArray) : CSafeBase(pType)
    	{
    		m_bArray=bArray;
    	}
    
    						~CSafe()
    	{
    		if(m_bArray)
    		{
    			delete[] m_Type;
    		}
    		else
    		{
    			delete m_Type;
    		}
    	}
    };
    

    ist dies so OK oder seht ihr Probleme?
    Danke,
    S.



  • Sieht schon recht gut aus, allerdings würde ich noch ein paar Verbesserungen vorschlagen:
    a) übergibt' den bArray-Parameter an den CSave<void*>-Ctor besser per Wert (bool sind nicht so groß, daß du dort const Reference benötigst) und evt. mit Defaultwert.
    b) Bau statt eines CSafe<void*> lieber eine partielle Spezialisierung template<typename T> CSafe<T*> auf.
    c) du könntest auch noch die Vector-Operatoren (* und ->) überladen.
    d) ich würde den CSafeBase-Copy-Ctor und Zuweisungsoperator lieber protected setzen und in CSafe eine eigene Variante definieren.



  • Danke 🙂

    a. Versteh ich nicht?
    b. Gemacht
    c. Gemacht.
    d. Das ist mir zu aufwendig. ich brauche die Klasse hauptsächlich für lokale Funktion, welche am Anfang verschiedene WinAPI-Handels erstellen... Da brauche ich die Zuweisung einfach nicht 🙂



  • a habe ich jetzt verstanden. ich lasse es aber so wie vorher, ab er mit defaultwert 🙂



  • Socker schrieb:

    ist dies so OK oder seht ihr Probleme?

    Nun ja; Es übersetzt nicht, weil SC_HANDLE und 'CloseServiceHandle( SC_HANDLE )' nicht definiert sind. Davon abgesehen kann man keinen 'allgemeinen Smart-Pointer' für z.B. ein int anlegen.

    Warum nicht einfach die sehr schönen und praxis-erprobten Smart-Pointer von boost verwenden.

    Dort kann man auch ein CloseServiceHandle mit einbauen. Etwa so:

    #include <boost/shared_ptr.hpp>
    SC_HANDLE getHandleIrgendwoher();
    typedef /*implementation depended*/ DEREF_SC_HANDLE; // bei windows-HANDLE wäre das z.B. void
        // ...
        boost::shared_ptr< DEREF_SC_HANDLE> hnd( getHandleIrgendwoher(), &CloseServiceHandle );
        // Zugriff über hnd.get()
    

    bei Löschen der letzten Kopie von 'hnd' wird CloseServiceHandle gerufen.

    Gruß
    Werner



  • SC_HANDLE ist von der WindowsTreiberProgrammierung 🙂

    Davon abgesehen kann man keinen 'allgemeinen Smart-Pointer' für z.B. ein int anlegen.

    Wollte ich ja gar nicht. Eigentlich nur für Windows-Handles und für mit new oder new[] allokierte Speicherbreiche

    Boost kenne ich nicht, wobei

    boost::shared_ptr< DEREF_SC_HANDLE> hnd( getHandleIrgendwoher(), &CloseServiceHandle );
    

    mir schon zu lang ist 🙂

    Safe<SC_HANDLE> Manager(getHandleIrgendwoher());
    

    ist doch viel schöner?



  • Socker schrieb:

    a. Versteh ich nicht?

    kurz: "CSafe(void* val,const bool& isarray)" ist Overkill - für eingebaute Typen ist "CSafe(void* val,bool isarray)" praktischer.

    @WinAPI-Handles: Da solltest du eventuell auf eine Bibliothek wie MFC umsteigen, damit hättest du für jeden Handle-Typ eine passende Wrapper-Klasse.
    (außerdem sind afaik die meisten HANDLE-Typen nur typedef's auf long, also kannst du deine CSafe-Klasse nicht getrennt für (z.B.) HWND und HDC spezialisieren)



  • nee, geht leider net. Bei der Treiberprogrammierung darf man das leider net 😞



  • Socker schrieb:

    SC_HANDLE ist von der WindowsTreiberProgrammierung 🙂

    Davon abgesehen kann man keinen 'allgemeinen Smart-Pointer' für z.B. ein int anlegen.

    Wollte ich ja gar nicht. Eigentlich nur für Windows-Handles und für mit new oder new[] allokierte Speicherbreiche

    Klaro! hinter new steht doch immer ein Typ - z.B. int oder halt sowas wie MyClass. Und mit Deinem Code kannst Du kein

    CSafe< MyClass > p( new MyClass ); // compiliert nicht
    

    schreiben, da es keine allgemeine Implementierung gibt. Die Variante mit void* ist nicht typsicher und bringt Unsicherheiten.

    Socker schrieb:

    Boost kenne ich nicht,

    was nicht ist, kann ja werden 😉 . C++ machen und boost nicht kennen ist - wie soll ich sagen - ist einfach indiskutabel; da fehlt einfach was.

    Socker schrieb:

    wobei

    boost::shared_ptr< DEREF_SC_HANDLE> hnd( getHandleIrgendwoher(), &CloseServiceHandle );
    

    mir schon zu lang ist 🙂

    .. kürzer als Deine Klasse 😉

    Gruß
    Weerner



  • @Werner:

    class C
    	{
    
    	};
    	CSafe<C*> T(new C);
    
    //mit...
    
    template<class T> class CSafe<T*> : public CSafeBase<T*>
    {
    private:
    	bool				m_bArray;
    
    public:
    						CSafe(T* pType, const bool& bArray=false) : CSafeBase(pType)
    	{
    		m_bArray=bArray;
    	}
    
    						~CSafe()
    	{
    		if(m_Type)
    		{
    			if(m_bArray)
    			{
    				delete[] m_Type;
    			}
    			else
    			{
    				delete m_Type;
    			}
    		}
    	}
    };
    

    Anyway, boost werde ich mir dann mal zu Gemüte führen 🙂


Anmelden zum Antworten