Objekt speichert snach Konstruktor Werte nicht oder falsch?
-
Ich sehe da zwei Konstruktoraufrufe und deren Ergebnis wird sofort verworfen. Aber ich sehe viele schlimme Sachen aus der Jürgen Wolf Schule der Pfuscherei:
Google die Sachen, die du nicht verstehst:
- Dein Konstruktor sollte wohl eher eine Initialisierungsliste sein.
- Ungarische Notation in C++? Ob das so eine gute Idee ist?
- Was soll dies tun:
this->oWuerfel = &Wuerfel::Wuerfel(1, 6);? Dies ist wohl die Zeile, die du meinst. Dies konstruiert ein Würfelobjekt, weist dessen Adresse oWuerfel zu und zerstört dann den Wuerfel. Pointerpfuscherei. - `Spieler* pSpieler[iAnzSpieler];
` Ein Array von Zeigern? Sicher, dass du dies möchtest?.
- `Spieler* pSpieler[iAnzSpieler];
` Arrays variabler Länge gibt es als Erweiterung gewisser Compiler, aber sind kein reguläres C++. Nimm std::vector.
- printf in C++. Warum?
- scanf in C++. Warum?
- scanf und std::cin gemischt. Hast du das überhaupt selber geschrieben oder aus Programmfragmenten aus dem Internet zusammengeklickt?
- fflush(stdin). Undefiniertes Verhalten Ahoi. Zumal das Array variabler Länge weiter oben andeutet, dass du vermutlich den GCC als Compiler benutzt. fflush(stdin) ist aber eine Compilererweiterung des MSVC. Dieser wiederum kann keine VLAs. Also geht da auf jeden Fall etwas schief.
pSpieler[i-1] = &Spieler::Spieler(sName);Nochmal so ein Pointerpfusch genau wie oben. Wo hast du diesen Mist her? Was soll das erreichen? Wieso machst du es nicht ganz normal?
-
SeppJ schrieb:
Dies ist wohl die Zeile, die du meinst. Dies konstruiert ein Würfelobjekt, weist dessen Adresse oWuerfel zu und zerstört dann den Wuerfel. Pointerpfuscherei.
Nein, das ist schlicht und einfach kein gültiges C++

