Verhalten von Basisklassen behalten und erweitern - eine gute Idee?



  • Ich habe eine Basisklasse, die diverses grundlegende Verhalten definiert. Einige Setter-Methoden machen z.B. nichts anderes, als Variablen zu setzen. In den abgeleiteten Klassen muss ich aber auf Veränderung einer solchen Variable reagieren, weil ich ggf. einen Cache aktualisiern muss.

    Wie implementiere ich das jetzt am besten? Soll ich in den abgeleiteten Klassen das Verhalten der Basisklasse überschreiben, muss die Variable, also den Wert, dann ggf. auch per Hand setzen, oder soll ich diese Setter in der Basisklasse als nicht-virtuell deklarieren, dafür aber virtuelle OnValueChanged()-Methoden einführen, die von den Settern aufgerufen werden? So könnte ich sicherstellen, dass das Basisverhalten immer gewährleistet bleibt, die abgeleiteten Klassen können aber trotzdem ihr eigenes Verhalten hinzufügen.

    Soll ich das so machen?



  • Du kannst ja aus einer Klasse auch eine überschriebene Funktion aufrufen, also kannst du das Problem vermeiden, dass du den setter neuschreiben musst, wenn du im Grunde nur etwas drum rum basteln willst.

    #include <iostream>
    
    class base {
      int i;
    public:
      virtual ~base() { }
      virtual void set_i(int j) {
        std::cout << "base::set_i(int j = " << j << ")\n";
        i = j;
      }
    };
    
    class derived : public base {
    public:
      virtual void set_i(int j) {
        std::cout << "derived::set_i(int j = " << j << ")\n";
        base::set_i(j);
      }
    };
    
    int main() {
      base b;
      b.set_i(10);
      derived d;
      d.set_i(100);
    }
    


  • Ja, meine Idee vermeidet das ja auch, fragt sich was besser ist...
    Den Aufruf der Basisklassenmethode könnte ich vergessen.

    #include <iostream>
    
    class base {
      int i;
    public:
      virtual ~base() { }
      void set_i(int j) {
        std::cout << "base::set_i(int j = " << j << ")\n";
        i = j;
        on_set_i(j);
      }
    protected:
      virtual void on_set_i(int j) {}
    };
    
    class derived : public base {
    public:
      virtual void on_set_i(int j) {
        std::cout << "derived::set_i(int j = " << j << ")\n";
      }
    };
    
    int main() {
      base b;
      b.set_i(10);
      derived d;
      d.set_i(100);
    }
    

    Diese Art schließt zwar ein Vergessen des Basisklassen-Aufrufs aus, schließt aber auch ein mögliches nicht-aufrufen aus.



  • "on_set_i" ist IMO keine gute idee.
    mach die klassische variante "überschriebene funktion ruft implementierung der basisklasse auf".
    das kennt jeder und versteht jeder.



  • hustbaer schrieb:

    "on_set_i" ist IMO keine gute idee.

    Ist ein Design Pattern das sich Template Method nennt.

    Das sollte jeder kennen...


Anmelden zum Antworten