C和C++的类型转换

C语言传统的类型转换

C方式的类型转换方式:(Type) (Expression)Type (Expression),后者比较古老。C风格的强制类型转换容易出问题,比较粗暴,如:

typedef void(PF)(int);
struct Point {
	int x; int y;
};
int v = 0x12345;
PF* pf = (PF*)v;	//转换方式过于粗暴,试问:能否保证变量v作为地址是否一定指向PF*类型的函数入口
char c = char(v);	//char类型的数据取值范围有限,能否保证整型数v按照char方式转换一定会在其值域中
Point* p = (Point*)v;	//同样,无法保证将v作为Point*类别的地址值,该地址值一定是一个Point结构体对象的地址

C方式强制类型转换存在的问题:

  • 过于粗暴——

    任意类型之间都可以进行转换,编译器很难判断其正确性

  • 难于定位——

    在源码中无法快速定位所有使用强制类型转换的语句

C++的新类型转换

C++将强制类型转换分为四种不同的类型,分别是static_castconst_castdynamic_castreinterpret_cast,其用法为xxx_cast<Type>(Expression)

static_cast

使用要点:

  • 用于基本类型之间的转换;(基本类型:int、float、double……)
  • 不能用于基本类型指针间的转换
  • 用于有继承关系类对象之间的转换和类指针之间的转换;

const_cast

使用要点:

  • 用于去除变量的只读属性;
  • 强制转换的目标类型必须是指针或引用;

reinterpret_cast

使用要点:

  • 用于指针类型间的强制转换;
  • 用于整数和指针类型间的强制转换;

dynamic_cast

使用要点:

  • 用于有继承关系的类指针间的转换;
  • 用于有交叉关系的类指针间的转换;
  • 具有类型检查的功能;
  • 需要虚函数的支持;

补充说明:

  • 使用dynamic_cast转换如果不成功,将得到空指针,成功将返回指向类对象的指针或引用;

  • dynamic_cast是运行时处理的,而其他三种都是编译时处理的;

  • 在类族中进行上行转换时,dynamic_cast和static_cast的效果是一样的,但在下行转换时,dynamic_cast具有类型检查功能,比static_cast更安全。

    • 上行转换:子类向父类转换(C++中的继承是全部接收,故父类的成员子类都具有,进行上行转换时一般不会有问题)

    • 下行转换:父类向子类转换;

    下行转换的成功与否与将要转换的类型有关,即「将要转换的类指针(或引用)所指向对象的实际类型」与「转换结果对象的类型」一定要相同,否则转换失败。

代码演示

#include <iostream>
using namespace std;
void static_cast_demo() {
	int i = 0x12345;
	char c = 'c';
	int* pi = &i;
	char* pc = &c;
	c = static_cast<char>(i);
	//pc = static_cast<char*>(pi); //Error,static_cast不能转换基本类型指针
	cout << "static_cast affect i to c:" << i << " to " << c << endl;
}
void const_cast_demo() {
	const int& j = 1;
	int& k = const_cast<int&>(j);
	
	const int x = 2;	//在C++中进入符号表,但仍按照C语言方式分配存储空间
	int& y = const_cast<int&>(x);	//相当于将x的内存空间重新起了一个别名,别名的使用方式不在有只读属性限定
	//int z = const_cast<int>(x); //Error,const_cast只能用于指针或引用类型的转换
	k = 5;
	cout << "k=" << k << ",j=" << j << endl;
	y = 8;
	cout << "x=" << x << ",y=" << y << endl; //由于x进入符号表,则从符号表中取用的时候仍为最初的值,而y是从分配的空间中读取值的
	cout << "&x=" << &x << ",&y" << &y << endl;	
}
void reinterpret_cast_demo() {
	int i = 0; char c = 'c';
	int* pi = &i; char* pc = &c;
	pc = reinterpret_cast<char*>(pi);	
	cout << "pc:" << (void*)pc << endl;//int*到char*之间的指针类型转换,由于cout输出字符指针是当作字符串的,所以用void*告诉程序按指针方式输出
	pi = reinterpret_cast<int*>(&c);	
	cout << "pi:" << pi << endl;//不同指针类型之间的强制类型转换
	pi = reinterpret_cast<int*>(i);	//整数和指针之间的强制类型转换
	//c = reinterpret_cast<char>(i);	//不支持基本类型之间的转换
	cout << "pi<int to int*>:" << pi << endl;
}
int main() {
	static_cast_demo();
	const_cast_demo();
	reinterpret_cast_demo();
}
posted @ 2020-06-29 05:00  暖浮生  阅读(269)  评论(0编辑  收藏  举报