类型转换
约 972 字大约 3 分钟
2025-04-06
C++
为了规范C
中的类型转换,加强类型转换的可视性,引入了四种强制类型转换操作符:
static_cast
reinterpret_cast
const_cast
dynamic_cast
static_cast
**<font style="color:rgb(0, 0, 0);">static_cast<type-id>(expression)</font>**
该运算符把expression
转换为type-id
类型,但没有运行时类型检查来保证转换的安全性。 编译器隐式执行任何类型转换都可由static_cast
显示完成
- 基本类型转换
double score = 59.5;
int nScore = static_cast<int>(score);
void
指针和其他类型指针之间的转换(其他类型指针之间不能转换)
void* p = new int(20);
int* pi = static_cast<int*>(p);
void* pc = static_cast<void*>(pi); //这里可以隐式转换,可以省略static_cast
delete p;
- 用于基类派生类之间指针、引用的转换
class Base
{
public:
virtual void show()
{
std::cout << "Base " << std::endl;
}
};
class Derive :public Base
{
char* name = nullptr;
public:
Derive()
{
name = new char[5]{ "玩蛇" };
}
~Derive()
{
delete name;
}
void print()
{
std::cout << "Derive " << name << std::endl;
}
};
* 下行转换:把基类指针、引用转为派生类的指针、引用(必须强制静态转换)
Base* base = new Base;
Derive* derive = static_cast<Derive*>(base);
derive->print();
delete base;
* 上行转换:把派生类指针、引用转为基类的指针、引用(可以自动隐式转换)
//指针
Derive* derive = new Derive;
Base* base = static_cast<Derive*>(derive);
//引用
Derive& refDerive = *derive;
Base& refBase = static_cast<Base&>(refDerive);
delete derive;
注意:下行转换使用static_cast
不安全,请使用dynamic_cast
(不安全:因为不知道基类的指针,到底是不是指向的要转换的派生类对象,如果不是,访问数据成员会有错误)
reinterpret_cast
为操作数的位模式提供较低层的重新解释,主要用于以下六种情况:
- 任意类型指针之间的转换
int* p = nullptr;
char* pc = reinterpret_cast<char*>(p);
- 指针转整型,整型转指针
int* p = nullptr;
uint64_t a = reinterpret_cast<uint64_t>(p); //x64 指针是8个字节,所以要用uint64_t保存,否则可能会丢失数据
double* pd = reinterpret_cast<double*>(a);
- 函数指针也可以转换哦~
uint64_t funMax = reinterpret_cast<uint64_t>(_max);
cout<<reinterpret_cast<int(*)(int, int)>(funMax)(2, 3);
int _max(int a, int b)
{
return a > b ? a : b;
}
- 一个官方案例
int arr[10];
for (int i = 0; i < 10; i++)
{
cout << arr+i <<" " <<hex<< ::hash(arr+i) << endl;;
}
uint32_t _hash(void* p)
{
uint64_t val = reinterpret_cast<uint64_t>(p);
return val ^ (val >> 32);
}
const_cast
const_cast
用来移除类型的const
属性。const_cast
中的类型必须是指针、引用或指向对象类型成员的指针
const
指针、引用不能直接赋值给非const的对象,需要去掉const之后再赋值
const char* name = "hello";
char* pname = const_cast<char*>(name);
const int& refA = 8;
int& refB = const_cast<int&>(refA);
- 可以在类的const函数里面修改成员变量
class Integer
{
private:
int number;
public:
Integer(int number = 0):number(number){}
operator int()const
{
const_cast<int&>(number)++; //必须去掉const才能修改
const_cast<Integer*>(this)->number++;
return number;
}
};
Integer num = 10;
int n = num; //11
dynamic_cast
dynamic_cast
用于有继承关系的多态类(基类必须有虚函数)的指针或引用之间的转换。
- 通过
dynamic_cast
,将派生类指针转换为基类指针(上行转换),这个操作与static_cast
的效果是一样的。 - 通过
dynamic_cast
,将基类指针转换为派生类指针(下行转换),dynamic_cast
具有类型检查的功能,比static_cast
更安全(如果转换的是指针,失败时会返回空指针;如果转换的是引用,会抛出std::bad_cast
异常)
Animal* dog = new Dog;
dog->cry();
//转成实际的类型
Dog* d = dynamic_cast<Dog*>(dog);
if (!d)
std::cout << "dog is not Dog" << std::endl;
d->cry();
//尝试转成其他子类,失败返回nullptr
Cat* cat = dynamic_cast<Cat*>(dog);
if (!cat)
std::cout << "dog is not Cat";
else
cat->cry();
Animal& refA = *dog;
//转成实际的类型
Dog& refD = dynamic_cast<Dog&>(refA);
refD.cry();
//尝试转成其他子类,失败抛异常
Cat& refC = dynamic_cast<Cat&>(refA);
refC.cry();