11

In C++ we can convert child class pointer to parent, but is there any way to convert it back: from parent, which was obtained from child, give child class back?

I mean:

class Parent
{
    ...
};

class Child : public Parent
{
    ...
};

int main(int argc, char const *argv[])
{
    Child* child = new Child();
    Parent* parent = child;
    Child* old_child = parent; // how to do this??
    return 0;
}

Thank you for your answers.

user2160982
  • 189
  • 1
  • 2
  • 10

4 Answers4

18

"but is there any way to convert it back: from parent, which was obtained from child, give child class back?"

Yes, as mentioned in the other answers, there are two ways to do this.

Child * old_child = dynamic_cast<Child*>(parent);

The result of the dynamic_cast<> can be checked at runtime, thus you can determine if the parent object really represents a Child instance:

if(!old_child) {
     // parent is not a Child instance
}

Also note to get this working properly, the classes in question need to have a vtable, that RTTI can actually determine their relation. The simplest form to achieve this, is giving the Parent class a virtual destructor function

class Parent {
public:
    virtual ~Parent() {}
    // or
    // virtual ~Parent() = default;
    // as suggested for latest standards
};

NOTE:
If this should apply to a general design decision, I would strongly disregard it. Use pure virtual interfaces instead, that are guaranteed to be implemented, or not.


The second way of static_cast<> can be used in environments, where you well know that parent actually is a child. The simplest form of this is the CRTP, where Parent takes the inheriting class as a template parameter

template <class Derived>
class Parent {

     void someFunc() {
         static_cast<Derived*>(this)->doSomething();
     }
};

class Child : public Parent<Child> {
public:
    void doSomething();
};

The validity of an instatiation of Parent<> and static_cast<> will be checked at compile time.

NOTE:
Another advantage is that you can use an interface for derived that makes use of

  • static class members of Derived
  • typedef's provided by Derived
  • ... more class traits, that can be checked at compile time
Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • The result of the dynamic_cast can be ... iff the base class is a true polymorphic type, aka has at least one virtual function or base. Otherwise it degrades to static_cast (It will be strength-reduced to static_cast when provably correct in any case). – Deduplicator Jul 20 '14 at 14:14
  • @Deduplicator THX! Better now? – πάντα ῥεῖ Jul 20 '14 at 14:22
  • 1
    Yes, +1. BTW: Using `= default;` instead of `{}` for the dtor body might be slightly longer but does not prevent the class from being trivial, with all attendent benefits (though it needs a slightly more modern compiler). – Deduplicator Jul 20 '14 at 14:25
2

You need to cast the object back to child. This is done like this:

 Child * old_child = static_cast<Child*>(parent);

and

 Child * old_child = dynamic_cast<Child*>(parent);
riklund
  • 1,031
  • 2
  • 8
  • 16
2
int main() { 
   Parent parent;
   Child child;

   // upcast - implicit type cast allowed
   Parent *pParent = &child; 

   // downcast - explicit type case required 
   Child *pChild = (Child *) &parent;
}

You should use the dynamic_cast to do this safely:

Child *p = dynamic_cast<Child *>(pParent)

EDIT

With dynamic_cast returns a null pointer if the type is not apart of the base class, also casting to a reference throws a bad_cast exception. dynamic_cast is particularly useful if you do not know what the object type will be.

On the other hand static_cast:

Child *p = static_cast<Child *>(pParent)

This assumes that you want to reverse an explicit conversion and perform no runtime checks. This allows for flexibility but must be used with caution.

The regular downcast shown above:

Child *pChild = (Child *) &parent;

Is a C-style down cast (like a static_cast), which may also cast to a private base class (not sure about, multiple inheritance), while static_cast would cause a compile-time error. Things like numeric conversions is a good example to use this on.

David Pullar
  • 706
  • 6
  • 18
0

Above answers are good, conceptually you can think like this,

Your Car object which is derived from Vehicle class. You can refer Car as Vehicle, and can convert to Car as it originally belonged to Car. But it will be a problem if your Vehicle object actually representing Bike and trying to convert to Car. Thats why you need safe casting.

class Vehicle
{
    ...
};

class Car : public Vehicle
{
     ...
};

class Bike : public Vehicle
{
     ...
};


int main(int argc, char const *argv[])
{
     Vehicle* vehicle = new Car();
     Car* old_car = dynamic_cast<Car *>(vehicle); 
     if(old_car) {
         // OK Vehicle is Car, use it
     }

     vehicle = new Bike();
     old_car = dynamic_cast<Car *>(vehicle); 
     if(old_car) {
         // No Vehicle isn't Car, this code won't execute
     }

     return 0;
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Haja Maideen
  • 450
  • 2
  • 4