In klasse auf std::liste zugreifen



  • Erstmal versucht du, das Inventar von "this" zu schreiben, und nicht das eines der vector-Elemente.

    Zweitens solltest du mal dein Design überdenken. Player::write() in der Form, wie du sie hier eingesetzt hast, ist unsinnig. Entweder du änderst sie so, daß sie nur die Daten von this ausgibt oder du machst eine statische Methode (oder gar eine globale Funktion) draus.

    Und drittens ist os<<(*iterInventory)->write(os) sinnlos - write() schreibt schon selbst und gibt den fertig geschriebenen Stream zurück, den mußt du nicht nochmal auf sich selbst ausgeben.

    PS: Und viertens hast du ein gewaltiges Speicherleck in deinem Hauptprogramm - du legst kiloweise Player-Objekte per new an und lässt sie dann auf dem Heap verrotten.



  • CStoll schrieb:

    Erstmal versucht du, das Inventar von "this" zu schreiben, und nicht das eines der vector-Elemente.

    Zweitens solltest du mal dein Design überdenken. Player::write() in der Form, wie du sie hier eingesetzt hast, ist unsinnig. Entweder du änderst sie so, daß sie nur die Daten von this ausgibt oder du machst eine statische Methode (oder gar eine globale Funktion) draus.

    Und drittens ist os<<(*iterInventory)->write(os) sinnlos - write() schreibt schon selbst und gibt den fertig geschriebenen Stream zurück, den mußt du nicht nochmal auf sich selbst ausgeben.

    PS: Und viertens hast du ein gewaltiges Speicherleck in deinem Hauptprogramm - du legst kiloweise Player-Objekte per new an und lässt sie dann auf dem Heap verrotten.

    ok ich hab die mit delete gelöscht hab nur net das ganze main geschrieben..
    das os<<(*iterInventory)->write(os) ruft die virtual funktion von Item auf die dann in der unterklasse definiert ist mit :

    virtual ostream &write(ostream&os) 
        { 
            os<<getFoodName()<<"\n" 
                <<getFeedingValue()<<"\n" 
                <<getFoodweight()<<"\n"; 
            return os; 
    
        }
    

    aber das problem liegt das in inventory nichts drin steht 😕 bin immoment bissl confused 😉



  • Erstens: Hast du die beiden delete[]-Zeilen jetzt ergänzt? Wenn ja, die sind (a) falsch (an der Stelle ist das [] zu viel) und (b) zu spät, weil sie nur die zuletzt angelegten Objekte wieder löschen. (und (c) ist es in C++ nicht erforderlich, alle Objekte auf dem Heap anzulegen - wenn du den Stack nutzt, sparst du dir eine Menge Ärger mit der Speicherverwaltung).

    Zweitens: Deine virtuelle Funktion kümmert sich doch schon selber um die Ausgaben. Der Rückgabewert ist der beschriebene Ausgabestrom - und den auf sich selbst zu schreiben macht wenig Sinn.

    Und drittens: An der Aktion sind zwei(+x) Player-Objekte beteiligt - das Objekt hinter pPlayer und das/die Elemente in deinem Vector. In den Vector-Elementen hast du das Inventar umsortiert, aber in der write()-Methode gibst du das Inventar von pPlayer aus (und der wurde beim push_back() kopiert und hat von den Aktionen im vector nichts mitbekommen).
    (wie ich schon sagte, du solltest den Sinn der Player::write()-Methode nochmal hinterfragen)



  • ok dann lösen wir zusammen eins nach dem anderen, das problem zuerst, ich würde gerne die datei abspeichern können und zwar mit inventar.
    ich bekomme folgendes gemacht und in der main geschrieben. write() wurde gelöscht

    if(!allPlayers.empty())
    					{
    						string dateiname;
    						cout<<"\nBitte Dateiname eingeben *.txt: ";
    						cin>>dateiname;
    						ofstream outfile(dateiname.c_str(), ios::out);
    						if(!outfile)
    						{
    							cerr<<"File could not be opened"<<endl;
    							exit(1);
    						}
    						std::vector<Player>::const_iterator iter; 
    						for(iter=allPlayers.begin(); iter!=allPlayers.end(); ++iter) 
    						{ 
    							outfile<<iter->getName()<<"\n"
    								<<iter->getMaximumWeight()<<"\n"
    								<<iter->getCurrentWeight()<<"\n";
    
                       //outfile<< inventory....... nur wie?????		
    		                            }//endfor
    
    						//pPlayer->write(outfile, allPlayers);						
    						outfile.close();
    
    					}else {cout<<" zuerst Datensatz einlesen!\n";}
    

    so damit habe ich die Player attribute in der Txtdatei nun fehlt nur
    das was in der Liste drin steht bei inventory. das heisst ich muss irgendwie auf die attribute der abgeleiteten klassen zugreifen können bzw eben auf das was in inventory abgespeichert ist. 😕



  • Schreib die Methode write() doch so um, daß sie EINEN Player (*this) ausgeben kann und ruf ihn dann in der Schleife auf (oder du wendest einfach den operator<<() aus deinem ersten Beitrag auf alle Player des vector's an).



  • CStoll schrieb:

    Schreib die Methode write() doch so um, daß sie EINEN Player (*this) ausgeben kann und ruf ihn dann in der Schleife auf (oder du wendest einfach den operator<<() aus deinem ersten Beitrag auf alle Player des vector's an).

    ich hab jetzt in player nee funktion geschrieben

    ostream& Player::getInventory(ostream& os)const
    {
      cout<<"Inventar:"<<endl;
      std::list<Item*>::const_iterator iter;
      for(iter=inventory.begin(); iter!=inventory.end(); ++iter) 
      { 
    	 return (*iter)->write(os);
      } 
    	//return (*iter)->write(os); //hmm muss net sein
    }
    

    und rufe jetzt mit :

    ofstream outfile(dateiname.c_str(), ios::out);
    						if(!outfile)
    						{
    							cerr<<"File could not be opened"<<endl;
    							exit(1);
    						}
    						std::vector<Player>::const_iterator iter; 
    						for(iter=allPlayers.begin(); iter!=allPlayers.end(); ++iter) 
    						{ 
    							outfile<<iter->getName()<<"\n"
    								<<iter->getMaximumWeight()<<"\n"
    								<<iter->getCurrentWeight()<<"\n";
    							outfile<<iter->getInventory(outfile);
    						}
    
    						outfile.close();
    

    so jetzt schreibt der auch das inventar 🙂
    allerdings bringt der noch nee merkwürdige adresse hinterher das muss ich noch wegbekommen.
    Wie meinst du das mit dem

    (oder du wendest einfach den operator<<() aus deinem ersten Beitrag auf alle Player des vector's an).

    ??
    wie soll das aussehen? weil das hab ich mir auch schon überlegt hmmm?



  • Erstmal verlässt du diese Methode (und damit auch die Schleife) schon im ersten Durchlauf - lass mal das 'return' in der Schleife weg:

    ostream& Player::getInventory(ostream& os)const
    {
      cout<<"Inventar:"<<endl;
      std::list<Item*>::const_iterator iter;
      for(iter=inventory.begin(); iter!=inventory.end(); ++iter) 
      { 
         (*iter)->write(os);
         os<<endl;
      }
      return os;
    }
    

    (über den Namen der Methode könnte man ja streiten ;))

    Und zweitens hast du schon den Punkt entdeckt, den ich oben angesprochen habe:

    CStoll schrieb:

    Zweitens: Deine virtuelle Funktion kümmert sich doch schon selber um die Ausgaben. Der Rückgabewert ist der beschriebene Ausgabestrom - und den auf sich selbst zu schreiben macht wenig Sinn.

    Die Anweisung outfile<< iter->getInventory(outfile); führt erst die obige Methode getInventory() aus (die schreibt das Inventar in deine Datei) und schreibt anschließend den Rückgabewert (der identisch ist mit outfile) hinterher - ein ofstream kann nicht ge"schrieben" werden, aber er hat einen Umwandlungsoperator nach void* (hauptsächlich für Konstrukte ala "while(datei)...") und wie er einen void* schreiben soll, weiß der Stream - als "nee merkwürdige Adresse". Lass einfach den Teil "outfile<<" an dieser Anweisung weg, um das zu umgehen.

    (oder du wendest einfach den operator<<() aus deinem ersten Beitrag auf alle Player des vector's an).

    ??
    wie soll das aussehen?

    Dazu mußt du den operator von oben noch so erweitern, daß er auch das Inventar ausgibt - und schon kann der Schleifenrumpf zusammengestaucht werden auf ein einfaches outfile<<*iter; .



  • <<*iter , hehe stimmt das is nee coole idee hehe ,danke !!

    so jetzt zum speicherleck problem, ich hoffe es ist jetzt nicht so dreist
    die komplette main zu posten. aber ich weiss nicht wo ich die delete´s reinsetzten soll, muss!

    // KLSS04.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include "Item.h"
    #include "Player.h"
    #include "Food.h"
    #include "Weapon.h"
    #include <iterator>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <stdexcept>
    #include <conio.h>// für _getch()
    
    using namespace std;
    
    void menu();
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	std::vector<Player> allPlayers;
    	std::ostream_iterator<Player>output(cout, " ");
    
    	Player *pPlayer=NULL;
    
    	menu();
    	bool end=false;
    	do
    	{
    
    		char choice;
    		choice = _getch();
    
    		switch(choice)
    		{
    		case '1': 
    			{	string plname;
    			int plweight;
    			cout<<"\nNeuer Spielername eingeben: ";
    			cin>>plname;
    			cout<<"Maximum-Gewicht eingeben:";
    			cin>>plweight;;
    			pPlayer= new Player(plname,plweight);
    			allPlayers.push_back(*pPlayer);
    			std::sort(allPlayers.begin(),allPlayers.end());
    			cin.clear();
    
    			}break;
    		case '2':	
    			{
    				cout<<" Alle Spieler anzeigen:";
    				std::copy(allPlayers.begin(), allPlayers.end(),output);
    
    			}break;
    
    		case '3':
    			{
    				if(!allPlayers.empty())
    				{
    					cout<<" Gegenstand aufnehmen:\n";
    
    					cout<<"Was wollen Sie aufnehmen Food oder Weapon?:";
    					cout<<"\n0 Food:\n"
    						<<"1 Weapon:\n"
    						<<"ihre Wahl?:";
    
    					char choice;
    					choice = _getch();
    
    					switch(choice)
    					{
    					case '0':{
    						string foodname;int feedingValue; int foodweight;
    						cout<<"\nWelches Nahrungmittel wollen sie aufnehmen?:";
    						cin>>foodname;
    						cout<<"\nGeben Sie den Naehrwert an:";
    						cin>>feedingValue;
    						cout<<"\nGeben Sie nun das Gewicht ein:";
    						cin>>foodweight;
    
    						Item *pItem= new Food(foodname,feedingValue,foodweight);
    						std::copy(allPlayers.begin(), allPlayers.end(),output);
    						cout<<" Zu welchem Spieler soll der Gegenstand hinzugefuegt werden?:";
    						string pname;
    						cin>>pname;
    						bool exist=false;
    						for (std::vector< Player >::iterator location=allPlayers.begin(); location!=allPlayers.end(); location++)
    						{
    							if (location->getName()==pname)
    							{
    								location->addItem(*pItem);
    								exist=true;
    							}
    						}
    						if (exist==false){cout<<"Name nicht vorhanden!\n!";}
    							 }
    						break;
    					case'1':{
    						string weaponname;int attackValue; int weaponweight;
    						cout<<"\nWelcher Waffe wollen sie aufnehmen?:";
    						cin>>weaponname;
    						cout<<"\nGeben Sie den Vernichtungsgrad an:";
    						cin>>attackValue;
    						cout<<"\nGeben Sie nun das Gewicht ein:";
    						cin>>weaponweight;
    
    						Item *pItem= new Weapon(weaponname,attackValue,weaponweight);
    						std::copy(allPlayers.begin(), allPlayers.end(),output);
    						cout<<" Zu welchem Spieler soll der Gegenstand hinzugefuegt werden?:";
    						string pname;
    						cin>>pname;
    						bool exist=false;
    						for (std::vector< Player >::iterator location=allPlayers.begin(); location!=allPlayers.end(); location++)
    						{
    							if (location->getName()==pname)
    							{
    								location->addItem(*pItem);
    								exist=true;
    							}
    						}
    						if (exist==false){cout<<"Name nicht vorhanden!\n!";}
    
    							}break;
    
    					default:{
    						cerr<<"Incorrect choice"<<endl;
    							}break;
    				}//end switch	
    				}else{cout<<" Kein Spieler vorhanden, erst hinzufuegen!\n";}		
    
    			}break;
    
    		case'4': { 
    					cout<<"\nSpiel speichern";
    					if(!allPlayers.empty())
    					{
    						string dateiname;
    						cout<<"\nBitte Dateiname eingeben *.txt: ";
    						cin>>dateiname;
    						ofstream outfile(dateiname.c_str(), ios::out);
    						if(!outfile)
    						{
    							cerr<<"File could not be opened"<<endl;
    							exit(1);
    						}
    						std::vector<Player>::const_iterator iter; 
    						for(iter=allPlayers.begin(); iter!=allPlayers.end(); ++iter) 
    						{ 
    
    							//outfile<<*iter; ausgabe über <<operator
    							outfile<<iter->getName()<<"\n"
    								<<iter->getMaximumWeight()<<"\n"
    								<<iter->getCurrentWeight()<<"\n";
    							outfile<<iter->getInventory(outfile);
    						}
    						outfile.close();
    
    					}else {cout<<" zuerst Datensatz einlesen!\n";}
    				 }break;
    		case'5':{
    					cout<<"\nSpiel laden\n";
    				}break;
    
    		case '6':{
    					cout<<"\nProgramm wird beendet\n";
    					end=true;
    				 } break;
    
    			default:
    				cerr<<"Incorrect choice"<<endl;
    				break;
    		}//end switch	
    		if(!end)
    		{	
    			menu();
    		}
    
    	}while(!end==true);
    
    	delete []pPlayer;
    
    	return 0;
    }
    
    void menu()
    {
    	cout<<"Enter your choice:\n"
    		<<"1 Neuer Spieler\n"
    		<<"2 Alle Spieler anzeigen\n"
    		<<"3 Gegenstand aufnehmen\n"
    		<<"4 Spiel Speichern\n"
    		<<"5 Spiel Laden\n"
    		<<"6 Spiel beenden\n bitte waehlen:";
    }
    

    wo , an welchen stellen , sollte ich delete verwenden? hmmm



  • Am besten gar nicht (und das new brauchst du auch nicht). Du kannst die Variable problemlos auf dem Stack anlegen, dann kümmert sich das Programm selber darum, sie wieder freizugeben.

    case '1': 
    {
        string plname;
        int plweight;
        cout<<"\nNeuer Spielername eingeben: ";
        cin>>plname;
        cout<<"Maximum-Gewicht eingeben:";
        cin>>plweight;;
        Player pl(plname,plweight);
        allPlayers.push_back(pl);
        std::sort(allPlayers.begin(),allPlayers.end());
        break;
    }
    

    (PS: bist du zufällig Java-Programmierer?)



  • jain,

    sten<<"student is"
    

    grade am erlernen von beiden. in 10 tagen ist meine prüfung in c++ und habe noch einige schwächen. grade bei dynamischer speicherverwaltung und vererbung.
    leider muss ich mit dynamischer erzeugung dieses programm bewältigen 😞 .frag mich auch was das soll, aber iss wohl so.. deshalb muss ich new und delete verwenden. fühl mich schon wie ein spaghetti-code-programmierer und bin in manchen dingen einer 😉 . Jedoch bin ich für alle hilfe die du, ihr mir bietet sehr dankbar und hab durch das forum schon viel gelernt 🙂 , desshalb vielen dank!


Anmelden zum Antworten