Difficulty properly instantiating a basic class

Hi there. Not a total newbie to programming, but a newbie to C and variants. (Extensive VB experience from 25 years ago).

I'm trying to get a handle on the class / object thing and so I've take the "Morse" 'make a library' tutorial and simplified it to show my problem/question.

I can (and did) paste the class definition (the .h part)and the constructor and methods (the .cpp part) from the Morse tutorial into a simple 'one tab' sketch and of course it works fine. I then removed most of it to 'dumb' it down into just a 'blink' program (left the 'dot' method). Still works of course.

Next I hard coded the pin number into the "pinMode()" and "digitalWrite() functions so I could get rid of the "int pin" parameter/argument that is handed off. (Remember, I'm doing this to demonstrate my issue ... not because I think it's great programming habit).

So here's my problem. Even though the sketch no longer needs to hand off any parameter / argument to the instantiated object for it to function, when I remove the parameter (the 'int pin' part) I can't get it to compile (various errors depending ...).

Here's the code -- I've posted it in runnable form, with the three changes noted which remove the parameters / arguments and supply the errors commented out.

(this is my first post and first time posting code -- I ran auto-format on the code before copying it, but I've no experience to know if it's going to format properly in the post)

// Class Definition:
class Morse
{
  public:               // Change #1
    Morse(int pin); // WORKS
    //Morse();       // DOESN'T WORK
    void dot();
};

//***********************************
//***********************************


// Constructor:           // Change #2
Morse::Morse(int pin) // WORKS
//Morse::Morse()       // DOESN'T WORK
{
  // I don't need anything done inbetween these brackets,
  // but if I remove them I get an error so I leave them.
}


//Method:
void Morse::dot()
{
  digitalWrite(13, HIGH);
  delay(200);
  digitalWrite(13, LOW);
  delay(200);
}

//***********************************
//***********************************

//Instantiate:     // Change #3
Morse morse(13);    // WORKS
//Morse morse();   // DOESN'T WORK

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  morse.dot();
}

Any suggestions? I'm simply trying to learn how to define and instantiate the simplest form of class/object/methods -- one without any parameters passed or returned. I can't seem to find a single example of this so I've been left to try to figure it out by trial and error.

Thanks
JB

So, you can't get it to compile, because you get "various errors". But, you didn't bother to tell us WHAT errors? Don't you think that information might be helpful to anyone trying to help you find your problem?

Regards,
Ray L.

//Morse morse();   // DOESN'T WORK

No need for brackets at default constructor calling I think.

Morse morse;

try this simple version

// Class Definition:
class Morse
{
  public:               // Change #1
    Morse(int pin);
    Morse();
    void dot();
};

Morse::Morse(int pin) // WORKS
      {  
        Serial.print("CONSTRUCTOR WITH PIN "); 
        Serial.println(pin); 
      } // WORKS
Morse::Morse()       // DOESN'T WORK
      {   Serial.println("DEFAULT CONSTRUCTOR");}       // DOESN'T WORK

void setup() {
    Serial.begin(115200); 
    Serial.println("Morse test");
    Morse m, M1(10);
}

void loop() {}

a run gives

Morse test
DEFAULT CONSTRUCTOR
CONSTRUCTOR WITH PIN 10

RayLivingston:
So, you can't get it to compile, because you get "various errors". But, you didn't bother to tell us WHAT errors? Don't you think that information might be helpful to anyone trying to help you find your problem?

Regards,
Ray L.

Actually, since there are three places in the code this issue is referenced (declaration, instantiation, method call) and there are at least 4 different ways to write those lines (void with brackets, void without brackets, brackets no void, no void no brackets) the number of combinations is such that had I posted the full code to each option (as you would have undoubtedly requested) with the error messages associated, I suspect your response would have been just as critical of me for clogging up a post with so many 'wrong' code examples.

You may not like it, but my choice was thought out carefully in an attempt to explain the problem without making people wade through bad example after bad example after bad example after bad example after bad example after bad example after bad example after bad example(see?).

I'll repeat my problem ... I can't figure out (nor find an example) of declaring, instantiating and utilizing a simple class / object / method -- one that does not involve declaring/passing any parameters/arguments. I can show you a hundred ways that don't work. I'm looking to be pointed towards one that does.

Thanks for your help.

JB

Balagos:

//Morse morse();   // DOESN'T WORK

No need for brackets at default constructor calling I think.

Morse morse;

Thanks Balagos.

Before posting I had tried all these combos:

void with brackets
void with no brackets
no void with brackets
no void, no brackets.

No luck with any combo. There is something fundamental I am doing wrong.

Thanks again.

JB

horace:
try this simple version

// Class Definition:

class Morse
{
  public:              // Change #1
    Morse(int pin);
    Morse();
    void dot();
};

Morse::Morse(int pin) // WORKS
      { 
        Serial.print("CONSTRUCTOR WITH PIN ");
        Serial.println(pin);
      } // WORKS
Morse::Morse()      // DOESN'T WORK
      {  Serial.println("DEFAULT CONSTRUCTOR");}      // DOESN'T WORK

void setup() {
    Serial.begin(115200);
    Serial.println("Morse test");
    Morse m, M1(10);
}

void loop() {}



a run gives


Morse test
DEFAULT CONSTRUCTOR
CONSTRUCTOR WITH PIN 10

Thanks Horace. I appreciate your efforts with the sample sketch, but unfortunately it doesn't get me any closer to answering my question .... in your declaration you are still including 'int pin' as a parameter and I'm specifically attempting to declare, instantiate and utilize the simplest possible form of class/object/method -- one that does not pass any arguments.

Thanks again.
JB

you require { .. } for each constructor, e.g.

