动态类型转换能检查出静态类型转换无法查出的错误,但它有额外开销,根据情况使用,这两个都是c++风格的,相对于c风格来说,c风格: double b = 2.0;int a = (int)b;
静态类型转换和动态类型转换的主要区别如下:
-
静态类型转换(static_cast)在编译期就进行类型转换,不进行运行时检查。所以上例中player* p0 = static_cast<Player*>(actuallyEnemy);这种转换可以成功编译,但实际运行可能会出现类型错误。
-
动态类型转换(dynamic_cast)会在运行期检查要转换的类型是否正确,可以避免静态转换可能出现的类型错误。它依赖于虚函数表来判断对象的实际类型。
-
所以上例中player* p2 = dynamic_cast<Player*>(actuallyPlayer);这种转换不需要虚函数表,因为类型是匹配的,所以可以成功。
而player* p1 = dynamic_cast<Player*>(actuallyEnemy);这里类型不匹配,所以这次动态转换会返回nullptr。
-
总之,静态类型转换依赖编译期类型信息转换,动态类型转换依赖运行期通过虚函数表判断实际类型进行转换,可以避免静态转换可能出现的类型错误。
-
但动态转换开辟额外开销,而静态转换效率较高。所以根据情况选择使用不同的转换方法。
是的,静态类型转换无法在运行时进行类型检查,只依赖于编译期的静态类型信息进行转换。
所以使用静态类型转换可能出现以下错误情况:
-
编译通过但运行时类型实际不匹配导致错误。如上例中从actuallyEnemy静态转换到Player*,但实际类型可能不是Player。
-
也可能编译通过但具有潜在错误,例如通过继承隐藏真实类型差异。
而动态类型转换通过运行期依赖虚表来获得对象的真实类型信息,可以检查类型是否匹配,避免上述错误。
简单总结:
-
静态类型转换依赖编译期类型信息,运行时无法检查类型,可能出现类型不匹配的错误。
-
动态类型转换通过运行期结合虚表检查类型匹配情况,可以避免静态转换可能出现的类型错误。
所以在不确定对象实际类型的情况下,优先使用动态类型转换可以避免潜在的类型安全问题。静态转换适用于类型可以确定匹配的情况。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm> /* sort*/
#include <functional> /*std::greater<int>()*/
#include "game.h"
class Entity {
public:
virtual void PrintName(){} /*因为这是Entity,所以肯定有虚函数,也就有v表,那么就可以使用
dynamic_cast*/
};
class Player : public Entity {
};
class Enemy : public Entity {
};
/*
*/
int main() {
Player* player = new Player();
Entity* actuallyPlayer = player; /*这里player转换成了Entity,但是想要转换再转换回去就不容易了*/
Entity* actuallyEnemy = new Enemy();
Player* p = (Player*)actuallyEnemy;/*这里就出现了问题,因为它实际上是Enemy*/
Player* p0 = static_cast<Player*>(actuallyEnemy);/* */
Player* p1 = dynamic_cast<Player*>(actuallyEnemy);/*动态类型转换可以检查出问题*/
Player* p2 = dynamic_cast<Player*>(actuallyPlayer);/*需要虚拟v表,为什么?*/
// game::runGame();
std::cin.get();
}