Ich dachte es ist nötig Destruktoren in Klassenhierachien virtuell zu definieren, da diese sonst evtl nicht alle aufgerufen werden.
Nicht grundsätzlich in Klassenhierarchien, sondern nur, wenn Polymorphie erwünscht ist. Vererbung impliziert nicht Polymorphie, man braucht diese längst nicht immer.
Kann man natürlich handhaben wie man will, aber ich persönlich möchte bei der Nutzung der Klasse nicht darauf achten welche Methoden ich jetzt virtual gemacht habe und welche nicht.
Falls ich Polymorphie nutzen möchte, deklariere ich Methoden, die überschrieben werden (inklusive Destruktor), natürlich auch virtuell. Wenn ich später plötzlich andere Memberfunktionen auch noch überschreiben möchte, hole ich das nach. Aber präventiv virtual hinschreiben mach ich eigentlich nie (ausser eine Überschreibung ist wirklich vorgesehen).
Zusammenfassend: Der Konstruktor einer Basisklasse soll entweder nicht virtuell und protected oder virtuell sein.
Du meinst sicher Destruktor. Aber auch hier würde ich nicht verallgemeinern. Eventuell will man ja nur Objekte der Basisklasse (sofern diese nicht abstrakt ist).
Das Aufrufen von nicht-virtuellen, aber trotzdem neu definierten Funktionen über einen Basisklassenverweis resultiert übrigens nicht per se in undefiniertem Verhalten. Es wird eben die Funktion der Basisklasse aufgerufen (Slicing). Undefiniert wird es, wenn es sich um den Destruktor handelt und nur das halbe Objekt zerstört wird, oder falls in der Funktion selber irgendwelche Anweisungen stehen, die sich darauf verlassen, dass das aufrufende Objekt komplett ist und sich nicht noch eine abgeleitete Klasse dahinter versteckt.