Несоответствие типа параметра конструктора PubSubClient

Я только изучаю Arduino, так что это чисто образовательный вызов.

Я хочу создать экземпляр клиента PubSubClient с параметром WiFiClient.


#include <WiFiClient.h>
#include <PubSubClient.h>

WiFiClient *wifi = NULL;
PubSubClient client(wifi);

void setup() {
  // put your setup code here, to run once:
}

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

компиляция возвращает меня:

Compilation error: no matching function for call to /home/tepo/Arduino/libraries/PubSubClient/src/PubSubClient.h:116:4: note:   candidate expects 0 arguments, 1 provided
/home/tepo/Arduino/libraries/PubSubClient/src/PubSubClient.h:88:7: note: candidate: 'PubSubClient::PubSubClient(const PubSubClient&)'
 class PubSubClient : public Print {
       ^~~~~~~~~~~~
/home/tepo/Arduino/libraries/PubSubClient/src/PubSubClient.h:88:7: note:   no known conversion for argument 1 from 'WiFiClient*' to 'const PubSubClient&'

exit status 1

Compilation error: no matching function for call to 'PubSubClient::PubSubClient(WiFiClient*&)'

и перечислим все остальные конструкторы.

Цепочка типов, похоже, сохраняется: класс WiFiClient: общедоступный ESPLwIPClient -> класс ESPLwIPClient: общедоступный клиент -> Клиент класса: общедоступный поток

PubSubClient ctor:

 PubSubClient(Client& client);

так почему же он не принимает WifiClient в качестве параметра?

, 👍0

Обсуждение

Клиент PubSubClient(*wifi);. он скомпилируется, но во время выполнения просто произойдет сбой, поскольку по адресу 0 не будет объекта WiFiClient., @Juraj

посмотрите пример кода в библиотеке, @jsotola


1 ответ


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

1

Проблема, с которой вы столкнулись при работе с конструктором PubSubClient в Arduino, связана с тем, как вы передаете объект WiFiClient. В настоящее время вы используете указатель (WiFiClient *wifi), но конструктор PubSubClient ожидает ссылку на объект Client, а не указатель.

Класс WiFiClient наследуется от Client, поэтому его можно использовать с PubSubClient. Однако вам необходимо передать экземпляр WiFiClient, а не указатель на экземпляр.

Вот как вы можете исправить свой код:

#include <WiFiClient.h>
#include <PubSubClient.h>

WiFiClient wifi;
PubSubClient client(wifi);

void setup() {
  // put your setup code here, to run once:
}

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

В этой исправленной версии wifi является экземпляром WiFiClient, а не указателем. Когда вы передаете Wi-Fi конструктору PubSubClient, он правильно соответствует ожидаемому Client& тип параметра клиента.

В C++ указатель (WiFiClient *) — это переменная, содержащая адрес объекта в памяти. Ссылка (WiFiClient &) — это псевдоним объекта. Конструктор PubSubClient ожидает ссылку, поскольку ему необходимо взаимодействовать с объектом Client на протяжении всего его жизненного цикла, а ссылки, как правило, безопаснее и проще использовать в этом контексте, чем указатели.

,

да, это сработало; однако я не могу понять, откуда берется настоящий экземпляр «wifi», поскольку я не создаю int, а в скетче я использую WifiManager, который, кажется, «вводит» его в объявленную переменную. (Я родом из мира java-spring). Вот почему я подумал, что в этом случае подойдет указатель; мне это кажется немного странным, оно просто каким-то образом "поставляется".., @greengold

Что значит, ты его не создаешь? WiFiClient wifi; создает его. В отличие от Java, вам не нужно выполнять new процедурно, чтобы создать экземпляр переменной класса., @Nick Gammon