Virtuelle Funktionen und Funktionen als Methodenrückgabe



  • Hallo zusammen!

    Ich versuche seit mehr als 4 Stunden eine Polynominterpolation in c++ zu programmieren, scheitere aber immer wieder an den Sprachelementen.

    Könnt Ihr mir erklären, wie man folgendes java-konstrukt in c++ umsetzen kann?

    interface Function {
      public double f(double array[], double x);
    };
    public class Test {
    static Function getTheFunction() {
     Function bsp = new Function()
       {
         public double f(double array[], double x) {
               return x*x*2 + array[0];
         } /* f(x) */
       };
      return bsp;
    }
    static public void main(String[] args) {
       Function show = getTheFunction();
       System.out.println(show.f(new double[]{0.5}, 9));
     }
    }
    

    Beziehnungsweise, wie ich das umgehen kann. Ich hab es auch schon mit Pointer auf Klassen versucht, aber ich bekomme immer einen Segmentationfault. Was läuft da falsch?

    #include <iostream>
    using namespace std;
    
    class Function {
    	public:
    		virtual double f(double *gitter, int dim, double x) = 0;
    };
    class LagrangeGrundpolynom : public virtual Function {
    	public:
    		double f(double *gitter, int dim, double x) {
    			double p = 0; 
    				for(int i = 0; i < dim; i ++)
    					p += gitter[i] * x;
    			return p;
    		};
    };
    int main() {
    
    double gitter[10] = {1,2,3,4,5,6,7,8,9,10};
    LagrangeGrundpolynom *lg = new LagrangeGrundpolynom();
    cout << lg->f(gitter,10,3) << endl;
    }
    

    😕
    Ich freue mich auf fachkundigen Rat!

    Mit vielen Grüßen!
    Roland



  • Was du machst, ist Java in C++ zu programmieren. C++ bietet aber andere Konzepte. Zum einen besteht nicht die einzige Möglichkeit für Callback-Mechanismen in polymorphen Objekten, zum anderen muss man angeforderten Speicher wieder freigeben.

    Spricht in deinem Falle etwas gegen normale Funktoren, die den operator() überladen, oder sogar Funktionszeiger?



  • Den segfault kann ich nicht nachvollziehen (auch valgrind spuckt nichts aus), aber du leckst am Ende Speicher (lg wird nicht freigegeben).

    Wie dem auch sei, man finge das ganze in C++ auf ganz andere Weise an. In einem einfachen Fall wie diesem täte es wohl ein Funktionszeiger, etwa

    #include <cstddef>
    #include <iostream>
    
    typedef double (*function_t)(int const *gitter, std::size_t dim, double x);
    
    double langrange_grundpolynom(int const *gitter, std::size_t dim, double x) {
      double p = 0;
      for(int i = 0; i < dim; ++i) {
        p += gitter[i] * x;
      }
    
      return p;
    }
    
    int main() {
      double gitter[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
      function_t func = lagrange_grundpolynom;
    
      std::cout << func(gitter, 10, 3) << std::endl;
    }
    

    Wenn komplexere Zusammenhänge gewünscht sind, beispielsweise Funktionsobjekte mit eigenem Status, wäre folgendes sinnvoll (Aktueller Compiler vorausgesetzt):

    #include <cstddef>
    #include <iostream>
    #include <tr1/functional>
    
    typedef std::tr1::function<double(double const *gitter, std::size_t dim)> function_t;
    
    class lagrange_grundpolynom {
    public:
      lagrange_grundpolynom(double x);
    
      double operator()(double const *gitter, std::size_t dim) const;
    
      double x_;
    };
    
    lagrange_grundpolynom::lagrange_grundpolynom(double x) : x_(x) { }
    
    double lagrange_grundpolynom::operator()(double const *gitter, std::size_t dim) const {
      double p = 0;
      for(int i = 0; i < dim; ++i) {
        p += gitter[i] * x_;
      }
    
      return p;
    }
    
    int main() {
      double gitter[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
      function_t func = lagrange_grundpolynom(3);
    
      std::cout << func(gitter, 10) << std::endl;
    }
    


  • Was du machst, ist Java in C++ zu programmieren.

    Das stimmt ^^.

    Danke euch beiden für die Tips: Ich habe tatsächlich noch nie typedef benutzt, sprich gar nicht gewusst, was es ist.

    Danke seldon für das Beispiel! Es funktioniert wunderbar und macht sozusagen genau das, was ich bewirken wollte.

    Zwei kleine Fragen noch:
    °Was macht die cstddef?
    °Habt ihr einen Tipp für mich, wo ich alle c++ Standartbibliotheken durchforsten kann?

    Beste Grüße!
    Roland



  • fromjavatocpp schrieb:

    °Habt ihr einen Tipp für mich, wo ich alle c++ Standartbibliotheken durchforsten kann?

    Das ist sehr viel drin:
    http://www.cplusplus.com/reference/

    Alternativ ein gutes Buch (siehe FAQ) oder das ultimative Nachschalgewerk ist natürlich der Standard. 😉 (aber eher weniger zum lernen zu empfehlen)



  • Ich würde dir auch unbedingt empfehlen, ein C++-Buch zuzulegen. Auch wenn C++ auf den ersten Blick ähnlich wie Java aussieht, werden komplett andere Konzepte verfolgt. Zum einen liegt der Schwerpunkt weniger auf Objektorientierung (C++ wird oft als Multi-Paradigmen-Sprache bezeichnet), zum anderen gibt es etliche Sprachmittel, die vorsichtiger zu handhaben sind. Das heisst, bei new musst du den Speicher wieder selbst freigeben (kein GC), Arrays prüfen ihre Indizes nicht automatisch und auch sonst gibt es sehr viele beachtenswerte Dinge wie z.B. Zeiger, oder grundsätzliche Wertsemantik.

    Keine Angst, man kann in C++ sehr gut von Low-Level-Operationen wie Speicherverwaltung abstrahieren, du musst dich also nicht wie in C ständig mit solchen Dingen rumschlagen. 😉



  • <cstddef> definiert ein paar Typen und Makros, die häufig bis gelegentlich gebraucht werden - NULL, offsetof, std::size_t und std::ptrdiff_t. In diesem Fall habe ich std::size_t benutzt, also brauchte ich <cstddef>.



  • seldon schrieb:

    <cstddef> ...

    Habe zumindest ich noch nie direkt includiert. Die einzigen C-Kompatibilitätsheader die ich in den letzten 2 Jahren aktiv verwendet habe sind <cassert> und <cmath>. Ich gestehe aber ein das ich NULL und std::size_t schon verwendet habe (nur werden die wohl indirekt eingebunden).


Anmelden zum Antworten