C ++ static_cast vs dynamic_cast

时间:2017-01-12 17:20:28

标签: c++

#include <iostream>

class Base {
};

class Derived : public Base {
};

int main() {
    Base* bptr = new Derived();

    Derived* dptr = static_cast<Derived*>(bptr);

    std::cout << dptr << std::endl;
}

在上面的代码中,我应该使用dynamic_cast但是正在使用 static_cast不正确。绝不应该使用static_cast 向下转换,因为编译器无法确定我们在做什么 正确投射。

为什么这不是编译错误?我正在使用gcc 4.9.2。你们好吗? 认为这是编译器中的错误,还是C ++标准允许这样的代码?

编辑:感谢您的回复。实际上,上面的基类是多态的 即它有虚函数,但我把它们留给了这个例子。我应该 已经抛出基地中的虚拟析构函数来表明它 是多态的 - 我的坏。

3 个答案:

答案 0 :(得分:6)

  

在上面的代码中,我应该使用dynamic_cast,但错误地使用static_cast。在向下转换时永远不应该使用static_cast,因为编译器无法确定我们是否正在进行正确转换。

具有讽刺意味的是,dynamic_cast实际上是不正确的演员,因为你的类型不是多态的。

那就是说,static_cast当然可以用来贬低。你是正确的,编译器不能进行类型检查,但在很多情况下你有Base*并且知道它指向Derived*,所以你可以手动进行转换。一个非常常见的案例是CRTP:

template <class Derived>
class Base {
    Derived& self() { return *static_cast<Derived*>(this); }
    // ...
};


class Foo : Base<Foo> { ... };

Base<T> 总是一个T,因此向下转播是安全的。

static_cast优于dynamic_cast的优势在于static_cast是免费的,但dynamic_cast是昂贵的。 C ++的口头禅不会为你不需要的东西付出代价。

答案 1 :(得分:1)

static_cast < new_type > ( expression )

  

如果new_type是指向某个类D的指针或引用,并且类型为   expression是指向其非虚拟基数B的指针或引用,   static_cast执行向下转换。如果B是,那么这个沮丧的人是不正确的   模糊,不可访问或虚拟基础(或虚拟基础的基础)   D.这样的static_cast不进行运行时检查以确保   对象的运行时类型实际上是D,只有在安全的情况下才可以安全使用   这个先决条件是通过其他方式保证的,例如何时   实现静态多态。可以使用安全垂头丧气   的dynamic_cast。

Source(说明项目2)

答案 2 :(得分:0)

您正确使用*Completions*。你是对的,编译器在一般情况下不知道强制转换是否正确,但static_cast正好适用于这种情况。

这里不能使用static_cast,因为该转换是针对多态类(具有虚拟成员函数的类)。这些类带有运行时信息;该信息允许代码在指向的对象的实际类型中选择该函数的正确实现。导入函数可以使用对象中的此类型信息来确定是否可以进行类型转换,然后确实正确执行转换(这对于多重和虚拟继承来说可能很棘手)。

没有虚函数的类(如示例类)不包含此运行时信息,并且dynamic_cast不能用于转换为更多派生类型。 (它仍可用于转换为相同类型或基类,即它可用于实际上不需要转换的转换。)