2015-09-10 55 views
3

这个问题是关于哪个C++ style cast应该用来进行这种转换。我知道C风格的演员可以实现这一点。什么类型的演员从父母到孩子?

对于以下class结构:

class Foo {}; 

class Bar : public Foo {}; 

说我给出:Foo* ptr;,我想将它转换为Bar*投的类型,我应该使用哪个?好像我必须用dynamic_cast,因为它是:

用于多态类型

我想避免dynamic_cast,因为它是一个运行时投的转换。

+0

这是你应该避免的事情,做这些事情是设计问题的标志。如果你认为你真的需要这个,你可以比较类的类型,如果它匹配,你可以static_cast指针...它的速度比dynamic_cast快,但如果你不知道确切的目的地类,它将不起作用。 – Melkon

+0

@Melkon如何检查typeid比dynamic_cast更快?你看到了哪个编译器和设置? –

+1

@MarkRansom:typeid检查不会遍历类层次结构。 – Melkon

回答

6

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

+0

我确实知道'ptr'是一个'Bar *'。所以我假设你在这个列表中引用了第二种类型的转换:http://en.cppreference.com/w/cpp/language/static_cast#Explanation –

+0

@JonathanMee是的,这就是我正在谈论的 - 尽管我认为基类不是非虚拟化的必要条件。 –

+0

你敢挑战http://en.cppreference.com的智慧O.O –

1

static_cast只要您确定您投射的对象真的是您期望的类型,就可以正常工作。根据你给出的例子,看起来你确定。

1

为了清楚起见:

我想避免dynamic_cast,因为它是一个运行时施放。

好了,你有一个运行时类型(给出一个静态类型的参考基础类,你不能一般知道动态类型的对象),所以运行时投是唯一完全安全的选择。

如果您认为自己的物体确实是Bar,但被误认为dynamic_cast<Bar*>会给您一个nullptrdynamic_cast<Bar&>会抛出异常。无论哪种方式,您都有机会在运行时处理运行时错误。正如M.M指出的那样,只有当您的基类具有或继承至少一个虚拟方法时才可用。

现在如果,一个偶然的机会,你可以静态一定的动态类型的对象的真正Bar,您可以使用static_cast。但是,如果你错了,你有未定义的行为,没有机会检测或处理错误。

例如。

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

顺便说一句,如果与运行时间投你的问题是性能,冒着UB为了节省时间名义你的代码文件之前是过早优化的定义。

+1

您的代码不正确,因为'dynamic_cast'只能用于具有至少一个虚拟功能的类。 –

+0

“你的基类对象的静态类型真的是Bar” - 这不是静态类型*的意思。 –

+0

好点,这是一个不幸的表述。 – Useless