Question

I've been reading tutorials on dynamic_cast for a program I'm working on, and I'm not quite grasping how to utilize it.

I have multiple methods which will pass in parameters that are superclass pointers, and from there, differentiate between which is which to figure out what operations to make.

For example, the superclass might be Value, and the subclass is RationalNumber.

My plan was to set an int value ID for RationalNumber to be, I don't know, 1, and then when I use dynamic_cast, it will determine that the Value* object is actually a RationalNumber, and the operation will be performed.

How am I able to implement this?

Was it helpful?

Solution

Typical example:

class Value
{
 public:
   virtual ~Value();
};

class RationalNumber : public Value
{
  ... 
}


Value *v = new RationalNumber(...)


... 
RationalNumber* test = dynamic_cast<RationalNumber*>(v);

if (v)
   cout << "v is a rational number" << endl;
else
   cout << "v is a not rational number" << endl;

Note however that this is NOT a good solution in nearly all cases where you have inheritance. I'm writing a compiler, and it's the first time I've ever used dynamic_cast - mostly because there are some fairly generic functions that deal with (for example) ExprAST class pointers, and to add ALL of the variants of functions that all the derived classes (31 classes at present count) of has into the ExprAST would be rather unpractical. (And of course, having a call that does expr->isVariableExprAST() is not that much better than VariableExprAST* var = dynamic_cast<VariableExprAST*>(expr); if (var) ... - it's the same amount of code, more or less).

But in most cases, NOT knowing what type you deal with is a much better solution.

A more suitable solution is to use a virtual function that is common for all classes, e.g:

class Value
{
 public:
   virtual ~Value();
   virtual void SomeMethod() = 0;
};

class RationalNumber : public Value
{
  ... 
  virtual void SomeMethod() { ... }
}

class IrrationalNumber : public Value
{
  ... 
  virtual void SomeMethod() { ... }
}


Value *v = ... 

v->SomeMethod();

In this case, you will not need to do ANY checks - you just need to implement the method SomeMethod for all subtypes.

OTHER TIPS

The dynamic_cast operator determines the type of an object during runtime, according to the value of the object's V-Table pointer (an implicit member field that is added to the class of the object when you have one or more virtual functions in that class).

There is nothing to implement here, and you can simply call it. For example:

bool isRationalNumber(Value* object)
{
    RationalNumber* number = dynamic_cast<RationalNumber*>(object);
    if (number == NULL)
        return false;
    return true;
}

Please note that you cannot use it on a class which does not declare at least one virtual function, as such class does not have a V-Table.

In addition, on some compilers you need to enable RTTI in the project settings.

And finally - a small suggestion (more of a personal opinion, so you may choose to ignore it):

Dynamic cast is pretty much in contrast with the concept of Polymorphism, in which you generalize objects with common attributes under a single base-class, and then refer to them using that generic base-class. With dynamic cast, you are essentially doing the opposite, as you are checking the specific type of the object before deciding what action to take.

So the suggestion is, try to avoid using it whenever possible.

If you see you have no alternatives, then check your design.

The standard way is to dynamic_cast the object to the derived class and then test if the result is null or not. For example (using your terminology):

void method(SuperClass* object) {

  SubClass* subclass = dynamic_cast<SubClass*>(object);

  if (subclass) {
    // the object is a 'SubClass'
    // do stuff...
  }

}

If you have several subclasses, you'll have to check them separately. E.g.:

void method(SuperClass* object) {

  SubClass_1* subclass_1 = dynamic_cast<SubClass_1*>(object);
  if (subclass_1) {
    // the object is a 'SubClass_1'
    // do stuff...
    return;
  }

  SubClass_2* subclass_2 = dynamic_cast<SubClass_2*>(object);
  if (subclass_2) {
    // the object is a 'SubClass_2'
    // do stuff...
    return;
  }


}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top