Ableiten von Stringklasse



  • Hallo!

    Ich bin gerade am Überlegen wann/wie ich meine Funktionen virtuell deklarieren muss.
    Problem: Ich habe eine eigene Stringklasse implementiert und möchte nun von dieser eine weitere Stringklasse ableiten, in der die Methode free() redefiniert wird. Hier habe ich nun die Methode free() in der Basis als virtuell definiert, Ebenso wie den Destruktor der Basisklasse. Nun hat die Basisstringklasse auch einen Kopierkonstruktor und die Operatoren =,+= überladen. Meiner Meinung nach müssen die 3 Methoden ebenfalls als virtuell definiert werden. Ist das korrekt?

    P.S.: Wann leite ich eine komplette Klasse virtuell ab?


  • Mod

    das hängt von der verwendung ab. vererbung ist kein implementationsdetail und es erscheint sehr zweifelhaft, dass sie genutzt werden sollte, um verschiedene stringklassen zu implementieren. strings sind - so wie ich es verstehe - value-objekte, die im regelfall ohne indirektion über pointer angefaßt werden. jedenfalls sind sie keinesfalls polymorph - und damit erübrigt sich die frage nach virtuellen memberfunktionen eigentlich schon. im übrigen sind konstruktoren nie virtuell (dort wo sie aufgerufen werden, ist der dynamische typ stets identisch mit dem statischen).



  • camper schrieb:

    im übrigen sind konstruktoren nie virtuell (dort wo sie aufgerufen werden, ist der dynamische typ stets identisch mit dem statischen).

    Ist richtig, nur möchte ich noch hinzufügen, dass Meyers eine Technik in seinem Buch Mehr Effektiv C++ Programmieren vorstellt, die er virtuelle Kopierkonstruktoren nennt:

    struct Base
    {
        virtual Base* clone() const = 0;
    };
    
    struct Derived1 : public Base
    {
        virtual Derived1* clone() const
        {
            return new Derived1(*this);
        }
    };
    
    struct Derived2 : public Base
    {
        virtual Derived2* clone() const
        {
            return new Derived2(*this);
        }
    };
    

    HaJo. schrieb:

    P.S.: Wann leite ich eine komplette Klasse virtuell ab?

    Wenn du über verschiedene Wege von einer Basisklasse mehrmals ableitest:

    class Superbase
    { };
    
    class Base1 : virtual public Superbase
    { };
    
    class Base2 : public virtual Superbase
    { };
    
    class Derived : public Base1, public Base2
    { };
    


  • Damit wird vermieden, dass z.B. gleichnamige Variablen mehrfach auftreten. Dies würde der Fall sein, wenn die Klasse nicht virtuell abgeleitet wäre. In diesem Fall gäbe es mehrere Variablen, die explizit mit dem ::-Operator angesprochen werden müssten.



  • Hajo hat seine eigene String-Klasse designed, er benutzt nicht die std::string. Also kann er auch ableiten, wenn er will.


  • Mod

    Artchi schrieb:

    Hajo hat seine eigene String-Klasse designed, er benutzt nicht die std::string. Also kann er auch ableiten, wenn er will.

    der argumentation knn ich nicht folgen. selbstverständlich kann er ableiten soviel er will - der zusammenhang mit std::string ist allerdings unklar. ich denke nur, dass hier das pferd vom falschen ende her aufgesattelt wird. vererbung stellt eine ganz bestimmte bezuiehung zwischen zwei klassen her, und wenn diese beziehung das darstellt, was modelliert werden soll, dann ist sie offenbar die richtig wahl. andernfalls aber eben wahrscheinlich nicht. und erfahrungsgemäß ist das ableiten von nicht-abstrakten basisklassen fast immer ein fehler (von speziellen fällen wie policies oder mix-ins sehen wir hier mal ab). der punkt ist, dass sich die anforderung, was virtuell sein muss (also zu polymoprphen verhalten führt), aus der problemstellung ergibt und eben nicht aus der bloßen tatsache, das eine klasse von der anderen abgeleitet wird - folglich ist die frage des OP hier eigentlich nicht zu beantworten.
    P.S. mit ableitung meine ich hier öffentliche ableitung - ich denke das war implizit gemeint, denn sonst stellt sich die frage nach virtual ja i.d.R. nicht.



  • Hallo!

    camper schrieb:

    das hängt von der verwendung ab. vererbung ist kein implementationsdetail und es erscheint sehr zweifelhaft, dass sie genutzt werden sollte, um verschiedene stringklassen zu implementieren.

    Naja, es macht meiner Meinung hier schon Sinn. Die Basisklasse ist eine (eigene) "normale" Stringklasse. Stringklasse2, die von Stringklasse erbt ist eine spezielle Version einer Stringklasse in der einige Methoden etwas anders arbeiten. Um hier nun keine komplett neue Version einer Stringklasse zu erstellen inkl. sämtlicher Member wie replace/substr/find... (die bei Änderungen in beiden Klassen überarbeitet werden müssten), habe ich von Stringklasse abgeleitet. Hinzu kommt noch, dass Stringklasse2 auch eine Stringklasse ist.

    camper schrieb:

    im übrigen sind konstruktoren nie virtuell (dort wo sie aufgerufen werden, ist der dynamische typ stets identisch mit dem statischen).

    Ausnahmen bestätigen die Regel wie Michael E. auch zeigt. Ich dachte halt nur, da der Kompiler bei virtuellen Funktionen "die richtige" verwendet würde es auch bei Konstruktoren (hier) Sinn machen.


Anmelden zum Antworten