Objekte nur einmal erzeugen



  • Mahlzeit!

    ich habe ein bißchen blödes Problem. Also ich habe eine Klasse, die verschiedene Sachen von der Festplatte lädt (z.B. Texturen).
    Nur will ich die Textur nur genau einmal laden, danach nur noch die bereits geladene Textur liefern. Im Moment sieht es in etwa so aus:

    class Loader {
       map<string, weak_ptr<Texture> m_textures;
    
       shared_ptr<Texture> loadTexture(const std::string& name);
    };
    
    // Benutzung:
    shared_ptr<Texture> myTex = loader->loadTexture("test.png"); // Erstes Mal, dass "test.png" angefordert wird => von Platte laden. 
    // Nach dem Aufruf ist ein weak_ptr auf die Texture in Loader::m_textures gespeichert
    
    shared_ptr<Texture> myTex2 = loader->loadTexture("test.png"); // Lädt nichts von der Platte. Liefert nur shared_ptr auf die bereits geladene Textur
    

    Sollte klar sein. Es gibt nur ein Problem: Manchmal will man feinere Kontrolle über das initiale Laden. Beim 1. Laden will man z.B. gerne angeben ob MipMaps erstellt werden oder auf welche Größe die Textur skaliert werden soll, also z.B sowas:

    shared_ptr<Texture> myTex = loader->loadTexture("test.png", 640, 480, 3);
    

    Das Problem ist nur, dass die zusätzlichen Parameter (640, 480, etc) bei allen weiteren load Aufrufen nicht mehr wichtig sind, ich sie aber doch immer angeben muss.

    Hat irgendwer eine Idee, wie man das etwas besser machen könnte?



  • Du kannst doch einfach eine loadTexture() -Überladung ohne Zusatzparameter anbieten, oder? Du musst dann sinnvolle Defaultwerte festlegen. Alternativ schreibst du dir eine Methode shared_ptr<Texture> getTexture(const std::string& name) , die nie neu lädt, d.h. bei Nicht-Vorhandensein einen Nullzeiger zurückgibt oder eine Exception wirft.

    Bei meinem (generischen) Ressourcen-System verwende ich Klassen, die angeben, wie ein Objekt geladen wird. Ich nenne sie "Keys", da sie gleichzeitig die Schlüssel in der Map sind. Sie bieten einen operator< für Strict Weak Ordering an. Zum Beispiel könntest du bei dir im operator< nur die Strings vergleichen (da es sich ja um die gleiche Textur handelt, falls der String gleich ist). Damit kannst du Keys auf verschiedene Weise erstellen, und je nachdem sind sie dann äquivalent im Bezug auf das Sortierkriterium.

    Angewandt sähe das so aus:

    TextureKey key("test.png", 640, 480, 3);
    shared_ptr<Texture> myTex = loader->loadTexture(key);
    


  • Nexus schrieb:

    Du kannst doch einfach eine loadTexture() -Überladung ohne Zusatzparameter anbieten, oder? Du musst dann sinnvolle Defaultwerte festlegen.

    Klar. Aber das ergibt nicht viel Sinn. Ich kann ja an hunderten Stellen loadTexture() aufrufen und alle sind gleichwertig. Dh. bei keinem Auruf weiß ich, ob die Textur nun wirklich geladen wird.
    Wenn ich aber nun einmal loadTexture() mit Parametern aufruf und alle weiteren Male ohne Parameter, dann erfordert das ja Wissen, ob sie geladen ist.



  • Ja klar. Aber bei jedem Mal, wo du die Zusatzparameter nicht angibst, gehst du eigentlich davon aus, dass sie schon mal angegeben wurden. Daher musst du sie streng genommen immer angeben, um ganz sicher zu sein.

    Oder du speicherst anfänglich eine Zuordnung von std::string zu diesen Parametern irgendwo ab. Oder schiebst Keys umher. Oder...



  • Dir ist aber schon klar, dass bei so einem Aufruf

    {
      shared_ptr<Texture> myTex = loader->loadTexture("test.png"); // Erstes Mal, dass "test.png" angefordert wird => von Platte laden.
    }
    // hier ist das Bild wieder weg!
    

    der Speicher nach der "}"-Klammer wieder freigegeben wird (der weak_ptr also ungültig ist), und du das Bild erneut laden musst? Dann müssten natürlich auch bei jedem Aufruf alle benötigten Parameter mitgegeben werden.



  • Ohne den Thread ganz gelesen zu haben, klingt das nach einem Singleton-Muster, das helfen könnte.
    http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)#Implementierung_in_C.2B.2B



  • Jay1980 schrieb:

    Ohne den Thread ganz gelesen zu haben, klingt das nach einem Singleton-Muster, das helfen könnte.
    http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)#Implementierung_in_C.2B.2B

    Der Beitrag ist auf so vielen Ebenen fail...


Log in to reply