Pass a Pointer or Ref to the constructor of an object

96 Views Asked by At

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;
}
1

There are 1 best solutions below

0
Ted Lyngmo On BEST ANSWER

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; }

    // ...
};