Methode benimmt sich merkwürdig bei Aufruf im Konstruktor einer anderen Klasse



  • Hallo liebe Community,

    entschuligt den blöden Titel.

    ich habe folgendes Problem:

    Ich habe einen Wrapper um eine std::map, die pairs aus Zeigern einer Basisklasse und ints auf strings abbildet

    std::map<std::string,pair<AbstrakteKarte*,int> >
    

    Es geht um ein Kartenspiel (Dominion,falls das jemand kennt) und die Wrapperklasse benutze ich als Kartenvorrat.
    Um Karten zu entnehmen gibt es folgende methode:

    AbstrakteKarte* Source::karteEntnehmen (std::string name)
    {
    	if(karteVorhanden(name))
    	{
    		elemente[name].second -= 1;
    		return elemente[name].first;
    	}
    	else
    	{
    		return 0;
    	}
    }
    

    Die funktion "karteVorhanden" sieht so aus:

    bool Source::karteVorhanden(std::string name)
    {
    	return elemente[name].second > 0;
    }
    

    diese Methode wird im Konstruktor einer anderen Klasse aufgerufen, die auf eine globale variable ("Karten") zugreift.
    Die Methode funktioniert "normalerweise" gut, aufgerufen im Konstruktor tritt immer der else-zweig ein.

    Stapel::Stapel()
    {	
    	elemente.resize(10);
    	for(int i = 0; i < 10;i++)
    	{
    		if(i < 7)
    		{
    			elemente.at(i) = karten.karteEntnehmen("Kupfer");
    		}
    		else
    		{
    			elemente.at(i) = karten.karteEntnehmen("Anwesen");
    		}
    	}
    }
    

    elemente ist ein Vektor, der AbstrakteKarte* pointer speichert.
    Momentan werden aber nur 10 Nuller gespeichert.
    Vielleicht ist das auch total Banal, aber ich kann mir den Fehler nicht erklären...
    achja, folgendes legt das richtige Verhalten an den Tag:

    int main()
    {
    	AbstrakteKarte* ptr = karten.karteEntnehmen("Kupfer");
    	cout << ptr->getName() << endl;    // nur zur Veranschaulichung
    }
    

    Danke schonmal für eure Hilfe.



  • Welchen Typ hat elemente? Ist es eine std::map? In dem Fall vermute ich, das at nicht das macht, was du dir erhoffst!

    Da wäre dann ein std::vector eher das gesuchte.

    Ansonsten kannst du noch Debug-Ausgaben hinzufügen.



  • kartevorhanden sollte mit Iteratoren arbeiten, da mit operator[] IMMER ein Eintrag in der map angelegt wird, falls noch keiner existiert.

    bool kartevorhanden(std:string const& name)
    {
      return elemente.find(name) != elemente.end();
    }
    

    oder gleich

    AbstrakteKarte* Source::karteEntnehmen (std::string const& name)
    {
      auto pos = elemente.find(name);
      if(pos == elemente.end())
      {
        return 0;
      }
    
      --(pos->second);
      return pos->first;
    }
    

    Zu deinem eigentlichen Problem: Benutze doch einfach den Debugger und schau, warum kartevorhanden evtl. false ergibt.



  • ahja gut, vielen Dank für den Tipp mit der map.

    Ich bin leider nicht wirklich vertraut mit debugging, aber ich werde mich damit auseinandersetzen.
    Ich versuche es mal, wenn ich nicht weiterkomme, frage ich nochmal nach.

    Vielen Dank!



  • Hyde++ schrieb:

    Ich bin leider nicht wirklich vertraut mit debugging, aber ich werde mich damit auseinandersetzen.

    Dann wirds aber Zeit! Um ehrlich zu sein, halte ich ein Projekt wie eine Dominion-Umsetzung für relativ komplex, wenn man es einigermaßen gut machen möchte. Wenn dann solche basics wie debugging und die Kenntnis von map::operator[] fehlen, halte ich es für recht gewagt, sich da ranzusetzen.



  • Ich gebe dir recht, und möchte auch nicht völlig naiv erscheinen.
    Ich wollte mich an ein (vielleicht zu, das kann ich nicht sagen) großes Projekt wagen, da ich gut lerne, wenn ich etwas nicht verstehe und mir lange den Kopf zerbrechen muss, um etwas zu lösen.
    Ich habe nicht den Anspruch, dass es sehr gut werden muss, aber ich möchte es wenigstens versuchen.
    Wenn ich damit scheitere oder an einem Punkt wieder völlig von vorne anfangen muss, ist das blöd, aber dann habe ich hoffentlich wenigstens etwas dabei gelernt.

    Danke für die Anregungen,
    grüße


Anmelden zum Antworten