Compilerfehler bei Verwendung von map



  • Vielen Danke für die schnellen Antworten 🙂
    Ich wusste nicht, dass die Werte in der Map sortiert werden.
    Ich würde gerne campers Funktion nehmen, aber wenn ich sie einfach so einfüge, kriege ich gleich den nächsten Fehler ("the function must exactly take one argument") 😞
    Habe bisher noch keine Operatorüberladung gemacht und das was ich zB im WikiBook zur Operatorüberladung lese, sieht eigentlich genauso aus wie das von camper^^

    struct Point {
    	int x;
    	int y;
    	bool operator<(const Point& lhs, const Point& rhs) {
    		return lhs.x < rhs.x || (lhs.x == rhs.x && lhs.y < rhs.y);
    	}
    };
    

    Bezüglich new: In meinem Anwendungsfall wollte ich erst die map per return übergeben, hab das aber schon geändert (ist also tatsächlich unnötig^^ 😃 )



  • Als Memberfunktion ist das Objekt selber "lhs".

    struct Point {
        int x;
        int y;
        bool operator<(const Point& other) {
            return x < other.x || (x == other.x && y < other.y);
        }
    };
    


  • Das hatte ich auch schon versucht (allerdings mit this.x und this.y), aber es kommt auch bei deiner Version immer noch eine Fehlermeldung 😕

    d:\cpp\mingw32\bin\../lib/gcc/mingw32/4.5.2/include/c++/bits/stl_function.h:230:22: error: passing 'const Point' as 'this' argument of 'bool Point::operator<(const Point&)' discards qualifiers

    (Die Compilermeldungen sind momentan für mich das unerfreulichste an C++)



  • Nimm campers Funktion als globale Funktion, also ausserhalb der Klasse.

    Globale Funktionen sind auch was, das man in Java nicht hat, aber in C++ relativ oft verwendet. Hier wäre eine globale Funktion operator< eindeutig besser als eine Memberfunktion.



  • Danke,das funktioniert jetzt 🙂
    Ich nehme an, die Funktion wird dann immer aufgerufen, wenn irgendwo, wo sie bekannt ist, irgendwer 2 Points mit dem entsprechenden Vergleichsoperator vergleicht?
    Wieso funktioniert denn eine Memberfunktion nicht?



  • asdfghjkl schrieb:

    Ich nehme an, die Funktion wird dann immer aufgerufen, wenn irgendwo, wo sie bekannt ist, irgendwer 2 Points mit dem entsprechenden Vergleichsoperator vergleicht?

    Genau. Immer wenn du einen Ausdruck a < b hast, wobei a und b vom Typ Point (oder dazu konvertierbar) sind. Siehe auch das Kapitel Operatorüberladung in deinem C++-Buch oder den entsprechenden Artikel im Magazin.

    asdfghjkl schrieb:

    Wieso funktioniert denn eine Memberfunktion nicht?

    Würde schon funktionieren, aber wäre hier wegen der Symmetrie schlecht. Hier müsste die Memberfunktion allerdings const -qualifiziert sein, da sie das Objekt nicht ändert.



  • asdfghjkl schrieb:

    Wieso funktioniert denn eine Memberfunktion nicht?

    Vielleicht nu, weil ein const fehlte, das const für this.

    bool operator<(const Point& other) const {
    


  • Nochmals Danke 😉
    Mit const funktioniert es tatsächlich auch als Memberfunktion (werde es zwar deinem Ratschlag folgend als globale Funktion nutzen, aber ich wollte halt auch wissen, wies funktioniert 😉 ).
    Mein sehr dünnes Anfängerbuch ist leider nicht besonders ausführlich, deswegen bin ich zu learning-by-doing übergegangen und versuche mir zurechtzusuchen oder -zuprobieren, wenn was nicht klappt 😉

    Eine Frage möchte ich aber noch eben anhängen, weil es für mich als Java Programmierer wirklich schwer nachzuvollziehen ist und ich das auch nach der Lektüre von 3 C++FürJavaProgrammierer-Tutorials nicht genau nachvollziehen kann:
    Wenn ich die als Argument übergebene map befülle mit den Points, die in der Funktion erstellt werden, kann es dann sein, dass die Punkte einfach gelöscht werden oder bleiben die erhalten? Oder werden die sogar kopiert, weil ich nicht Point* speichere?

    void cycle(int maxX, int maxY, int x, int y, map<Point, int>& toFill) {
    	for (int i = maxX; i >= x; i--) {
    		Point p;
    		p.x = i;
    		p.y = y;
    		int numWays = 0;
    		if (p.x < maxX) {
    			Point search;
    			search.x = p.x + 1;
    			search.y = p.y;
    			numWays += (toFill.find(search))->second;
    		}
    		if (p.y < maxY) {
    			Point search;
    			search.x = p.x;
    			search.y = p.y + 1;
    			numWays += (toFill.find(search))->second;
    		}
    
    		toFill.insert(make_pair(p, numWays));
              //Rest weggelassen
           }
    }
    


  • asdfghjkl schrieb:

    deswegen bin ich zu learning-by-doing übergegangen und versuche mir zurechtzusuchen oder -zuprobieren, wenn was nicht klappt 😉

    C++ ist für Learning-By-Doing sehr ungeeignet. Besonders wenn du von einer oberflächlich ähnlichen, aber eigentlich komplett verschiedenen Sprache wie Java kommst. Klar, die prozeduralen Dinge wie Schleifen, etc. sind gleich, aber spätestens bei OOP fangen die grossen Unterschiede an. Wenn nicht schon früher (Deklaration, Definition, Zeiger, Referenzen, ...).

    asdfghjkl schrieb:

    Oder werden die sogar kopiert, weil ich nicht Point* speichere?

    Genau das.



  • Ich habs so immerhin schon einmal geschafft ein kleines Geschicklichkeitsspiel mit Allegro zu schreiben mit makefile und allem (bin heute noch erstaunt darüber, dass es so gut geklappt hat^^ :D) Aber nach einem Neu-aufsetzen des Betriebssystems schaffe ich es nicht mehr Allegro einzubinden, obwohl ich alles mache wie vorher.. 🙄 Deswegen hatte ich mich bis vor kurzem von dem Gedanken verabschiedet C++ zu lernen^^ Und da ich Allegro sowieso nicht für so wichtig hielt, hab ich auch keinen Thread hier im Forum aufgemacht. Aber jetzt ist mein Interesse doch wieder erwacht und vllt kaufe ich mir bald ein richtiges C++ Buch (gibt es eigentlich schon welche, die Teile der neuen Spezifikation abdecken?)

    Nochmal zur map: Wenn ich jetzt soetwas machen würde:

    map<Point*, int> m;
    Point p;
    m.insert(make_pair(&p, 1));
    

    Dann würde doch die Gefahr bestehen, dass die Objekte gelöscht werden, oder?



  • Du speicherst die Adresse eines Stackobjektes, das automatisch gelöscht wird, sobald der scope verlassen wird. Nicht gut, da man später vielleicht noch darauf zugreifen will. Es sollte allerdings mit new funktionieren, aber die adresse sollte in einem smartpointer gespeichert werden, die ja automatisch löschen. Übrigends würde die map wenn du mit pointern arbeitest die adresse als key erwarten, falls du nicht eine alternative vergleichsmöglichkeit übergibst.



  • Danke, dann hab ich das Prinzip verstanden 🙂 Hab heute viel gelernt, es ist fast wie im Java-forum.de hier^^ 😉



  • Aber, wie ich hier so durchlese, es ist doch hoffentlich klar, dass std::map<T, T, T>::find() den iterator std::map<T, T, T>::end() zurückliefert, wenn der key nicht gefunden wurde? Und dass man dann nicht darauf zugreifen darf? Normalerweise muss man die rückgabe prüfen, da man sie nur nutzen darf, wenn iterator != myMap.end() ist, gemäß http://www.cplusplus.com/reference/stl/map/



  • asdfghjkl schrieb:

    Aber nach einem Neu-aufsetzen des Betriebssystems schaffe ich es nicht mehr Allegro einzubinden, obwohl ich alles mache wie vorher.. 🙄 Deswegen hatte ich mich bis vor kurzem von dem Gedanken verabschiedet C++ zu lernen^^

    Allegro ist ja nicht mal C++, sondern C, und dann erst noch hässliches (zumindest was ich bisher davon gesehen habe).

    Wenn du ein schönes Multimedia-Framework für C++ suchst, nimm SFML 🙂



  • es ist doch hoffentlich klar, dass std::map<T, T, T>::find() den iterator std::map<T, T, T>::end() zurückliefert, wenn der key nicht gefunden wurde?

    Es ist vom Aufbau der Funktion garantiert, dass der zu suchende Punkt bereits eingefügt wurde 😉

    Wenn du ein schönes Multimedia-Framework für C++ suchst, nimm SFML 🙂

    Danke für den Hinweis 🙂 Allegro war die Empfehlung in einem Buch über Spieleprogrammierung, in das ich mal kurz reinschaute. Die "Installation" ist echt ein Krampf...
    Bei SFML gefällt mir besonders die OpenGL Schnittstelle 🙂


Anmelden zum Antworten