Java Umsteigeprobleme
-
Hallo,
ich hoffe mal sehr daß meine Frage nicht allzu dumm is, aber ich habe schon diverse Stunden gegoogelt und versucht in den Büchern und Tutorials dazu was zu finden, aber so far ohne Erfolg.
Mein Problem bezieht sich auf Instanzen als "Variablen" in anderen Instanzen, d.h. um es am Beispiel zu verdeutlichen:
Ich schreibe ein Spiel und habe die Klasse Sternensystem, die jedesmal wenn sie mit "new" instanziiert wird diverse Instanzen der Klasse Planet instanziiert.
In Java würde ich also in der Klasse Planet sowas wieint groesse; SternenSystem heimatSystem;reinschreiben, damit jeder Planet quasi weiss, in welchem System er nun ist.
In C++ gibt es dieses Verfahren, eine Klasse quasi als Variable reinzuschreiben und dann zum Beispiel über den Konstruktor zu belegen, wohl nicht, ich glaube aber daß die Lösung meines Problems massiv was mit Zeigern und Heap zu tun haben müsste, jedoch hab ich als Javacoder davon zu wenig Ahnung um mein Problem zu lösen...
Dann wäre da noch ne Sache... Wie erkläre ich einer Klasse in C++ wen sie noch kennen sollte?
Bei Java gibts ja den import Befehl, ist das bei C++ alles über <include>?
Muss ich dann jede andere Klasse (meinetwegen CSternenSystem.cpp) einzeln per include reinholen oder wie?
-
Eigentlich besteht in dem Fall kein grosser Unterschied, zwischen Java und C++, ausser dem expliziten Gebrauch von Zeigern unter C++. Zu Zeigern solltest du dir am besten ein Tutorial durchlesen.
#include "SternenSystem.h" class Planet { private: int groesse; SternenSystem* heimatSystem; public: Planet(SternenSystem* hSystem) { heimatSystem = hSystem; } };irgendwoanders:
SternenSystem milchstrasse = new SternenSystem(); Planet erde = new Planet(milchstrasse);Zu den Includes:
Du teilst deiner Klasse in der Tat über "include" mit, wen sie "kennen" soll. Die include-Anweisung ist nichts anderes als eine Anweisung an den Compiler das "include<blub.h>" durch den text, der in "blub.h" steht zu ersetzen. Dem Compiler reicht allerdings die Deklaration der Klasse aus und er benötigt nicht die komplette Definition. Also solltest du dir angewöhnen deine Klassen in jeweils eine .h und eine .cpp aufzuteilen. In die .h kommt die reine Deklaration und in .cpp die Definition. Das erspart vor allem lange Compilezeiten.
-
Also du scheinst dich nur ansatzweise mit C++ beschäftigt zu haben. Das Problem ist, das du jetzt vonJava kommst, und versuchst dein Java-Wissen in C++ 1:1 zu übertragen. Und das geht nicht, da es sich um zwei verschiedene Sprachen handelt. Um aber deine erste Frage zu beantworten:
In C++ hast du insgesamt drei (!) verschiedene Variablen-Typen:
1. Objektvariablen
2. Referenzvariablen
3. Pointervariablen (davon gibts dann auch noch Smartpointer, anderes Thema)So, du willst also sagen, dein Planet ist IMMER und definitiv in einem Sonnensystem. Dafür würde ich eine Referenzvariable nehmen:
class Planet { private: SonnenSystem &sonnen_system; public: Planet(SonnenSystem &s) : sonnen_system(s) { } };Referenzen sind in C++ "ein anderer Name für ein Objekt." und können niemals NULL sein. Wenn du so willst, ist es ein "sicherer" Pointer. Man wird mich hier sicherlich dafür verprügeln, aber ich versuche es einem Javaner in aller Kürze zu vermitteln.

