Anfängerfrage wegen Klasse



  • Guten Morgen zusammen,
    ich scheitere derzeit am Implementieren meiner Beispielklasse. Ich möchte Schritt für Schritt das Spiel Pong nachstellen. Am Anfang steht das zeichnen des Spielfeldes und der beiden Schläger.
    Leider klappt es bereits mit wenigen Codezeilen nicht und ich verstehe nicht wieso.

    Hier das bisher lausige Programm:

    #include <iostream>
    
    using namespace std;
    
    class Pong {
    
    public:
        void SetSpielfeld(int x1, int y2);
        void MovePlayer();
    
    private:
        int x, y;
        int *Spielfigur1;
        Spielfigur1 = y; 
        int Spielfeld[x][y];
    };
    
    void Pong::SetSpielfeld(int x1, int y1)
    {
        x = x1;
        y = y1;
    }
    
    int main()
    {
        Pong po;
        po.SetSpielfeld(5,5);
        return 0;
    }
    

    Im Compiler erscheint immer: error: invalid use of non-static data member 'Pong::x' und der gleiche Fehler noch mit 'y'.
    Was mache ich hier den falsch?

    Speer



  • Was soll denn Zeile 14? Also: was willst Du erreichen?

    Pong::SetSpielfeld() soll wohl das Array Pong::Spielfeld erstellen.
    Das funktioniert so nicht. Die Arraygrößen müssen zur Compilezeit feststehen.

    Üblicherweise nimmst Du jetzt ein dynamisches Feld ( new ), bzw. ein Handle auf ein solches z.B. std::vector .

    SetSpielfeld()s Aufgabe würde wohl auch in einem Konstruktor abgefackelt werden.
    Hier im Forum findest Du mit Sicherheit Beispiele für zweidimensionale Spielfelder in allen Farben und Formen.



  • speer schrieb:

    private:
    int x, y;
    int *Spielfigur1;
    Spielfigur1 = y; 
    int Spielfeld[x][y];
    

    Das kann nicht kompilieren.
    Guckst du hier, sollte helfen.



  • Hallo zusammen,
    mir ist klar, dass der Compiler zur Laufzeit einen Wert benötigt. Der Aufruf in der main() erfolgt erst später. Ich könnte nun mittels #define eine Variable und Wert definieren. Dann aber habe ich doch eine globale Variable. Hier wurde immer wieder angemerkt das dass nicht gut sei.
    Was mich aber verwundert sind folgende Ausdrücke:

    private:
        int x=5, y=5;
        int Spielfeld[x][y];
    

    Wieso ist das nicht gültig?

    Speer



  • speer schrieb:

    Hallo zusammen,
    mir ist klar, dass der Compiler zur Laufzeit einen Wert benötigt. Der Aufruf in der main() erfolgt erst später. Ich könnte nun mittels #define eine Variable und Wert definieren. Dann aber habe ich doch eine globale Variable. Hier wurde immer wieder angemerkt das dass nicht gut sei.
    Was mich aber verwundert sind folgende Ausdrücke:

    private:
        int x=5, y=5;
        int Spielfeld[x][y];
    

    Wieso ist das nicht gültig?

    Speer

    Vielleicht, weils bei nachträglichem objekt.x=7 voll verwirrend wird.
    Probiers mal mit const int.



  • Hallo Volkard,
    mit const int kommt der gleiche Fehler. Wie es aussieht mag er die Dekleration des 2 Dimensionalen Array nicht. Sobald ich dort die Variablen x und y durch Werte ersetzt, ist der Compiler zufrieden.
    Also kann ich zur Laufzeit in einer Klasse kein dynamisches Array erzeugen sondern muss dies statisch tun.

    Speer


  • Mod

    Probier' mal static constexpr .

    Eigentlich hatte Volkard aber schon recht: const sollte genuegen.

    A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression [...]:
    - an lvalue-to-rvalue conversion unless it is applied to a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression

    Edit: Es muss selbstverstaendlich static sein! Sonst waere das nicht erlaubt, weil die Initialisierung ja erst im Konstruktor stattfindet.
    (Naja, der Hauptgrund waere, dass du ja im Prinzip folgendes schreibst:

    int const x = 7;
    int [this->x];
    

    Was keinen Sinn ergibt, weil dann die Groesse der Klasse von x abhaengt, und x erst im Konstruktor initialisiert wird (und evt. einen erst zur Laufzeit feststehenden Wert hat). Deswegen muss da ein static hin, dann sollte es funktionieren.)



  • Warum allozierst du den Speicher nicht einfach dynamisch? (new[], delete[]).
    Spielfeld ist dann zwar ein eindimensionales "Array", aber das ist ja auch keine Problem.



  • Singender Holzkübel schrieb:

    Warum allozierst du den Speicher nicht einfach dynamisch? (new[], delete[]).
    Spielfeld ist dann zwar ein eindimensionales "Array", aber das ist ja auch keine Problem.

    Direkt ne Ohrfeige verdient.

    Offensichtlich ist der OP noch nicht so erfahren, ihm dann aber Sauereien wie new/new[] anzubieten ist mehr als fahrlässig. Damit lässt du ihn schön vor die nächste Wand laufen, die dann nicht mehr so easy zu umschiffen ist.

    @OP:
    Nutz std:vector.



  • Skym0sh0 schrieb:

    Sauereien wie new/new[]

    Gesundheit.

    Skym0sh0 schrieb:

    Offensichtlich ist der OP noch nicht so erfahren, ihm dann aber Sauereien wie new/new[] anzubieten ist mehr als fahrlässig

    Speicherverwaltung in C++ ist fundamental. Einem C++ Anfänger zu raten irgendwelche Template-Klassen aus irgendwelchen Bibliotheken zu verwenden, und auf new/delete zu scheißen, das ist mehr als fahrlässig.



  • Singender Holzkübel schrieb:

    Skym0sh0 schrieb:

    Offensichtlich ist der OP noch nicht so erfahren, ihm dann aber Sauereien wie new/new[] anzubieten ist mehr als fahrlässig

    Speicherverwaltung in C++ ist fundamental. Einem C++ Anfänger zu raten irgendwelche Template-Klassen aus irgendwelchen Bibliotheken zu verwenden, und auf new/delete zu scheißen, das ist mehr als fahrlässig.

    Speicherverwaltung in C++ ist nicht fundamental.
    Speicherverwaltung in C++ ist etwas, was man nicht machen sollte.
    Speicherverwaltung in C++ ist fehlerhaft, unsicher, leak-anfällig, manuell, primitiv und anstrengend.
    Speicherverwaltung in C++ richtig hinzubekommen ist komplex und schwierig (wenn man es nicht gerade in RAII kapselt, wie - oh Wunder - std::vector).
    Speicherverwaltung in C++ sollte man keinem Anfänger machen lasssen.
    Speicherverwaltung in C++ sollte man Anfängern auch erst so spät wie möglich zeigen.



  • Nathan schrieb:

    Speicherverwaltung in C++ ist nicht fundamental.

    Allozierst du deinen Speicher etwa ausschließlich auf dem Stack?

    Nathan schrieb:

    Speicherverwaltung in C++ ist fehlerhaft, unsicher, leak-anfällig, manuell, primitiv und anstrengend.

    PEBKAC

    Nathan schrieb:

    Speicherverwaltung in C++ richtig hinzubekommen ist komplex und schwierig.

    Nein ist es nicht. Wenn man sich mit Scopes fließend auskennt ist das kein Problem.

    Nathan schrieb:

    Speicherverwaltung in C++ sollte man keinem Anfänger machen lasssen.
    Speicherverwaltung in C++ sollte man Anfängern auch erst so spät wie möglich zeigen.

    Wieso nicht? Wo liegt das Problem?



  • Mantras sind immer richtig, wusstest du das nicht? Murmel es solange vor dich hin, bis du es glaubst.



  • Singender Holzkübel schrieb:

    Nathan schrieb:

    Speicherverwaltung in C++ ist nicht fundamental.

    Allozierst du deinen Speicher etwa ausschließlich auf dem Stack?

    Nein, aber ich habe in meinem Code kein einziges new/new[]/delete/delete[] stehen.*

    *Bis auf mein selbstgebasteltes make_unique, aber das zählt nicht.

    Nathan schrieb:

    Speicherverwaltung in C++ ist fehlerhaft, unsicher, leak-anfällig, manuell, primitiv und anstrengend.

    PEBKAC

    Dann schreib mal bitte einen Code, der ein zweidimensionales Array von ints alloziert (ja, ich weiß, dass ist so nicht möglich, man braucht int* arr[]...), alle Elemente einlesen lässt und wieder ausgibt. Und ich sage dir, was daran falsch sein wird.

    Nathan schrieb:

    Speicherverwaltung in C++ richtig hinzubekommen ist komplex und schwierig.

    Nein ist es nicht. Wenn man sich mit Scopes fließend auskennt ist das kein Problem.

    Single entry single exit gilt nicht mehr in C++...

    Nathan schrieb:

    Speicherverwaltung in C++ sollte man keinem Anfänger machen lasssen.
    Speicherverwaltung in C++ sollte man Anfängern auch erst so spät wie möglich zeigen.

    Wieso nicht? Wo liegt das Problem?

    Es ist extrem kompliziert und schwierig das richtig hinzukriegen.



  • Nathan schrieb:

    Nathan schrieb:

    Speicherverwaltung in C++ sollte man keinem Anfänger machen lasssen.
    Speicherverwaltung in C++ sollte man Anfängern auch erst so spät wie möglich zeigen.

    Wieso nicht? Wo liegt das Problem?

    Es ist extrem kompliziert und schwierig das richtig hinzukriegen.

    Glaube ich nicht.



  • volkard schrieb:

    Nathan schrieb:

    Nathan schrieb:

    Speicherverwaltung in C++ sollte man keinem Anfänger machen lasssen.
    Speicherverwaltung in C++ sollte man Anfängern auch erst so spät wie möglich zeigen.

    Wieso nicht? Wo liegt das Problem?

    Es ist extrem kompliziert und schwierig das richtig hinzukriegen.

    Glaube ich nicht.

    Gut, falsche Adjektive.
    Es ist extrem mühselig und redunant.


  • Mod

    Also ich befolge: Zu jedem new gehört ein delete :

    auto p = new auto{784};
    
    delete p;
    

    Sogar wenn eine Exception im Konstruktor fliegt, räumt die Implementierung den allozierten Speicher weg.



  • Nathan schrieb:

    *Bis auf mein selbstgebasteltes make_unique, aber das zählt nicht.

    Selbst wenn du kein make_unique hättest, dann hättest du vllt ein paar new's/new[]'s, aber kein delete.

    Nathan schrieb:

    Nathan schrieb:

    Speicherverwaltung in C++ ist fehlerhaft, unsicher, leak-anfällig, manuell, primitiv und anstrengend.

    PEBKAC

    Dann schreib mal bitte einen Code, der ein zweidimensionales Array von ints alloziert (ja, ich weiß, dass ist so nicht möglich, man braucht int* arr[]...), alle Elemente einlesen lässt und wieder ausgibt. Und ich sage dir, was daran falsch sein wird.

    Und danach machst du das ganze auch mal für ein 3 dimensionales Array (keine Index Spielereien!)



  • Arcoth schrieb:

    Also ich befolge: Zu jedem new gehört ein delete :

    auto p = new auto{784};
    
    delete p;
    

    Sogar wenn eine Exception im Konstruktor fliegt, räumt die Implementierung den allozierten Speicher weg.

    Ich sagte in meinem Beispiel nicht ohne Grund mehrdimensional. :p
    Und jetzt tut bitte nicht alle so.



  • was gibt es hier überhaupt zu diskutieren? wer die vorteile von RAII nicht ausmerzen will ist bei C++ offensichtlich falsch.


Anmelden zum Antworten