Key einer map an CTor des Values übergeben, geht das?



  • Ich benutze eine Map um Buchstaben in UTF-32 zu speichern. Wenn ein Buchstabe noch nicht vorhanden ist, soll dieser geladen werden.

    std::map<unsigned long, Character> characters;
    characters[static_cast<unsigned long>('a')].Draw(); // Wenn a noch nicht geladen ist, erst laden, dann zeichnen
    

    Das Problem dabei ist, dass die Character-Klasse ja wissen muss welchen Buchstaben sie laden soll und deswegen der CTor einen Parameter hat. Wie lässt sich das lösen ohne dabei den Umweg über eine Init-Funktion zu gehen?



  • Eine Möglichkeit wäre, dass du dir eine Klasse (z.B.) UTF32Map definierst, die von std::map<unsigned long, Character> erbt. Darin redefinierst du deinen Zugriffs-Operator, operator[].
    In diesem kannst du nachschauen, ob der map bereits definiert ist, und wenn nicht kannst du einen neuen erstellen und einfügen.

    Ansonsten kannst du auch eine statische Zugriffsmethode erstellen, die dir einen Character zurückliefert, und entsprechend bei Nichtexistenz erst einen Character erzeugt und einfügt:
    z.B.

    static Character getCharacter( std::map<unsigned long, Character>& m, unsigned long k )
    

    Grüße
    Franz



  • Okay danke, dann werd ich das so machen.


  • Administrator

    franz schrieb:

    Eine Möglichkeit wäre, dass du dir eine Klasse (z.B.) UTF32Map definierst, die von std::map<unsigned long, Character> erbt. Darin redefinierst du deinen Zugriffs-Operator, operator[].
    In diesem kannst du nachschauen, ob der map bereits definiert ist, und wenn nicht kannst du einen neuen erstellen und einfügen.

    Von den Standardbibliothek Containern, sollte man nicht erben, da sie nicht dazu gedacht sind. Es ist jedenfalls ziemlich fehleranfällig.

    @joomoo,
    Es gibt dafür eine ziemlich einfache Methode von std::map :
    http://www.cplusplus.com/reference/stl/map/insert.html

    std::map<unsigned long, Character> characters;
    characters.insert(
      std::make_pair(
        static_cast<unsigned long>('a'),
        Character('a')
        )
      ).first->Draw();
    

    Grüssli



  • Den static_cast<unsigned long> kann man sich hier sparen, bei integralen Typen existiert eine implizite Konversion.

    Zudem finde ich das Folgende nicht sehr schön, ich persönlich ziehe eine Aufteilung in mehrere Anweisungen vor.

    characters.insert(
      std::make_pair(
        static_cast<unsigned long>('a'),
        Character('a')
        )
      ).first->Draw();
    


  • Dravere schrieb:

    Es gibt dafür eine ziemlich einfache Methode von std::map :
    http://www.cplusplus.com/reference/stl/map/insert.html

    std::map<unsigned long, Character> characters;
    characters.insert(
      std::make_pair(
        static_cast<unsigned long>('a'),
        Character('a')
        )
      ).first->Draw();
    

    Grüssli

    Das Problem hierbei ist, dass jedes mal der Konstruktor aufgerufen wird, oder nicht? Das ist in meinem Fall ziemlich ungünstig, da dann jeder Buchstabe nochmal für ein temporäres Objekt geladen wird.



  • vielleicht suchst du sowas?

    //braucht der benutzer gar nicht zu kennen
    class Character
    {//TODO: da fehlt noch was
    };
    
    //braucht der benutzer gar nicht zu kennen
    Charcter* LoadCharacter(unsigned long ch)
    {
       ifstream in(...
       Character* pch=new//TODO: da fehlt noch was
       return ch;
    }
    
    //braucht der benutzer gar nicht zu kennen
    std::set<unsigned long,Character*> theCharacters;
    
    //braucht der benutzer gar nicht zu kennen
    Charcter* GetCharacter(unsigned long ch)
    {
       Character* pch=theCharacters[ch];
       if(pch==0)
          pch=LoadCharacter(ch);
       return ch;
    }
    
    //das hier mag der benutzer
    void DrawCharacter(unsigned long ch,int x,int y)
    {
       Character* pch=GetCharacter[ch];
       DrawCharacter(ch,x,y);
    }
    
    //braucht der benutzer gar nicht zu kennen
    void DrawCharacter(Character* pch,int x,int y)
    {
       //TODO
    }
    


  • Okay. Und das ganze jetzt noch mit SmartPointern, oder ist das Overkill?



  • joomoo schrieb:

    Okay. Und das ganze jetzt noch mit SmartPointern, oder ist das Overkill?

    wir können dich eh nicht davon abhalten, mal ganz heftig mit SmartPointern zu spielen, oder?



  • volkard schrieb:

    joomoo schrieb:

    Okay. Und das ganze jetzt noch mit SmartPointern, oder ist das Overkill?

    wir können dich eh nicht davon abhalten, mal ganz heftig mit SmartPointern zu spielen, oder?

    Doch, indem ihr mir sagt, warum ich es nicht machen sollte.



  • wenn der benutzer selber LoadCharacter aufrufen darf, sind smart pointers eine überlegung wert. der benutzer ist nämlich schusselig und vergißt, den speicher wieder freizugeben.
    wenn der benutzer die ganzen "//braucht der benutzer gar nicht zu kennen" nicht kennt, sind smart pointers totaler overkill.



  • Ok, danke.


Anmelden zum Antworten