Недопустимое использование нестатической функции-члена

Чтобы объяснить мою проблему, я использовал 3 класса: Actions, Triggers и Combine.

Действия имитирует функцию действия, определенную извне.

Триггеры имеют ту функцию, которую необходимо выполнить.

Объединить объединяет Действия и Триггеры.

Теперь void combine_funcs() является функцией-членом класса Combine при совпадении между Triggers и Actions случиться -> передача функции для выполнения.

Здесь void Combine_funcs() показан с помощью std::bind, но он также был протестирован напрямую.

Вывод ошибки приведен ниже кода.

class Actions
{
  typedef void (*cb_func)(uint8_t resaon);

private:
  cb_func exter_func;

public:
  void get_external_func(cb_func func)
  {
    exter_func = func;
  }
  void callAction(uint8_t i)
  {
    exter_func(i);
  }
};

class Triggers
{
public:
  void this_is_external_func(uint8_t i)
  {
    Serial.println(i);
  }
};

class Combine
{
public:
  Actions a;
  Triggers b;

  void combine_funcs()
  {
    a.get_external_func(std::bind(&Triggers::this_is_external_func, this,std::placeholders::_1));
  }
  void loop()
  {
    if (millis() > 10000)
    {
      a.callAction();
    }
  }
};

Combine combo;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Start!");
  combo.combine_funcs();
}

void loop()
{
  // put your main code here, to run repeatedly:
  combo.loop();
}

Вывод компиляции:

/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: In member function 'void Combine::combine_funcs()':
    sketch_jul26a:36:34: error: cannot convert 'std::_Bind_helper<false, void (Triggers::*)(unsigned char), Combine*, const std::_Placeholder<1>&>::type' to 'Actions::cb_func' {aka 'void (*)(unsigned char)'}
       36 |     a.get_external_func(std::bind(&Triggers::this_is_external_func, this,std::placeholders::_1));
          |                         ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          |                                  |
          |                                  std::_Bind_helper<false, void (Triggers::*)(unsigned char), Combine*, const std::_Placeholder<1>&>::type
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:9:34: note:   initializing argument 1 of 'void Actions::get_external_func(Actions::cb_func)'
        9 |   void get_external_func(cb_func func)
          |                          ~~~~~~~~^~~~
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: In member function 'void Combine::loop()':
    sketch_jul26a:42:20: error: no matching function for call to 'Actions::callAction()'
       42 |       a.callAction();
          |                    ^
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:13:8: note: candidate: 'void Actions::callAction(uint8_t)'
       13 |   void callAction(uint8_t i)
          |        ^~~~~~~~~~
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:13:8: note:   candidate expects 1 argument, 0 provided
    exit status 1
    cannot convert 'std::_Bind_helper<false, void (Triggers::*)(unsigned char), Combine*, const std::_Placeholder<1>&>::type' to 'Actions::cb_func' {aka 'void (*)(unsigned char)'}

EDIT_1: изменить класс Объединить, чтобы он наследовал другие классы

class Combine : public Actions, Triggers
{
public:
  void combine_funcs()
  {
    get_external_func(this_is_external_func);
  }
  void loop()
  {
    if (millis() > 10000)
    {
      callAction(13);
    }
  }

выдает ту же ошибку:

/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: In member function 'void Combine::combine_funcs()':
sketch_jul26a:33:23: error: invalid use of non-static member function 'void Triggers::this_is_external_func(uint8_t)'
   33 |     get_external_func(this_is_external_func);
      |                       ^~~~~~~~~~~~~~~~~~~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:22:8: note: declared here
   22 |   void this_is_external_func(uint8_t i)
      |        ^~~~~~~~~~~~~~~~~~~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: At global scope:
sketch_jul26a:60:6: error: redefinition of 'void setup()'
   60 | void setup()
      |      ^~~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:46:6: note: 'void setup()' previously defined here
   46 | void setup()
      |      ^~~~~
sketch_jul26a:68:6: error: redefinition of 'void loop()'
   68 | void loop()
      |      ^~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:54:6: note: 'void loop()' previously defined here
   54 | void loop()
      |      ^~~~
exit status 1
invalid use of non-static member function 'void Triggers::this_is_external_func(uint8_t)'

};

