#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。你们认为这是编译器中的一个bug,还是C++标准允许这样的代码?
编辑:谢谢你的回复。实际上,上面的基类是多态的,即它有虚拟函数,但是在这个例子中我忽略了它们。我应该在Base中抛出一个虚拟析构函数,以明确它是多态的--这是我的错。
发布于 2017-01-12 17:29:59
在上面的代码中,我应该使用
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++的格言是不要为你不需要的东西付费。
发布于 2017-01-12 17:26:01
static_cast < new_type > ( expression )
如果
new_type是一个指针或对某个类D的引用,而expression的类型是一个指针或对它的非虚基B的引用,则static_cast执行向下转换。如果B是D的模棱两可的、不可访问的或虚拟的基(或虚拟基的基),则这种下拉式是不正确的。这样的static_cast不进行运行时检查以确保对象的运行时类型实际上是D,并且只有在其他方法(例如在实现静态多态时)保证了这个前提条件时才能安全地使用。可以用dynamic_cast进行安全的下传。
来源 (解释项目2)
发布于 2017-01-12 17:33:34
您完全正确地使用了static_cast。您是对的,在一般情况下,编译器可能不知道强制转换是否正确,但是static_cast确实存在于此场景中。
您不能在这里使用dynamic_cast,因为该转换用于多态类(那些具有虚拟成员函数的类)。这些类携带运行时信息;该信息允许代码在所指向对象的实际类型中选择该函数的正确实现。cast函数可以使用对象中的此类型信息来确定类型转换是否可行,然后正确地执行转换(这对于多重继承和虚拟继承来说可能比较棘手)。
没有虚拟函数的类(如示例类)不携带此运行时信息,而且不能使用dynamic_cast转换为更派生的类型。(它仍然可以用于转换到同一类型或基类,也就是说,它可以用于实际上不需要强制转换的转换。)
https://stackoverflow.com/questions/41619289
复制相似问题