Инициализировать класс внутри класса

Я строю класс 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();
}

, 👍0

Обсуждение

Вы имеете в виду имена переменных в исходном коде? Есть причины, по которым вы хотите, чтобы это и не использовали элемент в классе 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


2 ответа


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

1

Судя по вашему примеру использования, вы хотите, чтобы имена файлов создавались конструктором IPmonitoring. Однако, поскольку этот класс не может заранее знать , сколько места требуется для имен файлов, у вас остается два варианта:

  1. Пусть эти имена файлов являются элементами данных: массивами символов некоторого фиксированного размера. Это наложит ограничение на максимальную длину имени файла.

  2. Выделите массивы динамически во время построения.

Вот примерная реализация второго подхода:

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


1

У вас есть три варианта имен файлов и вообще.

  1. постоянный строковый литерал
  2. string buffer global или on stack с областью действия, допустимой при использовании строки
  3. динамически выделяемая строка в куче

с помощью 2) и 3) вы можете затем построить строку с помощью функций C str или sprintf

вариант 3) подходит для MCU, если вы создаете эти имена файлов только при запуске, а не при повторном создании скетча

Если вы выберете вариант 3), вы можете построить строки в конструкторе класса IPmonitoring, но вы не можете построить строку в части инициализации члена конструктора. Вы должны добавить сеттеры в класс flashLOG и после создания строк для имен файлов установить их в экземпляр flashLOG вместе с сеттерами.

,

@Парень.D Я улучшил ответ, @Juraj