【问题标题】:How to create array of templated objects without dynamic allocation如何在没有动态分配的情况下创建模板对象数组
【发布时间】:2021-03-14 15:49:14
【问题描述】:

我一直在用 C++ 编程语言为 SPI I/O 扩展器开发软件驱动程序。我决定以这种方式对 I/O 扩展器中的寄存器进行建模

class Register
{
  public:

    virtual bool read(void) = 0;
    virtual bool write(uint8_t data) = 0;
    virtual uint8_t getData(void) = 0;
    virtual uint8_t getAddress(void) = 0;

};

template <class T, uint8_t address>
class TypedRegister : public Register
{
  public:

    TypedRegister::TypedRegister() : reg_address(address){}
    bool read(void);
    bool write(uint8_t data);
    uint8_t getData(void);
    uint8_t getAddress(void);
    
  private:

    const uint8_t reg_address;
    T data;

};

将 I/O 扩展器中的所有寄存器放在一个数组中会很方便。问题是我无法以这种方式定义数组以避免内存的动态分配。数组定义

static constexpr uint8_t no_regs_in_expander = 18;
Register register_map[no_regs_in_expander];

不起作用,因为Register 是抽象类,所以唯一的一种可能性是以这种方式定义数组

static constexpr uint8_t no_regs_in_expander = 18;
Register* register_map[no_regs_in_expander];

但这意味着我需要通过new 运算符创建各个寄存器的实例,这在我的平台上是被禁止的。是否有任何可能性如何实现所有寄存器都可以在一个数组中并且实例是静态分配的状态?提前感谢您的建议。

【问题讨论】:

  • 动态多态性不需要动态内存分配。你可以让Register* ptr = &amp;obj;指向一个对象TypedRegister&lt;int, 0&gt; obj;,然后在ptr上调用虚函数。在您的情况下,您可以使用register_map[0] = &amp;obj;
  • 所有数组元素必须是同一类型。 Register 是抽象的无关紧要 - 如果不是,您将有“切片”。
  • @DanielLangr true 但如何将它们放在同一个数组中?
  • @largest_prime_is_463035818 我不确定这是否是 OP 想要的(如果他们知道自己想要什么 :)。我会稍等一下回复。此外,这可能以前被问过,将检查重复项。
  • 附带说明,您可能不需要在成员变量中复制模板参数address

标签: c++ arrays templates inheritance embedded


【解决方案1】:

动态多态性与动态内存分配无关。您可以拥有某个派生类的静态分配对象,并将其地址分配给指向基址的指针。在您的情况下,它可能如下所示:

Register* register_map[2];

TypedRegister<int, 0> obj1;
TypedRegister<long, 1> obj2;

register_map[0] = &obj1;
register_map[1] = &obj2;

for (ptr : register_map)
  ptr->write(0);

【讨论】:

    【解决方案2】:

    多态方法分派仅在通过对象的指针/引用调用虚拟方法时才有效。您不需要new 来创建指向对象的指针。但是,由于您没有可用的new,因此在这种情况下(假设您的 I/O 寄存器使用不同的模板参数值)您唯一的选择是首先单独声明对象,然后您可以将指向每个对象的指针存储在您的数组,例如:

    TypedRegister<...> reg1;
    TypedRegister<...> reg2;
    TypedRegister<...> reg3;
    ...
    
    static constexpr uint8_t no_regs_in_expander = 18;
    Register* register_map[no_regs_in_expander];
    register_map[0] = &reg1;
    register_map[1] = &reg2;
    register_map[2] = &reg3;
    ...
    

    【讨论】:

      猜你喜欢
      • 2016-04-06
      • 1970-01-01
      • 1970-01-01
      • 2014-10-02
      • 2018-12-11
      • 2012-05-14
      • 2016-11-03
      • 2016-07-03
      • 2011-07-09
      相关资源
      最近更新 更多