C ++多态性:从父类到子类
这个问题在这里已经有了答案:
“但是有什么办法可以将它转回来:从父母那里得到的,是从孩子那里得到的,给孩子上课呢?”
是的,正如其他答案中提到的那样,有两种方法可以做到这一点。
Child * old_child = dynamic_cast<Child*>(parent);
dynamic_cast<>
的结果可以在运行时检查,因此您可以确定parent
对象是否确实代表一个Child
实例:
if(!old_child) {
// parent is not a Child instance
}
还要注意为了使这个工作正常进行,所讨论的类需要有一个vtable,RTTI实际上可以确定它们的关系。 实现这一点的最简单形式是给Parent
类一个虚拟析构函数
class Parent {
public:
virtual ~Parent() {}
// or
// virtual ~Parent() = default;
// as suggested for latest standards
};
注意:
如果这应该适用于一般设计决定,我会强烈地忽视它。 改为使用纯虚拟接口 ,保证实施或不实施。
static_cast<>
的第二种方式可以用在你很清楚parent
实际是孩子的环境中。 最简单的形式就是CRTP , Parent
将继承类作为模板参数
template <class Derived>
class Parent {
void someFunc() {
static_cast<Derived*>(this)->doSomething();
}
};
class Child : public Parent<Child> {
public:
void doSomething();
};
Parent<>
和static_cast<>
的安装的有效性将在编译时检查。
注意:
另一个优点是你可以使用一个接口来派生使用
Derived
静态类成员 Derived
提供的typedef
你需要把对象转回给孩子。 这是这样做的:
Child * old_child = static_cast<Child*>(parent);
和
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;
}
您应该使用dynamic_cast
来安全地执行此操作:
Child *p = dynamic_cast<Child *>(pParent)
编辑
如果类型不是基类的一部分,则dynamic_cast
将返回一个空指针,并且转换为引用也会抛出bad_cast
异常。 如果您不知道对象类型是什么, dynamic_cast
特别有用。
另一方面static_cast
:
Child *p = static_cast<Child *>(pParent)
这假定您想要反转显式转换并且不执行运行时检查。 这允许灵活性,但必须谨慎使用。
上面显示的常规沮丧:
Child *pChild = (Child *) &parent;
是一种C风格的向下转换(如static_cast
),它也可以转换为私有的基类(不确定,多重继承),而static_cast
会导致编译时错误。 诸如数值转换之类的东西就是一个很好的例子。
上一篇: C++ Polymorphism: from parent class to child
下一篇: style cast" in g++