9

I am making a tiny game, and want to store high-scores. I made a Highscore-class in the top of the sketch file, like this:

class Highscore {
public:
  String name;
  int score;

  String toString() {
    return this->name + " - " + (String)score;
  }

  Highscore(String name, int score) {
    this->name = name;
    this->score = score;
  }
};

setup() { // etc

Now. Near the bottom of the sketch, I have a function I want to take a Highscore-object as a parameter, but the compiler will not let me. Example:

void writeHighscore(Highscore hs) {
  File f = SD.open("high.txt", FILE_WRITE);
  // Do stuff

The complation error is as follows:

sketch.ino:19:21: error: variable or field ‘writeHighscore’ declared void
sketch.ino:19:21: error: ‘Highscore’ was not declared in this scope
sketch.ino: In function ‘void setup()’:
sketch.ino:64:20: error: ‘writeHighscore’ was not declared in this scope

After changing parameter type to String, int or whatever, all the errors go away. I am able to create Highscore-objects INSIDE the writeHighscore() function, but how can I pass objects to it?

Edit 1 - Object creation

Highscore hs = Highscore("John", 975);
Serial.println(hs.toString()); // Prints "John - 975" as expected
writeHighscore(hs); // Error
5
  • can you please post the code where you create Highscore object?
    – Omer
    Nov 12, 2014 at 19:31
  • Included the object creation code.
    – krystah
    Nov 12, 2014 at 19:46
  • 2
    I think the problem is some missing bracket or so. Because there is no full code, I can guess and see: 1) setup() should be void setup(). But it should generate C++ warning/error. 2) Passing class parameter forces object copy when procedure is called. gcc should also generate a warning if copy constructor is missing. Use: void writeHighscore(Highscore &hs) or void writeHighscore(Highscore *hs) Copy compilable snipet in your post.
    – TMa
    Nov 12, 2014 at 20:02
  • Like stated in the original question, by changing the Highscore-parameter by, say, a String or an int, the errors go away, there are no missing brackets. I've also tried the &hs approach beforee writing the post, as well as passing the pointer writeHighscore(&hs) -> void writeHighscore(Highscore *hs) but to no avail.
    – krystah
    Nov 12, 2014 at 20:24
  • Please post the full source code, otherwise the line numbers in compilation errors are pointless.
    – jfpoilpret
    Nov 12, 2014 at 20:42

2 Answers 2

6

You are doing everything right, but you need to move the class outside of your .ino file for this to work. I'm not sure why the arduino IDE makes you do this (see edit) , but it is something I've run into before.

I just tested this, and moving the class declaration outside the ino and into a header file in the project folder makes it compile correctly. Just remember to include the header you make in the ino and to #include "Arduino.h" in the header to get access to "String" again.

Technically, only a forward declaration of the class needs to be in a different file.

Edit:

I'm relatively sure what is happening is the IDE is generating forward declarations for all your functions but not the class, which are placed before your class definition. This means that breaking the function regex the IDE uses with a dummy "throw()" fixes your problem. for example:

void writeHighscore(Highscore hs) throw() { ...

should work just fine (it worked for me)

2

This is a classic example of the IDE "helping" you by generating function prototypes, and not doing it very well. Example code to reproduce:

class Highscore {
public:
  String name;
  int score;
  String toString() {
    return this->name + " - " + (String)score;
  }

  Highscore(String name, int score) {
    this->name = name;
    this->score = score;
  }
};

void setup () { }
void loop () { }

void writeHighscore(Highscore hs) 
{
// do stuff
}

This gives the error:

sketch_jul06b:4: error: variable or field ‘writeHighscore’ declared void
sketch_jul06b:4: error: ‘Highscore’ was not declared in this scope

If you look at the output of the IDE preprocessor (you can do this by turning on verbose compilation, and finding out the name of the file it is actually compiling) you see this:

#line 1 "sketch_jul06b.ino"
#include "Arduino.h"
void setup ();
void loop ();
void writeHighscore(Highscore hs);
#line 1
class Highscore {
public:
  String name;
  int score;
  String toString() {
    return this->name + " - " + (String)score;
  }

  Highscore(String name, int score) {
    this->name = name;
    this->score = score;
  }
};

void setup () { }
void loop () { }

void writeHighscore(Highscore hs) 
{
// do stuff
}

The important part is that it put:

void writeHighscore(Highscore hs);

before where the class is declared.


You can fix the error by simply generating your own function prototype like this:

void writeHighscore(Highscore hs);  // function prototype
void writeHighscore(Highscore hs) 
{
// do stuff
}

Now it compiles without errors. It detects your own function prototype, and therefore does not generate its own. The first few lines of the generated file are now:

#line 1 "sketch_jul06b.ino"
#include "Arduino.h"
void setup ();
void loop ();
#line 1

That troubling prototype has gone.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.