2017-01-12 54 views
0
#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不应该被使用,而 向下投射。C++ static_cast vs dynamic_cast

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

编辑:谢谢你的回应。实际上,上面的基类是多态的 ,即它具有虚函数,但在本例中我省略了它们。我应该 在基地虚拟析构函数中抛出,以明确它是 是多态 - 我的不好。

+5

您可以从'Base *'的'static_cast' 'Derived *',但你是正确的,它不会执行任何类型检查。它仍然很有用,但如果通过其他方式知道该指针确实指向了“Dervied”对象。如果'Base *'实际上没有指向Derived *,那么由'static_cast'产生的Derived *'的任何解引用都会引发未定义的行为。 –

+0

在所有现实中,这完全是* static_cast是什么;毕竟,转向基类指针/引用是隐式完成的。 –

回答

1

static_cast <new_type> (expression)

如果new_type是一个指针或引用某些类d和 expression类型是指针或引用其非虚拟基B, 的static_cast执行向下转换。是形成不良的这个垂头丧气如果B是 暧昧,交通不便,或虚拟基(或虚拟基底的基底)D.这样的static_cast的 使得没有运行时检查,以确保 对象的运行时类型实际上是d,并且可以只有在 这个前提条件由其他方式保证时才能安全使用,例如 实现静态多态性。安全向下可以通过 dynamic_cast完成。

Source(说明项目2)

4

在上面的代码中,我应该使用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++的口头禅并不支付你不需要的东西。

0

你是完全正确的使用static_cast。你是对的,编译器可以在一般情况下不知道转换是否正确,但static_cast恰恰就是这种情况。

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

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

相关问题