enum als Argument // Klassenkonstruktion



  • Hi,

    wir sollen als Übung die Klasse Gebäude anlegen. Im Prinzip funktioniert das so wie es unten steht.
    Nur möchte ich die strings bei Bauart und Dachart durch enum-Listen ersetzen. Leider komme ich da gar nicht mehr weiter. 😞

    Geb.h

    #ifndef Geb_H
    #define Geb_H
    using namespace std;
    
    class Geb{
    	public:
    
    		Geb();
    
    		void setMeinHaus();
    
    		enum Bauartliste {Massivbau, Lehmbau, Holzbau, Fertigbauweise};
    
    		void setPostleitzahl(unsigned int g);
    		unsigned int getPostleitzahl();
    		unsigned short int getHausnummer();
    		void setHausnummer(unsigned short int f);
    		float getFlaeche();
    		void setFlaeche(float a);
    		string getStrasse();
    		void setStrasse(string b);
    		string getStadt();
    		void setStadt(string c);
    		int getBauart();
    		void setBauart(Bauartliste d);
    		string getDachart();
    		void setDachart(string e);
    
    		void print();
    
    		Geb(const Geb &Gebin);
    
    		~Geb();
    
    	private:
    		float Flaeche;
    		string Strasse;
    		enum Bauartliste {Massivbau, Lehmbau, Holzbau, Fertigbauweise};
    		Bauartliste Bauart;
    		string Dachart;
    		unsigned short int Hausnummer;
    		unsigned int Postleitzahl;
    		string Stadt;
    };
    #endif
    

    Gebfunc.cpp

    #include <iostream>
    #include <string>
    #include "Geb.h"
    
    using namespace std;
    
    void Geb::setMeinHaus()
    {
    	Hausnummer = 18;
    	Postleitzahl = 37073;
    	Flaeche = 19;
    	Strasse = "Hospitalstrasse";
    	Stadt = "Goettingen";
    	Bauart = Lehmbau;
    	Dachart = "geneigtesDach";
    }
    
    void Geb::setHausnummer(unsigned short int f)
    {
    	Hausnummer = f;
    }
    
    unsigned short int Geb::getHausnummer()
    {
    	return Hausnummer;
    }
    
    void Geb::setPostleitzahl(unsigned int g)
    {
    	Postleitzahl = g;
    }
    
    unsigned int Geb::getPostleitzahl()
    {
    	return Postleitzahl;
    }
    
    void Geb::setFlaeche(float a)
    {
    	Flaeche=a;
    }
    
    float Geb::getFlaeche()
    {
    	return Flaeche;
    }
    
    void Geb::setStrasse(string b)
    {
    	Strasse = b;
    }
    
    string Geb::getStrasse()
    {
    	return Strasse;
    }
    
    void Geb::setStadt(string c)
    {
    	Stadt = c;
    }
    
    string Geb::getStadt()
    {
    	return Stadt;
    }
    
    void Geb::setBauart(Bauartliste d)
    {
    	d=Bauart;
    }
    
    int Geb::getBauart()
    {
    	return Bauart;
    }
    
    void Geb::setDachart(string e)
    {
    	Dachart = e;
    }
    
    string Geb::getDachart()
    {
    	return Dachart;
    }
    
    void Geb::print()
    {
    	cout << Strasse << " " << Hausnummer << ", " << Postleitzahl << "  " << Stadt << "  " << Dachart << "  " << Flaeche << "m^2" << endl;
    	if (Bauart == 0) cout << "Massivbaut";
    	if (Bauart == 1) cout << "Lehmbau";
    	if (Bauart == 2) cout << "Holzbau";
    	if (Bauart == 3) cout << "Fertigbauweise";
    }
    
    Geb::Geb(const Geb &Gebin)
    {
    	Flaeche=Gebin.Flaeche;
    	Hausnummer=Gebin.Hausnummer;
    	Postleitzahl=Gebin.Postleitzahl;
    	Bauart=Gebin.Bauart;
    	Dachart=Gebin.Dachart;
    	Strasse=Gebin.Strasse;
    	Stadt=Gebin.Stadt;
    }
    
    Geb::Geb()
    {
    	Flaeche = 1000;
    	Hausnummer = 11;
    	Postleitzahl = 12345;
    	Bauart = Lehmbau;
    	Dachart = "Freigeformtes Dach";
    	Strasse = "Musterstrasse";
    	Stadt = "Musterstadt";
    }
    
    Geb::~Geb()
    {
    	//Destruktor
    }
    

    main.cpp

    #include <iostream>
    #include <string>
    #include "Geb.h"
    
    using namespace std;
    enum Bauartliste {Massivbau, Lehmbau, Holzbau, Fertigbauweise};
    
    int main()
    {
    	Geb a;			//Gebäude a wird angelegt
    	Geb b;			//Gebäude b wird angelegt
    	b.setMeinHaus(); //Gebäude b mit den Werten meines Hauses
    	a.print();		//Ausgabe der Werte des Musterhauses
    	b.print();		//Ausgabe der Werte meines Hauses
    
    	Geb c(a);		//Ein Objekt c wird mit dem Copykonstruktor gleich dem Musterhaus gesetzt...
    	c.print();		//... und mit der Printmethode ausgegeben
    
    	c.setFlaeche(500);  //Flaeche wird auf 500 gesetzt...
    	c.setStrasse("Hoellenweg"); // Straße wird verändert
    	c.setBauart(Massivbau);
    	c.print();			// ... und ausgegeben
    
    	system("PAUSE");
    	return 0;
    }
    

    Die Probleme sind dann irgendwie bei der Konstruktion der Funktion setBauart in Zeile25 von Geb.h und Zeile 68 von von Gebfunc.pp. Außerdem schluckt er Zeile 21 in main.cpp nicht, wo ich dann Massivbau einsetzen möchte.

    Wahrscheinlich würde mir schon ein Beispiel reichen, das zeigt wie ich einen enum Wert in eine Funktion einsetzen kann.

    Vielen Dank schonmal für die Mühe!



  • Perhalo schrieb:

    ...

    Mehrere Anmerkungen:
    1a. Dies hat nichts mit der MFC zu tun, ist reines C++ und gehört daher in das Ansi C++ Unterforum.
    1b. Für ein Forum wäre es gut, wenn du die Tabulatoren durch wenige Leerzeichen ersetzt (Einrückung => Lesbarkeit).

    2. Man sollte kryptische Abkürzungen vermeiden, z.B. Warum "b" als Parametername bei "void setStrasse(string b)", warum nicht einfach "strasse". Das erleichtert das Lesen ungemein (und Code wird häufiger gelesen als geschrieben). Und warum "Geb" als Klassenname und nicht "Gebaeude"? Du machst es dir selbst schwer, wenn du nach einen halben Jahr deinen Code nochmal lesen musst.

    3. Man sollte unnötige Kopien vermeiden, dazu gehört auch das man Übergabeparameter, die nicht zu den Integralen Datentypen (wie int, bool, double, enums...) handelt, als "const &" übergibt. Bei "void setStrasse(string b)" wird z.B. der String unnötig kopiert, besser wäre "void setStrasse(string const & b)".

    void Geb::setBauart(Bauartliste d)
    {
        // Falsch: d=Bauart;
        Bauart=d; // Du möchtest ja die Membervariable setzen.
    }
    
    void Geb::print()
    {
        cout << Strasse << " " << Hausnummer << ", " << Postleitzahl << "  " << Stadt << "  " << Dachart << "  " << Flaeche << "m^2" << endl;
    
        /* Unschön, wozu hat man den die Enumwerte, wenn man sie nicht verwendet?
           zudem würde ich hier einen switch vorziehen
        if (Bauart == 0) cout << "Massivbaut";
        if (Bauart == 1) cout << "Lehmbau";
        if (Bauart == 2) cout << "Holzbau";
        if (Bauart == 3) cout << "Fertigbauweise";
        */
    
        // Imho besser: (oder wenigstens ab den zweiten if eher else if verwenden)
        switch(Bauart) {
          case Massivbau:
              cout << "Massivbau";
              break;
          case Lehmbau:
              cout << "Lehmbau";
              break;
          case Holzbau:
              cout << "Holzbau";
              break;
          case Fertigbauweise:
              cout << "Fertigbauweise";
              break;
        }
    }
    
    // Initialisierungsliste (nur Konstruktoren), ist der nachträglichen Zuweisung
    // vorzuziehen.
    Geb::Geb(
      const Geb &Gebin)
    : Flaeche(Gebin.Flaeche),  // <-- Initialisierungsliste
      Hausnummer(Gebin.Hausnummer),
      Postleitzahl(Gebin.Postleitzahl),
      Bauart(Gebin.Bauart),
      Dachart(Gebin.Dachart),
      Strasse(Gebin.Strasse),
      Stadt(Gebin.Stadt)
    {
      // <-- Hier wird nachträglich zugewiesen
    }
    


  • zu 1) entschuldigung. Ich werde demnächst stärker darauf achten.

    zu 2) Alles klar. Habe ich geändert. Bin nicht auf die Idee gekommen den ersten Buchstaben einfach klein zu schreiben^^

    zu 3) Bin nur Nebenfächler und hab das so aus dem Skript übernommen. Was du genau meinst verstehe ich auch nicht. Aber die Funktionen arbeiten ja fast alle wie gewünscht.

    Problem ist nur immer noch folgendes:

    void setBauart(Bauartliste bauart);
    
    void Geb::setBauart(Bauartliste bauart)
    {
    	Bauart = bauart;
    }
    
    c.setBauart(Massivbau);
    

    Also sprich die setMethode mit dem enum Typ.
    "Ein Wert vom Typ Geb::Bauartliste kann keiner Entität vom Typ Geb::Bauartliste zugeordnet werden"

    P.S.: Der Switch - Case ist natürlich besser, danke!



  • Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++ (auch C++0x) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Massivbau liegt wie alle anderen enum-Werte im Geb-Scope.

    c.setBauart(Geb::Massivbau);
    

    im Übrigen lies dir bitte mal den Link in meiner Signatur durch, besonders den Punkt bezüglich gekürztem Code...



  • Perhalo schrieb:

    zu 3) Bin nur Nebenfächler und hab das so aus dem Skript übernommen. Was du genau meinst verstehe ich auch nicht. Aber die Funktionen arbeiten ja fast alle wie gewünscht.

    #include <string>
    
    void set1(std::string text) {}         // text ist Kopie vom Originalwert
    void set2(std::string const & text) {} // text ist Verweis/Aliasname auf Original
    
    int main()
    {
        std::string text = "Test";
        set1(text);
        set2(text);
    }
    

    Wenn man Werte übergibt gibt es mehrere Möglichkeiten. Wenn man nur den Typnamen angibt, handelt es sich bei dem Parameter um eine Kopie. Dies ist nicht schlimm, wenn die Kopie "billig" ist, bei integralen Datentypen wie int, double und ähnlichen ist dies auch der empfohlene Weg.

    Bei komplexen Objekten ist die Kopie aber teuer (Dauert Zeit...) und zumeist auch unnötig, hier empfiehlt sich eine Referenzübergabe (Konstant, damit das Original nicht geändert wird) - Intern wird dies meist durch eine Zeigerübergabe realisiert.

    Perhalo schrieb:

    Problem ist nur immer noch folgendes:

    void setBauart(Bauartliste bauart);
    
    void Geb::setBauart(Bauartliste bauart)
    {
    	Bauart = bauart;
    }
    
    c.setBauart(Massivbau);
    

    Da du das enum innerhalb der Klasse deklariert hast, wird es vermutlich nötig sein außerhalb der Klassendeklaration im Header den kompletten Namen anzugeben (Der ist nicht "Bauartliste", sondern "Geb::Bauartliste"). Eine Alternative hierzu wäre es, das Enum oberhalb der Klasse zu deklarieren.



  • noch ne "Anmerkung":

    Bauartliste

    , den Namen als Enum-Typ wuerd ich Dir um die Ohren hauen in dem Zusammenhang. Das ist schon fast vorsätzliche Irreführung 🙂

    Enum ist ein Typ, der aufs mal nur einen Wert annehmen kann. Keine Menge !
    Auch wenn Du eine "Liste" mit möglichen werten für einen Enum definierst, gibt der Typ selber keine Menge her 🙂

    Nimm lieber sowas wie BauartT, BauartType oder sowas ....

    Ciao ...



  • Danke sehr für die Hilfe! Hab alle einfließen lassen und jetzt läufts wie geschmiert 🙂



  • was genau hast du denn jetzt verändert ? ich sitze schon seit 3 tagen mit meiner gruppe an der aufgabe und wir sind alle am verzweifeln ... wir waren auf ähnliche ergebnisse gekommen wie in der erstgenannten variante jedoch haben wir es erst garnicht zum laufen bekommen ...



  • @neulings
    Kurz mal ein Spaziergang machen um den Kopf frei zu bekommen und dann Punkt für Punkt diesen Beitrag angehen.
    Es wird dir/euch wenig helfen, wenn ihr da auf einmal eine fertige Lösung habt.


Anmelden zum Antworten