Klassen Vererbung override und final sinnvol



  • Hallo,
    ich hab da mal 2 Fragen.
    1. Ich habe in meinen Buch folgende Frage

    Exercise 15.12: Is it ever useful to declare a member function as both
    override and final? Why or why not?
    

    Meine Antwort wäre Ja.
    Wenn zb. Klasse A die Hauptklasse ist und Klasse B von Klasse erbt. Beide haben ihre eigene Print Funktion jetzt erbt Klasse C von Klasse B aber diesmal möchte ich nicht das Klasse C eine eigene Print Funktion hat. Mach das sinn?

    2. Ich denke mal es ist sinnvoll immer override hinter den Funktionen zu schreiben aber sollte ich dann auch immer virtuel hinschreiben wenn ich davon ausgehe das eine andere Funktion einer anderen Klasse diese überschreibt?

    Hier noch ein Beispiel:

    #include <iostream>
    #include <string>
    
    class A {
    public:
    	A() : basename("hello") {}
    	virtual void print(std::ostream &os) { os << basename; }
    private:
    	std::string basename;
    };
    class B : public A {
    public:
    	B() : i(0) 
    		{A();}
    	void print(std::ostream &os) override final
    	//oder virtuel void print(std::ostream &os) override final
    		{ A::print(os); os << " " << i; }
    private:
    	int i;
    };
    class C : public B {
    public:
    	C() {B();}
    	//soll keine eigene Print Funktion haben
    };
    
    int main()
    {
    	A a1;
    	B b1;
    	C c1;
    	a1.print(std::cout);
    	std::cout << std::endl;
    	b1.print(std::cout);
    	std::cout << std::endl;
    	c1.print(std::cout);
    
    }
    


  • 1. Was macht override genau? Einen Fehler ausgeben, wenn die Funktion nicht als virtual in der Basisklasse deklariert wurde.
    Und was macht final? Verhindern, dass virtuelle Funktionen weiter überschrieben werden.
    Und jetzt überleg mal, was wohl passiert, wenn du final hinter eine nicht virtuelle Funktion schreibst. Es gibt einen Fehler, denn eine nicht virtuelle Funktion kann nicht final sein. Das heißt, der Punkt von override - einen Fehler aufzudecken, wenn man eine Funktion überschreiben will, es aber nicht tut - ist durch final alleine schon erfüllt!
    2. Eine Funktion, die mit override markiert ist, ist by Design auch virtual. Ein zusätzliches Spezifizieren mit virtual ist daher redundant.



  • OK Danke.
    Aber zu 1 nochmal ich sage ja mit override das ich eine virtuelle Funktion überschreibe und mit final das diese virtuelle Funktion von weiteren abgeleiteten Klassen nicht überschrieben werden darf. Wenn ich nur final schreibe konnte man doch auch meinen das die print Funktion in der Klasse B gar nicht überschreibt oder?



  • Ich sehe du hast override noch nicht ganz verstanden.
    override ist komplett optional!
    Deklariert man in einer abgeleiteten Klasse eine Funktion mit der selben Signatur wie in einer Basisklasse und ist diese Funktion in der Basisklasse als virtual deklariert, wird die Funktion in der abgeleiteten Klasse überschreiben. Komplett egal ob man nun in der abgeleiteten Klasse die Funktion mit virtual, override oder sonst was versieht.
    override hilft nur dabei Tippfehler im Funktionsnamen o.ä aufzudecken. Wenn der Programmierer nämlich eine Funktion foo in B überschreiben will, aber stattdessen fou schreibt, kann der Compiler ohne override nicht erkennen, dass foo überschrieben werden soll, was dann logischerweise zu Bugs führt. Mit override, weiß der Compiler, ob eine Funktion überschrieben werden soll und gibt einen Fehler aus, wenn das nciht passiert.
    Ob die Funktion jetzt überschrieben wird, ist komplett unabhängig davon, ob da override steht.



  • Ok ich hab mich wohl einfach schlecht ausgedrückt.
    Mir ist klar das ich nicht override schreiben muss und das ich virtuel nur in der Hauptklasse schreiben muss. Es ging nur darum es zu einem "guten" Stil gehört virtuel nicht nur in der Haupt sonder auch in den Abgeleiteten Klassen zu verwenden. Ist ja eigentlich unnötig da override schon aussagt das die Funktion virtuell ist.



  • Eben.
    Es gehörte früher zu einem guten Stil, virtual hinzu schreiben, damit andere Leser erkennen, dass die Funktion überschrieben werden soll und ihnen ggf. Tippfehler auffallen.
    Seit C++11 ist override besser, da es die Information sowohl dem Leser als auch dem Compiler gibt.


Anmelden zum Antworten