[英]C++ static_cast vs dynamic_cast
#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 ++标准允许此类代码?
编辑:感谢您的答复。 实际上,上面的基类是多态的,即它具有虚函数,但在本示例中我将其省略。 我应该在Base中抛出一个虚拟析构函数,以表明它是多态的,这很糟糕。
在上面的代码中,我应该使用
dynamic_cast
但使用的static_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 ++的口头禅是不为您不需要的东西付费。
static_cast < new_type > ( expression )
如果
new_type
是指向某个类D的指针或引用,而expression
的类型是指向其非虚拟基数B的指针或引用,则static_cast执行向下转换。 如果B是D的模棱两可,不可访问或虚拟基础(或虚拟基础的基础),则此向下转换格式错误。此类static_cast不进行运行时检查以确保对象的运行时类型实际上为D,并且只能使用如果通过其他方式(例如实现静态多态性)保证了此前提,则可以安全地进行操作。 安全下调可以通过dynamic_cast完成。
来源 (说明项目2)
您正在正确正确地使用static_cast
。 没错,在一般情况下,编译器可以不知道static_cast
是否正确,但是在这种情况下static_cast
确实存在。
您不能在此处使用dynamic_cast
,因为该强制转换用于多态类(那些具有虚拟成员函数的类)。 这些类包含运行时信息。 该信息允许代码在所指向的对象的实际类型中选择该功能的正确实现。 转换功能可以使用对象中的此类型信息来确定是否可以进行类型转换,然后确实执行正确的转换(使用多重继承和虚拟继承可能会很棘手)。
没有虚拟函数的类(例如您的示例类)不包含此运行时信息,并且dynamic_cast
不能用于强制转换为更多派生类型。 (它仍然可以用于强制转换为相同类型或基类,即可以用于实际上不需要强制转换的转换。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.