CodeFusionMobile
CodeFusionMobile

Reputation: 15130

Polymorphic recursive calls in C++?

I've just discovered some very odd behavior in my program. I have a tree where every Node is a subclass of Node. I recursively calculate a bounding box by traversing the tree until I reach the unit primitives (i.e. a Cube : Node) at the leaf nodes.

The recursive function getBoundingBox() is declared as virtual and correctly traverses the tree. Leaf nodes override the function and return a unit cube.

However, when I trace the program it appears that the override has no effect on the recursive function getBoundingBox(), even though it works just fine for another function like getName().

Example:

class Node;

typedef shared_ptr<Node> node_ptr;

class Node
{
protected:
  vector<node_ptr> mChildren;
public:
  virtual string getName() { return "Node";}
  virtual BoundingBox getBoundingBox()
  {
    //Merge Bounding Boxes of Children
    BoundingBox bb = BoundingBox();
    //For each child
    for(vector<node_ptr>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) {
      string name = (*it)->getName();//Correctly returns Node or Cube depending on type of (*it)
      bb = BoundingBox::Merge(bb, (*it)->getBoundingBox());//Always calls Node::getBoundingBox(); regardless of type
    }
    return bb;
  }
};

class Cube : public Node
{
public:
  virtual string getName() { return "Cube";}
  virtual BoundingBox getBoundingBox()
  {
    return BoundingBox::CreateUnitCube();
  }
};

Is there some sort of caveat about recursive polymorphism in c++ that I'm missing?

Upvotes: 1

Views: 859

Answers (2)

Walter
Walter

Reputation: 45474

I think your inheritance structure is muddled up. It makes more sense to have a base class Node which may be abstract

class BaseNode {
public:
  virtual BoundingBox getBoundingBox() const = 0;
};

and then define the different types of nodes

using node_ptr = std::shared_ptr<BaseNode>;
class Node : public BaseNode
{
  std::vector<node_ptr> mChildren;
public:
  BoundingBox getBoundingBox() const noexcept
  {
    BoundingBox bb;
    for(auto pc:mChildren)
      bb.merge(pc->getBoundingBox());
    return bb;
  }
};

class Cube : public BaseNode
{
public:
  BoundingBox getBoundingBox() const noexcept
  { return BoundingBox::CreateUnitCube(); }
};

Upvotes: 1

Avidan Borisov
Avidan Borisov

Reputation: 3325

Cube isn't a Node as you didn't use public inheritance.

I'm not sure how your actual code even compiles, but try to change it to:

class Cube : public Node

Upvotes: 0

Related Questions