Как перебрать объекты или передать объект функции?
Я не уверен, что это больше вопрос C++, но я просмотрел оба и до сих пор не знаю.
У меня есть скетч, который управляет 6 шаговыми двигателями с помощью библиотеки AccelStepper, и, чтобы сократить код, я хотел бы просто перебрать их или передать их функции по отдельности. Все они инициализируются с разными параметрами, а затем помещаются в массив.
Однако я получаю сообщение об ошибке "запрошено преобразование из SomeClass() в нескалярный тип SomeClass" или "запрошено преобразование из SomeClass (*)()" в нескалярный тип SomeClass" в зависимости от что я пытаюсь.
У меня есть опыт работы с C и Java, немного с C++, и я думал, что это будет простой массив указателей, но я не могу найти правильную комбинацию.
Я сделал урезанную версию, которую пытаюсь скомпилировать с помощью gcc, чтобы продемонстрировать любой подход. Я удалил все попытки указателей с помощью & или * чтобы объяснить, что я хочу:
SomeClass classA();
SomeClass classB();
// ошибка: запрошено преобразование из 'SomeClass()' в нескалярный тип 'SomeClass'
SomeClass things[2] = {classA, classB};
int init(class SomeClass thing) {
std::cout << "Setting up thing ";
thing.setFoo(100);
}
int main() {
for (int i=0; i < 2; i++) {
things[i].setFoo(100);
}
// не удалось преобразовать 'classA' из 'SomeClass (*)()' в 'SomeClass'
init(classA);
return 0;
}
И просто для полноты мои файлы классов, которые являются упрощенными версиями класса AccelStepper:
SomeClass.h:
#include <stdlib.h>
class SomeClass
{
public:
SomeClass();
void setFoo(float foo);
};
SomeClass.cpp:
#include <stdlib.h>
#include <string>
#include <iostream>
#include "SomeClass.h"
SomeClass::SomeClass()
{
}
void SomeClass::setFoo(float foo)
{
std::cout << "foo ";
}
Надеюсь, кто-то не против объяснить то, что, наверное, действительно просто и очевидно! :)
@jbyrnes, 👍0
1 ответ
Лучший ответ:
В вашем наброске есть пара фундаментальных ошибок. В основном ваша конструкция экземпляров вашего класса:
SomeClass classA();
SomeClass classB();
Они рассматриваются как функции, возвращающие объект SomeClass, а не конструкторы SomeClass. Вместо этого они должны просто читать:
SomeClass classA;
SomeClass classB;
Что касается остального, вам гораздо лучше использовать указатели на классы — это значительно упрощает их передачу. Например, ваш массив будет выглядеть так:
SomeClass *things[2] = {&classA, &classB};
Это массив указателей на объекты. Он просто сохраняет адреса, по которым они находятся, а не дублирует объекты в новые объекты в массиве.
Тогда ваш цикл будет работать следующим образом:
for (int i=0; i < 2; i++) {
things[i]->setFoo(100);
}
Обратите внимание на использование ->
вместо .
, поскольку вы используете указатель на объект.
Аналогично ваша функция init()
будет выглядеть так:
int init(SomeClass *thing) {
Serial.println("Setting up thing");
thing->setFoo(100);
}
init(&classA);
Однако, если вы никогда не собираетесь использовать с ним содержимое своего массива, вы можете использовать ссылку вместо указателя:
int init(SomeClass &thing) {
Serial.println("Setting up thing");
thing.setFoo(100);
}
init(classA);
Он выполняет ту же работу, что и указатель, но оставляет вам то, что выглядит как настоящий объект, а не указатель на объект. На самом деле он просто использует псевдоним для нового имени объекта по тому же адресу, поэтому вы все еще можете получить доступ то же самое с использованием .
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- GCC msg "note: in definition of macro 'max'" сообщение об ошибке
- Работает ли конструкция int array[100] = {0} на Arduino?
- Массив динамического размера в качестве члена класса
- Работает с gcc, но не с Arduino. ошибка: taking address of temporary array
- Прерывания внутри класса, связанные с функцией класса
- Как писать скетчи, совместимые с makefile?
- Недопустимое использование нестатической функции-члена
Спасибо за Ваш ответ! Я должен был включить более сложный конструктор, фактические объекты создаются, например: AccelStepper stepperA(AccelStepper::HALF4WIRE, MotorPinA1, MotorPinA3, MotorPinA2, MotorPinA4); Это все еще держится с вышеизложенным?, @jbyrnes
Из моего опыта работы с C это выглядит как указатель на массив указателей: SomeClass *things[2] = {&classA, &classB}; Отличается ли он в C++?, @jbyrnes
Нет, это просто массив [] указателей *. Если бы это был указатель на массив указателей, то это был бы SomeClass **things[2] — точно такой же, как в C., @Majenko
Если ваш конструктор принимает параметры, вы добавляете параметры. Если нет, то нет. Это немного сбивает с толку, и я понятия не имею, почему они так поступили., @Majenko
@Majenko спасибо за ваш ответ. Это очень помогло. Однако мне было интересно, вместо массива указателей со ссылками на объекты класса, не могли бы мы просто иметь массив этих объектов и ссылаться на них как myObj &obj = arr[idx];?, @Phil