Calling overridden virtual methods from constructor

I'm new to C++ , although have programmed Arduinos using C before and have been programming Windows apps for 30 odd years. So I understand concepts like virtual methods and overridng them but I'm struggling to get an overridden virtual method in a derived class called by the constructor.
Here's the code

class VelbusNode
{
public:
  VelbusNode();
  virtual void init();
protected: // some data members
  byte nodeType = 0x05; // use this value unless changed
  byte mapVersion;
};

class VelbusNode_VMBGPO: public VelbusNode
{
  public:
  VelbusNode_VMBGPO();  
    virtual void init() override;
};

The implementation of the base class looks like this

VelbusNode::VelbusNode()
{ 
  init();
}

void VelbusNode::init()
{
  mapVersion = 1;
}

and the derived class like this

VelbusNode_VMBGPO::VelbusNode_VMBGPO()
:  VelbusNode::VelbusNode()
{}
void VelbusNode_VMBGPO::init() 
{  
  VelbusNode::init(); // call the base class version first
  nodeType = 0x21;   // now override the values
}

and finally the code is used like this

  VelbusNode_VMBGPO* node;
  node = new VelbusNode_VMBGPO();

When I inspect the value assigned the node->nodeType it is the value set in the initial declaration i.e. 0x05. mapVersion is 1 as expected because the base init code has been called.

Given that the declaration and call to the constructor is for the derived class (VelbusNode_VMBGPO) I'd be expecting to see the base constructor call the overridden init function. But it appears to only call its own function, which makes the concept of polymorphism a bit broken.

What do I need to change so that the constructor for the instance of the derived class calls the correct code ?

you would get better and faster answers if you would provide a full working example.

You could call the init in the constructor of the derived class.

class VelbusNode {
  public:
    VelbusNode();
    virtual void init();

    byte getNodeType() {
       return nodeType; 
    }
  protected: // some data members
    byte nodeType = 0x05; // use this value unless changed
    byte mapVersion;
};

class VelbusNode_VMBGPO: public VelbusNode {
  public:
    VelbusNode_VMBGPO();
    virtual void init() override;
};

VelbusNode::VelbusNode() {
  init();
}

void VelbusNode::init() {
  mapVersion = 1;
}

VelbusNode_VMBGPO::VelbusNode_VMBGPO()
  :  VelbusNode::VelbusNode()
{init();}  // !

void VelbusNode_VMBGPO::init() {
  VelbusNode::init(); // call the base class version first
  nodeType = 0x21;   // now override the values
}

void setup() {
  Serial.begin(115200);
  VelbusNode_VMBGPO* node;
  node = new VelbusNode_VMBGPO();
  Serial.println(node->getNodeType(), HEX); 
}

void loop() {
  // put your main code here, to run repeatedly:

}

but there are for sure better answers out there.

Thanks for the reply. I've just stumbled upon this but it seems to be counter intuitive.
I think it is because from what I've read C++ constructors are not virtual so they do not act in a polymorphic way, unlike normal functions. Which is not how my experience outside of C++ works.

So, a bit of a learning curve and trying not to trip myself up by assuming similar paradigms as other languages.

That's a known problem with C++ constructors. Many classes have a begin() method that does the intended initialization after and outside the constructor.

Thanks for the tip.
As a Delphi/Pascal and C# developer it is a different paradigm for me, but figuring out that programming "mental" model is about 50% of the task.
I'll look at using that rather than relying on the constructor to call it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.