Strukturierung einer Anwendung



  • Hallo zusammen!

    Ich versuche mich gerade daran, eine kleine DirectX Anwendung objektorientiert umzusetzen. Nun schreibe ich hier im C++ Forum, weil es mir nicht um DirectX Funktionen geht, sondern um die (objektorientierte) Struktur des Programmes. Die Anwendung läuft, ohne in Klassen unterteilt worden zu sein, soweit ganz gut.
    Deswegen bitte ich jetzt um Hilfe, einen Rat, wie ich mein Programm am besten strukturiere (Ihr merkt, Objektorientierung gehört bislang nicht zu den Dingen, die ich oft "gemacht" habe).

    In diesem (http://www.c-plusplus.net/forum/viewtopic-var-t-is-178380.html) "parallelen" Thread ist so eine Frage auch schon gestellt worden, allerdings verstehe ich die Lösungsansätze nicht...
    Ich schreibe mal auf, was ich mir vorstelle und hoffe auf einige Tipps von euch... 🙂

    //Konstruktor und Destruktor lasse ich mal weg, der besseren Anschauung wegen
    
    //verwaltung.h
    class Verwaltung
    {
      private:
        int verwaltungsvar_1;
        float verwaltungsvar_2;
    
      public:
        void init();    
        void run();
        void end();
    };
    
    //verwaltung.cpp
    verwaltung Cverw;    //hier erstelle ich doch ein globales Objekt der Verwaltungsklasse, oder?
    
    void verwaltung::init()
    {
      Cinput.init_keys();    //geht das?
    }
    void verwaltung::run()
    {
      Cinput.check_keys();    //geht das?
      Clogik.berechneNaechstenSchritt();    //geht das?
    }
    
    //input.h
    class input
    {
      private:
    
      public:
        init_keys();
        check_keys();
    };
    
    //input.cpp
    input Cinput;    //hier erstelle ich doch ein globales Objekt der inputklasse, oder?
    
    void input::init_keys()
    {
      //mache irgendwas
    }
    
    void input::run()
    {
      Cverw.verwaltungsvar_1=5;        //geht das?
    }
    
    //logik.h
    class logik
    {
      private:
    
      public:
        void berechneNaechstenSchritt();
    }
    
    //logik.cpp
    logik Clogik;
    void logik::berechneNaechstenSchritt()
    {
      if(Cverw.verwaltungsvar_1==7)
      {
        //mache irgendwas
      }
      Cverw.verwaltungsvar_2=3;
    }
    

    Es geht mir also darum, aus verschiedenen Klassen (zB input und logik) auf gemeinsam verwendete Variablen zuzugreifen, die ich meiner Meinung nach in einer "Verwaltungsklasse" am besten speichere.
    Probiert, herumgespielt und viel gelesen zu diesem Thema habe ich jetzt schon eine Weile, aber es funktioniert alles nicht so wie erhofft.
    Ist das überhaupt ein guter Ansatz?

    Vielen Dank schon mal im Voraus!



  • denkst du es liest jemand die 6 seiten?

    so als ein Vorschlag wäre Singleton. Aber da können auf dich üble Probleme zukommen, wenn du nicht aufpasst. Beim erstellen eher seltener, je nach dem wie die erstellt werden. Beim Zerstören, wenn ein Objekt benötig wird, der schon freigegeben wurde. Oder wenn die Objekte sich beim Erstellen gegenseitig benötigen.

    richtig gute lösung habe ich für das ganze noch keine gefunden. Aber verwende selbst Singletons. Die Erstellungsreihenfolge lege ich dann einfach selbst fest. Z.b. in der main() A::Singleton(), B::Singleton() verwende.

    Schau dir Loki lib an. Könnte aber auch schwerer zu benutzen sein. Wenn du das entsprechende Buch nicht gelesen hast (Modernes C++ Design). Wenn du es noch nicht kennst. Solltest das nachholen, wenn du etwas erfahrung mit größeren Programmen (und vor allem mit schlechten Libs) gesammelt hast. Dann weißt du wozu das ganze gut ist.

    Ansonsten bin ich der Überzeugung, dass man nicht für jeden Kram eine eigene Klasse braucht. Manche würden mir da wohl widersprechen....
    z.b. du in einer Klasse nur Funktionen hast, also ohne Datenelemte. Würde ich da lieber Funktionen nehmen.

    Achja noch was zum Gesamtaufbau:
    Statt Singletons verwenden einige soetwas wie eine Root Klasse. Die dann die anderen Objekte (Logik, Input, usw.) verwaltet und zurückgibt.
    Ich persönlich mag sowas nicht, weil ich dann die Klassen nicht unabhängig von einander benutzen kann.
    Andererseits wäre soetwas vielleicht sinnvoll, wenn der Endnutzer keine Ahnung von den konkreten Klassen haben sollte, du aber abstrakte Klassen mit Schnittstellen zur verfügung stellst. Ist Richtung COM. Also auch DirectX.

    Wenn dir das nicht hilft, ignoriers einfach. Da ich zu faul bin die 6 seiten des anderen Threads zu lesen, und deswegen nicht so genau weiß was du eigentlich willst. 🙂



  • iop schrieb:

    Es geht mir also darum, aus verschiedenen Klassen (zB input und logik) auf gemeinsam verwendete Variablen zuzugreifen, die ich meiner Meinung nach in einer "Verwaltungsklasse" am besten speichere.

    Verwende am besten das Singleton Muster, das zusammen mit anderen Mustern z.B.
    hier

    http://www.vico.org/pages/PatronsDisseny.html

    skizziert wird.

    Zu Singleton et al. findest Du Unmengen weiterer Info bei Google.

    Aber

    iop schrieb:

    //sowas
    verwaltung Cverw;
    // [...]
    // oder 
    input Cinput;
    

    geht gar nicht!

    Wenn da irgendetwas mit grossem "C" anfängt dann ist es die Klasse.

    //sowas
    class CVerwaltung 
    {
    //...
    };
    
    CVerwaltung verw;
    

    und nicht umgekehrt!

    Auuserdem ist es i.A. nicht günstig, Konstruktoren im Modul-(cpp-Datei)Kontext aufzurufen (und das passiert hier implizit).

    Wenn Du's nicht glaubst, beantworte mal die Frage in welcher Reihenfolge die Instanzen beim Programmstart erzeugt werden wenn mehrere Module vorhanden sind. 😉

    Wenn Du Dir z.B. ein Singleton baust und andere Konstruktoren dies nutzen könnte es sein dass der Instanzzeiger noch nicht auf NULL gesetzt ist!
    Davor könnte Dich zwar Dein Compiler bewahren, aber es ist kein guter Stil sich darauf zu verlassen.

    Grüsse

    *this



  • Hallo und ein großes Dankeschön erstmal für die Antworten!

    Den Thread habe ich gestartet, weil mein Programm in der aufgeführten Struktur nicht lief - was an der Struktur lag, so dachte ich jedenfalls. Im Endeffekt lag der Fehler jedoch in einer Banalität, die mir (nach Murphys Gesetz natürlich) erst nach dem Threadschreiben aufgefallen ist. 🙄

    Ja, Singletons, das habe ich jetzt schon einige Male gelesen. Werde mich informieren.

    @matimatiker

    Ich persönlich mag sowas nicht, weil ich dann die Klassen nicht unabhängig von einander benutzen kann.

    Meinst Du damit, eine Klasse so auszulagern, dass ich sie auch in anderen Programmen nutzen kann? Oder was meinst Du mit "unabhängig?

    Wegen der Schreibweise mit dem "C" - sehe ich ein und werde ich ändern 🙂

    Zu den Konstruktoren habe ich noch eine Frage: wo soll ich denn den Konstruktor von zB der Input Klasse in dieser Programmstruktur aufrufen? Ich hätte jetzt auf "im 'Verwaltung'-Konstruktor" getippt, was aber leider nicht geht (-> Linker Fehler).

    Danke nochmal für die Antworten!



  • iop schrieb:

    @matimatiker

    Ich persönlich mag sowas nicht, weil ich dann die Klassen nicht unabhängig von einander benutzen kann.

    Meinst Du damit, eine Klasse so auszulagern, dass ich sie auch in anderen Programmen nutzen kann? Oder was meinst Du mit "unabhängig?

    jein, du kannst die Klasse auch in anderen Programmen nutzen, obwohl sie von anderen abhängig ist die, du nicht brauchst. Aber im Prinzip läuft es darauf hinaus. Z.b. habe bei meiner Lib ein Logging-Framework, Klassen Serialisierung, und paar Klassen um Einstellungen zu speichern und zu laden.
    Wenn ich dann z.b. nur die Logging-Klasse brauche, müssen die anderen garnicht eingebunden werden. Natürlich kann ich die anderen zwei genauso unabhängig von einander nutzen. Sie bilden soetwas wie eine abgschlosse Bibliothek in sich.
    Das meinte ich mit unabhängig.

    Zu den Konstruktoren habe ich noch eine Frage: wo soll ich denn den Konstruktor von zB der Input Klasse in dieser Programmstruktur aufrufen? Ich hätte jetzt auf "im 'Verwaltung'-Konstruktor" getippt, was aber leider nicht geht (-> Linker Fehler).

    Schau dir Singletons an! oder als kurzfassung:

    class Singleton
    {
    public:
       static Singleton& GetSingleton(){
          if (pInstance_ != 0)
             pInstance_ = new Singleton;
          return *pInstance_;
       }
    private:
       static Singleton* pInstance_;
    };
    

    Was das statische erstellen von Objekten in der Cpp-Klasse angeht. Das kann zu Problemen führen. Zumindest ich kämpfe damit gerade. Aber mache ich demnächst einen Thread auf.


Anmelden zum Antworten