[nicht mehr aktuell|halb gelöst] Prozedurale Programmierung trotz While-Schleife?
-
Morgen,
bei meinem Problem geht es darum, dass die mir bekannte Lösungsansätze nicht meinen Bedürfnissen entsprechen.
Ich habe ein SDL-OpenGL-Programm, das üblicherweise in eine for-schleife läuft.
Dennoch würde ich gern innerhalb dieser For-Schleife komplexe Abläufe nach prozeduralem Vorbild schreiben.
Stark vereinfacht wäre ein unkomfortabler Ansatz folgender:bool running = true; int index = 0; Klasse objekt; while(running) { switch (index) { case 0: objekt.init("bla"); index++; break; case 1: objekt.funktion(1,2,3); index++; break; case 2: objekt.funktion(3,5,2); index++; break; case 3: objekt.funktion3(); index++; break; default: running = false; break; } }
Mit anderen Worten:
viel unkomfortabler Code.Eine andere Möglichkeit wäre es, einen Parser zu schreiben. Allerdings bedeutet dies viel Aufwand, eine transparente Datei, die nicht mitkompiliert wird und einen Verlust an Möglichkeiten.
Daher die Frage:
Gäbe es eine Möglichkeit, prozedural-ähnlichen Code zu schreiben, der dennoch in einer Laufzeit ausgeführt wird? Wenn ja, welchen?Mit freundlichen Grüßen,
Ki
-
Was verstehst du genau unter prozedural?
Suchst du vielleicht sowas wie
std::map<int, std::function<...> >
? Also eine Abbildung von Ganzzahlen auf irgendwelche Funktionen?Oder willst du Code zur Laufzeit interpretieren? Dann wäre vielleicht eine Skriptsprache wie Lua etwas für dich.
-
was spricht dagegen?
Klasse objekt; objekt.init("bla"); objekt.funktion(1,2,3); objekt.funktion(3,5,2); objekt.funktion3();
macht genau das gleiche wie die 'prozedurale while-Schleife'
-
einfach&genial schrieb:
objekt.init("bla");
Das spricht dagegen.
-
314159265358979 schrieb:
einfach&genial schrieb:
objekt.init("bla");
Das spricht dagegen.
Wieso? einfach&genial's Code macht doch genau das gleiche wie diese while-switch-Konstruktion. Oder übersehe ich was?
-
_matze schrieb:
314159265358979 schrieb:
einfach&genial schrieb:
objekt.init("bla");
Das spricht dagegen.
Wieso? einfach&genial's Code macht doch genau das gleiche wie diese while-switch-Konstruktion. Oder übersehe ich was?
Ist ja auch so, aber init gehört in den Konstruktor
-
314159265358979 schrieb:
Ist ja auch so, aber init gehört in den Konstruktor
Ach so... du musst an deiner Wortkargheit arbeiten.
-
Nicht ganz, per while/switch könnte er mit einem beliebigem Index starten.
-
Ethon schrieb:
Nicht ganz, per while/switch könnte er mit einem beliebigem Index starten.
Nicht ganz, ohne
init()
explodiert nämlich alles.
-
_matze schrieb:
Ethon schrieb:
Nicht ganz, per while/switch könnte er mit einem beliebigem Index starten.
Nicht ganz, ohne
init()
explodiert nämlich alles.Dann muss es eben das erste mal mit einem Index 0 gestartet werden und ab dann eben beliebig.
-
Also doch Konstruktor :p
-
Prozedurale Programmierung heisst nichts anderes als 'Der Programmablauf wird allein und vollständig über den Aufruf von Prozeduren (Funktionen) geregelt. Ereignisabhängige Aufrufe gibt es nicht oder müssen selbst programmiert werden.' Prozedural programmieren kann man auch mit C++ jederzeit machen. Du willst offenbar eine Klasse. Geht problemlos. Dann muss nur die gesamte Funktionalität der Klasse übertragen und diese im Konstruktor sauber initialisiert sein!
Vielleicht erkärst du etwas mehr zur Zielsetung?
Geht möglicherweise ohne Klasse einfacher!
-
berniebutt schrieb:
Prozedurale Programmierung heisst nichts anderes als 'Der Programmablauf wird allein und vollständig über den Aufruf von Prozeduren (Funktionen) geregelt. Ereignisabhängige Aufrufe gibt es nicht oder müssen selbst programmiert werden.' Prozedural programmieren kann man auch mit C++ jederzeit machen. Du willst offenbar eine Klasse. Geht problemlos. Dann muss nur die gesamte Funktionalität der Klasse übertragen und diese im Konstruktor sauber initialisiert sein!
Vielleicht erkärst du etwas mehr zur Zielsetung?
Geht möglicherweise ohne Klasse einfacher!
Mir geht es nicht um prozedurale Programmierung an sich, sondern darum einen Ablauf darzustellen, wie man es z.B. beim Prozeduralen Programmieren machen würde.
Ethon schrieb:
_matze schrieb:
Ethon schrieb:
Nicht ganz, per while/switch könnte er mit einem beliebigem Index starten.
Nicht ganz, ohne
init()
explodiert nämlich alles.Dann muss es eben das erste mal mit einem Index 0 gestartet werden und ab dann eben beliebig.
Das Code-Beispiel war stark vereinfacht und das init() war nur ein Beispiel für eine beliebige Wertzuweisung. Ich möchte einfach nach einer gewissen Anzahl an Schleifendurchläufen etwas anderes machen als vorher.
Z.B. soll ein ein Bild erst einfaden, dann ein paar Frames so bleiben, dann wieder ausfaden. Oder wenn eine Taste gedrückt wird, soll dies und das passieren.
Bisher war noch alles trotz switch-Programmierung übersichtlich, doch nun, es soll eine Visual Novel werden, komme ich zur Ingame-Programmierung.
Es soll also eine Textbox angezeigt werden, deren Inhalt sich mit einem Druck auf Enter logischerweise verändert.
Dazwischen werden auch noch Sounds abgespielt, Bilder angezeigt, mit ihnen herumgespielt, Musik gewechselt, das Spiel gespeichert, was eben alles in so ein Spiel gehört.Da wäre es sehr viel einfacher und angenehmer, hintereinander weg zu schreiben, anstatt eine Funktion mit einem call-by-reference-index zu haben, die Hunderte oder Tausende von cases beinhaltet.
Kurz gesagt:
Ich will einen interaktiven Audiovisuellen Ablauf programmieren.
-
Ich habe das Programm jetzt noch einmal von 0 aufgebaut und zur besseren Übersicht die einzelnen in der while-Schleife einfach in Klassen eingeteilt, stoße jedoch bei der Vererbung schon wieder ein auf ein neues Problem.
Um die Szenen zu verwalten, habe ich mir folgende Superklasse angelegt:
sceneBase.h
// ein bisschen Include class SceneBase { // VARIABLES int scene_; SDL_Event event_; // FUNCTIONS virtual int start_(); virtual int input_(); virtual int logic_(int& scene); virtual int render_(); virtual int loop_(int& frame, bool& cap, Timer& fps); public: // CONSTRUCTOR SceneBase(int& scene); // GETTER // FUNCTIONS };
scneBase.h
#include "sceneBase.h" SceneBase::SceneBase(int& scene) : scene_(scene) { // Variables int frame = 0; //Keep track of the current frame bool cap = true; //Whether or not to cap the frame rate Timer fps; //The frame rate regulator start_(); scene = loop_(frame, cap, fps); } int SceneBase::loop_(int& frame, bool& cap, Timer& fps) { while ( true ) { //Start the frame timer fps.start(); if ( input_() == -1 ) return -1; if ( logic_(scene_) == -1 ) // break when logic_() returns -1 return scene_; render_(); // Code zur FPS-Regulierung } return scene_; } // Die restlichen Funktionen
Die Funktionsweise ist also simpel:
Wenn ein Objekt einer Szenen-Klasse angelegt wird, ruft der Konstruktor den klasseneigenen Loop auf. Nach Abbrechen des Loops (z.B. bei Szenenwechsel oder Programmende) wird das Objekt zerstört und im nächsten Durchlauf des Haupt-Loops entweder ein Objekt der nächsten Szene angelegt oder das Programm beendet.Wenn ich nun aber zum Beispiel die Szene ScenePre erstelle, ergibt sich folgendes Problem:
scenePre.h
#ifndef SCENEPRE_H #define SCENEPRE_H #include "sceneBase.h" class ScenePre : public SceneBase { // VARIABLES // FUNCTIONS int start_(); public: // CONSTRUCTOR ScenePre(int& scene); }; #endif
scenePre.cpp
#include "scenePre.h" ScenePre::ScenePre(int& scene) : SceneBase(scene) {} int ScenePre::start_() { std::cout << "test" << std::endl; //TODO Abrufung im SceneBase-Konstruktor? return 0; }
Eigentlich sollte die Funktion int SceneBase::start_() nun überschrieben und durch den Konstruktor aufgerufen werden. Jedoch wird nicht die überschriebene start_()-Funktion aufgerufen, sondern die der Super-Klasse.
Wie kann ich dieses Problem korrigieren?
-
Das Problem ist, dass dein Derived noch nicht fertig konstruiert ist. Virtuelle Funktionen funktionieren in Konstruktoren aus genau diesem Grund nicht - wenn Base eine Funktion aus Derived aufrufen könnte, würden dadurch schwer findbare Fehler entstehen.
-
Ich habe jetzt eine Funktion runScene(int) angelegt, was funktioniert.
Jetzt habe ich zwar eine Code-Zeile mehr pro Szene, aber Hauptsache, es funktioniert. Danke.