wird alles richtig gelöscht?



  • Ich weiß, ich stelle viele Fragen, aber nun glaube ich endlich, nach langem üben mit Zeigern, std::list und Klassen (abstrakte klassen verstehe ich noch nicht ganz), ein schönes Design hin bekommen zu haben! Ich führe einfach eine "liste" über meine unterklassen die ich erstellt habe, und wenn ich updaten will, dann werden meine ganzen unterklassen up gedatet. Dabei benutze ich eine for Schleife, wo ich alle meine Unterklassen durch gehe und deren Update() Methode aufrufe. Meine Hauptklasse ist dabei eine abstrakte klasse, und dient nur als Manager:

    Die Haupt Klasse:

    class Owner
    {
    public:
    	Owner() { }
    
    	virtual ~Owner() 
    	{ 
    		for(list<Owner*>::iterator i = ListChild.begin();i != ListChild.end(); i++ )
    		{
    			(*i)->Release();
    		}
    	    ListChild.clear();
    	}
    
    	virtual void Update()
    	{
    		for(list<Owner*>::iterator i = ListChild.begin(); i != ListChild.end(); i++)
    		{
    		  (*i)->Update();
    		}
        }
    
    	virtual void Release() { }
    
    	void AddChild(Owner* child)
    	{
    		ListChild.push_back(child);
        }
    
    protected:
    	list<Owner*> ListChild;
    };
    

    Meine Schöne unterklasse:

    class NiceChild: public Owner
    {
    public:
    	NiceChild() { }
    	~NiceChild() { }
    
    	void Update()
    	{
    		MessageBox(NULL, "Ich bin schön!", "Info", NULL);
    	}
    	void Release()
    	{
    		MessageBox(NULL, "nicht mehr schön!", "Info", NULL);
    		delete this; 
    	}
    };
    

    Und meine Böse klasse:

    class BadChild: public Owner
    {
    public:
    	BadChild() { }
    	~BadChild() { }
    
    	void Update()
    	{
    		MessageBox(NULL, "Ich bin Böse!", "Info", NULL);
    	}
    	void Release()
    	{
    		MessageBox(NULL, "Nicht mehr Böse!", "Info", NULL);
    		delete this; 
    	}
    };
    

    Wenn ich das ganze nun benutze:

    Owner* OWN = new Owner;
    	NiceChild* NC1 = new NiceChild;
    	NiceChild* NC2 = new NiceChild;
    	BadChild* BC1 = new BadChild;
    	BadChild* BC2 = new BadChild;
    	OWN->AddChild(NC1);
    	OWN->AddChild(NC2);
    	OWN->AddChild(BC1);
    	OWN->AddChild(BC2);
    
    	OWN->Update();
    
    	delete OWN;
    

    Funktioniert alles wunderbar, es tauchen keine fehler auf, und alle Messageboxes werden ausgeführt, insgesammt 8 mal. Nun frage ich mich aber, ob auch alles richtig gelöscht wird? Gibt es dort vieleicht noch andere ausbesserungsmöglichkeiten?



  • Naja statt "virtual void Release()" verwendet man normalerweise einfach einen virtuellen dtor. Vor allem finde ich die Asymmetrie schlecht: Owner muss über den dtor gelöscht werden (da Owner::Release nix tut), die von Owner abgeleiteten Klassen werden aber über Release gelöscht. Wenn du nun folgendes machst...

    Owner* OWN = new Owner;
    
    NiceChild* OC1 = new Owner;
    OWN->AddChild(OC1);
    
    OWN->Update();
    
    delete OWN;
    

    ...hast du ein schönes Memory-Leak.

    ----

    Und statt manuell löschen kann (sollte) man smart pointer oder pointer container verwenden. Dadurch fallen etliche Zeilen Code weg, und man kann kaum noch was übersehen oder sonstwie unabsichtlich falsch machen.



  • Also, wenn ich dich richtig verstanden habe, muss ich das so machen:

    class Owner
    {
    public:
    	Owner() { }
    
    	virtual ~Owner() 
    	{ 
    		for(list<Owner*>::iterator i = ListChild.begin();i != ListChild.end(); i++ )
    		{
    			//(*i)-> ???;
    			delete (*i);
    		}
    	    ListChild.clear();
    	}
    
    	virtual void Update()
    	{
    		for(list<Owner*>::iterator i = ListChild.begin(); i != ListChild.end(); i++)
    		{
    		  (*i)->Update();
    		}
        }
    
    	void AddChild(Owner* child)
    	{
    		ListChild.push_back(child);
        }
    
    protected:
    	list<Owner*> ListChild;
    };
    

    Der destructor der Childs werden ausgeführt.



  • Code-Walker schrieb:

    Also, wenn ich dich richtig verstanden habe, muss ich das so machen:

    Öffentliche Vererbung sollte immer "ist ein" bedeuten... NiceChild ist ein Owner?

    Über das Thema Grundlagen sowie Design hatte ich ja schon einmal etwas gesagt.

    cu André



  • Ich versuche mich ja grade mit den Grundlagen von OOP mehr vertraut zu machen!



  • Code-Walker schrieb:

    Ich versuche mich ja grade mit den Grundlagen von OOP mehr vertraut zu machen!

    Mir ist aber deine Intention noch nicht klar. Bzw. erschließt sich mir noch nicht ganz der Sinn und vor allem nicht deine Benennungen. Trennen wir das Problem erstmal auf, soweit wie ich es verstanden habe:

    Du willst irgendwelche Komponenten haben (wenn ich deine Engineüberlegungen zusätzlich mit hereinnehme), die ihrerseits wieder untergeordnete Elemente enthalten können - liege ich mit dieser Einschätzung richtig? (Thema: Entwurfsmuster, konkret Kompositum).

    Wenn ja, schau dir mal den Beispielcode im zweiten Link an.

    cu André



  • sieht soweit korrekt aus. das "delete (*i);" passt auch, genau so macht man das (wenn man keine smart-pointer verwendet).

    mach dich aber sobalb wie möglich mit smart pointern (z.b. boost::shared_ptr bzw. tr1::shared_ptr) vertraut, die sind wirklich praktisch. ersparen viel ärger und kopfzerbrechen wegen dingen um die man sich nicht wirklich selbst kümmern muss (und sollte).



  • Sowas hier meine ich:

    http://upload.wikimedia.org/wikipedia/de/2/2d/Kompositum_Objekte.png

    Leider ist das bei mir noch ein klein wenig komplitzierter. Manche von den classen sollen singletons sein, zum beispiel die oberste und die zwei unteren sind singletons. Manche von den letzten müssen wiederum auch singletons sein. Dann muss einer der mttleren auf die nachbarn zugreifen können, und die unteren müssen auf manche seine nachbarn zugreifen können ...



  • Du solltest aufpassen, wenn du so viele Abhängigkeiten hast. Es kann schnell mal passieren, dass man sich nicht mehr im Klaren über die Rechte an den Klassen ist oder sonst die Übersicht verliert. Ausserdem kann es gut sein, dass sich die Kompilierzeit erhöht.

    Auch die vielen Singletons, die du da verwendest, lassen mich etwas am Design zweifeln...



  • Nunja, eigentlich sind die singletos ganz gut. Wenn ich eine camera habe, kannich ja schlecht zwei kameras haben, den auch im spiel hat man keine gespaltene persöhnlichkeit. Und ich brauche ja auch nur ein device, und auch nur ein Fenster.



  • Code-Walker schrieb:

    Nunja, eigentlich sind die singletos ganz gut. Wenn ich eine camera habe, kannich ja schlecht zwei kameras haben, den auch im spiel hat man keine gespaltene persöhnlichkeit. Und ich brauche ja auch nur ein device, und auch nur ein Fenster.

    Du kannst ohne weiteres auch mehrere Kameras haben. Mal an Splittscreen gedacht? Oder eine "virtuelle" Kamera, um etwas zu simulieren?
    Fenster sind mehrere auch gut möglich, sowie auch mehrere Devices. (OK. Devices sind mehrere eher selten der Fall, aber das andere macht wirklich Sinn.)



  • EDITED::

    Sry, hab net nachgedaht was ich schreibe, hab fieber. Was ich meine, ich habe jetzt alles woeit hinbekommen, nur muss wenn ich jetzt ein Mesh lade, dieser wissen, wo die camera ist. Das heißt die child mussen miteinander komunizieren können. Mir würde da nur einfallen, das man sowas wie ein suchdurchlauf macht, aber da muss es doch bestimmt noch bessere möglichkeiten geben?


Anmelden zum Antworten