• 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();
    }
    
  • 相关阅读:
    十五周学习笔记
    十四周学习笔记
    程序员修炼之道二
    程序员修炼之道
    构建之法十七
    十三周学习笔记总结
    个人课程总结
    构建之法十六
    构建之法十二
    文章单词统计接龙
  • 原文地址:https://www.cnblogs.com/coro/p/13205907.html
Copyright © 2020-2023  润新知