Reputation: 15130
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
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
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