I'm Missing Something In Regards To Inheritance. Help Me Correct My Demo Sketch?

Hello gurus,
I'm in the process of animating lights, leds and even buzzer tones in a synchronized way for an Arduino project. I've had some luck, however my code wasn't very "DRY" (Don't Repeat Yourself). There was redundancy and it was time to refactor with a parent Animator class that could provide functionality for the different component classes. I'm making progress, however I'm newer to C++ and am missing something or a couple somethings.

I want my child classes override the parent Animator methods, calling "super()" for animation/timing tracking, then doing their own unique bits after that. The simplified version below is "working", however I'm not sure how I would call a parent method that affects the child's variables. As I type, it seems like I'm trying to make the child mutable by the parent (maybe not a good idea). See comments in code (note, not in the exact same context as actual project however replicates the core issue of protected vars):

The main sketch:

#include "LightAnimator.h"

LightAnimator* lightAnimator;

void setup() {
  lightAnimator = new LightAnimator();
  lightAnimator->setup();
}

void loop() {
  lightAnimator->loop();
  // run other loops for other animators here...
}

Share animator class:

#ifndef Animator_h
#define Animator_h

#include <Arduino.h>

class Animator {
  protected:
    const int frameStartStops[2][2];
    int currentTestValue = -1;

  public:
    // constructor
    Animator():
      // initiators
      frameStartStops {
        {0, 1}, // focusing on the 0 value for this demo
        {2, 3}
      }
    {
      // constructor method contents
    }

    // class setup
    void setup()
    {
      Serial.begin(9600);
      delay(2000);

      // continue with child class stuff here
    }

    // class loop
    void loop()
    {
      this->currentTestValue = this->frameStartStops[0][0];
      Serial.println(this->currentTestValue);
      // This is going to set a value of 0.
      // It would be nice for child class to benefit from value of 10...?

      //continue with child class stuff here
    }
};

#endif

A child class that just isn't updating the local variables that need updated:

#ifndef LightAnimator_h
#define LightAnimator_h

#include <Arduino.h>
#include "Animator.h"

class LightAnimator: public Animator {
  protected:
    const int frameStartStops[2][2];
    // If I include the below, the value will always be -1 (not 10).
    // If I exclude the below, it will be the parent class's 0 value, not from frameStartStops 10 value here.
    // It's like the 'super' call is not acting that way or I'm just missing something.
    int currentTestValue = -1;

  public:
    // constructor
    LightAnimator():
      // initiators
      frameStartStops {
        {10, 19}, //focusing on the 10 value for this demo
        {20, 29}
      }
    {
      // constructor method contents
    }

    // class setup
    void setup()
    {
      Animator::setup();
      Serial.println(this->frameStartStops[0][0]);
      // Cool I'll see 10 here, so initiator ran correctly for this class, overriding parent.
    }

    void loop()
    {
      // super()
      Animator::loop();
      // I put a lot of time saving utility in the parent class.
      // However, it's going to be providing the parent class's 0 value instead of this class's 10 (if I don't set it in this class).
      // Or, it will always be -1 if/as initially set in this class.
      Serial.println(this->currentTestValue);
    }
};

#endif

Thanks for taking a look! I'm trying to stretch my abilities in this area and could use a few good pointers. :slight_smile:

To update fields of parent class, you can do:

Animator::currentTestValue = 10;

But this is very bad practice.

The idea of inheritance is to extend the functionality of a class but in your case the base and inherited classes look identical.

owntheweb:
I want my child classes override the parent Animator methods,,

For a method to be override-able, you must mark it virtual.

arduino_new:
To update fields of parent class, you can do:

Animator::currentTestValue = 10;

Only needed if there is a currentTestValue hiding the variable. Usually the following works just fine.

currentTestValue = 10;

I could well be wrong but, maybe what you want is a virtual function.

Hmm. Virtual might* be the way to go (will try and get back)! Also, focussing on "pure" functions may be the way to go via a utility maybe. Also, child use does vary from parent use, just not for this post as there's way too much to look at (can post if really interested, just a lot there).

Expanding on code a bit, managing the animation was duplicating something like this at the top of each child class with mild variations (along with overlapping methods to manage these variables):

  protected:
    // Animation tracking setup
    byte animate = 0; // to animate or not to animate
    int curAnim = 0; // the animation constant set when starting an animation
    int animInt = 0; // current animation frame
    int startAnimInt = 0; // animation frame to start on
    int endAnimInt = 0; // animation frame to end on
    byte animToLoop = 0; // to loop or not to loop
    int animNumLoops = 0; // 0 = loop forever or higher for number of loops
    int animCurLoops = 0; // current loop count
    unsigned long animStartTime = 0;
    unsigned long animCurTime = 0;
    // number of millis to delay without using blocking delay()
    const static unsigned long animFrameHold = 70;
    // this type will change per child class, defining animation individual frame content
    const char frames[2][2];
    // define start and stop frames for each animation to be overriden by child classes
    const int frameStartStops[6][2];

A child class may animate at a different animFrameHold value, more or less frame values, etc.

Let me muck around for a touch and get back ASAP. :smiley:

Hmm do dice thus far. I think I'm going to go the route of making a little more redundant to start (I have three animating things), then read up on C++ a bit more and refactor.

I did learn new things about C++ today though. Thanks all for the feedback.