Как я могу передать объект в качестве параметра функции?

8

Я делаю крошечную игру и хочу хранить рекорды. Я сделал Highscore-класс в верхней части файла эскиза, например так:

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

Сейчас же. В нижней части эскиза у меня есть функция, которую я хочу взять Highscore-объект в качестве параметра, но компилятор не позволит мне. Пример:

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

Ошибка компиляции выглядит следующим образом:

sketch.ino: 19: 21: ошибка: переменная или поле 'writeHighscore' объявлено void
sketch.ino: 19: 21: ошибка: 'Рекорды' не были объявлены в этой области
sketch.ino: в функции 'void setup ()':
sketch.ino: 64: 20: ошибка: writeHighscore не было объявлено в этой области

После изменения типа параметра на String, int или что-либо еще все ошибки исчезают. Я могу создавать Highscore-объекты ВНУТРИ writeHighscore()функции, но как я могу передать ей объекты?

Редактировать 1 - Создание объекта

Highscore hs = Highscore("John", 975);
Serial.println(hs.toString()); // Prints "John - 975" as expected
writeHighscore(hs); // Error
krystah
источник
Можете ли вы опубликовать код, где вы создаете объект Highscore?
Омер
Включен код создания объекта.
krystah
2
Я думаю, что проблема в некоторой недостающей скобке или около того. Поскольку нет полного кода, я могу догадаться и увидеть: 1) setup () должен быть void setup () . Но это должно генерировать C ++ предупреждение / ошибка. 2) Передача параметра класса приводит к принудительному копированию объекта при вызове процедуры. gcc также должен генерировать предупреждение, если отсутствует конструктор копирования. Используйте: void writeHighscore (Highscore & hs) или void writeHighscore (Highscore * hs) Скопируйте скомпилированный фрагмент в свое сообщение.
ТМа
Как указано в исходном вопросе, при изменении параметра Highscore, скажем, на String или int, ошибки исчезают, пропуски в скобках отсутствуют. Я также попробовал &hsподход до написания поста и прохождения указателя writeHighscore(&hs)-> void writeHighscore(Highscore *hs)но безрезультатно.
Крыст
Пожалуйста, разместите полный исходный код, иначе номера строк в ошибках компиляции не имеют смысла.
jfpoilpret

Ответы:

6

Вы все делаете правильно, но вам нужно переместить класс за пределы вашего файла .ino, чтобы это работало. Я не уверен, почему Arduino IDE заставляет вас делать это (см. правку), но это то, с чем я сталкивался раньше.

Я только что проверил это, и перемещение объявления класса за пределы ino и в файл заголовка в папке проекта делает его компиляцией правильно. Просто не забудьте включить заголовок, который вы делаете в ino и #include "Arduino.h"в заголовок, чтобы снова получить доступ к «String».

Технически, только предварительное объявление класса должно быть в другом файле.

Редактировать:

Я относительно уверен, что происходит, потому что IDE генерирует предварительные объявления для всех ваших функций, но не для класса, которые помещаются перед определением вашего класса. Это означает, что нарушение функции regex, которую IDE использует с помощью фиктивной функции throw (), решает вашу проблему. например:

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

должно работать просто отлично (у меня это сработало)

BrettAM
источник
2

Это классический пример того, как IDE «помогает», генерируя прототипы функций, и не очень хорошо это делает. Пример кода для воспроизведения:

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
}

Это дает ошибку:

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

Если вы посмотрите на вывод препроцессора IDE (вы можете сделать это, включив подробную компиляцию и выяснив имя файла, который он на самом деле компилирует), вы увидите это:

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

Важной частью является то, что это положить:

void writeHighscore(Highscore hs);

до того, где класс объявлен.


Вы можете исправить ошибку, просто сгенерировав собственный прототип функции следующим образом:

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

Теперь он компилируется без ошибок. Он обнаруживает ваш собственный прототип функции и, следовательно, не генерирует свой собственный. Первые несколько строк сгенерированного файла теперь:

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

Этот тревожный прототип исчез.

Ник Гаммон
источник