Wie kann ich ein Objekt als Parameter an eine Funktion übergeben?

8

Ich mache ein winziges Spiel und möchte Highscores speichern. Ich habe oben in der Skizzendatei eine Highscore-Klasse erstellt, wie folgt:

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

Jetzt. Am unteren Rand der Skizze habe ich eine Funktion, die ich als Highscore-Objekt als Parameter verwenden möchte, aber der Compiler lässt mich nicht. Beispiel:

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

Der Komplikationsfehler ist wie folgt:

skizze.ino: 19: 21: fehler: Variable oder feld 'writeHighscore' deklariert void
skizze.ino: 19: 21: fehler: 'highscore' wurde in diesem
bereich nicht deklariert skizze.ino: In der funktion 'void setup ()':
Skizze.ino: 64: 20: Fehler: 'writeHighscore' wurde in diesem Bereich nicht deklariert

Nachdem Sie den Parametertyp in String, int oder was auch immer geändert haben, verschwinden alle Fehler. Ich kann Highscore-Objekte INNERHALB der writeHighscore()Funktion erstellen , aber wie kann ich Objekte an diese übergeben?

Bearbeiten 1 - Objekterstellung

Highscore hs = Highscore("John", 975);
Serial.println(hs.toString()); // Prints "John - 975" as expected
writeHighscore(hs); // Error
krystah
quelle
Können Sie bitte den Code posten, in dem Sie das Highscore-Objekt erstellen?
Omer
Enthält den Objekterstellungscode.
Krystah
2
Ich denke, das Problem ist eine fehlende Klammer oder so. Da es keinen vollständigen Code gibt, kann ich raten und sehen: 1) setup () sollte void setup () sein . Aber es sollte C ++ Warnung / Fehler erzeugen. 2) Das Übergeben des Klassenparameters erzwingt die Objektkopie, wenn die Prozedur aufgerufen wird. gcc sollte auch eine Warnung generieren, wenn der Kopierkonstruktor fehlt. Verwenden Sie: void writeHighscore (Highscore & hs) oder void writeHighscore (Highscore * hs) Kopieren Sie das kompilierbare Snipet in Ihren Beitrag.
TMa
Wie in der ursprünglichen Frage angegeben, verschwinden die Fehler, wenn der Highscore-Parameter beispielsweise durch einen String oder ein Int geändert wird. Es fehlen keine Klammern. Ich habe auch versucht, den &hsAnsatz vor dem Schreiben des Beitrags sowie das Übergeben des Zeigers writeHighscore(&hs)-> void writeHighscore(Highscore *hs)aber ohne Erfolg.
Krystah
Bitte posten Sie den vollständigen Quellcode, sonst sind die Zeilennummern bei Kompilierungsfehlern sinnlos.
Jfpoilpret

Antworten:

6

Sie machen alles richtig, aber Sie müssen die Klasse aus Ihrer .ino-Datei verschieben, damit dies funktioniert. Ich bin mir nicht sicher, warum die Arduino-IDE Sie dazu bringt (siehe Bearbeiten), aber es ist etwas, auf das ich vorher gestoßen bin.

Ich habe dies gerade getestet, und wenn die Klassendeklaration außerhalb von ino in eine Header-Datei im Projektordner verschoben wird, wird sie korrekt kompiliert. Denken Sie daran, den von Ihnen erstellten Header in das Ino und #include "Arduino.h"in den Header aufzunehmen, um erneut auf "String" zuzugreifen.

Technisch gesehen muss sich nur eine Vorwärtsdeklaration der Klasse in einer anderen Datei befinden.

Bearbeiten:

Ich bin mir ziemlich sicher, dass die IDE Vorwärtsdeklarationen für alle Ihre Funktionen generiert, nicht jedoch für die Klasse, die vor Ihrer Klassendefinition stehen. Dies bedeutet, dass das Unterbrechen des von der IDE verwendeten regulären Regex mit einem Dummy "throw ()" Ihr Problem behebt. zum Beispiel:

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

sollte gut funktionieren (es hat bei mir funktioniert)

BrettAM
quelle
2

Dies ist ein klassisches Beispiel für die IDE, die Ihnen "hilft", indem sie Funktionsprototypen generiert und dies nicht sehr gut macht. Zu reproduzierender Beispielcode:

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
}

Dies gibt den Fehler:

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

Wenn Sie sich die Ausgabe des IDE-Präprozessors ansehen (Sie können dies tun, indem Sie die ausführliche Kompilierung aktivieren und den Namen der Datei ermitteln, die tatsächlich kompiliert wird), sehen Sie Folgendes:

#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
}

Der wichtige Teil ist, dass es sagte:

void writeHighscore(Highscore hs);

vor wo die Klasse deklariert wird.


Sie können den Fehler beheben, indem Sie einfach Ihren eigenen Funktionsprototyp wie folgt generieren:

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

Jetzt wird es fehlerfrei kompiliert. Es erkennt Ihren eigenen Funktionsprototyp und generiert daher keinen eigenen. Die ersten Zeilen der generierten Datei lauten jetzt:

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

Dieser beunruhigende Prototyp ist verschwunden.

Nick Gammon
quelle