Frage zur Klassenverwendung in Klassen



  • Hallo zusammen,
    seit neustem probiere ich einen neuen Programmierstil aus, der mir bis jetzt noch nicht so geläufig war. Ich habe zwei Klassen, wobei ich eine nur in der anderen benutze. Ich erstelle also eine Instanz der einen Klasse in der anderen.

    Das Problem ist nun, dass wenn ich auf zweite Klasse zugreifen möchte, eine Methode in der ersten Klasse machen muss, um auf die zweite zuzugreifen.

    Ich muss also sehr viele Methoden in der ersten KLasse erstellen, die einfach nur auf Methoden der zweiten Klasse zugreifen.

    Bei sehr großen Klassen habe ich dann beispielsweise 30 Methoden, die nichts anderes machen als andere aufzurufen.

    Meine Frage: Ich denke, dass dies programmtechnisch eher ungünstig ist, da sehr viel Speicherplatz nur für diese "Aufrufmethoden" benötigt wird. Ist es üblich so Programme bzw. Klassen zu gestalten und wenn ja (mir gefällt nämlich eigentlich der Gedanke, dass ich eine Instanz einer Klasse in einer anderen Klasse deklariere) wie kann ich vielleicht besser vorgehen?

    Vielen Dank für eure Hilfe
    lg, freakC++



  • Das was du hier beschreibst nennt man Kapselung oder Geheimnisprinzip. Der innere Aufbau der Klasse wird vor dem Aufrufer verborgen. An meiner FH wird das als guter Stil gelehrt. Es wird aber bestimmt auch Leute geben, die da extrem gegen sind.



  • Ich weis schon wie man das nennt, doch frage ich mich, ob dies guter PRogrammierstil ist, da ich jedes Mal eine Methode deklarieren muss, die nichts anderes macht, als eine andere aufzurufen! Das braucht sau viel Speicher!

    Was kann man dagegen tun?

    Vielen Dank
    lg, freakC++



  • Die Frage ist doch eigentlich, was Du erreichen willst und in welcher Beziehung die Klassen zueinander stehen. Wenn Du alle Methoden der gekapselten Klasse über Neudefinitionen zugänglich machst, finde ich das Design eher fragwürdig.


  • Mod

    freakC++ schrieb:

    Das braucht sau viel Speicher!

    Was braucht sSpeicher? Und wieviel ist "sau viel"?

    Wenn es nicht gerade ein Adapter oder etwas ähnliches ist, sollte eigentlich kene Notwendigkeit bestehen, das komplette Interface zu duplizieren: das deutet dann eher darauf hin, dass die Aufgabenverteilung zwischen den Klassen nicht ganz klar ist. "Sehr große Klassen" sollte es nicht geben.



  • freakC++ schrieb:

    Ich weis schon wie man das nennt, doch frage ich mich, ob dies guter PRogrammierstil ist, da ich jedes Mal eine Methode deklarieren muss, die nichts anderes macht, als eine andere aufzurufen! Das braucht sau viel Speicher!

    Speicher brauch dies wenn überhaupt nur einmalig (Methoden existieren nur einmal und nicht pro Objekt). Und unter C++ würde ich immer Methoden für den Elementzugriff verwenden, da man dann die Implementierung nachträglich ändern kann ohne die Schnittstelle der Klasse zu verändern.

    Beispielsweise muss nachträglich noch eine Prüfung hinzugefügt werden, die Klasse speichert einen Wert nicht mehr direkt (Proxyklasse...).



  • Wie mysterio schon sagte, ist es sicherlich davon abhängig wie die Klassen zu einander in Beziehung stehen. Ein Beispiel: Du willst eine Graphen-Klasse realisieren, dazu brauchst du Knoten. Hier ist es sicherlich praktisch eine Knoten-Klasse zu definieren mit der deine Graphen-Klasse arbeitet. Da eigentlich nur deine Graphen-Klasse mit den Knoten zu tun hat kann man diese gekapselt in der Graphen-Klasse definieren.

    class CGraph {
    
        protected:
    
            class CVertice {
    
            };
    };
    

    Mir fällt jetzt kein tolles Beispiel ein wo man die Klasse lieber ausserhalb definieren sollte. Aber wenn du nur Methoden in der Superklasse definierst um methoden der Childklasse aufzurufen, dann definiere doch deine Überklasse virtuel bzw. deren Methoden und Leite davon deine eigentliche Klasse ab.

    Hoffe das hilft dir etwas weiter.

    Lg Tobi



  • Hallo zusammen,
    vielen Dank für eure zahlreichen Antworten.

    1.) @TObi: Du hast jetzt direkt in einer Klasse eine andere Klassendeklaration gemacht. Ist das auch üblich? Ich dachte eher daran, dass ich beispielsweise 2 Units habe, in jede ein Klasse reinschreibe und dann in der einen Klasse eine Instanz der anderen erstelle.

    2.) Ich gebe am besten einfach mal ein Beispiel. Angenommen man will mal wieder einen Taschenrechner erstellen. Nun erstelle ich eine Klasse namens CTaschenrechner und eine Klasse CRechenarten:

    class CRechenarten
    {
     public:
      void addieren(void);
      void subtrahieren(void);
    };
    
    class CTaschenrechner
    {
     private: 
      CRechenarten Rechnen;
     public:
      void addieren{Rechnen.addieren();};//diese Methode ruft nur eine andere auf
      void subtrahieren{Rechnen.subtrahieren();}; //diese auch
    };
    

    Da ich in meinem Hauptprogramm nur mit einer Instanz von CTaschenrechner arbeite, aber dennoch auf "addieren" zugreifen möchte, muss ich extra eine Methode erstellen, die einfach nur darauf zugreift.

    Ich bin mir unsicher bei:
    --> ist das guter Stil? Wenn ich mal mehr Methoden habe, dann würde meine Klasse CTaschenrechner überquillen, weil total viele Methoden gebraucht würden, um Rechenarten aufzurufen (Wurzel, Exponential, Integral, multiplizieren, dividieren....).

    --> Ich denke, dass das kein guter Stil ist (auch wenn es eigentlich strenge OOP ist), da man ja bekanntlich keine riesen Klassen machen soll. Wie kann ich das ändern. Wie sollte ich meine Klassenstruktur ändern, damit das nicht passiert?

    Auch wenn vielleicht die eine Frage schon indirekt beantwortet worden ist, würde ich mich über weitere Hilfe freuen!

    Vielen Dank für euer Bemühen
    lg, freakC++



  • Indirektion ist nichts schlimmes. Deine Methodenaufrufe kosten nicht mehr Speicherplatz auf dem RAM. Da du den Aufruf der eigentlichen Klassenmethode (richtigerweise) direkt in die andere Methode ohne Trennung von Deklaration und Definition schreibst, ist sie implizit inline und erzeugt am Ende höchstens einen minimal längeren Hex-Code.
    Dein Rechnerbeispiel ist nicht so gut dafür geeignet, finde ich, so bringt es dir wirklich nur mehr Schreibaufwand.

    Es gibt so unendliche viele Möglichkeiten, dieses Thema zu implementieren. Du benutzt gerade Komposition. Du kannst genausogut auch private Vererbung nutzen, was aber nicht die erste Wahl sein sollte. Du kannst auch das pImpl-Idiom nutzen und statt einem Objekt ein Zeiger auf das Objekt in der Klasse speichern. Beim Einsatz mit swap() kannst du bei gefährlichen Operationen wie Division durch 0 auch exception-sicher arbeiten.
    Oder du legst normale Nicht-Element-Funktionen-(Templates) an, die Objekte miteinander zusammenrechnet, dann kannst du dir die Implementierungs-Klasse sparen.


Log in to reply