C++ Polymorphism: from parent class to child [duplicate]

丶灬走出姿态 提交于 2021-02-06 20:01:42

问题


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.


回答1:


"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



回答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);



回答3:


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.




回答4:


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;
}


来源:https://stackoverflow.com/questions/24851067/c-polymorphism-from-parent-class-to-child

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!