1

I am using C++ virtual functions. I have a base class treeNode and two derived classed splitNode and leafNode. some pointers in the splitNodes point to other nodes which may be either splitNode or leafNode. At runtime, how can I check whether the pointer points to a leaf or split node, whithout changing the structure of the nodes (i.e., I don't want to add any new function to them).

Regards

remo
  • 880
  • 2
  • 14
  • 32
  • Heard of `dynamic_cast` or `typeid`? – Nawaz Sep 30 '13 at 14:25
  • `dynamic_cast` works, but is very expensive at runtime. – edtheprogrammerguy Sep 30 '13 at 14:26
  • No, I don't want to cast it. I want its type at runtime. I am searching about typeid... – remo Sep 30 '13 at 14:27
  • The pointer can point to a split or leaf node. I only want to check what is the real type of the object the pointer points to? – remo Sep 30 '13 at 14:29
  • 2
    But why do you need to do that? With a different design you probably don't need to know. – Georg Fritzsche Sep 30 '13 at 14:30
  • 1
    In a kd-tree, I want to disable a node. As all of my data are saved within leaf nodes, I can set such a ''disabled'' flag in such nodes. During the search in a split node, I want to check if a node is a leaf really, so I can check the flag, or else if the node is a split one, I must continue the search down to the tree – remo Sep 30 '13 at 14:35
  • @RezaMortazavi `virtual bool isLeaf() const`. That's one way to do it better than with a cast/RTTI. – Angew is no longer proud of SO Sep 30 '13 at 14:43
  • 3
    Then you can have `virtual splitNode::disable()` that calls `disable()` on its children, and a `virtual leafNode::disable()` that sets the flag. No check needed. – Dima Sep 30 '13 at 14:43

5 Answers5

3

It isn't clear why you would want to do this, but you can use dynamic_cast:

treeNode* theNode = ....;
splitNode sNode* = dynamic_cast<splitNode*>(theNode);
bool isSplitNode = sNode != nullptr;

or just

bool isSplitNode = dynamic_cast<splitNode*>(theNode);

You shouldn't have to do this if you are using polymorphism correctly.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
2

Implement a virtual GetType method in your base class and override it in subclasses. This is the most efficient way.

Remember Open closed principle. You should take advantage of polymorphism.

Ogre Psalm33
  • 21,366
  • 16
  • 74
  • 92
mehmet mecek
  • 2,615
  • 2
  • 21
  • 25
1

You can do this by using dynamic_cast, or the typeid operator. However, generally this is a very bad idea. If your virtual function needs to know the exact type of the object, then something is wrong with your design.

If you have this situation:

class treeNode
{
  virtual int foo()
  {
    // do some default thing, maybe nothing
  }
};

class splitNode : public treeNode
{
  virtual int foo()
  {
    // do whatever splitNode wants to do
  }
};

class leafNode : public treeNode
{
  virtual int foo()
  {
    // do whatever leafNode wants to do
  }
};

and you have a pointer treeNode *p; that points to either a splitNode or a leafNode object, and you call p->foo(), then the appropriate version of foo() will be called. That is the whole point of virtual functions.

Also, see this question.

Community
  • 1
  • 1
Dima
  • 38,860
  • 14
  • 75
  • 115
0

Have an enum member for what type it is, or a virtual function that returns the number of child nodes. Personally I would just have one node class with an enum (or null child pointers for leafs) for this kind of thing.

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
0

You can get the underlying type of a pointer to a runtime-polymorphic object using the typeid operator. Here's an example that fits your described design:

struct treeNode
{
};

struct splitNode : treeNode
{
    treeNode* left;
    treeNode* right;
};

struct leafNode : treeNode
{
    bool disabled;
};

void traverse(splitNode* node);
void traverse(leafNode* node);

void traverse(treeNode* node)
{
    if(typeid(*node) == typeid(leafNode))
    {
        return traverse(static_cast<leafNode*>(node));
    }
    return traverse(static_cast<splitNode*>(node));
}

Note that dynamic_cast does pretty much the same thing.

The performance of typeid can be poor compared to storing some form of type-id in the base class and using static_cast. Despite that caveat, it's extremely useful for code which isn't performance critical (e.g. most code).

willj
  • 2,991
  • 12
  • 24