Bewertung von Klassendesign mit Vererbung, Basisklasse stellt Methoden zur Verfügung, Abgeleitete Klassen die Daten



  • Hallo,

    ich hätte eine Frage bzgl. meines Klassendesigns. Und zwar habe ich eine Basisklasse, von der einige andere Klassen erben. Grundsätzlich geht es darum, dass die Basisklasse Methoden bereit stellen sollen, während die eigentliche Datenhalten in den Klassen gemacht werden soll die von der Basisklasse erben.

    Hier beispielhaft die Basisklasse:

    class CMyBaseClass
    {
    public:
      /*member functions*/
      int GetIndex(REGISTRATION_s* pClient);
      void PrintRegistrationInfo(REGISTRATION_s* data2Print);
    
      CMyBaseClass(void);
      ~CMyBaseClass(void);
    };
    

    Und hier eine Klasse, die von der oberen Klasse erbt:

    class CMyChildClass : public CMyBaseClass
    {
    private: 
      static const int OFFSET = 1000; 
      REGISTRATION_s myClients[MAX_CLIENTS];
      REGISTRATION_s* const paMyClients; /*constant pointer*/
    
    public:
      CMyChildClass(void);
      ~CMyChildClass(void);
      REGISTRATION_s* const GetClientPointer(void);
      int GetUserOffset(void);
    };
    

    In dem Default-Konstruktor lasse ich den Pointer paMyClients auf das array myClients zeigen und verändere ihn danach natürlich nicht mehr. Nun mache ich in meinem Code z.B. folgendes:

    CMyChildClass sampleClass();
    int myIndex = sampleClass.GetIndex( sampleClass.GetClientPointer() );
    

    D.h. also, die abgeleitete Klasse ruft eine Methode der Basisklasse auf, und übergibt dieser Methode einen konstanten Pointer auf das Nullte Element des privaten Arrays. Die Basisklasse hat dadurch natürlich Zugriff auf alle Elemente des Arrays, weil sie ja einen Zeiger auf das nullte Element hat, und diesen mit einem Index beliebig hoch zählen kann.

    Meine eigentliche Frage ist nun die, ob das so im Sinne des Erfinders ist mit dem privaten Daten? Oder ist so etwas schon vom Ansatz her falsch, dass eine Basisklasse Methoden bereit stellt, die von abgeleiteten Klassen mit deren Daten aufgerufen wird?

    Für Hinweise, konstruktive Kritik, und ggf. einen Schubs in die richtige Richtung wäre ich sehr dankbar!



  • Es stellt sich natürlich die Frage, wie zweckmässig das Folgende ist:

    int myIndex = sampleClass.GetIndex( sampleClass.GetClientPointer() );
    

    Wie wird das angewendet? Übergibt man GetIndex() immer den Client-Zeiger der Basisklasse? Abgesehen davon - muss GetClientPointer() eine Memberfunktion sein, greift sie auf private Member zu (nicht Parameter)? Ansonsten könntest du sie statisch machen. Und vielleicht einen anderen Namen wählen, das ist nämlich nicht unbedingt eine typische Getter-Funktion.

    Nochmals zu oben: Falls die Methode sowieso immer auf Basisklassen-Arrays zeigen soll, wäre vielleicht Polymorphie eine Lösung. Das heisst, du deklarierst in der Basisklasse eine rein virtuelle Funktion, die dort noch nicht implementiert wird. In der abgeleiteten Klasse implementierst du sie und kannst dadurch auf das Array zugreifen. Oder, falls das auch geht, kannst du die Methode natürlich erst in der abgeleiteten Klasse deklarieren.

    Ausserdem würde ich an deiner Stelle von der ungarischen Notation (C- und pa-Präfixe) wegkommen. Das kannst du nämlich niemals konsistent durchführen. Und falls du mal einen Typen wechselst, brauchst du die Namen auch noch anzupassen. Meistens ergibt sich der Datentyp einer Variable aus dem Kontext, bei moderneren IDEs braucht man nur mit der Maus darüber zu fahren.

    Noch was: Mit

    CMyChildClass sampleClass();
    

    erstellst du keine Instanz, sondern deklarierst eine Funktion mit Rückgabewert CMyChildClass . Lass deshalb die Klammern weg. Und das void in leeren Parameterlisten ist in C++ auch eher unüblich.



  • Hallo,

    vielen Dank für die umfangreiche Antwort. Ja, GetIndex kriegt eigentlich immer den Pointer auf das Array in der abgeleiteten Klasse. Hintergrund ist der, dass die abgeleitete Klasse ein Array enthält. Dieses Array repräsentiert Registrierungsdaten verschiedener Clients. Und mit der GetIndex-Methode kriege ich als Rückgabewert einen Index, der noch nicht verwendet, also frei ist.

    Was ist der Unterschied zwische privaten Membern und Parametern? Ich verstehe da deine Frage nicht ganz. Mit der Benamung hast du natürlich recht, da muss ich mir noch Gedanken machen.

    Nochmals zu oben: Falls die Methode sowieso immer auf Basisklassen-Arrays zeigen soll, wäre vielleicht Polymorphie eine Lösung. Das heisst, du deklarierst in der Basisklasse eine rein virtuelle Funktion, die dort noch nicht implementiert wird. In der abgeleiteten Klasse implementierst du sie und kannst dadurch auf das Array zugreifen. Oder, falls das auch geht, kannst du die Methode natürlich erst in der abgeleiteten Klasse deklarieren.

    Auch hier kann ich dir leider (noch) nicht ganz folgen. Also die Methode (ich nehme an, du meinst die GetIndex-Methode) erhält als Parameter immer den Pointer auf das nullte Element des Arrays, welches sich in der abgeleiteten Klasse befindet und private ist. Das ist auch der Grund warum die Methode GetClientPointer existiert, weil das Array sowie der const Pointer auf das Nullte Element private sind.

    Danke auch für den Hinweis mit dem void und der ungarischen Notation. Mir wird an solchen Stellen immer klar, dass ich meinen eigenen Stil noch nicht ganz gefunden habe. Also vielen Dank auf jeden Fall nochmal für die ausführliche Antwort, für weiteres bin ich gerne offen.



  • Gast45189 schrieb:

    Was ist der Unterschied zwische privaten Membern und Parametern? Ich verstehe da deine Frage nicht ganz. Mit der Benamung hast du natürlich recht, da muss ich mir noch Gedanken machen.

    Normalerweise werden Memberfunktionen eingesetzt, um auf private Membervariablen der Klasse zuzugreifen. Ansonsten können sie nämlich freie oder statische Funktionen sein. Wenn du sowieso das Array als Parameter an die Funktion übergibst, braucht sie ja eigentlich das "Privileg" einer Memberfunktion nicht mehr. Halbwegs verständlich? 😉

    Gast45189 schrieb:

    Auch hier kann ich dir leider (noch) nicht ganz folgen. Also die Methode (ich nehme an, du meinst die GetIndex-Methode) erhält als Parameter immer den Pointer auf das nullte Element des Arrays, welches sich in der abgeleiteten Klasse befindet und private ist. Das ist auch der Grund warum die Methode GetClientPointer existiert, weil das Array sowie der const Pointer auf das Nullte Element private sind.

    Sagt dir der Begriff Polymorphie etwas? Damit kannst du wie gesagt in der Basisklasse Methoden deklarieren, die du erst in abgeleiteten Klassen definierst.

    Aber bist du dir wirklich sicher, dass du die Methode GetIndex() in der Basisklasse brauchst? Reicht es nicht, diese in der abgeleiteten Klasse zu definieren? Ich frage mich hierbei nämlich, ob die Vererbung so richtig durchdacht ist - denn dein Design impliziert, dass jede CMyBaseClass eine CMyChildClass sein muss (weil sie eine Methode anbietet, die nur mit dieser abgeleiteten Klasse funktioniert). Und das widerspricht den Prinzipien der Objektorientierung.


Log in to reply