pointer an eine methode übergeben???



  • Hallo Zusammen, ich habe ein kleines Prog geschrieben das zur laufzeit ein dynamisches objekt erstellt. das funktioniert auch soweit...nach dem ich aber das erstellen des objektes in eine funktion gepackt habe, habe ich keinen zugriff mehr auf dieses objekt...jedefalls funktioniert die ausgabe der inhalte nicht mehr...kann mir jemand einen tipp geben??

    void fktSetupSpieler(Auto* rennauto[4], int anzahlteams)
    {
    	int tankinhalt, kmstand, verbrauch, geschwindigkeit;
    	string team;
    
    	for(int i=0;i<anzahlteams;i++)
    	{
    		cout << "Bitte geben Sie nun nacheinander für das "<< i+1 <<". Fahrzeug ein:\n";
    		cout << "- Teamname: ";
    		cin >> team;
    		cout << "- Tankinhalt: ";
    		cin >> tankinhalt;
    		cout << "- KM-Stand: ";
    		cin >> kmstand;
    		cout << "- Verbrauch: ";
    		cin >> verbrauch;	
    		cout << "- Max-Geschwindigkeit: ";
    		cin >> geschwindigkeit;
    
    		rennauto[i] = new Auto(team, tankinhalt, kmstand, verbrauch, geschwindigkeit);
    	}
    }
    int main(void)
    {
    	cout << "Bitte geben Sie die Anzahl der Teams ein (Max. 4): \n" << endl;
    	cin >> anzahlteams;
    	Auto* rennauto[4];
    	fktSetupSpieler(&rennauto[4], anzahlteams);
    /*
    .
    .
    .
    */
    /*Das Funktioniert nicht mehr seit dem ich das erstellen des Objektes (der Objekte) in eine Funktion gepackt habe...Fehler beim zugriff auf dem Pointer
    Sieht jemand den Fehler???*/
    	for(int i=0; i<anzahlteams; i++)
    	{
    		(*rennauto[i]).~Auto();
    	}
    /*
    .
    .
    .
    */
    	system("pause");
    	return 0;
    }
    
    //Die Klasse
    //Auto.h
    class Auto
    {
    protected:
    	string Team;
    	int TankInhalt;
    	int KmStand;
    	int Verbrauch;
    	int Geschwindigkeit;
    public:
    	Auto(string, int, int, int, int);
    	virtual ~Auto(void);
    };
    
    //Die Auto.cpp
    Auto::Auto(string iTeam, int iTankInhalt, int iKmStand, int iVerbrauch, int iGeschwindigkeit)
    {
    	KmStand= iKmStand;
    	TankInhalt = iTankInhalt;
    	Verbrauch = iVerbrauch;
    	Geschwindigkeit = iGeschwindigkeit;
    	Team = iTeam;
    }
    
    Auto::~Auto(void)
    {
    	cout << "----------------------------------------------" << endl;
    	cout << "\t ***\tTeam: " << Team << "\t ***" <<  endl;
    	cout << "\t -Tankinhalt: " << TankInhalt << endl;
    	cout << "\t -Kilometerstand: " << KmStand << endl;
    	cout << "\t -Verbrauch: " << Verbrauch << endl;
    	cout << "\t -Max-Geschwindigkeit: " << Geschwindigkeit << endl;
    	cout << "----------------------------------------------" <<endl;
    }
    

    Danke für Ideen



  • Mh, weißt du, was hier passiert?:

    void func( int i )
    {
        i = 10;
    }
    
    int main()
    {
        int x = 1;
        func( x );
    }
    

    Das x ist nach dem Funktionsaufruf immer noch 1. Das liegt daran, dass es in C++ so ist, dass bei Funktionsaufrufen immer nur die Kopien der Parameter übergeben werden. Um den Wert x wirklich zu ändern, musst du die Adresse der Variable kennen, um ihren Wert im Arbeitsspeicher zu ändern. Z.B. so:

    void func( int* i )
    {
        *i = 10;
    }
    
    int main()
    {
        int x = 1;
        func( &x );
    }
    

    Oder aber per Referenz, ist ähnlich wie ein Zeiger (hat auch die Adresse), du kannst diese aber nicht ändern. Außerdem fällt die Zeigerarithmetik weg und du musst/kannst nicht dereferenzieren.

    void func( int& i )
    {
        i = 10;
    }
    
    int main()
    {
        int x = 1;
        func( x );
    }
    

    Achso, und was du mit new holst (den Speicher), musst du mit delete wieder freigeben! Den Destruktor aufzurufen wie du's gemacht hast, macht man eigentlich nicht 😉

    Ansonsten aber schön, dass du mit strings und streams arbeitest 👍
    Nach welchem Tutorial gehst du denn vor?



  • Hi, danke erst mal für die schnelle antwort...aber das was Du schreibst habe ich schon angewendet oder ist dirt ein fehler drinen

    //Funktionsaufruf mit der Übergabe der Adresse
    fktSetupSpieler(&rennauto[4], anzahlteams);
    
    //Die Funktion
    void fktSetupSpieler(Auto* rennauto[4], int anzahlteams)
    {
     //Inhalt in die Adresse *rennauto[i] schreiben...
    }//Hier müsste doch doch der Inhalt auch noch vorhanden sein?
    


  • Zitat:

    nsonsten aber schön, dass du mit strings und streams arbeitest 👍
    Nach welchem Tutorial gehst du denn vor?

    Meinst Du das jetzt Ironisch??
    Ich gehe nach keine Tut vor, habe nur eine Aufgabe die ich mit wenig komplexität lösen möchte, wobei ich dies schon für super viel spaghetti code halte...naja erst funktionieren dann optimieren 😋

    Gruß



  • Nein, das mit dem "ansonsten schön" meinte ich nicht ironisch!

    Zum Thema: Du übergibst deiner Methode eine Zeiger-Variable, die beim Funktionsaufruf kopiert wird. Du weist jetzt der kopierten Zeiger-Variable einen Wert zu, deshalb kommt der neue Wert für den Zeiger in deiner main-Funktion nicht an 😉 Deshalb brauchst du halt einen Zeiger oder eine Referenz auf die Zeiger, damit du die Adresse der Zeiger in der main-Funktion verändern kannst. Bisschen kompliziert, ich weiß, aber zum Glück auch logisch :xmas1:



  • @Mr. Badestrand, er übergibt einen Auto**, was soll daran falsch sein???

    @ferro: Bitte ignoriere doch einfach das was Badestrand über Zeiger schreibt, es stimmt nämlich nicht, bzw. es ist in diesem Fall nicht anwendbar, da dein Fehler ganz wo anders liegt. Der Funktionskopf ist soweit in Ordnung, die Verwendung des Auto** in der Funktion genauso, bloss der Aufruf der Funktion ist falsch. Und natürlich der direkte Aufruf des Destruktors.

    Etwas genauer:

    //void fktSetupSpieler(Auto* rennauto[4], int anzahlteams)
    // Die Syntax oben ist "scheisse" und gehört IMO verboten. Es wundert mich nicht dass hier andauernd Anfänger drüber stolpern.
    // "Auto* rennauto[4]" heisst in der Parameterliste nämlich GENAU dasselbe wie einfach "Auto** rennauto".
    // Deswegen schreibt man das am Besten auch so:
    
    void fktSetupSpieler(Auto** rennauto, int anzahlteams)
    {
        for(int i=0;i<anzahlteams;i++)
        {
            rennauto[i] = new Auto(/* ... */); // das ist so OK, passiert das was beabsichtigt ist.
        }
    }
    
    // Bis hierher nur ein "Stilproblem", nun zu den echten Fehlern:
    
    // int main(void)
    // OK, auch nur ein stilproblem, aber bitte kein "int foo(void)" in C++ schreiben sondern einfach "int foo()":
    int main()
    {
        // ...
        Auto* rennauto[4];
    //  fktSetupSpieler(&rennauto[4], anzahlteams);
        //  --> fehler 1 <--
        //  So, das da oben ist nun wirklich falsch. was hier passiert ist:
        //  "rennauto" ist ein array von 4 "Auto*". "rennauto[4]" ist der fünfte dieser "Auto*", also der fünften der 4 Zeiger (was schonmal nicht geht!).
        //  "&x" ist die Adresse von x, und daher ist "&rennauto[4]" die Adresse des
        //  fünften Zeigers (des es ja garnichtmehr gibt). Zeigt also genau HINTER das Array.
    
        //  Richtig wäre:
    //  fktSetupSpieler(rennauto, anzahlteams);
        // Oder weils etwas klarer (expliziter) ist:
        fktSetupSpieler(&rennauto[0], anzahlteams);
    
    // ...
    
        for(int i=0; i<anzahlteams; i++)
        {
    //      (*rennauto[i]).~Auto();
            //  --> fehler 2 <--
            // Also erstmal kann man das oben viel einfacher schreiben, nämlich so:
    //      rennauto[i]->~Auto();
            // Ist aber immer noch falsch. Du rufst den Destruktor "direkt" auf, was fast immer falsch ist.
            // Und überlies das "fast" im letzten Satz ruhig, du kannst davon ausgehen dass du nie
            // bzw. in den nächsten Jahren nie in eine Situation kommen wirst wo es gut und richtig
            // wäre den Destruktor "direkt" aufzurufen.
            // Richtig ist hier das Gegenstück zu "new" zu verwenden, nämlich "delete":
            delete rennauto[i];
        }
    
        // ...
    }
    


  • @hustbaer:

    Danke für deinen Tip, so funktioniert es...ich habe die Funktion auch gleich in eine Methode gepackt...

    ps.
    Zum int main(void) <-- Das will unser Prof. so haben. Das sind seine Programmier richtlinien..
    §2)
    void ist die C++ Bezeichnung für "nix. Wenn wie "nix" meinen, sagen wir es auch und schweigen nicht einfach. Also int main(void) statt int main()

    Aus diesem grund schreibe ich es auch rein, da es bei einer Klausur, wenn es fehlen sollte, Punktabzüge gibt



  • hustbaer schrieb:

    @Mr. Badestrand, er übergibt einen Auto**, was soll daran falsch sein???

    Ups, hab ich mich anscheinend verlesen. (Tschuldigung, ferro)

    hustbaer schrieb:

    @ferro: Bitte ignoriere doch einfach das was Badestrand über Zeiger schreibt, es stimmt nämlich nicht, bzw. es ist in diesem Fall nicht anwendbar, da dein Fehler ganz wo anders liegt.

    Ich sehe ein, dass ich keine Ahnung hab, besser ich tue wieder das was ich am besten kann und gehe wieder auf die Wiese und flechte Kränze aus Gänseblümchen 😞



  • §2 void ist die C++ Bezeichnung für "nix. Wenn wie "nix" meinen, sagen wir es auch und schweigen nicht einfach. Also int main(void) statt int main().

    Naja die Professoren sind meist etwas nunja sagen wir mal "unprofessionel" im Umgang mit C++. Bzw. auf gut Deutsch: Der soll die Schnauze halten weil er keine Ahnung hat 😛

    Naja egal, aufjedenfall musst du dich daran halten, wenn er es sagt. Er darf dir sogar die Punkte dafür abziehen, da er es euch vorher gesagt hat, auch wenn seine Begründung nicht das Wahre ist.


Anmelden zum Antworten