wir alle kennen dynamische Vererbung in C++. Falls nicht, hier noch eine schnelle Erklärung:
template <typename Implementation> class Interface {
private:
void methodA() { } // darf die Implementierung überschreiben; muss sie aber nicht
void methodB(int) { } // die ebenfalls
public:
void doIt() { // Darf nicht überschrieben werden!
static_cast<Implementation *>(this)->methodA();
static_cast<Implementation *>(this)->methodB(123);
}
};
Ironisch an der ganzen Sache ist, dass in C++ Laufzeitpolymorphismus statisch verifiziert wird, aber statischer Polymorphismus nicht:
In der Variante mit virtual kann ich durch override symbolisieren, dass ich die Methode überschreiben will; und das Programm wird nicht kompiliert, falls die überschriebene Methodensignatur nicht passt. Außerdem kann ich Überschreiben durch pur virtuelle Deklaration erzwingen (virtual = 0), oder eine Funktion via final unüberschreibbar machen.
Diese Möglichkeiten gibt es bei statischem Polymorphismus direkt nicht. Es gibt eine gewisse Menge von Hilfskonstrukten, durch die man das besser absichern kann – zum Beispiel den Test, ob die Implementierung auch tatsächlich von der Schnittstelle erbt (und nicht einfach irgendwas anderes in den Template-Parameter gesteckt wurde):
static_assert(boost::is_base_of<Implementation, Derived>::value_type, "fffuuuuu");
Und was macht man um sicherzustellen, dass die abgeleitete Klasse die richtigen Methoden überschrieben hat? Es gibt zwar tausend Möglichkeiten, festzustellen, ob eine Klasse eine Methode bestimmten Namens anbietet – aber auch die Parameterliste für perfekte Überschreibung zu prüfen erscheint mir nicht mehr trivial. Ich breche mir darum alle Wochen mal wieder was, wenn eine Überladung nicht ganz passt und der Compiler ohne Mucken die falsche Funktion aufruft.
Was kann man also tun, um zu prüfen, ob eine nicht-virtuelle überschriebene Funktion in der Basisklasse existiert und zugreifbar ist (override), bzw. nicht existiert (new und final)?
tl;dr: Womit statischen Polymorphismus verifizieren?