¿Cómo puedo pasar un objeto como parámetro a una función?

8

Estoy haciendo un pequeño juego y quiero almacenar puntuaciones altas. Hice una clase Highscore en la parte superior del archivo de boceto, así:

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

Ahora. Cerca de la parte inferior del boceto, tengo una función que quiero tomar un objeto Highscore como parámetro, pero el compilador no me lo permite. Ejemplo:

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

El error de compilación es el siguiente:

sketch.ino: 19: 21: error: variable o campo 'writeHighscore' declarado vacío
sketch.ino: 19: 21: error: 'Highscore' no se declaró en este ámbito
sketch.ino: En la función 'void setup ()':
sketch.ino: 64: 20: error: 'writeHighscore' no se declaró en este ámbito

Después de cambiar el tipo de parámetro a String, int o lo que sea, todos los errores desaparecen. Puedo crear Highscore-objetos DENTRO de la writeHighscore()función, pero ¿cómo puedo pasarle objetos?

Edición 1 - Creación de objetos

Highscore hs = Highscore("John", 975);
Serial.println(hs.toString()); // Prints "John - 975" as expected
writeHighscore(hs); // Error
krystah
fuente
¿puede publicar el código donde crea el objeto Highscore?
Omer
Incluye el código de creación del objeto.
krystah
2
Creo que el problema es un paréntesis perdido más o menos. Debido a que no hay un código completo, puedo adivinar y ver: 1) la configuración () debería ser una configuración nula () . Pero debería generar advertencia / error de C ++. 2) Pasar el parámetro de clase fuerza la copia del objeto cuando se llama al procedimiento. gcc también debería generar una advertencia si falta el constructor de copia. Use: void writeHighscore (Highscore & hs) o void writeHighscore (Highscore * hs) Copie el fragmento compilable en su publicación.
TMa
Como se indicó en la pregunta original, al cambiar el parámetro Highscore por, digamos, una Cadena o un int, los errores desaparecen, no faltan corchetes. También probé el &hsenfoque antes de escribir la publicación, así como pasar el puntero writeHighscore(&hs)-> void writeHighscore(Highscore *hs)pero fue en vano.
krystah
Publique el código fuente completo; de lo contrario, los números de línea en los errores de compilación no tienen sentido.
jfpoilpret

Respuestas:

6

Estás haciendo todo bien, pero necesitas mover la clase fuera de tu archivo .ino para que esto funcione. No estoy seguro de por qué el IDE de Arduino te hace hacer esto (ver edición), pero es algo con lo que me he encontrado antes.

Acabo de probar esto, y mover la declaración de clase fuera del ino y dentro de un archivo de encabezado en la carpeta del proyecto hace que se compile correctamente. Solo recuerda incluir el encabezado que hagas en el ino y #include "Arduino.h"en el encabezado para obtener acceso a "String" nuevamente.

Técnicamente, solo una declaración directa de la clase debe estar en un archivo diferente.

Editar:

Estoy relativamente seguro de que lo que está sucediendo es que el IDE está generando declaraciones directas para todas sus funciones, pero no para la clase, que se colocan antes de su definición de clase. Esto significa que romper la función regex que utiliza el IDE con un "throw ()" ficticio soluciona su problema. por ejemplo:

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

debería funcionar bien (funcionó para mí)

BrettAM
fuente
2

Este es un ejemplo clásico del IDE "ayudándole" generando prototipos de funciones y no haciéndolo muy bien. Código de ejemplo para reproducir:

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
}

Esto da el error:

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

Si observa el resultado del preprocesador IDE (puede hacerlo activando la compilación detallada y descubriendo el nombre del archivo que realmente está compilando) verá esto:

#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 parte importante es que pone:

void writeHighscore(Highscore hs);

antes de donde se declara la clase.


Puede corregir el error simplemente generando su propio prototipo de función como este:

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

Ahora se compila sin errores. Detecta su propio prototipo de función y, por lo tanto, no genera el suyo. Las primeras líneas del archivo generado son ahora:

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

Ese prototipo problemático se ha ido.

Nick Gammon
fuente