Comment passer un objet en paramètre à une fonction?

8

Je fais un petit jeu et je veux enregistrer des scores élevés. J'ai créé une classe Highscore en haut du fichier d'esquisse, comme ceci:

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

Maintenant. Près du bas de l'esquisse, j'ai une fonction que je veux prendre un objet Highscore comme paramètre, mais le compilateur ne me le permet pas. Exemple:

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

L'erreur de complation est la suivante:

sketch.ino: 19: 21: erreur: variable ou champ 'writeHighscore' déclaré nul
sketch.ino: 19: 21: erreur: 'Highscore' n'a pas été déclaré dans cette étendue
sketch.ino: Dans la fonction 'void setup ()':
sketch.ino: 64: 20: erreur: 'writeHighscore' n'a pas été déclaré dans cette étendue

Après avoir changé le type de paramètre en String, int ou autre, toutes les erreurs disparaissent. Je peux créer des objets Highscore à l'intérieur de la writeHighscore()fonction, mais comment puis-je lui passer des objets?

Édition 1 - Création d'objets

Highscore hs = Highscore("John", 975);
Serial.println(hs.toString()); // Prints "John - 975" as expected
writeHighscore(hs); // Error
krystah
la source
pouvez-vous s'il vous plaît poster le code où vous créez un objet Highscore?
Omer
Inclus le code de création d'objet.
krystah
2
Je pense que le problème est un support manquant. Parce qu'il n'y a pas de code complet, je peux deviner et voir: 1) setup () devrait être vide setup () . Mais cela devrait générer un avertissement / erreur C ++. 2) Le passage du paramètre de classe force la copie d'objet lors de l'appel de la procédure. gcc devrait également générer un avertissement si le constructeur de copie est manquant. Utilisez: void writeHighscore (Highscore & hs) ou void writeHighscore (Highscore * hs) Copiez le snipet compilable dans votre article.
TMa
Comme indiqué dans la question d'origine, en modifiant le paramètre Highscore par, disons, une chaîne ou un entier, les erreurs disparaissent, il n'y a pas de parenthèses manquantes. J'ai également essayé l' &hsapproche avant d'écrire le message, ainsi que de passer le pointeur writeHighscore(&hs)-> void writeHighscore(Highscore *hs)mais en vain.
krystah
Veuillez publier le code source complet, sinon les numéros de ligne dans les erreurs de compilation sont inutiles.
jfpoilpret

Réponses:

6

Vous faites tout correctement, mais vous devez déplacer la classe en dehors de votre fichier .ino pour que cela fonctionne. Je ne sais pas pourquoi l'IDE Arduino vous fait faire ça (voir modifier), mais c'est quelque chose que j'ai rencontré auparavant.

Je viens de tester cela, et le déplacement de la déclaration de classe en dehors de l'ino et dans un fichier d'en-tête dans le dossier du projet permet de la compiler correctement. N'oubliez pas d'inclure l'en-tête que vous créez dans l'ino et #include "Arduino.h"dans l'en-tête pour accéder à nouveau à "String".

Techniquement, seule une déclaration directe de la classe doit être dans un fichier différent.

Éditer:

Je suis relativement sûr de ce qui se passe, c'est que l'EDI génère des déclarations avancées pour toutes vos fonctions, mais pas la classe, qui sont placées avant la définition de votre classe. Cela signifie que la rupture de l'expression rationnelle de fonction que l'EDI utilise avec un "throw ()" factice résout votre problème. par exemple:

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

devrait fonctionner très bien (cela a fonctionné pour moi)

BrettAM
la source
2

C'est un exemple classique de l'IDE qui "vous aide" en générant des prototypes de fonction, et en ne le faisant pas très bien. Exemple de code à reproduire:

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
}

Cela donne l'erreur:

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

Si vous regardez la sortie du préprocesseur IDE (vous pouvez le faire en activant la compilation détaillée et en trouvant le nom du fichier qu'il est en train de compiler), vous voyez ceci:

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

La partie importante est qu'elle met:

void writeHighscore(Highscore hs);

avant où la classe est déclarée.


Vous pouvez corriger l'erreur en générant simplement votre propre prototype de fonction comme ceci:

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

Maintenant, il compile sans erreur. Il détecte votre propre prototype de fonction et ne génère donc pas le sien. Les premières lignes du fichier généré sont maintenant:

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

Ce prototype troublant a disparu.

Nick Gammon
la source