Sichtbarkeit von Objekten in switch-Anweisung



  • Hallo zusammen.
    Ich bekomme einen Fehler beim Kompilieren des Codes. Mir ist klar, dass es hier an der Sichtbarkeit der Objekte in der switch-Anweisung liegt, allerdings weiss ich 1. nicht warum und 2. wie ich das Problem lösen kann. Vielleicht kann mir jemand helfen. Ich muss dazu sagen, dass ich gerade erst anfange mit C++ OOP zu programmieren.
    Vielen Dank schonmal im Voraus, wenn mir jemand einen Hinweis geben kann, wie ich eine Lösung finde.

    //main.cpp
    #include <iostream>
    #include "interface.h"
    #include "einheiten.h"
    
    using namespace std;
    
    int main(void)
    {
    	InterfaceMenue *ifm = new InterfaceMenue;
    
    	while (true)
    	{
    	switch (ifm->start()) // Objektmethode gibt einen Int-Wert zurück
    	{
    	case 1:
    		cout << "Eingabe war 1\n";
    		if (ifm->erstellen() == 1) // Nach Benutzereingabe werden die Objekte erstellt
    		{
    			Einheit *Zug1 = new Einheit;
    			Einheit *Zug2 = new Einheit;
    		} else
    			ifm->start();
    		break;
    	case 2:
    		{
    		cout << "Eingabe war 2\n"; // Hier soll der Status der beiden Objekte ausgegeben werden
    		ifm->status(*Zug1); // error C2065: 'Zug1': nichtdeklarierter Bezeichner
    		ifm->status(*Zug2); // error C2065: 'Zug2': nichtdeklarierter Bezeichner					
    		break;
    		}
    	case 3:
    		{
    		cout << "Eingabe war 3\n";
    		break;
    		}
    	case 4:
    		{
    		cout << "Eingabe war 4\n";
    		break;
    		}
    	case 5:
    		{
    		cout << "Eingabe war 5\n";
    		exit(1);
    		}
    	}
    	}
    	cin.get();
    	return 0;
    }
    

  • Mod

    Lies dir die Grundlagen über Variablengültigkeitsbereiche durch, dann wird dir Ursache und Antwort klar. Kurzfassung: Eine Variable lebt nur so lange bis du eine geschweifte Klammer zu machst. Mit OOP hat dieses Phänomen übrigens nichts zu tun.

    Und du hast früher mal Java programmiert, oder? In C++ kannst (und solltest) du das viele Gepointere und new vergessen.



  • Allerdings sind Objekte, die auf dem Heap erstellt worden sind doch gar nicht an Blöcke gebunden, sondern existieren solange, bis sie mit delete gelöscht werden.
    Ich bin zumindest soweit, dass ich weiss, dass bei case 2 es auch der Fall sein kann, dass es die beiden Objekte (Zug1 und Zug2) noch gar nicht gibt.
    Warum ich mit new und Pointern arbeite hat folgenden Grund: Ziel ist es hier später, dass ich in einem Menü den Benutzer frage ob er ein Objekt erstellen will und dieses Objekt dann neu angelegt werden soll. Wenn ich mich nicht irre, dann geht das nur mit new. Ich habe schon einige Stunden gegoogelt und auch diverse C++ Bücher durchgesehen, jedoch konnte ich so genau nichts dazu finden.

    mkG Nasghat



  • Dann speichere die Objekte in einem auto_ptr, oder, wenn du C++0x hast, in einem unique_ptr.


  • Mod

    Nasghat schrieb:

    Allerdings sind Objekte, die auf dem Heap erstellt worden sind doch gar nicht an Blöcke gebunden, sondern existieren solange, bis sie mit delete gelöscht werden.

    Richtig. Aber für deine Pointer Zug1 und Zug2 gilt das nicht. Die Objekte existieren schon noch, aber du weißt nicht mehr wo, wenn die Pointer den Scope verlassen.



  • Dann würde es doch Sinn machen, wenn ich die Objekte in einen Vector packe. So könnte ich dann prüfen, ob überhaupt Objekte vorhanden sind, hätte dann gleich eine Art Objektzähler und kann sie auch gleich ansprechen, oder?

    mkG Nasghat



  • Wozu das alles?



  • Für den Moment möchte ich einfach nur, dass wenn der Benutzer in einem Menü "1" eingibt, ein neues Objekt erstellt wird und wenn er eine "2" eingibt, der Status der Objekte ausgegeben wird.

    MkG Nasghat



  • Nasghat schrieb:

    Allerdings sind Objekte, die auf dem Heap erstellt worden sind doch gar nicht an Blöcke gebunden, sondern existieren solange, bis sie mit delete gelöscht werden.

    Wenn du etwas auf dem Heap anlegst, dann verliert die Variable, mit der du einen Wert (im Heap) ansprichst, ihre Gültigkeit, jedoch das, das hinter der Variable steht, also der Wert im Speicher, bleibt weiterhin geschützt, d.h. der Speicher wird nicht freigegeben.

    lg



  • Nasghat schrieb:

    Für den Moment möchte ich einfach nur, dass wenn der Benutzer in einem Menü "1" eingibt, ein neues Objekt erstellt wird und wenn er eine "2" eingibt, der Status der Objekte ausgegeben wird.

    Die Pointer müssen dazu aber schon vorher existieren:

    Einheit *zug1 = null;
    ...
    
    switch(...) {
        case 1: zug1 = new Einheit(); ... /* was wenn zug1 schon irgendwo hingezegit hat -> falls != 0 sollte hier noch ein delete passieren (*) */ break;
        case 2: zug1->doSomething(); /* achtung besser auf null prüfen */ break;
    }
    

    Oder sollen bei () zusätzliche Objekte angelegt werden? Dann brauchst du einen std::vector<Einheit>.

    MfG SideWinder



  • Nasghat schrieb:

    Für den Moment möchte ich einfach nur, dass wenn der Benutzer in einem Menü "1" eingibt, ein neues Objekt erstellt wird.

    Da dabei ja erst zur Laufzeit entschieden wird, wie viele Objekte letztendlich erstellt werden... dann nimm doch einfach ein std::vector und lege die Objekte darin ab.

    lg



  • Ich habe es mit einem Vector probiert, so klappt es auch erstmal...jetzt muss ich nur noch den Fall abfangen, dass, falls noch kein Objekt vom Typ Einheit besteht, der vector nicht auf etwas zeigt, das es nicht gibt.
    Hier mal kurz der Code mit dem Vector:
    Auf jeden Fall schon mal besten Dank für die Ideen.

    //main.cpp
    #include <vector>
    #include <iostream>
    #include "interface.h"
    #include "einheiten.h"
    
    using namespace std;
    
    int main(void)
    {
    	InterfaceMenue *ifm = new InterfaceMenue;
    	vector<Einheit> vEinh;
    	//vector<Einheit>::iterator vEinh_Iter;
    
    	while (true)
    	{
    	switch (ifm->start()) // Objektmethode gibt einen Int-Wert zurück
    	{
    	case 1:
    		cout << "Eingabe war 1\n";
    		if (ifm->erstellen() == 1) // Nach Benutzereingabe werden die Objekte erstellt
    		{
    			Einheit *Zug1 = new Einheit;
    			vEinh.push_back(*Zug1);
    		} else
    			ifm->start();
    		break;
    	case 2:
    		{
    		cout << "Eingabe war 2\n"; 
    		ifm->status(vEinh[0]); 		// Hier soll der Status des Objekts ausgegeben werden	
    		break;
    		}
    	case 3:
    		{
    		cout << "Eingabe war 3\n";
    		break;
    		}
    	case 4:
    		{
    		cout << "Eingabe war 4\n";
    		break;
    		}
    	case 5:
    		{
    		cout << "Eingabe war 5\n";
    		exit(1);
    		}
    	}
    	}
    	cin.get();
    	return 0;
    }
    


  • Vermeide new so oft es geht, dabei einstehendir wie hier gerne Memory Leaks. Falls du doch etwas auf dem Heap erstellen willst, solltest du lieber den std::unique_ptr nehmen.

    InterfaceMenue *ifm = new InterfaceMenue;
    // besser
    InterfaceMenue ifm;
    
    // Achtung, Memory Leak!
    Einheit *Zug1 = new Einheit;
    vEinh.push_back(*Zug1);
    // besser
    Einheit Zug1;
    vEinh.push_back(Zug1);
    

  • Mod

    Ich sehe immer noch nicht die Notwendigkeit, überhaupt new zu benutzen. Warum nicht die konkreten Objekte im Vector ablegen?



  • Smartpointer...


  • Mod

    314159265358979 schrieb:

    Smartpointer...

    Nochmal: Wieso überhaupt Pointer? Distanziert euch doch mal von dem was der Threadersteller gemacht hat und schaut auf das was er will. Und dann überlegt, wie ihr das machen würdet.



  • Sorry, habe die Seite 2 des Threads komplett übersehen. Kannst meinen Post (und diesen) löschen.


  • Mod

    314159265358979 schrieb:

    Sorry, habe die Seite 2 des Threads komplett übersehen. Kannst meinen Post (und diesen) löschen.

    Ach, ist schon ok, zum Thema Pointer passt es und vielleicht will ja noch jemand etwas dazu lernen.



  • #include <vector> 
    #include <iostream>
    #include <cstdlib> /* --> exit(1) */ 
    #include "interface.h" 
    #include "einheiten.h"
    
    using namespace std;
    
    typedef void (COMMAND*)(InterfaceMenu*, vector<Einheit>*);
    
    void FirstCmd(InterfaceMenu* ifm, vector<Einheit> *vEinh){
     if(ifm->erstellen() == 1)
      vEinh->push_back(Einheit::Einheit());
    }
    
    void SecondCmd(InterfaceMenu* ifm, vector<Einheit> *vEinh){
     ifm->status(&vEinh[0]);
    }
    
    void DoNothingCmd(InterfaceMenu* ifm, vector<Einheit> *vEinh){
    }
    
    void QuitCmd(InterfaceMenu* ifm, vector<Einheit> *vEinh){
     exit(1);
    }
    
    COMMAND Reaktion[] = {DoNothingCmd, FirstCmd, SecondCmd, DoNothingCmd, DoNothingCmd, QuitCmd};
    
    int main(){
     int iStartRet;
     vector<Einheit> vEinh;
     InterfaceMenu ifm;
     do{
      if((iStartRet = ifm.start()) < 6 && iStartRet > 0){
    	cout << "Eingabe war " << iStartRet << "\n";
    	Reaktion[iStartRet](&ifm, &vEinh);
      }
     }while(true);
     cin.get();
     return 0;
    }
    

    Ungetestet, aber könnte (ev. mit ein paar Korrekturen) so klappen.
    Immerhin das new und das switch hätte man so wegbekommen,
    weil die haben ja die Probleme verursacht? Um das ging's doch?



  • ifm->status(&(*vEinh)[0]); /* Zeile 17 */
    

Anmelden zum Antworten