Pointer dagegen brauchst du nur dann, wenn ein Planet ein Sonnensystem kennen kann. Ist ein Unterschied, ob ein Planet immer sein Sonnensystem kennen muß! Die Geschichte mit dem Heap und Pointer ist dann eine andere Geschichte, die nur indirekt was mit deinem "Problem" zu tun hat.
class Planet { private: SonnenSystem &sonnen_system1; // Referenz SonnenSystem *sonnen_system2; // Pointer, kann auch NULL sein SonnenSystem sonnen_system3; // Eigenständige Objektinstanz!!! public: // da sonnen_system1 nicht NULL sein darf, // muß es vor der Konstruktion bekannt sein. // hier vom User per Konstruktor-Parameter übergeben: Planet(SonnenSystem &s) : sonnen_system1(s) { } };class Planet { private: SonnenSystem &sonnen_system; public: Planet(SonnenSystem &s) { sonnen_system = s; // FEHLER! da Konstruktion schon angelaufen. } };In C++ kommt man im Gegensatz zu C mit sehr wenig Pointern aus, und das sollte man auch so handhaben. Also nach Möglichkeit immer Referenzen benutzen, wo es möglich ist. Manchmal kommt man zwar nicht um Pointer herum, aber kein Grund nur diese zu benutzen. Denn Referenzen wurden nicht aus Jux und Dollerei in C++ eingeführt.
-
cin schrieb:
Eigentlich besteht in dem Fall kein grosser Unterschied, zwischen Java und C++, ausser dem expliziten Gebrauch von Zeigern unter C++. Zu Zeigern solltest du dir am besten ein Tutorial durchlesen.
Also, wenn es keinen Unterschied geben würde, würde es diese Fragen nicht geben, oder? Warum empfihlst du in dem Fall keinen Referenzen? Ich kann mir nicht vorstellen, das ein Planet in KEINEM Sonnensystem sein kann.
-
Ja, GEIL!!!!

Danke danke danke für die schnelle und gute Antwort, bin jetzt wesentlich schlauer, hatte nur auch noch die ganze Reihgenfolge und die Prototypen verplant, zusammen mti der ganz anderen Setzung von {} unter C++.
Eine letzte Frage bleibt aber noch:
Wie sieht das aus mit der Einbindung von ganzen Verzeichnissen per <include>?Nehmen wir mal an, ich habe in C:\meinProjekt\unterverzeichnis alle meine lustigen .cpp und .hpp Dateien (sind .h eigentlich besser? oder ist das nur um schöneren Stil zu haben/besser kompatibel zu sein oder sonstwas?) und will nun möglichst alles mit einem Befehl reinknallen, wie sieht da der geeignete Befehl aus?
Ich hab da auch schon versucht was zu zu finden, immerhin stand irgendwo daß man wohl nur "/" und keine "\" nehmen sollte oder so, aber wenn ich versuche ihm nen Pfad zu füttern meint gcc nur lakonisch, er würde keine Datei und kein Verzeichnis mit dem Namen finden

und nochmals DANKE
-
Um alle Headers mit einem Schlag zu inkluden, mußt du eine weitere Header erstellen, die alle Header inkludiert.

// Das ist Datei: planeten_spiel.hpp #include "planet.hpp" #include "sonnensystem.hpp" #include "imperator.hpp"Und dann kannst du in deinem Spiel z.B. einfach planeten_spiel.hpp inkludieren.
ABER, sowas macht man eigentlich nicht. Denn in sehr großen Projekten und großen Libraries kann dadurch die Compile-Zeit extrem groß werden. Klar, für kleine Projekte ist das kein Problem. Aber man gewöhnt sich dann halt schlechten Stil an. Sowas würde ich nur zum "ebend mal ausprobieren" benutzen.
Ja, Slash anstatt Backslash deshalb benutzen, weil unter Linux, Unix und anderen Systemen das Backslash als Pfadtrenner unbekannt ist. Windows kommt aber problemlos mit dem gewöhnlichen Slash aus.
Zu deinem Problem, das er deine Includes nicht findet. Folgende Regeln:
// spitze Klammern sagen dem Präprozessor, er soll in seinen Systempfaden bzw. Compilerpfaden nach der Datei suchen: #include <header1.hpp> // Anführungsstriche sagen dem Präprozessor, er soll im aktuellen Projektverzeichnis nach der Datei suchen: #include "header2.hpp".hpp oder .h ist geschmackssache, manche machen sogar .hxx. Aber .hpp sagt schon mal dem User aus, das es sich um eine C++ Headerdatei handelt. Aber dem Compiler ist es egal.
-
Hm, ich muss mein Problem nochmal präzisieren:
kann ich zum beispiel schreiben:
#include "C:/Projektverzeichnis/unterverzeichnis/"um alle Dateien in diesem Verzeichnis auf einmal einzubinden?
oder kann ich nur Dateien, die unterhalb meines Hauptordners liegen z.b. mit
#include "/StellarObj/"einbinden?
Oder wirklich nur eine einzige Datei pro #include alá:
#include "/StellarObj/Planet.hpp" #include "/StellarObj/Ich bekomme bei meinen Tests hier ständig nur "not found" errors, ausser ich gebe ihm eine einzelne Datei in dem Verzeichnis in dem die Klasse mit dem #include liegt
#include "Planet.hpp"das funzt immerhin...

-
Nein, du mußt eine DATEI angeben. Du kannst schlecht ein Verzeichnis inkludieren, weil der Präprozessor (ein Programm das vor dem Compiler läuft) dumm ist und beim #include eine reine Textersetzung macht. Soll heißen, da wo #include steht, wird zur Laufzeit der Inhalt der Headerdatei reinkopiert (ja, es ist ein echtes Copy+Paste, nur das man das nicht sieht, weil das nur zur Laufzeit passiert) und der Compiler bekommt fertige Sourcedateien.
So funktioniert nunmal das Kompiliersystem von C++.
-
Vielen Dank für deine Geduld, aber wenn man das ganze Java Zeugs im Kopf hat ist einiges in den Tutorials doch sehr mißverständlich.
Ich gehe dann jetzt schlafen, hab morgen um 7.15 n Date mitm Chirurgen

-
So, nachdem ich im Krankehaus war und mein Körper um eine Titanschraube ärmer ist dann noch zwei Fragen:
1. : Warum
Planet(SonnenSystem &s) : sonnen_system1(s)?
Was tut der Code nach dem ":" genau?
und
2. Warum schreibt ihr eure Funktionen in den public Teil der Klasse, in meinem Buch wird immer alles nach der Klasse z.b. mit
CSun::erstelleSonne()deklariert.
Mal wieder nur Übersichtlichkeit?
-
zu 1.
Das Konstrukt nennt man Initialisierungsliste. Da in C++ Referenzen nie uninitialisiert sein dürfen, sowie Objektinstanzen beim Aufruf dieses Konstruktors auch konstruiert werden, ist das der Platz um Referenzen zu initialisieren und Objekte zu konstruieren. Beispiel:class X { GrosserTyp a; RefTyp & b; X(RefTyp& arg) // hier werden a und b initialisiert { a = GrosserTyp(12); // ineffizient: a wird zuerst initialisiert und dann überschrieben b = arg; // VERBOTEN, weil b vorher hätte benutzt werden können } // Lösung: C(RefTyp& arg): a(12), // GrosserTyp wird mit Parameter 12 initialisiert b(arg) // Die Referenz wird mit arg initialisiert {} };zu 2.
Das hängt von zweierlei ab: Hier im Forum wird es oft der Übersichtlichkeit halber "inline" geschrieben. Das hat allerdings den Nachteil dass der Code in jeder Compilierungseinheit neu erzeugt wird (Platzverschwendung) und zudem doppelte Symbole hervorrufen kann. Manchmal ist inlining gewünscht, etwa damit der Compiler besser optimieren kann, bei großen Methoden würde ich davon eher abraten.
Wenn Du Dein Projekt ausserdem aufteilen willst (.cpp/.hpp), bleibt Dir garnichts anderes übrig als die Methodenkörper ausserhalb der Klasse (die in der .hpp-Datei steht) in die .cpp zu packen.
-
Das mit dem Inlining mache ich nur hier im Forum, damit ich nicht so viel tippen muß. Ich habe dadurch ja keinen Nachteil, da der Fragesteller nur ein bestimmtes Problem gelöst haben will. Umsetzen muß es der Fragesteller dann für sich auf den richtigen Weg.
So machen das alle anderen hier auch, ist nur Fauelheit, weil man pers. keinen Vorteil hat, es "richtig" zu machen.
-
Eine kleine Frage: Wieso willst du von Java auf C++ umsteigen?
@Artchi: noch einen Post, dann hast du 3000

-
xindon schrieb:
Eine kleine Frage: Wieso willst du von Java auf C++ umsteigen?
@Artchi: noch einen Post, dann hast du 3000

1. Weil ich denke daß man C++ einfach können sollte als Informatiker (auch wegen Hintergrundwissen, es ist ja der Vorfahre von Java)
2. Weil C++ in der Spieleentwicklung (und damit beschäftige ich mich) absoluter Standard ist.
-
GrafToericht schrieb:
xindon schrieb:
Eine kleine Frage: Wieso willst du von Java auf C++ umsteigen?
@Artchi: noch einen Post, dann hast du 3000

1. Weil ich denke daß man C++ einfach können sollte als Informatiker (auch wegen Hintergrundwissen, es ist ja der Vorfahre von Java)
2. Weil C++ in der Spieleentwicklung (und damit beschäftige ich mich) absoluter Standard ist.
Die Frage ist vll. dumm, aber warum antwortest du auf einen post
4 monate später? (Nur rein Interessenhalber)
-
Klar darfst du fragen, es gibt keine dummen Fragen, nur dumme Antworten..
Die Antwort ist:
Weil ich wegen meines Studiums (genauergesagt Analysis II und Programmierpraktikum in Java) keine Zeit hatte, mich um mein Spiel zu kümmern und nun ,bewaffnet mit mehreren Büchern, wieder die Arbeit aufnehme.Was mich gleich dazu bringt daß ich da ne Frage habe. Es geht um Objektorientierung und wie das genau aussieht in C++.
Wann benutze ich zur Instanziierung einer Klasse z.b.
Game Spiel5; Spiel5.starten();und wann mus ich sowas hier bringen:
pointerPlayer = NULL; pointerPlayer = new Player; pointerPlayer->schiesseBall();und kann ich auch direkt auf eine Membervariable der Klasse zugreifen (wenn diese public ist) und wie geht das (bitte mit Code!) in beiden Fällen?
Kenne solche Unterschiede bei Instanziierung und Zugriff von Java her nicht

Hat das irgendwas mit dem Umstand zu tun, ob ich den Code in mehrere Dateien aufgeteilt habe?
Mein Lehrbuch schreibt da leider nix explizites zu und die Compiler errors mit denen ich mich rumschlage helfen mir auch nicht so sehr weiter...
-
Mit new instanzierst du dynamische Objekte, diese bleiben solange bestehen, bis du sie mit delete wieder löschst.
Ohne new sondern als Stackobjekt, legst du Objekte an, die nur solange bestehen, bis sie den Scope verlassen.
{ // Scope-Anfang Game spiel15; Game *spiel20 = new Game(); //.. } //Scope-Ende -> spiel15 wird hier autom. gelöscht, spiel20 existiert weiter.
-
Okay, bleibt noch die Frage mit dem Zugriff auf Membervariablen...
Geht das dann völlig analog zu Java mit
spiel5.anzahlSpieler;machen bzw. im zweiten Fall mit
spiel5->anzahlSpieler;?
In meinem Buch wird das immer mit Funktionen gemacht also z.b.
spiel5->getAnzahlSpieler();aber mich würde interessieren, ob das auch ganz direkt ginge
EDIT: Habs selber rausbekommen, danke

-
Noch eine (etwas knifflige?) Sache, im wesentlichen eine Anlehnung an das ganz oben beschriebene Problem:
Ich habe zwei Klassen (in .hpp un .cpp Dateien) hat, meinetwegen ein Spiel und eine Klasse für ein Menü, die erste Klasse ruft die zweite auf (also das Spiel startet ein Menü), soll ihr "this" als Parameter mitgeben, damit das Menu dem Spiel sagen kann, was vom User eingegeben wurde.
//Datei Game.cpp Menu *pointerMenu; pointerMenu = 0; pointerMenu = new Menu(this);//Datei Menu.cpp Menu (Game *pointerGame) //Der Compiler meckert schon, wenn da was anderes als "const" steht //in der Header Datei, danach kommt dann sowas wie ")" expected before "*" :( { pointerGame->galaxySize = 25; //nur was zum testen pointerGame->numplayers = 100; }Kann mir da wer weiterhelfen? Ich hoffe mein Problem ist deutlich geworden...
-
Hi,
GrafToericht schrieb:
...
...//in der Header Datei, danach kommt dann sowas wie ")" expected before "*" :( ......
Das ist die "typische Fehlermeldung", wenn er einen Typen (hier wohl "Game") nicht kennt. Abhilfe: Richtiges Inkludieren.
Da Du den Typen schon bei der Deklaration von Menu brauchst, schlage ich vor://in Datei Menu.hpp #include "Game.h"//in Datei Menu.cpp #include "Menu.h"Mit Letzterem stellst Du gleichzeitig sicher, dass Deklaration (in hpp) und Definition (in cpp) nicht auseinanderlaufen.
Da Du offensichtlich "gegenseitig verweist" (Game -> Menu und Menu->Game), solltest Du unbedingt "include guards" verwenden).Gruß,
Simon2.
-
GrafToericht schrieb:
...
...//Datei Menu.cpp Menu (Game *pointerGame) //Der Compiler meckert schon, wenn da was anderes als "const" steht .......
Magst Du das etwas qualifizierter schildern ?
WO in den jeweiligen Dateien steht das ?
In den Konstruktoren ? (also Game::Game(...) und Menu::Menu(...)) In "const-Funktionen" ?Gruß,
Simon2.