I am writing a very simple Arduino class to control two motors.
I have a simple class definition inside my header file Motor.h:
class Motor
{
public:
Motor();
void left(int speed);
void right(int speed);
void setupRight(int rightSpeed_pin, int rightDirection_pin);
void setupLeft(int leftSpeed_pin, int leftDirection_pin);
private:
int _rightMotorSpeedPin;
int _rightMotorDirectionPin;
int _leftMotorSpeedPin;
int _leftMotorDirectionPin;
};
In my main library file, Motor.cpp, I have the following Class constructor:
Motor::Motor() {
// Intentionally do nothing.
}
When I try to initialize my class in my primary program with the line:
Motor motor();
I get the following compilation error:
MotorClassExample.ino: In function 'void setup()':
MotorClassExample:7: error: request for member 'setupRight' in 'motor', which is of non-class type 'Motor()'
MotorClassExample:8: error: request for member 'setupLeft' in 'motor', which is of non-class type 'Motor()'
request for member 'setupRight' in 'motor', which is of non-class type 'Motor()'
The baffling part is that if I include even a garbage, throwaway argument to the Motor Class constructor like this:
class Motor
{
public:
Motor(int garbage);
...
And in the .cpp file:
Motor::Motor(int garbage) { }
And in my main file:
Motor motor(1);
Everything works perfectly without complaint. I've done quite a bit of searching through Arduino forums, but found nothing to explain this odd behavior. Why would the class constructor require an argument? Is this some weird relic tied in to AVR or something?
You've run into the "most vexing parse" problem (named that because it's annoying, of course).
Motor motor();
declares a function called motor
that takes no arguments and returns a Motor
. (No different from int test();
or similar)
To define an instance of Motor
called motor
, use Motor motor;
with no parentheses.
As an addition to the accepted answer:
Since C++11 you can use the "uniform initialization" syntax. An advantage of uniform initialization over functional form is, that braces cannot be confused with function declarations, which happened in your case. The syntax can be used like the functional one, except that you use braces {}.
There are some good examples over here
Rectangle rectb; // default constructor called
Rectangle rectc(); // function declaration (default constructor NOT called)
Rectangle rectd{}; // default constructor called
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With