0

I have been developing software driver for the SPI I/O expander in the C++ programming language. I have decided to model the registers in the I/O expander in this manner

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;

};

It would be convenient for me to have all the registers in the I/O expander in an array. The problem is that I am not able to define the array in such manner to avoid the dynamic allocation of memory. The array definition

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

does not work because the Register is abstract class so the only one possibility is to define the array in this manner

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

but it means that I need to create instances of the individual registers via new operator which is prohibited on my platform. Is there any posibility how to achieve a state where all the registers can be in one array and the instances are statically allocated? Thanks in advance for an advice.

8
  • 2
    Dynamic polymorphism does not require dynamic memory allocation. You can have an object TypedRegister<int, 0> obj; pointed to by Register* ptr = &obj;, and then call virtual functions on ptr. In your case, you can use register_map[0] = &obj;. Commented Dec 2, 2020 at 16:39
  • All array elements must be of the same type. That Register is abstract is irrelevant - if it weren't you would have "slicing". Commented Dec 2, 2020 at 16:40
  • @DanielLangr true but how to put them in the same array? Commented Dec 2, 2020 at 16:40
  • 1
    @largest_prime_is_463035818 I am not sure whether it is what OP wants (if they know what they want :). I will wait a bit for a response. Moreover, this may have been asked before, will check for duplicates. Commented Dec 2, 2020 at 16:42
  • 1
    On a side note, you probably don't need to duplicate the template parameter address in a member variable. Commented Dec 2, 2020 at 16:46

2 Answers 2

2

Dynamic polymorphism is not related to dynamic memory allocations. You can have a statically allocated object of some derived class and assign its address to a pointer-to-base. In your case, it might look as follows:

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);
Sign up to request clarification or add additional context in comments.

Comments

2

Polymorphic method dispatch only works when a virtual method is called via a pointer/reference to an object. You don't need new to create a pointer to an object. However, since you don't have new available, your only option in this case (assuming your I/O registers use different template parameter values) is to first declare the objects individually and then you can store pointers to each object in your array, eg:

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;
...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.