C++ Polymorphism: from parent class to child
在C++中,我们可以将子类指针转换为父级,但是有没有方法可以将它转换回:从父级中得到的父级,给子类返回?
我的意思是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } |
谢谢你的回答。
"but is there any way to convert it back: from parent, which was obtained from child, give child class back?"
是的,正如其他答案中提到的,有两种方法可以做到这一点。
1 | Child * old_child = dynamic_cast<Child*>(parent); |
可以在运行时检查
1 2 3 | if(!old_child) { // parent is not a Child instance } |
还要注意,为了使这个工作正常,所讨论的类需要有一个vtable,rtti实际上可以确定它们的关系。实现这一点的最简单形式是给
1 2 3 4 5 6 7 | class Parent { public: virtual ~Parent() {} // or // virtual ~Parent() = default; // as suggested for latest standards }; |
注:如果这适用于一般的设计决策,我会坚决无视它。使用纯虚拟接口来代替,不管是否保证要实现。
第二种方法
1 2 3 4 5 6 7 8 9 10 11 12 | template <class Derived> class Parent { void someFunc() { static_cast<Derived*>(this)->doSomething(); } }; class Child : public Parent<Child> { public: void doSomething(); }; |
将在编译时检查
注:另一个优点是,可以使用派生接口
Derived 的静态类成员- 由
Derived 提供的typedef 。 - …更多的类特性,可以在编译时检查
1 2 3 4 5 6 7 8 9 10 | int main() { Parent parent; Child child; // upcast - implicit type cast allowed Parent *pParent = &child; // downcast - explicit type case required Child *pChild = (Child *) &parent; } |
您应该使用
1 | Child *p = dynamic_cast<Child *>(pParent) |
编辑
如果类型不是基类的一部分,WITH
另一方面,
1 | Child *p = static_cast<Child *>(pParent) |
这假定您要反转显式转换,并且不执行运行时检查。这允许灵活性,但必须谨慎使用。
上面所示的常规向下投射:
1 | Child *pChild = (Child *) &parent; |
是C样式的向下强制转换(如
您需要将对象强制转换回child。这样做:
1 | Child * old_child = static_cast<Child*>(parent); |
和
1 | Child * old_child = dynamic_cast<Child*>(parent); |
上面的答案很好,从概念上来说你可以这样想,
您的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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; } |