Parameterless constructor
Asked Answered
N

1

5

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?

Nook answered 19/7, 2015 at 0:18 Comment(6)
Looks like a case of most vexing parse, something I might add doesn't come up in c#. SevenSegmentLed sevenSegmentLed(); this is interpreted by the compiler as a function declaration.Azores
Thanks I figured it was something like that, so what do I do about it?Nook
Btw, even if you got the syntax right, global variables are very rarely (I almost want to say never) a good idea in C++.Watkins
I agree about global variables generally (we don't even have such a thing in .net) but I have learned it its a standard practice in arduino/embedded programming world. There are lots of traditionally BAD things you do when programming an 8Mz microcontroller with 32k of ramNook
Global variable is fine here in the context of the microcontroller code, with the obvious caveat that you want as little mutable global state as possible. However putting the code before main might be result in some different assembly on the AVR platform IIRC. I can't remember exactly how the Arduino IDE generates the underlying c++ code that gets compiled by AVR-GCC but I think it just puts setup into the start of main.Azores
I don't see how a global variable would solve issues that arise from this, but well, I never used such a system.Watkins
A
11

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.

Azores answered 19/7, 2015 at 0:25 Comment(1)
Thanks that is very helpful, I am pleased that I am not the only person vexed by this kind of thing.Nook

© 2022 - 2024 — McMap. All rights reserved.