// Class Definition:
class Morse
{
  public:               // Change #1
    Morse(int pin); // WORKS
    Morse();       // DOESN'T WORK
    void dot();
};

//***********************************
//***********************************


// Constructor:           // Change #2
Morse::Morse(int pin) // WORKS
{}
Morse::Morse()       // DOESN'T WORK
{
  // I don't need anything done inbetween these brackets,
  // but if I remove them I get an error so I leave them.
}

//Instantiate:     // Change #3
Morse morse(13);    // WORKS
Morse morse1;   // DOESN'T WORK
Morse morse2();

you also also named both objects morse I changed the second to morse1 - note that morse2() also works

horace:
you also also named both objects morse I changed the second to morse1 - note that morse2() also works

I didn't choose the names --- that code is simply copied from the 'official' tutorial posted on this site.

Thanks again.

JB

ThinAirDesigns:
I didn't choose the names --- that code is simply copied from the tutorial posted on this site.

strange - must have been a bug in the tutorial
you cannot have two (or more) variables/objects with the same identifer in the same scope

horace:
strange - must have been a bug in the tutorial
you cannot have two (or more) variables/objects with the same identifer in the same scope

Interesting. I thought it was odd, but who am I (a stark raving beginner) to argue with the tutorial ... AND it compiles and functions properly.

Thanks again.

JB

do you have a link to the tutorial
you can use the same identifier in different scopes, e.g.

class Morse
{
  public:               // Change #1
    Morse(int pin); // WORKS
    Morse();       
};

Morse morse(13);    // WORKS
//Morse morse;   // error: redefinition of 'Morse morse'

void test(void)
{
  Morse morse;  // another morse!!
}

horace:
do you have a link to the tutorial

Following is a link to the tutorial, but please let's not get the thread off track too much inside the tutorial. My question is not related to the tutorial -- I merely pasted some simply and working code from it as a starting point. My question is about something that is not done nor addressed in the tutorial.

Thank
JB

https://www.arduino.cc/en/Hacking/LibraryTutorial

Can you supply the actual code that exhibits the problem then?

aarg:
Can you supply the actual code that exhibits the problem then?

As I replied to RayLivingston above, there are countless versions I have coded that exhibit the problem and I posted one of them in my initial post.

In the code I posted, I even tried made it easy for someone to toggle back and forth between working code and non-working code (just switch out the short "WORKS" lines with the "DOESN'T WORK" lines.

If you really need more than one non-working way to write the sketch, let me know -- I have lots of them. :slight_smile:

JB

aarg, here is the snippet from my original post, toggled into the non-working state.

Thanks
JB

// Class Definition:
class Morse
{
  public:           // Change #1
    //Morse(int pin); // WORKS
    Morse;      // DOESN'T WORK
    void dot();
};

//***********************************
//***********************************


// Constructor:       // Change #2
//Morse::Morse(int pin) // WORKS
Morse::Morse      // DOESN'T WORK
{
  // I don't need anything done inbetween these brackets,
  // but if I remove them I get an error so I leave them.
}


//Method:
void Morse::dot()
{
  digitalWrite(13, HIGH);
  delay(200);
  digitalWrite(13, LOW);
  delay(200);
}

//***********************************
//***********************************

//Instantiate:     // Change #3
//Morse morse(13);    // WORKS
Morse morse;   // DOESN'T WORK

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  morse.dot();
}

This is the correct instantiation of an object using the default (no argument) constructor:

Morse morse1;

This is incorrect:

Morse morse2();

It's incorrect because the compiler interprets it as a prototype for a function that takes no arguments and returns an object of type Morse.

gfvalvo, thanks for your reply and suggestion of removing the brackets entirely. Your explanation makes sense to me.

As I mentioned above, I had tried that previously to no avail. Following is the non-working code snipped with the brackets removed per your suggestion.

Thanks
JB

// Class Definition:
class Morse
{
  public:
    Morse;
    void dot();
};

//***********************************
//***********************************


// Constructor:
Morse::Morse
{
  // I don't need anything done inbetween these brackets,
  // but if I remove them I get an error so I leave them.
}


//Method:
void Morse::dot()
{
  digitalWrite(13, HIGH);
  delay(200);
  digitalWrite(13, LOW);
  delay(200);
}

//***********************************
//***********************************

//Instantiate:
Morse morse;

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  morse1.dot();
}

This works:

// Class Definition:
class Morse
{
  public:
    Morse();
    void dot();
};

// Constructor:
Morse::Morse()
{
  // I don't need anything done inbetween these brackets,
  // but if I remove them I get an error so I leave them.
}

//Method:
void Morse::dot()
{
  digitalWrite(13, HIGH);
  delay(200);
  digitalWrite(13, LOW);
  delay(200);
}

//Instantiate:
Morse morse1;

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  morse1.dot();
}

So does this:

// Class Definition:
class Morse
{
  public:           // Change #1
    //Morse(int pin); // WORKS
 //   Morse();      // DOESN'T WORK
    void dot();
};

//***********************************
//***********************************

//Method:
void Morse::dot()
{
  digitalWrite(6, HIGH);
  delay(200);
  digitalWrite(6, LOW);
  delay(200);
}

//***********************************
//***********************************

//Instantiate:     // Change #3
//Morse morse(13);    // WORKS
Morse morse;   // DOESN'T WORK

void setup()
{
  pinMode(6, OUTPUT);
    delay(2000);
    digitalWrite(6, HIGH);
  delay(2000);
 
}

void loop()
{
  morse.dot();
}

I removed all reference to the default constructor because the compiler provides it. You can override it if you need it to initialize something, but since you don't, just leave it out. Note that pin thirteen didn't flash on my board so I had to change it to a hardwired led.

This reference might help constructors