Forum: PC-Programmierung C++ Klassen-Methoden per Funktionspointer übergeben


von Jochen (Gast)


Lesenswert?

Hallo,

folgende Problematik.

Ich habe zwei generische Funktionen geschrieben, die Minimum und Maximum 
einer Funktion finden. Das Interface sieht so aus:
1
// Iteratively find a local minimum or maximum of a
2
// function in a given interval
3
4
// The function to be minimized / maximized takes one
5
// double argument and returns a double:
6
7
typedef double(*fnptr_type)(double);
8
9
// - lower_bound and upper_bound define the initial search interval
10
// - the iteration stops when max_iterations have been performed
11
//   or the current search interval is smaller than residual_error
12
13
double find_minimum(fnptr_type fnptr, double lower_bound, double upper_bound, double residual_error, int max_iterations);
14
double find_maximum(fnptr_type fnptr, double lower_bound, double upper_bound, double residual_error, int max_iterations);

Jetzt würde ich gerne aus einer Klasse heraus, für eine Methode dieser 
Klasse, ein Minimum suchen.

Also zum Beispiel mit calculate_this aus dieser Klasse:
1
class t_technical_thing
2
{
3
4
    public:
5
6
        explicit t_technical_thing(double some_initial_value);
7
        void update_simulation(double delta_time);
8
9
    private:
10
11
        double calculate_this(double some_input);
12
        double caclulate_that(double some_other_input);
13
14
};

So hatte ich mir die Benutzung vorgestellt:
1
  double min_this = find_minimum(calculate_this, 0.1, 1.0, 0.001, 20);

Jetzt kann ich die Methoden-Klasse nicht als Funktionspointer übergeben, 
weil Typ und Kontext nicht stimmen. Wie löst man so ein Problem am 
besten?

Sollte ich die Klasse technical_thing von einer Mimimizer-Klasse 
ableiten? Oder gibt es einen sinnvollen Weg, den Typ zu casten, so dass 
die Übergabe des Funktionspointers klappt?

Ich hoffe das Problem ist verständlich beschrieben.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Du solltest das Interface Deiner Funktion auf `std::function< 
dobule(double) >` ändern. Dann kann der Aufrufer beliebige 
Konvertierungen verwenden, um alles mögliche auf diese Form zu bringen 
(z.b. auch Funktionen mit mehreren Parametern).

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Wenn du std::function akzeptierst, kannst du mit std::bind auch 
Member-Funktionen übergeben. Alternativ kann man auch Lambdas nehmen, 
was etwas intuitiver ist:
1
#include <iostream>
2
#include <functional>
3
4
double find_minimum(std::function<double(double)> f, double lower_bound, double upper_bound, double residual_error, int max_iterations) {
5
  return f (42);
6
}
7
8
double fun2 (double x) { return 3*x; }
9
10
class X {
11
  public:
12
    double fun (double x) { return 2*x; }
13
    void foo () {
14
      // Variante mit std::bind
15
      std::cout << find_minimum (std::bind(&X::fun, this, std::placeholders::_1), 1, 2, 3, 4) << std::endl;
16
      // Variante mit Lambda
17
      std::cout << find_minimum ([&] (double x) { return fun (x); }, 1, 2, 3, 4) << std::endl;
18
19
      // Normale Funktion
20
      std::cout << find_minimum (fun2, 1, 2, 3, 4) << std::endl;
21
    }
22
};
23
24
int main () {
25
  X x;
26
  x.foo ();
27
}

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Alternativ könntest Du aus Deinen Funktionen aber auch ein Template 
machen, und die Funktion als "etwas" (T) übergeben, dass sich wie eine 
Funktion (double (double)) verhält:
1
template < typename T >
2
double find_minimum(T func, double lower_bound, double upper_bound, double residual_error, int max_iterations)
3
{
4
   ...
5
   const double val = func( ... );
6
   ...
7
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Herkömmliche Funktionspointer auf Memberfunktionen funktionieren nur 
ohne "this"-Pointer, dazu müssen sie als static deklariert werden.

static hat damit in C++ eine komplett andere Bedeutung als in C.

Wenn eine Memberfunktion einer Klasse mit einer Objektinstanz arbeiten 
soll, muss der benötigte "this"-Pointer als Argument beim 
Funktionsaufruf mitgegeben und in der Memberfunktion jeweils explizit 
genutzt werden.

von Rolf M. (rmagnus)


Lesenswert?

Rufus Τ. F. schrieb:
> Herkömmliche Funktionspointer auf Memberfunktionen funktionieren nur
> ohne "this"-Pointer, dazu müssen sie als static deklariert werden.
>
> static hat damit in C++ eine komplett andere Bedeutung als in C.

Naja, C++ hat einen Kontext (Klassen), den es in C nicht gibt. An den 
Stellen, wo es auch in C static gibt, hat es die selbe Bedeutung wie in 
C++.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.