I am a fairly experienced .net developer but new to Arduino and C/C++ and I am trying to create my first library which is a simple driver for a 7 segment led display. I have many obtuse compiler errors but in the spirit of one thing at a time this is the first. I want to add a parameterless constructor to my class and when I do library compiles fine but when I try to use the class in a sketch the compiler gives me the rather obtuse "request for member 'setDigit' in 'sevenSegmentLed', which is of non-class type 'SevenSegmentLed()"
The simplest example code is below:
#ifndef SevenSegmentLed_h
#define SevenSegmentLed_h
#include "Arduino.h"
class SevenSegmentLed
{
public:
void setDigit(int digit);
SevenSegmentLed();
};
#endif
#include "Arduino.h"
#include "SevenSegmentLed.h"
SevenSegmentLed::SevenSegmentLed()
{
}
void SevenSegmentLed::setDigit(int digit)
{
}
#include "SevenSegmentLed.h"
SevenSegmentLed sevenSegmentLed();
void setup() {
sevenSegmentLed.setDigit(4);
}
void loop() {
// put your main code here, to run repeatedly:
}
However if I change the constructor signature to: SevenSegmentLed(int wtf);
and instantiate it thus: SevenSegmentLed sevenSegmentLed(1);
it compiles just fine. So as the parameter says, WTF?
A constructor that takes no parameters is called a parameterless constructor. Parameterless constructors are invoked whenever an object is instantiated by using the new operator and no arguments are provided to new . For more information, see Instance Constructors.
Parameter-less ConstructorWhen a constructor is declared without any parameter or argument, then it is called a parameter-less constructor. A parameter-less constructor works like a default constructor and this constructor can contain statements, or it can be empty.
It is required so that code that doesn't know anything about parameterised constructors can construct one of your objects based on the convention that a parameterless constructor is available. On deserialization, and object instance is required so the deserialization process will create one using this constructor.
When a data member is shared among different instances it is imperative that data should be consistent among all the instances of the class. And also there is no way to call static constructor explicitly. Therefore the purpose of having a parameterized static constructor is useless.
I believe the issue is that this:
SevenSegmentLed sevenSegmentLed();
Is interpreted as a function declaration and not an initialization. Note that you can't have this problem with c# because you have the new
keyword disambiguating for you so this particular problem is avoided.
To fix you can do 2 things:
Use the c++ uniform initialization syntax (introduced in newer c++ standard to avoid exactly your issue):
SevenSegmentLed sevenSegmentLed{};
Or use the following syntax:
SevenSegmentLed sevenSegmentLed;
The main benefit of the uniform syntax is that it's uniform. So for example if you have a constructor that takes an integer you can write it like this:
SevenSegmentLed sevenSegmentLed{1};
Generally speaking the uniform initialization syntax is preferable, when I was writing the c++ guideline at my work (mostly c# and php guys) I decided to go with this as it's the most clear and unambiguous.
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