Fairly new to C++ and having an issue with ref vs. pointer. The code below is a class for a simple motor and works. I would like to pass the pin expander in the constructor, but cannot seem to get that working.
I call the methods with &expander. I tried adding a setter and getter for the expander but that did not seem to work.
Is this the best way, and can I pass it to the constructor?
This is the header
#ifndef PMotor_H
#define PMotor_H
#include <Arduino.h>
#include <PCF8575.h>
class PMotor {
private:
uint8_t pinA;
uint8_t pinB;
uint8_t direction;
public:
// Constructor
PMotor(uint8_t pinA, uint8_t pinB);
// Turn the motor on with a specified speed.
void on(uint8_t direction, PCF8575 *expander);
// Turn the motor on with a specified speed, for a given time.
void on(uint8_t direction, int millisec, PCF8575 *expander);
// Turn the motor off.
void off(PCF8575 *expander);
bool movingCW();
bool movingCCW();
};
#endif
This is the CPP
#include "PMotor.h"
#include <PCF8575.h>
bool mCW;
bool mCCW;
PMotor::PMotor(uint8_t pinA, uint8_t pinB) {
this->pinA = pinA;
this->pinB = pinB;
}
void PMotor::on(uint8_t direction, PCF8575 *expander) {
if (direction == 0) {
expander->write(pinA, HIGH);
expander->write(pinB, LOW);
mCW = true;
mCCW = false;
} else {
expander->write(pinA, LOW);
expander->write(pinB, HIGH);
mCW = false;
mCCW = true;
}
}
void PMotor::on(uint8_t direction, int millisec, PCF8575 *expander) {
this->on(direction, expander);
delay(millisec);
this->off(expander);
}
void PMotor::off(PCF8575 *expander) {
expander->write(this->pinA, LOW);
expander->write(this->pinB, LOW);
mCW = false;
mCCW = true;
}
bool PMotor::movingCW() {
return mCW;
}
bool PMotor::movingCCW() {
return mCCW;
}
I would like to pass the pin expander in the constructor, but cannot seem to get that working.
Here's one way that involves taking the expander by reference but storing a pointer. Taking it by reference makes sure that you don't get a nullptr
- and storing it as a pointer makes it easy to add copy/move semantics to your class.
class PMotor {
private:
PCF8575* expander; // store a pointer
uint8_t pinA;
uint8_t pinB;
uint8_t direction;
public:
// Constructor - takes an expander by reference:
PMotor(PCF8575& expander, uint8_t pinA, uint8_t pinB);
// No expander needed in the rest:
// Turn the motor on with a specified speed.
void on(uint8_t direction);
// Turn the motor on with a specified speed, for a given time.
void on(uint8_t direction, int millisec);
// Turn the motor off.
void off();
bool movingCW();
bool movingCCW();
};
Then the implementation of the member functions can look pretty much like they already do - only with the PCF8575*
argument removed.
The constructor would simply be:
PMotor::PMotor(PCF8575& expander, uint8_t pinA, uint8_t pinB) :
expander(&expander), // store the pointer
pinA(pinA),
pinB(pinB)
{}
If you would also like to have a setter and getter for the expander, it could look like this:
class PMotor {
public:
// ...
// setter, sets a new expander and returns a reference to the old one
PCF8575& Expander(PCF8575& new_expander) {
PCF8575* old_expander = expander;
expander = &new_expander;
return *old_expander;
}
// getters for the expander
PCF8575& Expander() { return *expander; }
const PCF8575& Expander() const { return *expander; }
// ...
};