-
Hallo,
Danke für die Antworten. Ja es ist richtig, ich kann vermtulich vieles besser machen.
Dein Konstruktor sollte wohl eher eine Initialisierungsliste sein.
Initialisierungslisten kannte ich bisher noch nicht. Ist aber hier ich nicht für den Fehler verantwortlich.
Ungarische Notation in C++? Ob das so eine gute Idee ist?
Naja mein Professor meint ja und dass etwa 80% der Unternehmen das als Programmierrichtlinie verwenden. Sicherlich eine subjektive Meinung.
Was soll dies tun: this->oWuerfel = &Wuerfel::Wuerfel(1, 6);? Dies ist wohl die Zeile, die du meinst. Dies konstruiert ein Würfelobjekt, weist dessen Adresse oWuerfel zu und zerstört dann den Wuerfel. Pointerpfuscherei.
Nach meinem Verständnis wird von rechts nach links gearbeitet. Grob:
-Wuerfel::Wuerfel(1, 6) //Würfel wird erzeug
-&Wuerfel::Wuerfel(1, 6) //Speicherzelle von dem erzeugten Würfel
-this->oWuerfel = &Wuerfel::Wuerfel(1, 6) //Speicherzelle des Würfels wird der Membervariablen zugewiesen.
Dass der Würfel danach zerstört wird ist mir so nicht bekannt. Ich würde es ja wirklich gerne vermeiden mit Pointern zu arbeiten. Ich komme ja eignetlich aus der Java Welt, aber im Netz fidne ich hauptsächlich Beispiele die mit Pointern arbeiten. Ich habe auch schon versucht ohne Pointer zu arbeiten, aber dann brauchte ich immer auch einen Standardkonstruktor, da z.B. Spieler* pSpieler[iAnzSpieler]; erlaubt ist, Spieler spieler[iAnzSpieler] aber nicht. Ich würde es aber gerne vermeiden wollen einen Standardkonstruktor zu verwenden.Spieler* pSpieler[iAnzSpieler]; Ein Array von Zeigern? Sicher, dass du dies möchtest?.
Naja ich habe mich dafür aufgrund der Standardkonstruktorproblematik entschieden. Spieler spieler[3]; wäre mir persönlich 10 mal lieber.
Spieler* pSpieler[iAnzSpieler]; Arrays variabler Länge gibt es als Erweiterung gewisser Compiler, aber sind kein reguläres C++. Nimm std::vector.
Eine paar Zeilen weiter oben steht int const iAnzSpieler = 10; Ich dachte mir ich ziehe die Konfiguration nach oben in den Code, damit man nicht irgendwo in der mitte suchen muss. Die Anzahl ist also quasi fix.
printf in C++. Warum?
scanf in C++. Warum?Dass sind die Wege die ich bisher kannte um Werte einzulesen und auszugeben.
scanf und std::cin gemischt. Hast du das überhaupt selber geschrieben oder aus Programmfragmenten aus dem Internet zusammengeklickt?
Ja habe ich selbst geschrieben. Am Anfang habe ich nur mit scanf und printf gearbeitet, bis ich dann ein Problem bei den strings hatte die ich nicht mit scanf einlesen konnte. Deshalb habe ich dann cin und cout benutzt.
fflush(stdin). Undefiniertes Verhalten Ahoi. Zumal das Array variabler Länge weiter oben andeutet, dass du vermutlich den GCC als Compiler benutzt. fflush(stdin) ist aber eine Compilererweiterung des MSVC. Dieser wiederum kann keine VLAs. Also geht da auf jeden Fall etwas schief.
Der Professor hat gemeint, wir sollen fflush(stdin) nach jeder Verwendung von scanf schreiben, da ansonsten die Konsole nicht mehr "anhält", wenn man das nächste mal getchar() schreibt.
pSpieler[i-1] = &Spieler::Spieler(sName); Nochmal so ein Pointerpfusch genau wie oben. Wo hast du diesen Mist her? Was soll das erreichen? Wieso machst du es nicht ganz normal?
Weil ich auf den Standardkonstruktor verzichten will und nur einen Konstruktor erlauben bei dem der Spieler mit richtigen Werten erstellt wird.
Wenn du Pointer nicht verstehst, dann nutze sie auch nicht. Der Spieler den du in der Schleife erstellst existiert nur in seinem Scope. Du musst ihn kopieren, keinen Pointer auf ihn Speichern.
Die Einstellung finde ich falsch. Ich arbeite nicht für eine Firma, sondern mache ein Übungsprogramm. Da finde ich es genau richtig neue Sachen auszuprobieren. Die Dekleration des Spielerarrays ist doch außerhalb der Schleife, dann reicht mir der Scope doch. Aber ich vermute Du meintest damit etwas anderes.
Gruß hyperion
-
hyperion1 schrieb:
Initialisierungslisten kannte ich bisher noch nicht. Ist aber hier ich nicht für den Fehler verantwortlich.
Komische Lernreihenfolge. Jetzt wo du sie kennst, nutze sie.
hyperion1 schrieb:
Naja mein Professor meint ja und dass etwa 80% der Unternehmen das als Programmierrichtlinie verwenden. Sicherlich eine subjektive Meinung.
Kannst du uns mal ein Unternehmen nennen, dass in C**++** entwickelt, und durchgängig auf die ungarische Notation setzt?
hyperion1 schrieb:
Nach meinem Verständnis wird von rechts nach links gearbeitet.
Das stimmt. Aber du erzeugst ein Temporäres Objekt und speicherst die Adresse. Dass das nicht klappen kann, sollte doch einleuchtend sein?
hyperion1 schrieb:
Eine paar Zeilen weiter oben steht int const iAnzSpieler = 10; Ich dachte mir ich ziehe die Konfiguration nach oben in den Code, damit man nicht irgendwo in der mitte suchen muss. Die Anzahl ist also quasi fix.
Nimm trotzdem std::vector und lass den Nutzer entscheiden wie viele Spieler es gibt. Oder prüfe vector.size() vs SpielerZahl. Oder nimm wenigstens std::unique_ptr, aber das ist eine andere Geschichte, nimm eine Lösung von oben.

hyperion1 schrieb:
Deshalb habe ich dann cin und cout benutzt.
Nutze ab jetzt immer std::cin und std::cout.
hyperion1 schrieb:
Der Professor hat gemeint, wir sollen fflush(stdin) nach jeder Verwendung von scanf schreiben, da ansonsten die Konsole nicht mehr "anhält", wenn man das nächste mal getchar() schreibt.
*schnief* ernsthaft?