, 👍1

Обсуждение

Помогает ли этот Q+A? https://stackoverflow.com/a/72450270/10292145, @VE7JRO

@ VE7JRO, можете ли вы объяснить, зачем мне нужен void* ?, @Guy . D

почему бы не установить объект в качестве параметра?, @Juraj

@Juraj я пытался, но безуспешно, @Guy . D

@guyd - Когда я пытаюсь скомпилировать ваш код, я получаю разные ошибки. Я использую другой компилятор, чем вы, поэтому моя первая ошибка приводит меня сюда: https://stackoverflow.com/questions/14261013/bind-is-not-a-member-of-std В мире Arduino они указывают я здесь: https://forum.arduino.cc/t/include-functional-error/397411 Единственные вопросы, которые у меня есть к вам, это почему вы пишете свой код таким образом и какую проблему вы пытаетесь решить?, @VE7JRO

Почему бы не использовать наследование классов, например, class Combine public Action {}? Однако решение в стороне, не создавайте классы ради создания классов, все три ваших класса не нужны или должны принадлежать где-то еще как методы., @hcheung

Я попытаюсь объяснить мою большую проблему: У меня есть 2 класса, которые я написал и протестировал. Один из них — это состояния чтения кнопок, включая класс тайм-аутов, а второй класс связан с включением/выключением индикаторов, включая индикаторы PWM. ОБА используются и тестируются ранее. Третья библиотека сочетает в себе как параметры на флэш-памяти, так и команду MQTT (как своего рода оболочку), даже имеет несколько экземпляров моего третьего класса. Я хочу использовать все свои 3 класса как работающее наследие, а не переписывать все заново., @Guy . D

Я имел в виду, что тип параметра должен быть классом, и вы передаете туда объект и выполняете функцию для этого объекта. функция-член должна быть вызвана для объекта, поэтому вы можете использовать эту функцию в качестве параметра. он не знает, на каком объекте он должен выполняться., @Juraj

@Juraj, можешь объяснить на примере?, @Guy . D

может позже сегодня, @Juraj

Вам нужно вызвать this_is_external_func() для объекта, но вы не предоставляете его в callAction(). Я вижу две альтернативы: 1) Предоставить объект для вызова метода. 2) Сделать метод функцией класса, которому не нужен объект., @the busybee

@hcheung воспользовался вашим советом для inherete (см. редактирование 1), но результаты те же., @Guy . D

возвращаемый тип привязки не совпадает с типом исходной функции, @Juraj

@Juraj Можешь указать?, @Guy . D

Я изменил ваш скетч с помощью auto f = std:bind.... и a.get_external_func(f);, и сообщение об ошибке стало немного яснее., @Juraj

@Juraj - СУПЕР!!! это был первый вывод, который я получил, что я сделал неправильно., @Guy . D


1 ответ


Лучший ответ:

1

Проблема в том, что возвращаемый тип привязки не совпадает с типом исходной функции, поэтому его нельзя установить с помощью void get_external_func(cb_func func).

Но это похоже на проблему X->Y. Если вы используете ООП, используйте объекты.

Я рассматриваю набросок в вопросе как тест, поэтому хочу прокомментировать другие части и то, как их правильно сделать. Я только что внес минимальные изменения, чтобы передать объект и вызвать метод (функцию-член) с объектом.


class Triggers
{
public:
  void func(uint8_t i)
  {
    Serial.println(i);
  }
};

class Actions
{
  Triggers* trigers;
  
public:
  void set_triggers(Triggers* t)
  {
    trigers = t;
  }
  
  virtual void callAction(uint8_t i)
  {
    trigers->func(i);
  }
};

class Combine
{
public:
  Actions a;
  Triggers b;

  void combine_funcs()
  {
    a.set_triggers(&b);
  }
  void loop()
  {
    if (millis() < 10000)
    {
      a.callAction(1);
    }
  }
};

Combine combo;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Start!");
  combo.combine_funcs();
}

void loop()
{
  // put your main code here, to run repeatedly:
  combo.loop();
}
,