c++ - 如何选择一个类来动态实例化?

标签 c++ oop design-patterns embedded c++20

我正在解决一个问题,我们有一个接口(interface)类,其中包含实现接口(interface)功能的各种子类。不同的硬件配置将根据配置文件(使用 constexpr 用 C++ 编写)使用最适合它们的子类。

最初,我们的目的是为每个硬件配置使用的类构造函数使用函数指针,直到发现 C++ 中禁止使用指向构造函数的函数指针。我们正在探索这条道路,因为我们想避免全局定义的类。也考虑过使用工厂来允许函数指针,但考虑到我们正在运行的内存受限环境(以及工厂方法动态分配内存的要求),我认为它并不理想。

我们还避免使用宏来选择实现,因为我们不想每次在使用接口(interface)的每个地方创建接口(interface)的新实现时都添加条件编译分支。

例如一些效果:

#if defined(FOO)
    Foo object;
#elif defined(BAR)
    Bar object;
#elif defined(BAZ)
    Baz object;
#endif

此外,我们将有一个场景,其中将实例化可变数量的接口(interface)实例。实例的数量将在编译时根据硬件配置得知,并且应该始终相对较小(< 20)。不幸的是,这排除了(据我所知)宏或 using 声明的使用。

我可能会忽略哪些技术,这些技术可以让我根据要部署到的硬件配置,在配置文件中选择编译时要使用的接口(interface)实现?或者,如果根据我概述的要求这是不可能的,那么我应该考虑什么更好的策略来解决我的问题?

最佳答案

根据我的理解,您可能可以得到 CRTP pattern用于您的界面和子类。在 std::variant 的帮助下,您将能够为您在编译时设置的每个配置拥有一组所需的(变体)实例。假设std::variant结构不会破坏您的硬件 ROM 要求,因为 sizeof(<variant_type)将是最大值 sizeof子类。

See a live demo godbolt.org

#include <iostream>
#include <variant>
#include <array>

// Base interface class
template <typename Derived>
class Base {
public:
    void doSomething() {
        static_cast<Derived*>(this)->doSomethingImpl();
    }

private:
    constexpr Base() = default;
    friend Derived;
};

// Child class implementations
class Foo : public Base<Foo> {
public:
    constexpr Foo() = default;
    void doSomethingImpl() {
        std::cout << "Foo implementation\n";
    }
};

class Bar : public Base<Bar> {
   // ....
};

class Baz : public Base<Baz> {
   // ....
};

// Change this value to configure the hardware
constexpr short hardwareConfig = 4;  

// Implementation selection based on the configuration
template <short Config>
struct InterfaceChooser;

template <>
struct InterfaceChooser<1> {
    using Implementation = std::variant<Foo, Bar>;
};

template <>
struct InterfaceChooser<2> {
    using Implementation = std::variant<Bar, Baz>;
};

template <>
struct InterfaceChooser<3> {
    using Implementation = std::variant<Foo, Baz>;
};

template <>
struct InterfaceChooser<4> {
    using Implementation = std::variant<Foo, Bar, Baz>;
};

int main() 
{
    // Instantiate the interface using the chosen implementation based on the configuration
    using Implementation = InterfaceChooser<hardwareConfig>::Implementation;
    std::array<Implementation, std::variant_size_v<Implementation>> arrayOfObjects{
        Foo{}, Bar{}, Baz{}
    };

    // Call doSomething() for each object in arrayOfObjects
    for (auto& obj : arrayOfObjects) {
        std::visit([](auto& object) { object.doSomething(); }, obj);
    }
}

更改 hardwareConfig对于不同的配置,并可能在另一个类模板中实现变体数组,以便可以自定义子成员函数调用。

关于c++ - 如何选择一个类来动态实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76610616/

相关文章:

c++ - map 插入失败 : can not overwrite first element?

Python面向对象编程: Composition

PHP:链接方法调用

c++ - 6 色图顶点着色算法

c++ - 如何在sql表中查找str

c++ - 为什么 bool 类型的二维数组不保存 0 和 1?

c++ - 类的奇怪问题

design-patterns - 工厂方法设计模式

c# - 长继承层次

java - 一种将可变数据结构声明为输出并实际返回不可变数据结构的方法