(c ++) Импорт .hpp, только зная его имя по строке - PullRequest
0 голосов
/ 08 апреля 2020

получил вопрос (извините, мой engli sh может быть случайным)

Мне нужно импортировать функцию «decoding ()», известную в файле sensorName.hpp, но так как список датчиков может изменить время, я должен сохранить их имя в векторе (идентификатор датчика 1, имя1, идентификатор датчика 2, имя2 и т. д. c). Я знаю, что мне нужно вызвать nameX :: decoding () в nameX.hpp, (nameX означает датчик X), но я знаю только nameX по строке, и я полагаю, что не могу просто объединить его со строкой ".hpp" и надеюсь, что это сработает.

Вот мой код:

    void decoding(string data, std::vector<string> ids)
    {
      //reading data to determine the sensor
      string id = data[0] + data[1]
      int len = (ids.size())/2
      for (size_t i = 0; i < len; i++) {
        if (ids[i] == id) {
          //
          string name = ids[i+1]
          UNKNOWNNAME::decoding(data)
        }
        if (i == len && ids[i] != id) {
          //error to add
          std::cout<<"error: unknown sensor";
        }
      }

    }

Спасибо за вашу помощь, я довольно новичок в c ++ и могу предоставить более четкие объяснения, если это необходимо .

Тимтаниум

1 Ответ

0 голосов
/ 08 апреля 2020

Я думаю, что вы можете путать, выбирая функцию из динамического файла c и выбирая функцию из динамического c типа (что более распространено!) .

В объектно-ориентированном программировании одной из самых основных идей c является полиморфизм - возможность использовать несколько типов одинаково, даже если они будет действовать по-другому; Например, вы хотите, чтобы все типы датчиков имели функцию decode (decoding - ненадлежащее имя), которая будет действовать по-разному для каждого типа датчика, но иметь одинаковую подпись . Вы просто хотите иметь возможность вызывать функцию decode, и будет вызвана правильная реализация.

Для этого нам нужно создать один интерфейс (который в C ++ является общим базовым классом), который будет содержать функцию decode, которую должен реализовать каждый класс, который наследует от него. Это выглядит так:

#include <string>
#include <vector>
#include <memory>

class ISensor
{
public:
    virtual void decode(const std::string& data) = 0;

    virtual std::string get_name() const = 0;
    virtual uint64_t get_id() const = 0;

    virtual ~ISensor() = default;
};

class BaseSensor : public ISensor
{
public:
    virtual void decode(const std::string& data) = 0;

    std::string get_name() const override { return name; }

    uint64_t get_id() const override { return id; }

protected:

    BaseSensor(const std::string& name_, uint64_t id_) :
        name(name_),
        id(id_)
        {
        }

    std::string name;
    uint64_t id;
};

class SensorA final : public BaseSensor
{
public:
    SensorA(uint64_t id_) :
        BaseSensor("SensorA", id_)
    {
    }

    void decode(const std::string& data) final
    {
        // do something
    }
};

class SensorB final : public BaseSensor
{
public:
    SensorB(uint64_t id_) :
        BaseSensor("SensorB", id_)
    {
    }

    ~SensorB() = default;

    void decode(const std::string& data) final
    {
        // do something different
    }
};

Это частичное объяснение, поскольку это очень сложная идея в программировании, но, вероятно, это направление, которому вы должны следовать.

Использование как следует:

int main()
{
    std::string data ="some data";

    std::vector<std::unique_ptr<ISensor>> vec;
    vec.push_back(std::unique_ptr<ISensor>(new SensorA(0)));
    vec.push_back(std::unique_ptr<ISensor>(new SensorB(1)));

    for (const auto& sensor: vec)
    {
        sensor->decode(data);
    }
}

Замечание - лично я не смешиваю интерфейсы и базовые классы. Интерфейс чисто виртуальный, а базовый класс построен так, что общий код (такой как get_id или get_name) будет реализован только один раз, а все остальные вещи могут быть реализованы в производных классах. Обратите внимание, что в моем примере я использую указатели только на интерфейс, а не на базовый класс.

Когда вы вызываете sensor->decode(data), он выберет во время выполнения правильную реализацию этой функции, в соответствии с к типу времени выполнения этого объекта (этот механизм называется dynamici c -dispatch ). Единственное, что вам нужно сделать, это внедрить decode в каждый тип датчика, и все хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...