Class within a class "does not have class type" error message

Hi - I am trying to write a class that encapsulates functionality within an already published PushButton class (http://github.com/kristianklein/PushButton)

I am building a mass I/O project and using CANbus to pass I/O messages between ATMega2560 boards I am building.

I have stripped out the canbus stuff below and just included code that is spawning the error in the compiler.

test.ino

#include "CanButton.h"

#define BUTTON1_PIN 8
#define BUTTON1_LED_PIN 9

#define BUTTON2_PIN 4
#define BUTTON2_LED_PIN 6

#define BUTTON_COUNT 2

CanButton button1(BUTTON1_PIN, BUTTON1_LED_PIN, 0);
CanButton button2(BUTTON2_PIN, BUTTON2_LED_PIN, 1);

CanButton *buttons[BUTTON_COUNT] = {&button1, &button2};

void setup() {
  for (int i=0; i < BUTTON_COUNT; i++) {
    buttons[i]->setup();
}

void loop() {
}

CanButton.h

/*
  CanButton.h - Library for building CANbus buttons
*/

#ifndef CanButton_h
#define CanButton_h

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

class CanButton
{
  private:
    byte _inputPin;
    byte _ledPin;
    unsigned int _buttonID;
    PushButton _button();
    int _buttonState;

  public:
    CanButton(byte inputPin, byte ledPin, unsigned int buttonID);
    void setup();
    int buttonUpdate();
};

#endif

CanButton.cpp

/*
  CanButton.h - Library for building CANbus buttons
*/

#include "Arduino.h"
#include "CanButton.h"
#include <PushButton.h>


CanButton::CanButton(byte inputPin, byte ledPin, unsigned int buttonID) {
  _inputPin = inputPin;
  _ledPin = ledPin;
  _buttonID = buttonID;
  _buttonState = 2;
}

void CanButton::setup() {
  pinMode(_inputPin, INPUT_PULLUP);
  pinMode(_ledPin, OUTPUT);
  PushButton _button(_inputPin);
  _button.setActiveLogic(LOW);
  _button.disableDoubleClick();
}

int CanButton::buttonUpdate() {
  _button.update();  //the update() method of class PushButton has been working fine for me when using outside of my new class
  //if (_button.isClicked()) _buttonState = 1;
  //if (_button.isReleased()) _buttonState = 0;
  return _buttonState;
}

Compiler error

sketch/CanButton.cpp: In member function 'int CanButton::buttonUpdate()':
CanButton.cpp:26:3: error: '((CanButton*)this)->CanButton::_button' does not have class type
   _button.update();
   ^
/Users/brantwinter/Documents/Arduino/canbus_proto/canbus_proto.ino: In function 'void setup()':
canbus_proto:54:16: error: request for member 'setup' in 'buttons[i]', which is of pointer type 'CanButton*' (maybe you meant to use '->' ?)
     buttons[i].setup();
                ^
exit status 1
'((CanButton*)this)->CanButton::_button' does not have class type

I don’t understand why its complaining about:

'((CanButton*)this)->CanButton::_button' does not have class type

_button is a private object of the class CanButton and has a type of PushButton (from the included class)

What am I doing wrong??!!

You're declaring _button as a function taking no arguments, returning a PushButton object. Remove the parentheses after PushButton _button.

Pieter

I tried that earlier and had different errors, I’ll try again tonight when I get home. I found this thread as well which may explain a better way for me to declare and initialise the PushButton object within my class - using class inside a class - Programming Questions - Arduino Forum

Looking at the GitHub link you posted, the PushButton class doesn’t have a default constructor, so you have to pass it a pin number when constructing it (i.e. in the constructor of your class).
Another problem is that your local PushButton shadows the member variable in CanButton::setup().
And there’s no reason to create an array of pointers to CanButtons in your main sketch, just create an array of CanButton objects directly.
Some other remarks: use constants, not #define preprocessor macros, underscores in front of variable names don’t improve the readability and are unnecessary, use #pragma once in favor of the old C-style #ifndef guards.

Try this:

#include "CanButton.h"

const uint8_t BUTTON1_PIN = 8;
const uint8_t BUTTON1_LED_PIN = 9;

const uint8_t BUTTON2_PIN = 4;
const uint8_t BUTTON2_LED_PIN = 6;

CanButton buttons[] = {
  {BUTTON1_PIN, BUTTON1_LED_PIN, 0},
  {BUTTON2_PIN, BUTTON2_LED_PIN, 1},
};

void setup() {
  for (CanButton &button : buttons) {  // range-based for loop
    button.setup();
  }
}

void loop() {}
/*
  CanButton.h - Library for building CANbus buttons
*/

#pragma once

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

class CanButton {
  private:
    byte inputPin;
    byte ledPin;
    unsigned int buttonID;
    PushButton button;
    int buttonState;

  public:
    CanButton(byte inputPin, byte ledPin, unsigned int buttonID);
    void setup();
    int buttonUpdate();
};
/*
  CanButton.cpp - Library for building CANbus buttons
*/

#include "CanButton.h"

CanButton::CanButton(byte inputPin, byte ledPin, unsigned int buttonID)
  : inputPin(inputPin), ledPin(ledPin), buttonID(buttonID), button(inputPin) {}

void CanButton::setup() {
  pinMode(inputPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  button.setActiveLogic(LOW);
  button.disableDoubleClick();
}

int CanButton::buttonUpdate() {
  button.update();
  if (button.isClicked()) 
    buttonState = 1;
  else if (button.isReleased()) 
    buttonState = 0;
  return buttonState;
}

Note that you’re saving the pin number twice, once as CanButton::inputPin, and once as CanButton::button::pin_.

Thanks for the reply @PieterP - I don't quite understand the syntax in the constructor below. I thought the defacto C standard was to use underscores for private class variables. I find it more ocnfusing having the same variable name for the method as the private class variable names.

I don't understand the 2nd line that you have below. Why does it start with the ':' ?

PieterP:
CanButton::CanButton(byte inputPin, byte ledPin, unsigned int buttonID)
: inputPin(inputPin), ledPin(ledPin), buttonID(buttonID), button(inputPin) {}

solderdog:
I don’t understand the 2nd line that you have below. Why does it start with the ‘:’ ?

Initializer List

solderdog:
I find it more ocnfusing having the same variable name for the method as the private class variable names.

The example doesn't do that. It has the same names for the constructor's formal parameters as the class's member variables. It does look kind of funny, but a lot of people do it. I can't speak to a "best practice".

Ok - I seem to understand the initializer list now - thanks.

Also - I don't understand how the two button objects can later be referenced if they are instantiated in the array as proposed? I had created the array of pointers to the individual object variable names so I could reference their class variables / methods later.

CanButton buttons[] = {
  {BUTTON1_PIN, BUTTON1_LED_PIN, 0},
  {BUTTON2_PIN, BUTTON2_LED_PIN, 1},
};

I do I just iterate over the array using the same construct as in setup() and not worry about individual object names?

for (CanButton &button : buttons) {  // range-based for loop
    button.buttonUpdate()
  }

solderdog:
Also - I don't understand how the two button objects can later be referenced if they are instantiated in the array as proposed?

The same way you would reference the individual objects in an array of 'float', 'uint32_t', or any other data type.

gfvalvo:
The same way you would reference the individual objects in an array of 'float', 'uint32_t', or any other data type.

Nevermind... I feel stupid now.
buttons[0].buttonUpdate(), buttons[1].buttonUpdate() etc