wie kann ich eine klassenübergreifende Deklaration erstellen?

  • C++

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Bartosz.

    wie kann ich eine klassenübergreifende Deklaration erstellen?

    Moin,

    wie kann ich eine klassenübergreifende Deklaration eines Boolean erstellen? Es geht um den bool aktiv.

    ich habe wie immer meine Game Loop in der main.cpp

    C-Quellcode

    1. while (aktiv)
    2. {
    3. Game.timing();
    4. Game.input();
    5. Game.Logic();
    6. Game.render_output();
    7. }


    und in der Game.cpp soll der im Falle eines Drückens der ESC-Taste auf false gesetzt werden (Zeile 36).

    C-Quellcode

    1. void Spiel::Logic()
    2. {
    3. if (Key[0]) //↑
    4. {
    5. if (DoesPieceFit2(du.X, du.Y - 1))
    6. {
    7. du.Y = du.Y - 1;
    8. }
    9. }
    10. if (Key[1]) //↓
    11. {
    12. if (DoesPieceFit2(du.X, du.Y + 1))
    13. {
    14. du.Y = du.Y + 1;
    15. }
    16. }
    17. if (Key[2]) //←
    18. {
    19. if (DoesPieceFit2(du.X - 1, du.Y))
    20. {
    21. du.X = du.X - 1;
    22. }
    23. }
    24. if (Key[3]) //→
    25. {
    26. if (DoesPieceFit2(du.X + 1, du.Y))
    27. {
    28. du.X = du.X + 1;
    29. }
    30. }
    31. if (Key[4]) //RSHIFT
    32. {
    33. }
    34. if (Key[5]) //ESC
    35. {
    36. //aktiv = false;
    37. }
    38. if (Key[6]) // STRG
    39. {
    40. }
    41. }


    Falls das wichtig ist: es gibt auch eine Game.h
    @Bartosz als public static im Hauptprogramm.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Will nicht. Was habe ich falsch gemacht?
    E0169 Es wurde eine Deklaration erwartet.

    ===
    EDIT: Quatsch, natürlich nur static bool aktiv = true;, global in der Game.cpp
    ===
    EDIT 2: Jedoch bleibt aktiv auf true -.-
    ===
    EDIT 3: Ich habe jetzt bool aktiv = true; in der main.cpp und als global extern bool aktiv; in der Game.h. Ich habe gehört, das soll man nicht (das scheint ein bisschen chaotisch), aber es funktioniert ^^
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Bartosz“ ()

    Das "aktiv" auf "true" bleibt kann an mehreren Dingen liegen.

    Ich gehe mal davon aus das du über mehrere Threads darauf zugreifst, daher komme ich zu zwei Schlüssen:

    1. Optimisation
    Der Compiler kann keine Nebeneffekte von "aktiv" ausmachen und geht davon aus, dass es nie verändert werden wird. (was es aber wird, nur nicht sichtbar für den Compiler)
    Dies kann verhindert werden indem man die Variable als volatile kennzeichnet.

    2. Keine Cache-Kohärenz
    Da zwei threads darauf zugreifen, kann es passieren das diese auf zwei verschiedene Kerne ausgelegt werden die jeweils ihren eigenen Cache besitzen.
    Wenn du jetzt im einen Thread eine Variable änderst die auch Sichtbar in einem anderen Thread ist, kann es sein, dass wenn du die Variable in einem Thread änderst, der CPU Cache des anderen Kernes noch nicht geflusht wurde und somit nicht den Sichtbaren neuwert besitzt.

    Mein Tipp also ist es, std::atomic<bool> zu verwenden.

    Nun... Was aber sind atomics?
    Atomics haben zwei Aufgaben:

    1. Tear-Free
    Atomics gehen sicher das Datenoperationen während der Durchführung nicht zerreißen, also nicht halb durchgeführt werden.
    Normalerweise sollte dies bei booleschen Werten sowieso kein Problem darstellen, da sie nur 8bit groß sind und somit in ein WORD passen. Dennoch sollte man sich nicht darauf verlassen. (denn auch Instruktionen können zerrissen werden, diesbezüglich gemeint sind RMW Operationen)
    Dies ist der eigentliche Namensgeber für atomics, da dieser Wapper sichergeht das diese Operation also eine Operation durchgeführt wird.
    Atomar ist der kleinste Bestandteil, kann nicht aufgeteilt werden, daher atomic.

    2. Memory-Barriers
    Die wichtigere Eigenschaft die atomics aber besitzen und hier bei deinem Problem die eigentliche Abhilfe schaffen sind sogenannte Memory-Barriers.
    Diese sogenannten Memory-Barriers sollen verhindern das unnötiges Memory-Reordering vonstatten geht und dem Cache versichert immer up-to-date zu sein. (dies ist natürlich auch von negativen Aspekten gezeichnet, da das flushen von Caches zu mehreren Cache-Misses führt)

    Also versuchs mal damit.
    Wenn das nicht klappt, gibt es bei dir ein generelles Zugriffsproblem.

    Und des weiteren, man sollte tatsächlich vermeiden Globalen Datenmüll zu verwenden. Extern, wenn es keinen driftigen Grund gibt, zeigt eigentlich meistens ein Designproblem an.
    Mit extern kannst du sehr schnell ein ODR Problem erleiden.

    Deshalb verwende lieber ein static. (obwohl auch da gibt es Dinge die Besser gemacht werden könnten, aber was solls)
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „Elanda“ ()

    Hi @Elanda, danke, dass du dir so viel Mühe gibst und so viel erklärst. :!:

    Ich habe in der main.cpp das std::atomic<bool> aktiv; geschrieben, jedoch hat VS den Fehler "nicht deklariert" in der Game.cpp ausgegeben.
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Bartosz schrieb:

    in der main.cpp das std::atomic<bool> aktiv; geschrieben
    Hast du auch im entsprechenden Header-File die Deklaration (extern std::atomic<bool> aktiv;) geschrieben? Hast du das Header-File inkludiert? Bist du dir sicher, dass du das in der main.cpp haben willst? Globale Variablen würde ich eher meiden.
    Mit freundlichen Grüßen,
    Thunderbolt
    Ich habe mir die Threadgeschichte nochmal angesehen und will jetzt ganz kurz Missverständnisse ausräumen:
    • sofort nachdem @RodFromGermany seinen Vorschlag nannte, probierte ich diesen aus und stellte fest, dass es nicht geht (Edit 1 und 2). Ich erinnerte mich jedoch, dass man extern verwenden kann.
    • In Post 3, Edit 2, schrieb ich, dass aktiv auf true blieb. Mit Edit 3 meinte ich, dass es jetzt doch geht, aber dass ich lieber kein extern verwenden will, wo ihr auch zustimmt (dass man's nicht macht).
    • @'Elanda' hat auf Edit 2 geantwortet und ich habe heute morgen (dusseligerweise) gedacht, mit seinem Vorschalg std::atomic<bool> aktiv brauche ich dann das extern in der Game-File nicht mehr :rolleyes:. Mit dem extern in der game-Header-File geht's natürlich. Danke an @Thunderbolt an dieser Stelle!
    Long story short: Static will nicht :huh: , extern und std:atomic<bool> gehen. ^^
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Warte kurz einen Moment.
    War das static in einer Klasse oder im Namespace-Bereich?

    Es gibt da nämlich zu beachten das static mehr als nur eine Bedeutung hat.

    In einer Klasse bedeutet static das die Variable denselben Speicher über alle Instanzen der Klasse besitzt.
    Heißt es wird immer nur einen Wert besitzen, egal von wo oder wie du es änderst, alle werden das gleiche sehen können!

    JEDOCH, und jetzt wird es tricky:
    Im globalen Bereich hat static eine andere Bedeutung.
    Und zwar bedeutet es "internal linkage", was soviel heißt wie das jede cpp Datei ihren eigenen Speicher für die Variable besitzt.

    Wenn du jetzt also static aktiv im Header definierst.
    Werden alle cpp Dateien ihre eigene Kopie der Variable besitzen und gehören somit nicht mehr zusammen.
    Das könnte hiermit erklären wieso extern für dich funktioniert aber nicht static.

    Mein Tipp zu deiner Misere:
    KLASSEN VERWENDEN
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Elanda“ ()

    die habe ich platziert im globalen bereich der main.cpp, also noch vor int main (void) und so
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Ja und das ist der Fehler.
    Statics im Globalen Bereich bewirken das Gegenteil.

    Edit:
    Ach nur in der cpp?
    Dann können es andere ja nicht sehen!
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------

    Bartosz schrieb:

    nur static bool aktiv = true;, global in der Game.cpp

    Hier mal ein Beispiel, wie statische Klassenvariablen funktionieren:

    C-Quellcode: Test.h

    1. #pragma once
    2. class Test {
    3. public:
    4. static bool aktiv; // Das ist nur die Deklaration („Hey, Compiler, es gibt eine statische Variable ‘aktiv’ vom Typ ‘bool’ auf der Klasse ‘Test‘“).
    5. };


    C-Quellcode: Test.cpp

    1. #include "Test.h"
    2. bool Test::aktiv = true; // Das ist die tatsächliche Definition. Hier wird der Speicherbereich der Variable angelegt und initialisiert.


    C-Quellcode: main.cpp

    1. #include "Test.h"
    2. int main() {
    3. Test::aktiv = false;
    4. }
    Mit freundlichen Grüßen,
    Thunderbolt
    Als Tipp:
    Wenn du C++17 verwendest kannst du dir das mit dem definieren der static sparen.

    Sag einfach

    C-Quellcode

    1. inline static bool aktiv = true;

    Dann benötigst du die Definition in der cpp nicht
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------