hyperion1 schrieb:
Weil ich auf den Standardkonstruktor verzichten will und nur einen Konstruktor erlauben bei dem der Spieler mit richtigen Werten erstellt wird.
Das hat damit nichts zu tun. Siehe meinen Code oben.
hyperion1 schrieb:
Die Einstellung finde ich falsch. Ich arbeite nicht für eine Firma, sondern mache ein Übungsprogramm.
Trotzdem bringt es nichts, etwas, das man noch nicht mal ansatzweise durchschaut hat, in irgendeinem Kontext zu verwenden. Erst mal die einzelnen Sprachelemente testen und sie hinterher auf die Aufgabe übertragen.
Edit:
Mal zur verdeutlichung:int *p; // Zeiger auf ein int, zeigt irgendwo hin. { // neuer Scope int i = 5; // Speicherplatz für i wird reserviert. p = &i; // p zeigt jetzt auf i std::cout << i << " = " << *p << '\n'; // Soweit alles gültig. std::cout << &i << " = " << p << '\n'; // Die Adresse von i } // Hier wird i zerstört std::cout << *p << '\n'; // Autsch! p zeigt noch auf i, aber i existiert nicht mehr!
-
hyperion1 schrieb:
Naja mein Professor meint ja und dass etwa 80% der Unternehmen das als Programmierrichtlinie verwenden. Sicherlich eine subjektive Meinung.
Dein Professor ist ein Idiot.
hyperion1 schrieb:
Nach meinem Verständnis wird von rechts nach links gearbeitet. Grob:
-Wuerfel::Wuerfel(1, 6) //Würfel wird erzeugHier wird nix erzeugt, weil das kein gültiger Konstruktoraufruf ist. Es muss Wuerfel(1, 6) heißen.
hyperion1 schrieb:
-&Wuerfel::Wuerfel(1, 6) //Speicherzelle von dem erzeugten Würfel
Ein ordentlicher Compiler warnt vor sowas. http://ideone.com/oCMDY
hyperion1 schrieb:
Der Professor hat gemeint...
Der Professor ist ein Idiot.
Zusammenfassung: Der Professor ist scheiße, der Compiler ist scheiße. Wechsle am besten beides.
-
Hallo,
Danke, ich habe eure Tipps nun zum Großteil umgesetzt. Es funktioniert auch soweit, sofern man es akzeptiert einen Standardkonstruktor bereitzustellen.
Gruß hyperion
-
hyperion1 schrieb:
akzeptiert einen Standardkonstruktor bereitzustellen.
class Player { std::string name_; public: Player(const std::string &name) : name_(name) // C++11 mit move {} }; int main() { const unsigned player_count = 8; std::vector<Player> players; while (players.size() != player_count) { std::cout << "Please enter player name: "; std::string name; std::cin >> name; player.push_back(Player(name)); // C++11 mit move } }
-
Kannst du nochmal erklären, was du für oder gegen Standardkonstruktoren hast? Entweder das Objekt lässt sich sinnvoll ohne Angabe von Parametern initialisieren oder eben nicht. Das ist Design, keine technische Notwendigkeit. Wenn du aus technischen Gründen einen Defaultkonstruktor brauchst, obwohl du keinen möchtest, dann machst du etwas falsch. So ein Fall wäre z.B. die Benutzung roher Arrays. Zufällig ist dies genau, was du tust. Habe ich aber schon was zu geschrieben.
-
SeppJ schrieb:
Kannst du nochmal erklären, was du für oder gegen Standardkonstruktoren hast? Entweder das Objekt lässt sich sinnvoll ohne Angabe von Parametern initialisieren oder eben nicht. Das ist Design, keine technische Notwendigkeit. Wenn du aus technischen Gründen einen Defaultkonstruktor brauchst, obwohl du keinen möchtest, dann machst du etwas falsch. So ein Fall wäre z.B. die Benutzung roher Arrays. Zufällig ist dies genau, was du tust. Habe ich aber schon was zu geschrieben.
er wird vrmtl std::vector falsch verwenden (macht irgendwas, was ein resize zur Folge hat - ich vermute mal den falschen ctor aufrufen^^)
bb
-
314159265358979 schrieb:
hyperion1 schrieb:
&Wuerfel::Wuerfel(1, 6) //Speicherzelle von dem erzeugten Würfel
Ein ordentlicher Compiler warnt vor sowas. http://ideone.com/oCMDY
Ich wundere mich gerade, dass das überhaupt kompiliert (wenn auch mit Warnung). Ich hätte gedacht, so'was geht nur beim Microsoft-Compiler mit eingeschalteten Erweiterungen...
-
Bei user-defined RValues geht das.
