文章目录
🌈C++类型转换
📝C语言风格的转换
C语言提供了自己的一套转换规则,有好处也有坏处。
C语言的风格:(type_name)expression;
C语言提供了隐式类型转换和显式类型转换。显式类型转换一般也叫做强转,隐式类型转换编译器完成,如果转换不了就报错。
而C语言类型转换的风格好处就是简单,缺陷比如转换的可视性差,显式类型转换的写法就只有一种,难以精准的跟踪错误。
🌰char ch=1.1,char ch=1在.cpp下都是合法的,这就是隐式类型转换,C语言下如果把一个结构体给int就会报错,因为编译器不知道怎么去转,C++下可以通过实现operator int()实现类型转换或者提供合适的构造函数完成隐式类型转换,下面以在.cpp中实现operator int()为例
下面这段代码由于隐式类型转换导致了死循环
C语言的类型转换其实已经足够完成需求了,但是可视性不太好,比如你不能在代码库中搜索它(就一对括号怎么去搜索),所以C++提供了一套类型转换,相当于语法糖了,此外还会进行一些编译性检查(比如dynamic_cast转换失败则返回空指针)。但其实作用都是一样的。
📝C++风格的类型转换
C++标准为了增加类型转换的可见性,提供了四种类型转化的方式。
📄static_cast
静态类型转换,进行相关类型的转换,但不能转换两个不相关的类型(即编译器看到这个转换是行不通的就会报错)。
static_cast < type-id > ( expression )
int main()
{
double a = (int)5.5 + 5.3;//结果是10.3
double b = static_cast <int>(5.5) + 5.3;
cout << "a: " << a << endl;
cout << "b: " << b << endl;
return 0;
}
转换不相关的类型:
📄reinterpret_cast
很暴力的一个操作符,由英文直译过来就是重新解释的转型。白话就是将一段内存重新解释。
下面的例子把一个结构体指针解释为int再加上5.3。
struct Test
{
int a;
};
int main()
{
Test* t = new Test;
double c = reinterpret_cast <int>(&t) + 5.3;
cout << c << endl;
return 0;
}
📄const_cast
删除变量的const属性,一般和指针或引用连用
int main()
{
const int a = 1;//a是常变量,在栈上
int* p = const_cast<int*>(&a);
*p = 2;
cout << a << endl;
cout << *p << endl;
return 0;
}
📄dynamic_cast
dynamic_cast,安全的向下转型。
多态的转换中向下转型(父类转为子类)用dynamic是安全的,但是父类必须有虚函数,否则编译报错,且只能用于指针或引用。
- 父类指针一开始指向一个父类对象,再给到子类类型的指针,存在越界的风险,如果为了保证安全则需要检查。
父类的指针指向子类对象(向上转型),再给到子类指针,合理。
所以建议使用dynamic_cast,因为可以保证安全, 转换失败返回空指针(NULL)。
- dynamic_cast的底层与RTTI有关,借助RTTI拿到类型信息,所以dynamic_cast更像一个函数,因为不是编译指令,所以会带来一些性能的损失。
下面给一个代码例子
class Entity
{
public:
virtual void Print() {};//dynamic_cast使用的前提必须是父类有虚函数
};
class Player:public Entity
{
};
class Enemy :public Entity
{
};
void Check(void* p)
{
if (p)
{
cout << "转换成功" << endl;
}
else
{
cout << "转换失败" << endl;
}
}
int main()
{
Entity* e = new Entity();
Entity* actuallyPlayer = new Player();//向上转型
//安全的向下转型
Player* player =(Player*)actuallyPlayer;//向下转型需要转换类型
Player* player2 = dynamic_cast<Player*>(actuallyPlayer);
Check(player2); cout << endl;
//不安全的向下转型
Player* player3 = (Player*)e;
Player* player4 = dynamic_cast<Player*>(e);
Check(player4); cout << endl;
Entity* actuallyEnemy = new Enemy();
Player* player5 = dynamic_cast<Player*>(actuallyEnemy);
Check(player5); cout << endl;
return 0;
}
dynamic也常常利用返回值是否是空指针来判断指针具体指向谁。
🌈小结
-
static_cast用于相关类型的转换
-
reinterpret_cast用于重新解释内存(很暴力,用的时候心里要有数)
-
const_cast常用来取出const属性,常与指针连用来修改const变量的值
-
dynamic_cast,在多态里提供安全的向下转换(转换不安全就返回空指针,只要对返回的指针进行判断我们就能知道此次转换安不安全了)