Array of methods

Hallo zusammen,
ja, ich habe bereits google bemüht, die Antworten haben aber irgendwie nicht funktioniert oder ich habe es einfach noch nicht verstanden.

Gibt es nicht einen eleganten Weg folgende Funktion mit einem "Array von Methoden" zu realisieren?
(Gerne mit ein wenig Erklärung)

int call_func(int funcnum) {
  switch (funcnum) {
    case 0:
      return sc_0.tuwas();
      break;
    case 1:
      return sc_1.tuwas();
      break;
    case 2:
      return sc_2.tuwas();
      break;
    default:
      {
        Serial.println("Error in call_func");
        return -1;
      }
  }
}

Ic hab's mal so probiert, aber es kommt nicht durch den Compiler

int call_func (int funcnum){
  typedef int (*f_t)();
  f_t functions[]={
    sc_0.tuwas(),
    sc_1.tuwas(),
    sc_2.tuwas(),
  };
  return functions[funcnum]();
}

Vielen Dank im Voraus
EK

f_t functions[]={
    sc_0.tuwas,
    sc_1.tuwas,
    sc_2.tuwas,
  };

Tja...
Du beschreibst gekonnt, dass du in einer Sackgasse angekommen bist.
Aber leider hältst du den Kontext geheim.
z.B.: Was soll das überhaupt werden?
Wer ist sc_X?

32Bit µC?
Dann evtl. Standard library header <functional> - cppreference.com

Tipp:
Nicht durchnummerieren, sondern Arrays verwenden

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

int foo1() {
  return 1;
}
int foo2() {
  return 1;
}
int foo3() {
  return 1;
}


int (*functions[])()  = {
  &foo1,
  &foo2,
  &foo3,
};

void main() {


  (*functions[0])();

  
}

Die Adressen der Methoden sind leider alle gleich, wenn alle sc_X der gleichen Klasse entstammen. Also keine Unterscheidung beim Aufruf möglich

f_t dinge[]={
    sc_0,
    sc_1,
    sc_2,
  };

// später dann
dinge[1].tuwas();

Ist die einfachste Variante und auch für AVR geeignet.

int (*functions[])()  = {
  foo1,
  foo2,
  foo3,
};

... Fehlermeldungen lesen und posten ist auch hilfreich.

Seht nur nirgends was sc_0 etc. ist. Und die Frage war nach dem Array of functions, nicht ob das Sinn macht :slight_smile:

Nicht wirklich.

Array of methods

Ja.. schade...

Es kann nur eine struct oder class Instanz sein.
Was anderes lässt C++ nicht zu.

Bei Struct geht's problemlos, bei Instanz stürzt das Programm ab - ist aber Stoff für eine neue Frage :slight_smile:

Da struct und class bis auf ein paar Kleinigkeiten identisch sind, wundert mich das.

Aber:
Da das sowieso nicht funktionieren kann, spielt das auch keine Rolex.

Der Weg in Posting #4 funktioniert bestens (wenn man mal die Fehler beseitigt hat), ist im Prinzip nur eine Springtabelle wie du's überall hast.

Bei Klassen funktionierts nicht, weil die Adresse der Instanz der Klasse auch auf den Stack gepusht wird bevor die Methode angesprungen wird. Der 1. Parameter fehlt jetzt im 1. Posting - und den kann man auch nicht so einfach (ohne schwarze Magie) nachbilden, das mag der C++-Compiler gar nicht. Der Workaround schaut dann fast wie LISP-Code aus :blush:

1 Like

Wie gesagt, es scheint sich hier eher um Instanzen zu drehen.
Nicht Funktionen.
Und der Methodenname ist auch immer gleich. Das ist sehr praktisch, da so mit einfachen Mitteln umsetzbar.

Alles andere wird schwierig, bis hässlich.

#include <stdio.h>

void a() { puts(__PRETTY_FUNCTION__); }
void b() { puts(__PRETTY_FUNCTION__); }
void c() { puts(__PRETTY_FUNCTION__); }

void (*f[])(void)={a,b,c};

int main() {
    f[0]();
    f[1]();
    f[2]();
}   

Ergebnis:

a
b
c
#include <Streaming.h> // die Lib findest du selber ;-)
Print &cout = Serial; // cout Emulation für "Arme"

class CallAble
{
  public:
  virtual void tuWas()
  {
    cout << __PRETTY_FUNCTION__ << endl;
  }
};

class Wand : public CallAble
{
  public:
  virtual void tuWas() override
  {
    cout << "Wand" << endl;
    CallAble::tuWas();
  }
};

Wand wand {};

template<byte zahl>
class Zahl : public CallAble
{
  public:
  virtual void tuWas() override
  {
    cout << zahl << endl;
  }
};

CallAble *feld[]
{
  new CallAble{},
  new CallAble{},
  new Zahl<154>{},
  new Zahl<3>{},
  new Zahl<42>{},
  &wand,
};



void setup() 
{
  Serial.begin(9600);
  cout << F("Start: ") << F(__FILE__) << endl; 

  for(CallAble *c:feld) c->tuWas();
}

void loop() 
{

}

Ich hatte gedacht, dass meine Informationen ausreichen - scheinbar nicht!
Der Aufruf ist eine Methode in verschiedenen Klassen.
Alle Klassen machen komische Muster mit FastLED.
Alle Klassen sind unterschiedlich.

class scenario_xy {
  int last_millis, delay_milli;
  void efx() {  // hier der Code hin
    for (int i = 0; i < NUM_LEDS; leds[i++] = CRGB(random8(), random8(), random8()))
      ;
  };
public:
  void init() {
    delay_milli = 200;
  }
  int tuwas() {
    int m = millis();
    if ((m - last_millis) < delay_milli) {
      return 0;
    }
    last_millis = m;
    efx();
    return 1;
  }
};
scenario_xy sc_xy;

Fein!
Also habe ich aus versehen richtig geraten.
Danke für die Rückmeldung/Bestätigung.

Hier hast du auch vollkommen recht!

Merke:
Je größer die Geheimhaltung, desto unbrauchbarer sind die Antworten.
Du handelst also gegen deine eigenen Interessen.
Ohne Zwang, ohne Nutzen.

Gib's zu, du hast deine Glaskugel fisch geputzt ... :sunglasses:

Ja, nee....
Habe nur in die Kiste mit meinen üblichen Designpattern geschaut und eins rausgefischt, welches an die Frage herankommt.

Ist ja auch nicht das erste mal, dass ich sowas hier im Forum zum Einsatz bringe.

Klingt nach einem Naturgesetz - kann ich aber nicht verifizieren, da ich durch ein Verringern der Geheimhaltung die Brauchbarkeit der Antworten nicht vergrößern konnte.
(Eine Seite des Terms hat sich also geändert die andere Seite blieb konstant)

Ich schrieb ja oben [quote="ettettette, post:1, topic:1353200"]
(Gerne mit ein wenig Erklärung)
[/quote]
Ohne auch nur eine rudimentäre Erklärung wenigstens eins der Beispiele komme ich nicht weiter.

Das Beispiel 15 scheint mir von Euch als zielführend angesehen zu werden - ich habe versucht, das zu übertragen, verstehe es aber nicht ganz - egal wie ich es mache, es hagelt Compilerfehler.
Liegt das viellicht an