Destruktor wird nicht aufgerufen?!



  • Hallo,

    ich hab folgende zwei Klassen:

    ///////////////////////////////////////////////////////////
    // omeSingleton ///////////////////////////////////////////
    ///////////////////////////////////////////////////////////
    template<typename T>
    class omeSingleton {
    private:
    	static T*	m_pSingleton;	
    public:
    	omeSingleton() {
    		assert(!m_pSingleton);
    		m_pSingleton = static_cast<T*>(this);	
    	}
    	virtual ~omeSingleton() {
    		assert(m_pSingleton);
    		m_pSingleton = 0;
    	}
    public:
    	static inline void Create() {
    		if (m_pSingleton)
    			return;
    		new T();
    	}
    	static inline T& GetSingleton() {
    		assert(m_pSingleton);
    		return *m_pSingleton;
    	}
    	static inline T* GetSingletonPtr() {
    		assert(m_pSingleton);
    		return m_pSingleton;
    	}
    	static inline void Destroy() {
    		if (m_pSingleton) {
    			delete m_pSingleton;
    		}
    		m_pSingleton = 0;
    	}
    };
    
    template<typename T> T* omeSingleton<T>::m_pSingleton = 0;
    
    ///////////////////////////////////////////////////////////
    // omeKernel //////////////////////////////////////////////
    ///////////////////////////////////////////////////////////
    class omeKernel : public omeSingleton<omeKernel> {
    protected:
    	std::list<omeSmartPointer<omeITask> >	m_taskList;
    	std::list<omeSmartPointer<omeITask> >	m_pausedTaskList;
    public:
    	omeKernel();
    	~omeKernel();
    
    	int Execute();
    
    	bool AddTask( omeSmartPointer<omeITask>& t );
    	void SuspendTask( omeSmartPointer<omeITask>& t );
    	void ResumeTask( omeSmartPointer<omeITask>& t );
    	void RemoveTask( omeSmartPointer<omeITask>& t );
    	void KillAllTasks();
    };
    

    Mein Hauptprogramm sieht dann (stark gekürzt) so aus:

    /* the application's run function */
    void TestGame::Run( int argc, char* argv[] ) {
       // create singletons
       omeSettingsManager::Create();
       omeKernel::Create();
       omeRessourceManager::Create();
       omeObjectManager::Create();
       omeSoundManager::Create();
       // ...
       // clean up singletons
       omeSoundManager::Destroy();
       omeObjectManager::Destroy();
       omeRessourceManager::Destroy();
       omeKernel::Destroy();
       omeSettingsManager::Destroy();
    }
    

    Jetzt sollte doch sowohl der Konstruktor der Basis-Klasse omeSingleton als auch der Konstruktor der abgeleiteten Klasse omeKernel aufgerufen werden, oder? Komischerweise wird aber der Destruktor von omeKernel nicht aufgerufen.
    Woran kann das liegen?

    Mfg, smasher1985



  • static inline void Create() { 
       if (m_pSingleton) 
          return; 
       new T(); 
    }
    

    da zeigt nix aufs neue T()



  • aber hier:

    m_pSingleton = static_cast<T*>(this);
    

    oder etwa nicht?

    Mfg, smasher1985



  • sorry, hab mir den code nicht ganz angesehen
    bist du mit diesem minimalbeispiel einverstanden:

    template <class T>
    class base {
    	static T *ptr;
    
    public:
    	base () {
    		if (!ptr) ptr = static_cast<T*>(this);
    	}
    	virtual ~base () {
    		cout << "base::~base\n";
    		assert(ptr);
    		ptr = 0;
    	}
    
    	static void create () {
    		if (ptr) return;
    		new T();
    	}
    
    	static void destroy () {
    		delete ptr;
    	}
    };
    template <class T>
    T *base<T>::ptr;
    
    class test : public base<test> {
    public:
    	~test () { cout << "test::~test\n"; }
    };
    
    int main () {
    	test::create();
    	test::destroy();
    }
    

    das funktioniert bei mir.



  • jo, bin einverstanden 😉
    funktioniert bei mir auch - aber eben nur im Minimalbeispiel. Wo ist der Unterschied zu meiner Implementierung?

    Mfg, smasher1985



  • was tatsächlich ein problem sein kann ist diese zeile mit dem static_cast.
    vergiss nicht: im konstruktor von omeSingleton ist omeKernel noch nicht fertig konstruiert. was spricht gegen

    void Create () {
      if (!ptr) ptr = new T();
    }
    


  • smasher: kannst du statt dem ome vor jeder Klasse lieber ein Namespace verwenden? 😮 😮



  • Hab das jetzt geändert. Funktioniert einwandfrei, bewirkt aber genau das gleiche - kein Destruktoraufruf!!!

    Übrigens hab ich gerade noch rausgefunden, dass auch der Konstruktor der Basisklasse nicht aufgerufen wird. Ich hatte vergessen, das vorher zu überprüfen 🙄 also kommt es bei mir zu gar keinem Konstruktoraufruf!

    Mfg, smasher1985



  • De- oder Konstruktor?
    ruf den destruktor in der destroy funktion einmal explizit auf.
    also mit m_pSingleton->~T();
    der statische typ ist nun einmal omeKernel und von daher sollte auch omeKernel::~omeKernel aufgerufen werden;
    gibt einfach mal noch mehr code


Anmelden zum Antworten