Beispiel für Zeiger auf eine Funktion in einer Struktur definieren

rustyoldguy

Mitglied
Hallo Leute!

Hier hab ich mal ein Beispiel, wie man einen Zeiger auf eine Funktion in einer Struktur definieren kann.
Zur Arbeitserleichterung:
C++:
#include <iostream>
#include <math.h>

struct tbl
    {
     std::string cmdtxt;
     double (*funki)(double a);
    };

struct tbl tabelle[3] = {
    {"sin", sin},
    {"cos", cos},
    {"tan", tan},
    };

double bogenmass(double grad);


int main (int argc , char **argv)
{

int i;

double winkel = 30.000;

std::cout << "Enter an angle > 0 and < 90 degree: ";
std::cin >> winkel;

   for(i = 0; i < 3; i++)
        std::cout << tabelle[i].cmdtxt << "(" << winkel << ") = " << tabelle[i].funki(bogenmass(winkel)) << std::endl;

  return 0;
}

// Wandelt Grad in Bogenmass um, da sin cos und tan nur mit Bogenmaß als Parameter arbeiten
double bogenmass(double grad)
{
double boma, pi = 3.141592653589793;

boma = (grad * pi)  / 180; // Wuerde auch mit boma = (grad * M_PI) / 180; in Linux arbeiten
return boma;
}

Sorry für den Sprachenmix aus Deutsch und Englisch. Eigentlich wollte ich jemanden in einem englischsprachigen Forum helfen.
Kann aber den Beitrag nicht mehr finden. Ich denke mal, es gibt auch deutsche Interessenten. Auch wenn Beispiele nicht gerne
gesehen werden, denke ich:

exempla docent

Beispiele lehren.
 
Zuletzt bearbeitet:
Hmm, ja, ich bin ja d'accord dass ich für diesen Zweck auch Funktionspointer verwendet hätte, statt das ganze noch mal in eine std::function Klasse zu wrappen. Ansonsten ist der Code aber doch viel näher an C als an C++, wenn man mal von den IO Streams absieht. Die POD Klasse sieht verdächtig nach std:pair aus (ggf. std::tuple wenn es mehr Member wären). Wenn man das einigermaßen klug in ein std::array packt, ist das sogar constexpr.
OK, gut. Meine Idee dazu sähe etwa so aus:
C++:
#include <algorithm>
#include <array>
#include <cmath>
#include <iostream>
#include <utility>

// ab C++20 haben wir <numbers> mit std::numbers::pi_v<T> und std::numbers::pi (=pi_v<double>) zu diesem Zweck ...
template<typename T> constexpr static auto pi{ static_cast<T>(3.1415926535897932384626433832795028841971693993751058209749445923078164L) };

int main()
{
  enum : std::size_t { name, func };
  constexpr auto to_rad{ [](const double& deg) { return deg * pi<double> / 180; } };
  constexpr std::array<std::pair<const char*, double (*)(double)>, 3>
    table{ {{"sin", std::sin}, {"cos", std::cos}, {"tan", std::tan}} };

  double angle{};
  std::cout << "Enter an angle: ";
  std::cin >> angle;

  std::for_each(table.cbegin(), table.cend(), [&](const auto& op)
  {
    std::cout << std::get<name>(op) << "(" << angle << ") = " << std::get<func>(op)(to_rad(angle)) << '\n';
  });
}
 
Zuletzt bearbeitet:
Hallo German!

Dein Beispiel ist wirklich toll. Schön das du das hier als Beispiel gepostet hast. Mit deiner Bemerkung der Nähe zu c statt c++ hast du absolut Recht. Irgendwie habe ich das Gefühl, das Funktionspointer nicht sehr oft in den Foren angesprochen werden. Warum auch immer.
 
Warum auch immer.
In C++ hat man kaum Verwendung für Funktionspointer. Funktoren und Lambdas können sie ersetzen, wenn man nicht tatsächlich gerade auf Funktionen aus der C Library verweist. In C nutzt man sie auch eher nur für Pointer auf Callbackfunktionen. Bspw. verlangen qsort und bsearch Pointer auf Vergleichsfunktionen. In C++ würde man auch hier eher auf Funktoren oder polymorphe Klassen mit virtuellen Methoden zurückgreifen.
Eine Anwendung von Funktionspointern wie in deinem Beispiel, wo sie in einem Container verpackt zwischengelagert werden, ist sowohl in C als auch in C++ ziemlich "exotisch". Vermutlich findest du deshalb nicht viel dazu ;)
 
Zurück
Oben Unten