Инициализировать класс внутри класса
Я строю класс IP мониторинга, IPmonitoring
, который использует класс SPIFFS, который я написал, flashLOG
. Внутри IPmonitoring
у меня есть 2 экземпляра flashLOG
(код ниже).
У моего скетча есть несколько экземпляров IPmonitoring
для нескольких служб, которые я хочу контролировать. Я хочу, чтобы connectionLOG
и disconnectionLOG
имели уникальные и автоматизированные имена.
Например, если я отслеживаю службу под названием MQTT
, ее журнал подключения и отключения будет MQTT_discolog.txt
и MQTT_conlog.txt
... В моем приведенном ниже коде filename1
и filename2
являются const.
class IPmonitoring
{
private:
char *_IP;
char *_nick;
flashLOG connectionLOG;
flashLOG disconnectionLOG;
public:
IPmonitoring(char *IP, char *nick, char *filename1 = "/conlog.txt", char *filename2 = "/disconlog.txt")
: connectionLOG(filename1), disconnectionLOG(filename2)
{
_IP = IP;
_nick = nick;
}
EDIT1 - пример использования класса
моя цель состоит в том чтобы
имя файла 1 например было следующим MQTTbroker_connlog.txt
означая комбинацию _nick
и суффикса,
IPmonitoring MQTT_service("192.168.3.200","MQTTbroker");
void setup()
{
MQTT_service.start();
}
void loop()
{
MQTT_service.loop();
}
@Guy . D, 👍0
Обсуждение2 ответа
Лучший ответ:
Судя по вашему примеру использования, вы хотите, чтобы имена файлов создавались
конструктором IPmonitoring. Однако, поскольку этот класс не может заранее знать
, сколько места требуется для имен файлов, у вас остается
два варианта:
Пусть эти имена файлов являются элементами данных: массивами
символов
некоторого фиксированного размера. Это наложит ограничение на максимальную длину имени файла.Выделите массивы динамически во время построения.
Вот примерная реализация второго подхода:
class IPmonitoring
{
private:
const char *_IP;
const char *_nick;
const char *connectionLOG_filename;
const char *disconnectionLOG_filename;
flashLOG connectionLOG;
flashLOG disconnectionLOG;
// Возвращает динамически выделенную строку с соединением символов
// `a' и `b'.
const char *str_concat(const char *a, const char *b)
{
char *s = new char[strlen(a) + strlen(b) + 1];
strcpy(s, a);
strcat(s, b);
return s;
}
public:
IPmonitoring(const char *IP, const char *nick)
: _IP(IP), _nick(nick),
connectionLOG_filename(str_concat(nick, "_connlog.txt")),
disconnectionLOG_filename(str_concat(nick, "_disconnlog.txt")),
connectionLOG(connectionLOG_filename),
disconnectionLOG(disconnectionLOG_filename)
{}
~IPmonitoring(){
delete[] connectionLOG_filename;
delete[] disconnectionLOG_filename;
}
};
Обратите внимание на деструктор, который необходим, чтобы избежать утечек памяти, если только все экземпляры класса не выделены статически (что было бы хорошо , чтобы избежать фрагментации памяти). Вы можете реализовать конструктор копирования и оператор назначения копирования в соответствии с правилом трех.
Не могли бы вы, пожалуйста, объяснить : _IP(IP), _nick(ник)
Я никогда не использовал такой синтаксис, @Guy . D
@Парень.D: Это означает “Инициализировать _IP
со значением `IP”. Это функционально эквивалентно назначению, которое вы использовали в конструкторе, но синтаксически это инициализация, а не назначение. Это сделано для того, чтобы прояснить, что конструктор не делает ничего, кроме инициализации элементов данных., @Edgar Bonet
отлично! Не знал этого, @Guy . D
Не могли бы вы, пожалуйста, объяснить/ привести пример статического выделения класса ?, @Guy . D
@Guy.D: Смотрите свой собственный пример использования: объект является глобальной переменной, а глобальные переменные распределяются статически. В этом случае конструктор вызывается при запуске программы, перед " main ()", и деструктор обычно никогда не вызывается., @Edgar Bonet
Ладно, просто хотел убедиться, что ты имеешь в виду., @Guy . D
1. Имеет ли смысл использовать строки C++ ("std::string"), которые могут быть динамически объединены? -- 2. Начиная с C++14 правило, которому следует подчиняться, - это [Правило пяти](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2b_программирование)#Rule_of_Five)., @the busybee
У вас есть три варианта имен файлов и вообще.
- постоянный строковый литерал
- string buffer global или on stack с областью действия, допустимой при использовании строки
- динамически выделяемая строка в куче
с помощью 2) и 3) вы можете затем построить строку с помощью функций C str или sprintf
вариант 3) подходит для MCU, если вы создаете эти имена файлов только при запуске, а не при повторном создании скетча
Если вы выберете вариант 3), вы можете построить строки в конструкторе класса IPmonitoring, но вы не можете построить строку в части инициализации члена конструктора. Вы должны добавить сеттеры в
класс flashLOG и после создания строк для имен файлов установить их в
экземпляр flashLOG вместе с сеттерами.
@Парень.D Я улучшил ответ, @Juraj
- Как получить исходные файлы для библиотек Arduino?
- Ошибка: "недопустимое использование нестатической функции-члена" при вызове функции из моего собственного класса-метода
- Как подключить Wi-Fi Shield ESP-12E-ESP8266-UART-WIFI-Wireless-Shield к Arduino
- Существуют ли библиотеки сглаживания сигналов для Arduino?
- Wire.h не найден!
- Библиотека FastLED: Как настроить яркость одного пикселя в абсолютном масштабе?
- Как эта строка кода определяет, подключен ли последовательный интерфейс?
- Ошибка Specified folder/zip file does not contain a valid library
Вы имеете в виду имена переменных в исходном коде? Есть причины, по которым вы хотите, чтобы это и не использовали элемент в классе flashLOG, инициализированный его конструктором, чтобы сохранить его имя?, @Sacha
@Sacha да,
имя файла 1 " +
имя файла 2. Я не понимаю, что вы предлагаете, так как это способ ввода
flashLOG` (с именем файла ), @Guy . DЗабудьте о моем первом замечании. В вашем примере, как код, создающий экземпляр IPmonitoring, узнает имя службы, которую он будет отслеживать?, @Sacha
@Sacha - В случае, если у меня есть несколько экземпляров, использование "filename1" и "filename2" таким образом будут перезаписывать друг друга - это недопустимый способ сделать это, если я не напишу каждое имя в определенном, @Guy . D
у вас есть имена файлов в качестве параметров. поэтому создайте его с разными именами файлов, @Juraj
Пожалуйста, покажите нам какой-нибудь пример того, как вам нравится использовать класс "IPmonitoring"., @the busybee
@thebusybee см. правку 1, @Guy . D
@Juraj см. правку1, @Guy . D
Если бы вы позволили вызывающему абоненту указать полные имена файлов, задача была бы значительно проще. Я рассматриваю это как разумное решение. -- О, и поскольку вы программируете на C++, использование
std::string
вместо строк C (char []
) _ может упростить задачу., @the busybee