Class Methoden in for each Schleifen

Hallo,
ich spiele gerade etwas rum und dabei bin ich an einen Punkt gekommen den ich mir nicht beantworten kann , darum die Frage hier.
Es gibt mehrere Instanzen von einer Klasse die letztlich mit einer for "each" Schleifen bearbeitet werden sollen. Ich hab dazu mal ein Blink Beispiel gemacht. siehe Setup und Loop.

/*Beispiel zu Classen in Verbindung mit 
 * for each Schleifen
 * 
 */

const byte ledpin[] = {2, 3, 4};
const uint32_t blinkzeit[] = {250, 500, 1000};
const byte anzahl = sizeof(ledpin) / sizeof(ledpin[0]);

class Blink {
  private:
    uint32_t altzeit;
    bool zustand;

  public:
    byte pin;
    uint32_t blinkzeit;

    void begin(byte pn, uint32_t bz) {
      blinkzeit = bz;
      pin = pn;
      pinMode(pin, OUTPUT);
    }
    void run() {
      if (millis() - altzeit >= blinkzeit) {
        altzeit = millis();
        zustand = !zustand;
        digitalWrite(pin, zustand);
        Serial.print(pin), Serial.print("  ");
        Serial.println(zustand);
      }
    }
};


Blink blinker[anzahl]; //Instanzen erstellen


void setup() {
  // put your setup code here, to run once:
  byte idx = 0;
  for (auto &instanz : blinker) {
    instanz.begin(ledpin[idx], blinkzeit[idx]);
    idx++;
  }
  Serial.begin(115200);
  Serial.print("Anzahl."); Serial.println(anzahl);
}

void loop() {
  // put your main code here, to run repeatedly:

  for (auto &instanz : blinker ) {
    instanz.run();
  }
}

Es geht mit nun um die Frage ob in der for each Schleife eine Kopie der Methode, bzw. mehrere Variable auf dem Stack abgelegt wird/werden oder wird da mit einem Zeiger gearbeitet. Ist da zwingend ein auto nötig ? Ein byte geht jedenfalls nicht deshalb vermute ich einen etwas größeren Speicherbedarf. Dann wäre eine normale for Schleife ja eventuell besser ?
Heinz

Kopien von Methoden gibt es nicht. Wenn dann wird das ganze Objekt kopiert. Du hast eine Referenz. Damit wird auch nichts kopiert. Das ist nicht anders wie bei einer Referenz als Funktionsparameter.

auto lässt den Datentyp vom Compiler bestimmen. Zwingend ist das nie. Man muss ihn dann halt selbst hinschreiben (in diesem Fall Blink). Das ist vor allem bei Templates schwierig.

1 Like

du hast da mit dem & eine Referenz gemacht:

for (auto &instanz : blinker) {

Wie der Vorposter schon schrieb, jedoch in anderen Worten: Das auto hilft dir nur dass du den Typ nicht genauer schreiben musst. Du hättest auch

Blink 

nehmen können.

1 Like

Hallo ,
danke Euch beiden, da wars mal wieder classen sind auch nur Datentypen , völlig seltsam :wink: Ich werde es wohl nie ganz verinnerlichen :sob:

Gruß Heinz

Wenn du beabsichtigst einen Index mit zu führen, wie in setup(), dann ja!
Der Range based Loop soll einen ja gerade davor bewahren.

Auch hast du dort 3 Arrays, wo auch ein einzelnes reichen könnte.

Vorschlag:
(umgebaut auf Konstruktor mit Initialisierungsliste)

/*Beispiel zu Classen in Verbindung mit
   for each Schleifen

*/


template<typename T,size_t N> 
constexpr size_t anzahl(T(&)[N])
{
  return N;
}

class Blink
{
  private:
    uint32_t altzeit;
    bool zustand;

  public:
    byte pin;
    uint32_t blinkzeit;
    Blink(const byte ledpin, const uint32_t blinkzeit): pin(ledpin), blinkzeit(blinkzeit) {}

    void begin()
    {
      pinMode(pin, OUTPUT);
    }

    void run()
    {
      if (millis() - altzeit >= blinkzeit)
      {
        altzeit = millis();
        zustand = !zustand;
        digitalWrite(pin, zustand);
        Serial.print(pin), Serial.print("  ");
        Serial.println(zustand);
      }
    }
};

//Instanzen erstellen
Blink blinker[] {{2, 250}, {3, 500}, {4, 1000},};


void setup()
{
  Serial.begin(115200);
  Serial.print("Anzahl."); Serial.println(anzahl(blinker));
  for (auto &instanz : blinker)  instanz.begin();
}

void loop()
{
  for (auto &instanz : blinker )    instanz.run();
}

Da ist nichts seltsames dran....
(möchte ich meinen)

oh, jetzt hab ich parallel was ähnliches gemacht.

  • pins brauchen vermutlich nicht zur Laufzeit geändert werden, das kann man imho const machen

  • wenn const --> InitialisierungsListe

  • auch einer Variable im Konstruktor kann man einen Default-Wert mitgeben

  • Die Blinkzeit will man vieleicht zur Laufzeit ändern. Dann macht man einen Setter.
    Die Blinkzeit nicht public sein. Schreib dir einen Setter.
    Und weils ichs auch erst gerade gelernt habe, die Variablen brauchst nicht zur Unkenntlichkeit verstümmeln um sie im Code verwenden zu können.

/*Beispiel zu Classen in Verbindung mit
   for each Schleifen

*/

//const byte ledpin[] {2, 3, 4};
//const uint32_t blinkzeit[] {250, 500, 1000};

class Blink {
  private:
    const byte pin;
    uint32_t blinkzeit;
    uint32_t altzeit;
    bool zustand;

  public:
    Blink(byte pin, uint32_t blinkzeit = 1000) : pin {pin}, blinkzeit {blinkzeit} {}

    void begin() {
      pinMode(pin, OUTPUT);
    }

    void setBlinkzeit(uint32_t blinkzeit)
    {
      this->blinkzeit = blinkzeit;
    }
    
    void run() {
      if (millis() - altzeit >= blinkzeit) {
        altzeit = millis();
        zustand = !zustand;
        digitalWrite(pin, zustand);
        Serial.print(pin), Serial.print("  ");
        Serial.println(zustand);
      }
    }
};

Blink blinker[] 
{
  {2, 250}, 
  {3, 500}, 
  {4}
}; //Instanzen erstellen

const byte anzahl = sizeof(blinker) / sizeof(blinker[0]);

void setup() {
  // put your setup code here, to run once:
  byte idx = 0;
  for (auto &instanz : blinker) {
    instanz.begin();
    idx++;
  }
  Serial.begin(115200);
  Serial.print("Anzahl."); Serial.println(anzahl);
}

void loop() {
  // put your main code here, to run repeatedly:

  for (auto &instanz : blinker ) {
    instanz.run();
  }
}

Hallo,
@combie und @noiasca nochmals Danke Euch Beiden für die Beispiele, das mit dem Konstruktor war mir schon klar. Es wird halt bei vielen Parametern und vielen Instanzen schnell unübersichtlich finde ich ( in dem Beispiel ist das ja überschaubar) . Deshalb war mein Ansatz : Wie bekomme ich die erforderlichen Intitial-Parameter in viele Instanzen. So hab ich das ins Setup verlagert und zunächst mit einer normalen for... Schleife gemacht. Dann viel mir "for each" ein und so ist das entstanden.

in dem Zusammenhang ist natürlich

this->blinkzeit = blinkzeit;

hilfreich
Gruß Heinz

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.