Java Umsteigeprobleme



  • 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.



  • Um jetzt mal allzu umständlichen Schilderungen aus dem Weg zu gehen, hier der Code:

    //Datei Game.hpp
    #include "Menu.hpp"
    
    class Game
    {
          public:
                 Game();
    
                 int galaxySize;
                 int numPlayers;
    
                 Menu *pointerMenu;        
    };
    
    //Datei Game.cpp
    #include "Game.hpp"
    
    Game::Game() 
    {
                 pointerMenu = 0;
    
                 pointerMenu = new Menu(this);
    }
    
    //Datei Menu.hpp
    //#include "Game.hpp" Kann ich nicht machen sonst "include nested too deeply"
    
    class Menu
    {
          public:
    
          Menu(Game *pointerGame);
    };
    
    //Datei Menu.cpp
    #include "Menu.hpp"
    
    Menu :: Menu (Game *pointerGame)
    {
             pointerGame->galaxySize = 25;
             pointerGame->numplayers = 100;
    
    }
    

    Das Gedankliche Problem was dahintersteht ist, daß das Menü ja auf Eingabe des Users wartet und diese dann an das Spiel weiterreicht, wenn der User bestätigt.

    Deswegen muss das Menu ja das Spiel referenzieren können, nachdem es selbst von dem Spiel instanziiert wurde (ich habe das mit "this" als Konstruktorparameter versucht).

    Nur kann ich ja die Headerdateien nicht gegenseitig includen, sonst gibts ja ne Endlosschleife...



  • Du mußt die Game.hpp in der Menu.cpp inkludieren, weil du sie da brauchst. In der Menu.hpp muß der Compiler nur wissen, dass eine Klasse Game existiert. Dafür nimmt man eine forward-Deklaration

    //Datei Menu.hpp
    //#include "Game.hpp" Kann ich nicht machen sonst "include nested too deeply" - Richtig
    // statt dessen
    class Game;
    
    class Menu
    {
          public:
    
          Menu(Game *pointerGame);
    };
    


  • Danke Braunstein, aber nachdem ich das geändert habe bekomme ich immernoch nen Fehler nämlich:

    10 C:\Dev-Cpp\PointerProject\Game.hpp ISO C++ forbids declaration of `Menu' with no type

    Also hier in Zeile 12 der Game.hpp kennt er Menu nicht..


Anmelden zum Antworten