Can't set class variable?

In an attempt at understanding OOP in Arduino/C++ better, I have been trying to write a program that checks whether two buttons are pressed and lights up their corresponding LEDs. However, halfway through my project I've been facing an issue where _lastButtonState and _lastLedOnTime of the Button class seem to be 0 at all times (see my comments in the code.) Why is this? Even right after setting the variable to HIGH, the serial monitor receives a 0 when I print it.

 #include <Keyboard.h>


const byte button0Pin = 18;
const byte led0Pin = 5;
const byte button1Pin = 19;
const byte led1Pin = 6;


class Button {
  private:
    byte _buttonPin, _ledPin;
    
    unsigned long _lastLedOnTime;
    int _lastButtonState;
  public:
    Button(byte buttonPin, byte ledPin) {
      _buttonPin = buttonPin;
      _ledPin = ledPin;

      pinMode(buttonPin, INPUT_PULLUP);
      pinMode(ledPin, OUTPUT);
    }

    void blink() {
      _lastLedOnTime = millis();
      digitalWrite(_ledPin, HIGH);
    }

    bool isPressed() {
      bool buttonState = !digitalRead(_buttonPin);
      if(_lastButtonState == LOW && buttonState == HIGH) {
        // rising edge
        _lastButtonState == HIGH;
        Serial.println(_lastButtonState); // prints 0 ???
        Serial.println(_lastLedOnTime); // also 0 ??
        return true;
      }

      _lastButtonState == LOW;
      return false;
    }

    void update() {
      if(millis() - _lastLedOnTime >= 250) {
        digitalWrite(_ledPin, LOW);
      }
    }
};

struct Keys {
  int BUTTON_0 = 0;
  int BUTTON_1 = 1;
  int DOUBLE_PRESS = 2;
  
  int NO_KEY = 3;
} keyStrokes;

class KeyboardHandler {
  private:
    Button _button0, _button1;
    
    byte character = 0;
  public:
    KeyboardHandler(Button& button0, Button& button1):
      _button0(button0),
      _button1(button1)
    {
      Keyboard.begin();
    }

  int pressedKeys() {
    int button0_state = _button0.isPressed();
    int button1_state = _button1.isPressed();

    if(button0_state == HIGH && button1_state == LOW) {
      return 0;
    } else if(button0_state == LOW && button1_state == HIGH) {
      return 1;
    } else if(button0_state == HIGH && button1_state == HIGH) {
      return 2;
    }

    return 3;
  }

  void update() {
    _button0.update();
    _button1.update();
  }
};


Button button0 = Button(button0Pin, led0Pin);
Button button1 = Button(button1Pin, led1Pin);

KeyboardHandler keyHandler = KeyboardHandler(button0, button1);


void setup() {
  Serial.begin(115200);
}

void loop() {
  int pressedKeys = keyHandler.pressedKeys();
  if(pressedKeys == keyStrokes.BUTTON_0) {
    button0.blink();
  }

  keyHandler.update();
  delay(50);
}
        _lastButtonState == HIGH;
      _lastButtonState == LOW;

??

Please, post a sketch that at least gets compiled.

You have two buttons and two corresponding LEDs. The LEDs are expected to respond when the corresponding buttons are operated; that's your description.

Why have you included the Keyboard.h Library? What is the role of it here in your sketch.

Common mistake: '==' is the comparison operator. You want "_lastButtonState = HIGH;" because '=' is the assignment operator.

Also, avoid doing this in the constructor:

pinMode(buttonPin, INPUT_PULLUP) ;

because the Arduino environment may not be stable at the time that the constructor is invoked.

The OP has said in his post that he wants to learn OOP (Object Oriented Programming/Class Structure Based Program) Programming in the Arduino MEGA Platform by operating 2 LEDs by 2 push buttons.

1. This is my imagination of his hardware setup.
led2-SWx.png
Figure-1:

2. This is the non-Class Structure sketch to operate the LEDs of Fig-1; where, LED0 becomes ON and LED1 becomes OFF when K0 is pressed and LED1 becomes ON and LED0 becomes OFF when K1 is pressed.

void setup()
{
  Serial.begin(9600);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, INPUT_PULLUP);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
}

void loop()
{
  bool n1 = digitalRead(18);
  if (n1 == LOW)
  {
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
  }
  bool n2 = digitalRead(19);
  if (n2 == LOW)
  {
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
  }
}

3. The OP wants to transform the sketch of Step-2 into Class Structure based program. The Forum members may help him to achieve his goal either in correcting/modifying his posted sketch or in presenting a new sketch that will be simple and intuitive based on the standard procedures of creating class, object, methods etc.

4. The conceptual level of the Class Structured Program may look like this:

#include<MyCustomClass.h>  //
myCustomClass myClass(5, 6, 18, 19);    //object creation from Class name

void setup()
{
    Serial.begin(9600);
    myClass.classSetup();    //perform all initialization
}

void loop()
{
   myClass.DetectK0();
   myClass.DetectK1();
}

//---MyCustomClass.h-----------
class MyCustomClass
{
   private:
   ..................
   public:
   ..................
}

//--MyCustomClass.cpp-----------
#include<MyCustomClass.h>
void MyCustomClass::classSetup()
{
   //insert codes
}

void MyCustomClass::DetectK0()
{
    //insert codes
}

void MyCustomClass::DetectK1()
{
   //insert codes
}

led2-SWx.png

UKHeliBob:

        _lastButtonState == HIGH;
      _lastButtonState == LOW;

??

johnwasser:
Common mistake: '==' is the comparison operator. You want "_lastButtonState = HIGH;" because '=' is the assignment operator.

Oh, of course.. Thanks for pointing that out, I'm not even sure how I didn't spot that before.

GolamMostafa:
Please, post a sketch that at least gets compiled.

You have two buttons and two corresponding LEDs. The LEDs are expected to respond when the corresponding buttons are operated; that's your description.

Why have you included the Keyboard.h Library? What is the role of it here in your sketch.

I'm not sure why it doesn't compile for you? It works just fine on my machine.

Yes, that is indeed what I'm trying to accomplish.

I'm sorry if I wasn't clear in my original post, but I have not yet finished this project. I figured I didn't have to explain since it was probably unrelated to my error.

6v6gt:
Also, avoid doing this in the constructor:

pinMode(buttonPin, INPUT_PULLUP) ;

because the Arduino environment may not be stable at the time that the constructor is invoked.

Thank you for the tip, that actually makes a lot of sense. Would it be better to initialize my objects in setup()? That way it should be setting the pinmodes after the env has been fully initialized, correct?

DismissedGuy:
. . .
Thank you for the tip [arduino stuff in constructor], that actually makes a lot of sense. Would it be better to initialize my objects in setup()? That way it should be setting the pinmodes after the env has been fully initialized, correct?

Yes. That is it. The Arduino "standard" is to create a begin() method (as the example of Serial.begin() etc.) and call that from setup() for such initialisation.

6v6gt:
Yes. That is it. The Arduino "standard" is to create a begin() method (as the example of Serial.begin() etc.) and call that from setup() for such initialisation.

Ah alright, that actually looks a lot cleaner too. Thanks!