Я думаю, что вы можете путать, выбирая функцию из динамического файла 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
в каждый тип датчика, и все хорошо.