<map> mit Klassen ohne Default Konstruktor



  • Hallo,

    warum kann man keine Instanz einer Klasse, die keinen Default Konstruktor hat, in eine Map einfügen??? Das fogende Programm liefert mir zumindest immer den Compiler Gehler:
    g++ -c -o main.o main.cpp
    /usr/include/c++/3.2/bits/stl_map.h: In member function \_Tp& std::map<_Key, \_Tp, \_Compare, \_Alloc>::operator[](const \_Key&) [with \_Key = int, \_Tp = Base, \_Compare = std::less<int>, \_Alloc = std::allocator<std::pair<const int, Base> >]': main.cpp:23: instantiated from here /usr/include/c++/3.2/bits/stl_map.h:225: no matching function for call toBase
    ::Base()'
    main.cpp:5: candidates are: Base::Base(const Base&)
    main.cpp:7: Base::Base(int)

    #include <iostream>
    #include <map>
    
    class Base
    {
      public:
        Base(int v) : value(v) {};
    
        virtual~Base() {};
    
        int get_value() const { return value; };
    
      private:
        int value;
    };
    
    int main (int args, char **argv)
    {
    	typedef std::map<int, Base> map_t;
    	map_t my_map;
    
    	my_map[1] = Base(10);
    }
    

    Wie kann man das Problem beheben? (Default Konstruktor in die Klasse ist für mich keine Lösung)

    Danke schon mal,

    Chris



  • Dann musst du insert statt operator [] benutzen. operator[] erstellt nämlich ein Default-Objekt wenn das Objekt noch nicht in der Map existiert.



  • Ja, so klappt es:

    ...
    
    my_map.insert(map_t::value_type(1, Base(10));
    
    ...
    

    Jetzt habe ich aber ein weiters Problem. Wenn ich für einen Schlüsselwert erneut "insert" aufrufe, wird die alte Instanz nicht von der neuen überschrieben. Ist das so gewollt? Gibt es eine elegantere Lösung als einfach vorher ein "erase" aufzurufen?

    Gruß Chris



  • Guck mal den Rückgabewert von insert an. Der gibt ein std::pair zurück wo drinsteht ob eingefügt einen Iterator. Mit diesem Iterator kannst du es einfügen.





  • Wenn das Objekt bereits existiert, kannst du ja op[] verwenden.



  • Dr. Prof schrieb:

    Wenn das Objekt bereits existiert, kannst du ja op[] verwenden.

    Ne das geht nicht. Dann müsste ja wieder ein Default-Konstruktor zur Verfügung stehen. Das wird ja zur Compile-Zeit schon geprüft.



  • Da mußt du notfalls selber prüfen, ob das Element schon drin war (per find()) und je nach Ergebnis entweder einfügen oder überschreiben.

    (btw, insert() gibt ein pair<iterator,bool> zurück - wenn das zweite Element false ist, war der Wert schon da (und das erste Element enthaält einen Iterator darauf)


Anmelden zum Antworten