Das erscheint erstmal ziemlich sinnlos, wozu soll Klasse, die nichts implementiert, gut sein?
Eine pure abstract class macht Vorschriften, d.h. Klassen, die davon erben, sind gezwungen die vorgegebenen Methoden zu implementieren.
Bei grossen, komplexen Projekten von 1,000,000 Zeilen code ist ein Hauptproblem die Definition einheitlicher Schnittstellen zur Kommunikation der einzelnen Komponenten und die Minimierung von Abhängigkeiten. Dafür ist das Konzept der pure abstract class oder interface in Java, das einheitliches Verhalten erzwingt, extrem hilfreich.
In der Numerik tritt es häufig auf, dass man einen allgemeinen Algorithmus implementieren möchte, den man auf viele Fälle ( beliebige Funktionen) anwenden möchte. Z.B. Nullstellenbestimmung (Bisektion, Gauss-Newton), numerische Integration (Trapez, Simpson), ...
In Fortran/C löst man sowas mit function-pointers das sind ziemlich unangenehme, schwer verständliche Konstrukte.
In C++/JAVA/OO lässt sich das elegant und einfach mit interfaces (bzw. pure abstract class) lösen:
#include <cmath> class Func { // pure abstract class public: virtual double value( double x) = 0; }; class Nullstelle { // class with just one method public: // finde Nullstelle von f nach Bisektionsverfahren // f ist Objekt das interface Func implementiert, d.h. eine Methode double value(double) hat double find( double x1, double x2, Func &f ) { double f1 = f.value(x1); double f2 = f.value(x2); double xn = x1; double fn = f1; for ( int i=0; i<1000 && fabs(fn) > 1e-6; i++ ) { // Abbruch nach 1000 Iterationen oder bis auf 1e-6 an Nullstelle xn = (x1+x2)/2.; // Neues x in Mitte fn = f.value(xn); // Funktionswert dazu if ( fn*f2 > 0. ) { // gleiches Vorzeichen wir f2 ? x2 = xn; f2 = fn; // dann ersetze x2,f2 } else { x1 = xn; // andernfalls x1,f1 f1 = fn; } } return( xn ); } };
Das Programm in Klasse Nullstelle weiss nicht's über die eigentliche Funktion die es benutzt, es kennt nur die pure abstract class Func.
Erst bei Aufruf von ns.find(...) in einem Anwendungsprogramm wird festgelegt welches Objekt gerufen wird:
#include <iostream> #include <cmath> #include "Nullstelle.cpp" using namespace std; class TFunc1 : public Func { // concrete class 1 public: double value( double x) { // define method return( cos(x) -x); } }; class TFunc2 : public Func { // concrete class 2 public: double value( double x) { // define method return( exp(x) -x); } }; int main() { double x1 = 0., x2 = 1.6; // Startintervall TFunc1 t1; TFunc2 t2; Nullstelle ns; cout << "Nullstelle = " << ns.find( x1, x2, t1 ) << endl; cout << "Nullstelle = " << ns.find( x1, x2, t2 ) << endl; }
GDuckeck 2019-08-01