Search code examples
c++inheritanceobject-slicing

Array of Pointers to Different Derived Classes


I'm working on the core for a family of microprocessor units based off of the ATMEGA328P. I have a base class and two derived classes that I need to store mixed together in an array. I have the following:

// base class
class Channel {
   virtual String ReturnValuesAsString();
   virtual void ResetValues();
   ...
}

// derived class
class DigitalChannel : Channel {
   String ReturnValuesAsString() override;
   void ResetValues() override;
}

// derived class
class AnalogChannel : Channel {
   String ReturnValuesAsString() override;
   void ResetValues() override;
}

On my other object, I have the following:

class Input {
   Channel *Channels; //array of channels

   Input(int totalPossibleChannels, Channel *channels[]) {

      this->Channels = new Channel[totalPossibleChannels];

      // pseudocoded for loop using 'chanIndex' iterator to keep it short on this post
      for channel in channels {
         this->Channels[chanIndex] = *channels[chanIndex];
      }
   }
}

I initialize the input as follows:

DigitalChannel digitalChannel00 = DigitalChannel();
DigitalChannel digitalChannel01 = DigitalChannel();

Channel *digitalInputChannelsInput0[] = { &digitalChannel00, &digitalChannel01 };

Input input0 = Input(2, digitalInputChannelsInput0);

My problem is when I reference any of the channels similar to the following:

input0.Channels[0].ReturnValuesAsString();

I get the base class implementation of that method rather than the derived implementation. I've read a bit about this and it appears that this is caused by object slicing distilling them down to the base class. Is there another way that I can handle this? I don't have access to smart pointers or vectors on this platform (arduino is a limited port of c++). Thanks in advance! I'm open to any suggestions as well.

Update: Marking this as solved, but I wanted to add some more context to help others later

Here is the new structure:

class Input {
   Channel **Channels; //array of channel pointers

   Input(int totalPossibleChannels, Channel *channels[]) {

      this->Channels = new Channel *[totalPossibleChannels];

      // pseudocoded for loop using 'chanIndex' iterator to keep it short on this post
      for channel in channels {
         this->Channels[chanIndex] = channels[chanIndex];
      }
   }
}

I initialize the input as follows:

DigitalChannel digitalChannel00 = DigitalChannel();
DigitalChannel digitalChannel01 = DigitalChannel();

Channel *digitalInputChannelsInput0[] = { &digitalChannel00, &digitalChannel01 };

Input input0 = Input(2, digitalInputChannelsInput0);

Solution

  • you are maintaining an array of channel obejcts.
    For virtual function to work you need to maintain either pointer of base class type or a reference.

    Channel *Channels;
    

    creates an array of Channel obejcts. You need to create an array of pointer/reference to channel object i.e.

    Channel **Channels;
    

    Change the program accordingly to use pointer instead of object of channel type.