C++ Polymorphism: from parent class to child
This question already has an answer here:
"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
Derived
typedef
's provided by Derived
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);
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.
下一篇: C ++多态性:从父类到子类