C++中四种类型转换的用法
·
以下是用代码示例演示C++中四种类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast)的用法,每个示例都包含具体场景和注释说明:
#include <iostream>
#include <typeinfo> // 用于dynamic_cast异常处理
#include <cstdint> // 用于uintptr_t(存储指针的整数类型)
// 定义用于演示的类层次结构
class Base {
public:
// 含有虚函数,使Base成为多态类(支持dynamic_cast)
virtual void print() const {
std::cout << "This is Base class" << std::endl;
}
};
class Derived : public Base {
public:
void print() const override {
std::cout << "This is Derived class" << std::endl;
}
// 派生类特有方法
void derivedMethod() const {
std::cout << "Calling Derived-specific method" << std::endl;
}
};
class Unrelated {
public:
void print() const {
std::cout << "This is Unrelated class" << std::endl;
}
};
int main() {
// 1. static_cast:静态类型转换(编译时检查)
std::cout << "=== static_cast 示例 ===" << std::endl;
// 1.1 基本数据类型转换
int intNum = 10;
double doubleNum = static_cast<double>(intNum);
std::cout << "int -> double: " << doubleNum << " (类型大小: " << sizeof(doubleNum) << ")" << std::endl;
// 1.2 派生类到基类的上行转换(安全)
Derived derivedObj;
Base* basePtr = static_cast<Base*>(&derivedObj); // 等价于隐式转换
basePtr->print(); // 多态调用:输出Derived的print
// 1.3 基类到派生类的下行转换(不安全,无运行时检查)
Base baseObj;
Derived* derivedPtr = static_cast<Derived*>(&baseObj); // 编译通过,但危险
derivedPtr->print(); // 未定义行为(实际指向Base对象)
// 1.4 void*与其他指针的转换
int x = 100;
void* voidPtr = static_cast<void*>(&x);
int* intPtr = static_cast<int*>(voidPtr); // 安全转回原类型
std::cout << "通过void*转换后的值: " << *intPtr << std::endl;
std::cout << std::endl;
// 2. dynamic_cast:动态类型转换(运行时检查,仅用于多态类)
std::cout << "=== dynamic_cast 示例 ===" << std::endl;
Base* realDerivedPtr = new Derived(); // 实际指向派生类对象
Base* realBasePtr = new Base(); // 实际指向基类对象
// 2.1 指针转换:成功案例
Derived* castedDerived = dynamic_cast<Derived*>(realDerivedPtr);
if (castedDerived != nullptr) {
std::cout << "dynamic_cast 指针转换成功: ";
castedDerived->derivedMethod(); // 安全调用派生类方法
}
// 2.2 指针转换:失败案例
Derived* failedCast = dynamic_cast<Derived*>(realBasePtr);
if (failedCast == nullptr) {
std::cout << "dynamic_cast 指针转换失败(指向基类对象)" << std::endl;
}
// 2.3 引用转换:成功案例
Derived& derivedRef = dynamic_cast<Derived&>(*realDerivedPtr);
std::cout << "dynamic_cast 引用转换成功: ";
derivedRef.derivedMethod();
// 2.4 引用转换:失败案例(会抛出异常)
try {
Derived& badRef = dynamic_cast<Derived&>(*realBasePtr);
} catch (const std::bad_cast& e) {
std::cout << "dynamic_cast 引用转换失败: " << e.what() << std::endl;
}
delete realDerivedPtr;
delete realBasePtr;
std::cout << std::endl;
// 3. const_cast:常量性转换(修改const属性)
std::cout << "=== const_cast 示例 ===" << std::endl;
// 3.1 安全场景:原对象本身非const,仅指针是const
int nonConstVal = 20;
const int* constPtr = &nonConstVal;
int* mutablePtr = const_cast<int*>(constPtr); // 去除const
*mutablePtr = 30; // 安全,原对象是非const的
std::cout << "修改后的值(原对象非const): " << nonConstVal << std::endl;
// 3.2 危险场景:原对象是const,强制修改会导致未定义行为
const int constVal = 40;
const int* ptrToConst = &constVal;
int* badMutablePtr = const_cast<int*>(ptrToConst);
*badMutablePtr = 50; // 未定义行为(编译器可能优化constVal为只读)
std::cout << "原const对象的值(可能未变): " << constVal << std::endl;
std::cout << "通过指针访问的值(不确定): " << *badMutablePtr << std::endl;
std::cout << std::endl;
// 4. reinterpret_cast:重解释转换(底层二进制重解释)
std::cout << "=== reinterpret_cast 示例 ===" << std::endl;
// 4.1 指针与整数的转换
int num = 0x12345678;
int* numPtr = #
uintptr_t ptrAddr = reinterpret_cast<uintptr_t>(numPtr); // 指针转整数
std::cout << "指针地址(整数形式): 0x" << std::hex << ptrAddr << std::dec << std::endl;
int* restoredPtr = reinterpret_cast<int*>(ptrAddr); // 整数转回指针
std::cout << "恢复指针后的值: " << *restoredPtr << std::endl;
// 4.2 不同类型指针的转换(危险,语义完全改变)
float* floatPtr = reinterpret_cast<float*>(numPtr);
std::cout << "int指针重解释为float指针的值: " << *floatPtr << std::endl;
// 注意:这里的值与原int值的二进制相同,但语义完全不同(浮点数格式)
// 4.3 无关类指针的转换(危险,无继承关系)
Unrelated* unrelatedPtr = reinterpret_cast<Unrelated*>(numPtr);
unrelatedPtr->print(); // 未定义行为(实际指向int变量)
return 0;
}
代码说明
-
static_cast示例:- 演示了基本类型转换(
int→double)、类层次结构的上下行转换,以及void*与其他指针的转换 - 注意基类到派生类的下行转换是不安全的,编译器不做运行时检查
- 演示了基本类型转换(
-
dynamic_cast示例:- 仅用于多态类(含虚函数),通过运行时类型信息(RTTI)检查转换安全性
- 指针转换失败返回
nullptr,引用转换失败抛出std::bad_cast异常 - 适合需要安全地将基类指针/引用转换为派生类类型的场景
-
const_cast示例:- 用于修改指针/引用的
const属性,仅当原对象本身不是const时修改才安全 - 若原对象是
const,强制修改会导致未定义行为(结果不确定)
- 用于修改指针/引用的
-
reinterpret_cast示例:- 直接重解释底层二进制,不进行逻辑转换,结果高度依赖系统架构
- 演示了指针与整数的转换、不同类型指针的转换,这类转换风险极高,仅用于底层编程
编译运行注意
- 编译时需启用RTTI(通常默认启用,部分编译器需加
-frtti选项) reinterpret_cast的结果可能因编译器和平台(32位/64位)而异,移植性差- 实际开发中应优先使用前两种转换,谨慎使用
const_cast,尽量避免reinterpret_cast
通过这些示例,可以清晰看到四种转换的适用场景和潜在风险,帮助理解如何在实际代码中正确选择类型转换方式。
更多推荐


所有评论(0)