C++ 从父代到子代的转换类型是什么?

C++ 从父代到子代的转换类型是什么?,c++,casting,parent-child,dynamic-cast,reinterpret-cast,C++,Casting,Parent Child,Dynamic Cast,Reinterpret Cast,这个问题是关于应该使用哪个来进行转换。我知道C风格的cast可以实现这一点 对于以下类结构: class Foo {}; class Bar : public Foo {}; 说我被给予:Foo*ptr我想将其强制转换为条*我应该使用哪种类型的强制转换?似乎我必须按原样使用dynamic\u cast: 用于转换多态类型 我想避免dynamic\u cast,因为它是一个运行时强制转换。您是正确的,dynamic\u cast通常最适合这种情况。但是,如果您知道指针实际上指向派生类的对象,则

这个问题是关于应该使用哪个来进行转换。我知道C风格的cast可以实现这一点

对于以下
结构:

class Foo {};

class Bar : public Foo {};
说我被给予:
Foo*ptr我想将其强制转换为
条*
我应该使用哪种类型的强制转换?似乎我必须按原样使用
dynamic\u cast

用于转换多态类型


我想避免
dynamic\u cast
,因为它是一个运行时强制转换。

您是正确的,
dynamic\u cast
通常最适合这种情况。但是,如果您知道指针实际上指向派生类的对象,则可以使用
static\u cast
进行转换。如果你错了,指针不是派生类,你会得到未定义的行为。

static\u cast
只要你确定你正在转换的对象确实是你期望的类型,它就可以正常工作。根据您给出的示例,看起来您是肯定的。

为了清楚起见:

我想避免动态强制转换,因为它是运行时强制转换

嗯,您有一个运行时类型(给定基类的静态类型引用,您通常无法知道对象的动态类型),因此运行时强制转换是唯一完全安全的选项

如果您认为您的对象实际上是一个
,但您弄错了,
动态强制转换
将为您提供一个
空PTR
,或者
动态强制转换
将引发异常。无论哪种方式,您都有机会在运行时处理运行时错误。正如M.M所指出的,只有当基类具有或继承了至少一个虚拟方法时,这才可用

现在,如果您碰巧可以静态地确定对象的动态类型确实是
Bar
,您可以使用
static\u cast
。然而,如果您弄错了,那么您就有未定义的行为,并且没有机会检测或处理错误

例如

struct Foo{virtual~Foo(){};
结构栏:公共Foo{};
//安全,可返回空PTR
Bar*safe_ptr_cast(Foo*f){返回动态_cast(f);}
//安全,可以扔,但你可以抓住它
Bar&safe_ref_cast(Foo&f){返回动态_cast(f);}
//不安全-如果你错了,你只是破坏了一切
Bar*unsafe_ptr_cast(Foo*f){返回静态_cast(f);}

顺便说一句,如果您的运行时强制转换问题是性能问题,那么冒着UB的风险以便在您有代码要分析之前节省名义时间就是过早优化的定义。

@MarkRansom:typeid检查不会遍历类层次结构。缺少的
是公开的还是有意的?如果它的目的是改变事情。@无用:值得检查Izhaki-s的答案。dynamic_cast不仅检查目标类,而且所有类也从中派生。我认为大多数时候,当人们写动态类型ID检查时会更好。有时,typeid检查是不够的。这是一个无效的基准(正如在注释中指出的那样),一个3年前的编译器在我没有代码的类之间实现了动态强制转换(据我所知,这些类可能使用虚拟继承)。我不认为这个答案证明了什么,除了分析很难。非常肯定。你无法从
Bar
中获得有效的
Foo*
,因此没有办法将
动态转换为
Foo*
。我确实知道
ptr
是-a
Bar*
。因此,我假设您正在引用列表中的第二种转换类型:@JonathanMee是的,这就是我要说的-尽管我认为基类没有必要是非虚拟的。@JonathanMee您知道cppreference.com是一个wiki吗?无法保证添加该主题的人知道他们在谈论什么。唯一确定的词是标准本身。我确实知道它实际上是一个维基。对不起,我的讽刺我忘了它在互联网上的翻译不好。不幸的是,我似乎找不到比作者对
静态\u cast
的描述更具体的东西了,尽管你的陈述似乎得到了以下方面的支持:进一步研究后,我相信你的陈述是正确的,尽管作者说了什么。但是,如果您能提供另一个可靠的来源,表明即使类是
虚拟的
静态转换
也能工作,我会更乐意接受。您的代码是不正确的,因为
动态转换
只能在至少有一个虚拟函数的类上使用。“基类对象的静态类型实际上是Bar”-这不是静态类型的含义。
struct Foo { virtual ~Foo(){} };
struct Bar : public Foo {};

// safe, may return nullptr
Bar* safe_ptr_cast(Foo *f) { return dynamic_cast<Bar*>(f); }

// safe, may throw but you can catch it
Bar& safe_ref_cast(Foo &f) { return dynamic_cast<Bar&>(f); }

// unsafe - if you're wrong, you just broke everything
Bar* unsafe_ptr_cast(Foo *f) { return static_cast<Bar*>(f); }