Array von Objekten an Funktionen übergeben



  • Hallo allerseits,

    für eine Einsendeaufgabe soll ich ein einfaches Programm für eine Hotelzimmervewaltung schreiben. Das Programm soll objektorientiert sein, dafür habe ich eine Oberklasse "Zimmer" und zwei Unterklassen "EinzelZimmer" & "DoppelZimmer". Es gibt 10 Einzel- und 10 Doppelzimmer, also erstelle ich für beide Typen je ein Feld - und zwar so:

    /* Felder der Einzel- & Doppelzimmer erzeugen
    	--------------------------------------------- */
    		/* Einzelzimmer */
    		EinzelZimmer EinzelZimmerArray[10];
    		for (intZaehler = 0; intZaehler < 10; intZaehler++)
    		{
    			EinzelZimmerArray[intZaehler].ZimmernummerErzeugen(intZaehler);
    		}
    
    		/* Doppelzimmer */
    		DoppelZimmer DoppelZimmerArray[10];
    		for (intZaehler = 0; intZaehler < 10; intZaehler++)
    		{
    			DoppelZimmerArray[intZaehler].ZimmernummerErzeugen(intZaehler);
    		}
    

    Eine Funktion des Programms soll sein dass der Benutzer die Zimmer mit allen Daten anzeigen lassen kann - die freien, die belegten, oder alle.
    Nun habe ich über ein Menü die Auswahl bereit gestellt und wenn der User sich entscheidet die Zimmer abzufragen, schicke ich ihn in ein weiteres Menü - und zwar so:

    switch (charMenuepunkt[0])
    			{
    				case '1': MenueZimmerstati(EinzelZimmerArray[10], DoppelZimmerArray[10]);
    							system("Pause");
    							break;
    

    Der Prototyp der Funktion sieht so aus:

    void MenueZimmerstati(EinzelZimmer, DoppelZimmer);
    

    Ist er im neuen Menü, kann er sich entscheiden ob eben die freien, die belegten oder alle angezeigt werden sollen.
    Momentan habe ich testhalber nur die ersten beiden geschrieben - und das sieht so aus:

    - Untermenü:

    void MenueZimmerstati(EinzelZimmer EinzelZimmerArray[10], DoppelZimmer DoppelZimmerArray[10])
    {
    ...
    switch (charMenuepunkt[0])
    			{
    				case '1': strSuchKriterium = "frei";
    							StatiFreieBelegteZimmer(strSuchKriterium, EinzelZimmerArray[10], DoppelZimmerArray[10]);
    							system("Pause");
    							break;
    

    - anzeigen der gefragten Zimmer:

    void StatiFreieBelegteZimmer(string strSuchKriterium, EinzelZimmer EinzelZimmerArray[10], DoppelZimmer DoppelZimmerArray[10])
    {
    	/* Hilfsvariablen */
    	int intZaehler; /* zum Durchlaufen der Zimmer-Felder */
    
    	/* Durchlauf des EinzelZimmer-Feldes und Ausgabe der gefragten Daten */
    	for (intZaehler = 0; intZaehler < 10; intZaehler++)
    	{
    		/* Stati des aktuellen Elementes prüfen... */
    		if (EinzelZimmerArray[intZaehler].RueckgabeStatus() == strSuchKriterium)
    		{
    			/* ...und Ausgabe veranlassen, falss das aktuelle Zimmer den gefragten Wert enthällt */
    			EinzelZimmerArray[intZaehler].EinzelZimmerDatenAusgeben();
    
    			/* Übersichtszeile */
    			cout << "-----------------------------------------------\n";
    		}
    	}
    
    	/* Durchlauf des DoppelZimmer-Feldes und Ausgabe der gefragten Daten */
    	for (intZaehler = 0; intZaehler < 10; intZaehler++)
    	{
    		/* Stati des aktuellen Elementes prüfen... */
    		if (DoppelZimmerArray[intZaehler].RueckgabeStatus() == strSuchKriterium)
    		{
    			/* ...und Ausgabe veranlassen, falss das aktuelle Zimmer den gefragten Wert enthällt */
    			DoppelZimmerArray[intZaehler].DoppelZimmerDatenAusgeben();
    
    			/* Übersichtszeile */
    			cout << "-----------------------------------------------\n";
    		}
    	}
    }
    

    Der Prototyp der Funktion "StatiFreieBelegteZimmer" ist dieser:

    void StatiFreieBelegteZimmer(string, EinzelZimmer, DoppelZimmer);
    

    Folgendes Problem tritt nun auf:
    - wenn ich die Funktionen OHNE die Übergabe der Arrays laufen lasse (dann natürlich nur zum Test und ohne die Funktionalitäten) geht es
    - rufe ich die Funktionen MIT der Übergabe aufrufe, also wie ihr sie hier seht, bekomme ich diesen Fehler:

    1>------ Erstellen gestartet: Projekt: Aufbabe_2, Konfiguration: Debug Win32 ------

    1>EA2_main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol
    ""void __cdecl MenueZimmerstati(class EinzelZimmer,class DoppelZimmer)" (?MenueZimmerstati@@YAXVEinzelZimmer@@VDoppelZimmer@@@Z)" in Funktion "_main".

    1>MenueZimmerstati.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol
    ""void __cdecl StatiFreieBelegteZimmer(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class EinzelZimmer,class DoppelZimmer)"
    (?StatiFreieBelegteZimmer@@YAXV?basic_string@DU?basic\_string@DU?char_traits@D@std@@V?$allocator@D@2@@std@@VEinzelZimmer@@VDoppelZimmer@@@Z)" in Funktion
    ""void __cdecl MenueZimmerstati(class EinzelZimmer * const,class DoppelZimmer * const)" (?MenueZimmerstati@@YAXQAVEinzelZimmer@@QAVDoppelZimmer@@@Z)".

    1>C:\Users\sinnlos\Documents\My Dropbox\Studium\C++\Programme_Kurs\Programme_VisualStudio\_Einsendeaufgaben\Aufbabe_2\Debug\Aufbabe_2.exe :
    fatal error LNK1120: 2 nicht aufgelöste externe Verweise.

    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========

    Wie ihr vielleicht merkt bin ich noch neu bei C++. Im Internet habe ich schon einige ähnliche Bsp gelesen, mit Zeigern, Vektoren usw., das hatten wir im Kurs aber noch nicht und leider tu ich mich schwer die ähnlichen Bsp. auf meins umzulegen.

    Könnt ihr mir vielleicht sagen was ich beim Übergeben der Felder falsch mache..?? 😕

    Danke schon mal im Voraus..!! 😃



  • Hallo,

    bei der Übergabe eines Arrays darfst du nicht die Größe mitangeben (da es sonst ein Zugriff auf das x. Element bedeutet), also

    MenueZimmerstati(EinzelZimmerArray, DoppelZimmerArray);
    // sowie
    StatiFreieBelegteZimmer(strSuchKriterium, EinzelZimmerArray, DoppelZimmerArray);
    

    Im Sinne von OOP wäre es aber besser du hättest nur eine Liste von Zimmern (z.B. std::vector<Zimmer*> ) und die Funktionen würden nur mit den virtuellen Funktionen von Zimmer arbeiten.
    Haben denn die Klassen Einzel- und Doppelzimmer unterschiedliche Member, weil sonst würde ja auch einfach ein Member "AnzahlBetten" in der Basisklasse "Zimmer" reichen?



  • Ich sag nur Typ != Typ[].
    Wenn du im Prototyp nur Einzelzimmer schreibst, in der Implementierung aber Einzelzimmer[], dann sind das zwei verschiedene Funktionen. Der Linker sucht dann nach einer Funktion die zur entsprechenden Signatur passt. Da Foo(Typ) etwas anderes als Foo(Typ[]) ist findet er nichts und beschwert sich.
    Die Lösung ist also: Auch im Prototyp die eckigen Klammern an den Typnamen hängen.
    Nebenbei: Die Grenzenangabe bei Parametern beachtet der Compiler gar nicht, intern wird nur ein Zeiger übergeben (call by refrence).
    Und beim Aufruf einer Funktion die ein Array als Parameter haben möchte schreibt man Foo(ArrayName) und nicht Foo(ArrayName[ArrayGröße].

    EDIT: Zu langsam 😡


  • Mod

    Noch einer. Guck dir mal die anderen Threads hier im Forum an, scheint so als sei euer Kurs mit seiner Hausaufgabe ziemlich überfordert.



  • Danke für die schnellen Antworten..!! 😃 😃

    @ Th69
    Einfach die Größenangabe weglassen geht nicht, da bekomme ich schon bei schreiben einen Hinweis dass das ungültig ist (Visual C++) und kompilieren ist dann natürlich auch nicht drin...
    Hast du vielleicht einen Tip wo das mit der Liste und den Vektoren gut erklärt ist..? ..vielleicht mit Codebsp...?
    Fällt das auch unter die Kategorie Zeiger..?

    @ Jonas OSDever
    Hab ich was falsches geschrieben, oder hast du da was falsch interpretiert..? EinzelZimmer ist ja die Klasse, also der Datentyp vom Feld EinzelZimmerArray, da kommen doch auf keinen Fall die [] hin...?? 😕

    @ SeppJ
    Du müsstest mal die Schulungsunterlagen sehen..da waren teilweise auch die Codebeispiele falsch und haben nicht funktioniert..und das Buch das uns empfohlen wurde enthält NICHTS (!!) über Klassen... 😞 ..also bitte entschuldige mir/uns dass wir Schwierigkeiten haben... 😉



  • PS:
    Die Zimmer unterscheiden sich nur durch die Zimmernummern E01-E10 & D01-D10 und ihren Preis.
    Die Unterklassen habe ich gemacht um das mit der Vererbung und dem verwenden der Methoden zu üben... 😉



  • @ Jonas OSDever
    Hab jetzt deinen Tip probiert und so geht´s..!!
    😃 😃 VIELEN DANK..!! 😃 😃



  • Eisenspitze schrieb:

    @ SeppJ
    Du müsstest mal die Schulungsunterlagen sehen..da waren teilweise auch die Codebeispiele falsch und haben nicht funktioniert..und das Buch das uns empfohlen wurde enthält NICHTS (!!) über Klassen... 😞 ..also bitte entschuldige mir/uns dass wir Schwierigkeiten haben... 😉

    Welches Buch wurde euch denn empfohlen?

    Aus deinem letzten Beitrag schließe ich, dass sich das mit meiner 'falschen Interpretation' wohl erledigt hat, oder?
    Ich bezog mich auf den Prototyp

    void MenueZimmerstati(EinzelZimmer, DoppelZimmer);
    

    der mit

    void MenueZimmerstati(EinzelZimmer EinzelZimmerArray[10], DoppelZimmer DoppelZimmerArray[10])
    

    nicht zusammenpasst.



  • Verzeih mir bitte falls es so rübergekommen ist als würde ich dir was unterstellen... 😮

    Das ganze beschäftigt mich jetzt schon ein paar Tage und ich stelle fest dass ich einfach noch keine Ahnung vom C++ programmieren habe, wenn ich hier im Netz so rumsurve... ..und ich wusste einfach nicht dass man die [] auch an den Datentyp schreiben kann/muss.
    Kannst du mir das vielleicht erklären..? Was passiert da..?

    Das Buch heißt C-Programmierung lernen, von André Willms - und zu meiner Schande muss ich gestehen da steht schon was, nur über Strukturen und wie ich mittlerweile rausgefunden habe gibt´s Klassen erst seit C++... 😞 😕

    Das nächste Mal schmeiß ich das Skript weg und mach´s gleich aus´m Buch, dann kann ich´s auch leister lesen wenn fortlaufende Bsp. drin sind... 😉

    Also nochmals Danke..!! 😃



  • Sollt ihr denn jetzt C oder C++ nutzen? Bist du dir da sicher? Warum sollte man ein C Buch empfehlen, wenn C++ gefragt ist?



  • Ganz sicher. Empfohlen wurde uns das Buch und als Kompiler Dev C++.
    Meinem Statikprof (der auch einiges mit C/C++ macht) meinte es wäre eh besser zuerst C zu lernen, dabei hat er auch die Zeiger erwähnt, also hab ich mich nicht weiter gewundert...



  • Eisenspitze schrieb:

    Kompiler Dev C++.

    oO Na dann viel Spaß.
    Wie viel Zeit bleibt denn noch für diese Aufgabe? Ich meine man kann schon gut erst C und dann C++ lernen, aber auch für die Grundlagen sollte man etwas Zeit einplanen.



  • Die Empfehlung hab ich übergangen und nutze Visual C++, dass ist zum Lernen und Fehlersuchen deutlich effektiver... 😉

    Abgeben muss ich die Aufgabe am Mo., das ist noch zu schaffen..das einzige Problem war jetzt wirklich die Übergabe der Zimmer, bei mir jetzt eben in Arrays, an andere Funktionen. 🙄

    Klassen/Unterklassen definieren, die Vererbung, Funktionen auslagern, Menüs erstellen usw habe ich kapiert, ziemlich sicher 😉 , das war auch relativ leicht zu recherchieren. Auch "normale" Variablen mit Zeigern an Funktionen übergeben hab ich schon mal mit Erfolg versucht..also den Rest bekomme ich wohl hin..und ich hab halt auch mega Spaß dabei... :p



  • Also erstmal, ich will dir nix unterstellen. Ich möchte nur, dass du verstehst, warum mein Tipp funktioniert hat. Denn es gibt nichts schlimmeres (insbesondere für Anfänger) als etwas zu programmien, ohne zu wissen warum und wie es funktioniert.
    Also, hier kommt die Erklärung. Für den Compiler ist Typ und Typ[] ein Unterschied. Das liegt daran, dass ein Feld (also mehrere Variablen dieses Typs im Speicher aneinandergekleistert) so gesehen eine Art Container für mehrere Variablen gleichen Typs ist, die Über einen Index angesprochen werden. Und so erklärt sich letzendlich auch warum

    Foo(Bar);
    

    und

    Foo(Bar[]);
    

    nicht das gleiche sind. Der Compiler kann so unterscheiden, ob du nur eine Variable vom Typ Bar oder ein Feld vom Typ Bar haben willst. Wär ja auch schlimm wenn nicht. Was sollte z.B.

    int Quadrat(int Zahl) { return Zahl * Zahl; }
    

    machen, wenn ihm ein Array übergeben wird (sofern der Compi das durchgehen lassen würde)? Du siehst: Es hat seinene Gründe auch bei Parametern zwischen Array-Parametern und normalen Parametern zu unterscheiden.

    EDIT: Die Frage von cooky541 stell ich mir aber auch: Warum C Buch, wenn C++ gelehrt wird? 😕



  • Eisenspitze schrieb:

    Die Empfehlung hab ich übergangen und nutze Visual C++, dass ist zum Lernen und Fehlersuchen deutlich effektiver...

    👍

    Eisenspitze schrieb:

    Abgeben muss ich die Aufgabe am Mo., das ist noch zu schaffen..

    Die Frage ist halt wie viel du verstanden hast..

    Eisenspitze schrieb:

    und ich hab halt auch mega Spaß dabei

    Das ist immer ein gutes Zeichen dafür, dass du das auch packst.

    Wenn du Pointer verstanden hast vielleicht noch ein Tipp zu Arrays:

    void foo(int i[10]); // daraus macht der Compiler:
    void foo(int *i)
    {
      i[5] = 3; // Daraus macht der Compiler:
      *(i + 5) = 3;
    }
    

    Nur zum Verständnis. Das bedeutet nämlich dass Arrays so nicht kopiert werden, und das bedeutet, dass du die Dinge, die du in der Funktion am Array änderst, auch außerhalb änderst. (Und dass sich sizeof nicht so verhält wie man es vielleicht erwartet.)

    Weiter ist die Verwendung von system("pause") im Code etwas fragwürdig, da das nicht überall funktioniert. Vielleicht postest du mal etwas mehr von der Aufgabe wenn du weiter fortgeschritten bist, aber bitte ohne jede Zeile einzeln zu kommentieren, das bringt einen total aus dem Lesefluss. 😉



  • Jonas OSDever schrieb:

    EDIT: Die Frage von Pi stell ich mir aber auch: Warum C Buch, wenn C++ gelehrt wird? 😕

    Warum halten mich alle für ne Zahl? -.-



  • @Jonas
    Danke für die Erklärung, es ist echt unbefriedigend was zu programmieren was ich dann nicht mehr wiederholen kann... 😉

    @cooky451
    Auch dir danke für deinen Hinweis, das denke ich ist mir klar... 😃

    Wegen dem Code posten, kann ich auch Dateien hochladen..? Es ist schon ziemlich viel Code... 😕 ..alles peinlich genau kommentiert, da gibt´s Punkte drauf... 😉 ..aber dass lösch ich dann halt raus... 😃

    Wie macht ihr das mit den Kommentaren..? Teilweise hab ich schon Code ganz ohne gesehen, ist das nur schwierig weil ich Neuling bin..??



  • ..sorry, es ist auch schon spät..gemeint war ob das nur schwierig für mich zum leesn ist, weil ich Neuling bin... 😉

    Gute Nacht, morgen geht´s weiter... 😃



  • Eisenspitze schrieb:

    Wie macht ihr das mit den Kommentaren..?

    Den meisten Anfängern wird leider nur gesagt: Kommentiert viel und alles! Kommentare sind toll! (Könnte ein Zitat von meinem Informatiklehrer sein..)
    Aber wie und was man kommentiert wird völlig vernachlässigt. Denn viel wichtiger ist: Kommentieren warum man etwas macht und nicht was man macht, denn das steht ja im Code. Es gibt nichts Schlimmeres als:

    int main()
    {
      // Datei öffnen
      std::ifstream file("blubb.txt");
      // Aus Datei lesen
      std::string s;
      file >> s;
      // ...
    }
    

    Das ist schon mal die Grundregel. Weiter geht es mit: Großflächig kommentieren. Vielleicht vor eine lange Funktion/Klasse schreiben was sie macht, aber nicht jede Zeile kommentieren. Du darfst ruhig davon ausgehen, dass derjenige der den Code liest C++ kann, sonst hilft auch kein Kommentar mehr. Einzelne Zeilen nur dann kommentieren, wenn du denkst dass sie schwer verständlich sind. Und auch dann an die erste Regel denken: Kommentieren warum man etwas macht und nicht was man macht.

    Und nein, man kann hier nichts hochladen. Solange du nicht schon wie deine Kollegen 600 Zeilen Code hast, poste es einfach hier. Ansonsten lade es halt irgendwo hoch. Oder nutze gleich Seiten wie http://pastebin.com .



  • @cooky541: Sorry, du bietest dich halt als Pi an :p 😃
    @Eisenspitze: Wie gesagt, wenns nicht übermäßig lang ist Poste es einfach, ansonsten lads irgendow hoch.
    Zum hierposten: Wesentliche kommentare dürfen drin bleiben (z.B. die Beschreibung was eine Funktion von dier tut (bzw. tuen sollte) aber unwesentliches (z.B. dass man mit ofstream Dateien schreiben kann) fliegt raus. Außerdem solltest du den Code auf die Funktion in der der Fehler (vermutlich) auftritt sowie ihren Aufruf reduzieren. Beim Aufruf solltest du aber auch den für den Aufruf wichtigen Code mitposten, z.B. wie bestimmte Variablen initialisiert werden.



  • Danke für den Tipp, der ist echt gut.

    Die Dateien habe ich hochgeladen, sorry dass ich auch hier ein Neuling bin, ich hab´s bei Megaupload hochgeladen:

    main: http://www.megaupload.com/?d=9MUL27GV


Anmelden zum Antworten