前言
- C风格的强制类型转换很简单,都可以使用
Type b = (Type)a形式转换。但这种方式存在一些缺点,比如信息丢失或精度损失,代码可读性的下降等。 - 因此C++提供了四种类型转换符来应对不同场合。分别是
static_cast、dynamic_cast、reinterpret_cast、const_cast。
四种类型比较
| 类型转换符 | 用途 | 特点 |
|---|---|---|
| static_cast | 用于相关类型之间的转换 如基本数据类型之间的转换 派生类指针或引用转为基类指针或引用(上行转换)(总是安全的) 基类指针或引用转为派生类指针或引用(下行转换)(结果可能未定义) | 编译时检查类型兼容性 适用于相关类型之间的转换 |
| dynamic_cast | 主要用于基类和派生类之间的转换,会进行类型检查, 因此上行转换和上行转换都是安全的 | 运行时检查类型兼容性 适用于多态对象之间的转换 |
| reinterpret_cast | 主要用于指针或引用类型之间的转换 指针与整型数据之间的转换 | 不进行类型检查,只是简单地重新解释数据的二进制表示 高风险,容易导致未定义行为 |
| const_cast | 用于添加或移除变量的 const 或 volatile 属性 | 用于添加或移除 const 或 volatile 属性 不影响其他类型属性 |
四种类型详细介绍
static_cast
- 静态类型转换,类似C风格的强制转换。
- 可以进行基本数据类型的转换,
enum、struct、int、char、float、long等。-
int data = 10010; char cData = static_cast<char>(data);
-
- 不能转换指针类型,但是可以将指针与
void*进行互转。-
int data = 10010; int *pData = &data; long *plData = static_cast<long*>(pData); // 不允许转换 -
int data = 10010; int *pData = &data; void *pvData = static_cast<void*>(pData); // 可以转换 long *plData = static_cast<long*>(pvData); // 可以转换
-
- 不能用于两个不相关类型的转换,比如将
int*转为int。-
int data = 10010; int *p1 = &data; int num = static_cast<int>(p1); //不允许转换
-
- 从派生类指针或引用转换为基类指针或引用(上行转换)时,
static_cast总是安全的。-
class Animal { public: virtual void cry() { std::cout << "Animal cry..." << std::endl; } virtual ~Animal() {} }; class Dog :public Animal { public: void cry() override { std::cout << "Dog cry..." << std::endl; } void print() { std::cout << "I am dog" << std::endl; } }; int main() { Dog* pDog = new Dog; // 子类转为父类是安全的 Animal* pAnimal = static_cast<Animal*>(pDog); // 调用子类的cry方法 pAnimal->cry(); return 0; }
-
- 从基类指针或引用转换为派生类指针或引用(下行转换)时,
static_cast可以工作,但前提是必须确保基类指针实际上指向的是派生类对象。否则,结果将是未定义的。-
class Animal { public: virtual void cry() { std::cout << "Animal cry..." << std::endl; } virtual ~Animal() {} }; class Dog :public Animal { public: void cry() override { std::cout << "Dog cry..." << std::endl; } }; class Cat :public Animal { public: void cry() override { std::cout << "Cat cry..." << std::endl; } }; int main() { Animal* pAnimal = new Dog; Dog* pDog = static_cast<Dog*>(pAnimal); pDog->cry(); // 这里调用Dog的方法,是正常的 Cat* pCat = static_cast<Cat*>(pAnimal); pCat->cry(); // 这里仍然调用Dog的方法,是不正确的 return 0; }
-
dynamic_cast
- 动态类型转换。是一种运行时类型检查的强制类型转换操作符,主要用于处理基类与派生类之间的转换。
- 如果是指针类型转换失败,会返回空,如果是引用类型转换失败,会抛出一个
bad_cast异常。 - 从派生类指针或引用转换为基类指针或引用(上行转换)。
-
class Animal { public: virtual void cry() { std::cout << "Animal cry..." << std::endl; } virtual ~Animal() {} }; class Dog :public Animal { public: void cry() override { std::cout << "Dog cry..." << std::endl; } void print() { std::cout << "I am dog" << std::endl; } }; int main() { Dog* pDog = new Dog; // 子类转为父类 Animal* pAnimal = dynamic_cast<Animal*>(pDog); // 调用子类的cry方法 pAnimal->cry(); return 0; }
-
- 从基类指针或引用转换为派生类指针或引用(下行转换)。
-
class Animal { public: virtual void cry() { std::cout << "Animal cry..." << std::endl; } virtual ~Animal() {} }; class Dog :public Animal { public: void cry() override { std::cout << "Dog cry..." << std::endl; } }; class Cat :public Animal { public: void cry() override { std::cout << "Cat cry..." << std::endl; } }; int main() { Animal* pAnimal = new Dog; // 父类转为子类, 会进行类型检查 // 这里会转换成功 Dog* pDog = dynamic_cast<Dog*>(pAnimal); if (pDog == NULL) { std::cout << "pDog is null" << std::endl; return -1; } pDog->cry(); Cat* pCat = dynamic_cast<Cat*>(pAnimal); // 这里会转换失败 if (pCat == NULL) { std::cout << "pCat is null" << std::endl; return -1; } pCat->cry(); return 0; }
-
const_cast
- 主要用于去除const属性。直接看一个示例
-
int main() { int data = 10010; const int* pcData = &data; // 这样是无法修改的 //*pcData = 10020; // 可转为int*修改 int* pData = const_cast<int*>(pcData); *pData = 10020; // 打印结果都为10020 std::cout << "data: " << data << std::endl; std::cout << "*pcData: " << *pcData << std::endl; std::cout << "*pData: " << *pData << std::endl; return 0; }
-
reinterpret_cast
- 主要用于指针类型或者引用类型之间的转换。
- 将一个指针类型转为另一个指针类型
-
int data = 10010; int *pData = &data; char *pCh = reinterpret_cast<char*>(pData);
-
- 将一个引用类型转为另一个引用类型
-
int iData = 10010; int &pData = iData; char &cData = reinterpret_cast<char&>(pData);
-
- 指针与整型数据之间的转换。
-
int iData = 10010; char cData = 10; long long lData = 678290; // 结果可能未定义 char *pCh = reinterpret_cast<char*>(iData); pCh = reinterpret_cast<char*>(cData); pCh = reinterpret_cast<char*>(lData);
-
- 不允许进行基本类型的转换
-
int iData = 10010; // 不允许 char cData = reinterpret_cast<char>(iData);
-
- 注意事项
- 使用
reinterpret_cast进行不合适的转换可能会导致未定义行为。 reinterpret_cast的行为可能依赖于具体的硬件和编译器实现。因此,使用reinterpret_cast编写的代码可能不具备良好的可移植性。- 尽量避免使用
reinterpret_cast,除非确实需要低级别的控制。大多数情况下,使用static_cast或dynamic_cast更为安全和合适。 reinterpret_cast不提供任何类型的检查,因此使用时必须确保转换是合理的。
- 使用
4862

被折叠的 条评论
为什么被折叠?



