C风格强制转换
即通过圆括号直接转型,常见有以下几种情况:
- 浮点数赋值给整型,舍弃小数部分(符合一般思维,可放心使用)
- 整数赋值给浮点型,数值不变,底层改用指数格式存储(符合一般思维,可放心使用)
- double型小数赋值给float型小数,精度略微损失,可能出现数值范围溢出(小心使用)
- 字符赋值给整数型,保留原字节数据,因为字符本身就是用ASCII码表示的,本质就是八位的较小整数(理解字符的存储方式,就很容易接受)
- 整数赋值给字符型,截断高地址数据,只保留低地址的八位,因为char型最多只有八位(小心使用)
- 有符号整数赋值给无符号整数,将包括符号在内的全部字节的直接赋值,实际数值会改变(小心使用)
- 无符号整数赋值给有符号整数,也是将包括符号在内的全部字节的直接赋值,但是数值可能会改变(小心使用)
- unsigned int和int字节存储区别:unsigned int和int位数是一样的,但是int将首个bit位作为正负号,0表示正数,1表示负数。unsigned int和int之间都是以字节的方式相互赋值。当字节以0开头时,它们表示的数值是相同的,当字节以1开头时,它们则分别表示整数和负数。由于int将首位作为符号位,因此它实际能表示的最大正整数只有unsigned int的一半
static_cast静态转换
类似C风格的强制转换,只允许在有关联的指针类型或基本类型间使用
比如基类指针和子类指针,int和double,对象指针和void指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14int main() { double a = 1099.255; int b = static_cast<int>(a); char c[] = "hello"; string d = static_cast<string>(c); cout << a << endl; cout << b << endl; cout << c << endl; cout << d << endl; return 0; }
dynamic_cast动态转换
用于基类指针和子类指针之间的转换
虽然static_cast也具备这样的功能,但是是不安全的,dynamic_cast则会在转型时判断类型,如果类型不符则返回nullptr
由于类型信息是保存在虚函数表中的,因此dynamic_cast操作的基类必须包含virtual函数
不要觉得这个限制很麻烦,因为dynamic_cast的定位就是在多态场景下使用的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27class Animal { virtual void speak() {} }; class Cat : public Animal { void speak() {} }; class Dog : public Animal { void speak() {} }; int main() { Cat *a = new Cat; Animal *b = dynamic_cast<Animal *>(a); Cat *c = dynamic_cast<Cat *>(b); Dog *d = dynamic_cast<Dog *>(b); cout << a << endl; cout << b << endl; cout << c << endl; cout << d << endl; return 0; }
reinterpret_cast重译转换
reinterpret_cast用于将地址,强制转换为任意类型的指针
顾名思义,reinterpret_cast就是不改变指针地址,但是强制将地址处的内存字节解释为某种类型的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34class Object { public: char h = 'H'; char i = 'I'; char j = 'J'; int m = 100; int n = 200; int k = 300; int x = 400; int y = 500; int z = 600; }; int main() { Object a; double *b = reinterpret_cast<double *>(&a); bool *c = reinterpret_cast<bool *>(&a); char *d = reinterpret_cast<char *>(&a); int *e = reinterpret_cast<int *>(&a); int *f = reinterpret_cast<int *>(&a.m); cout << &a << endl; cout << *b << endl; cout << *c << endl; cout << *d << endl; cout << d[1] << endl; cout << d[2] << endl; cout << *e << endl; cout << *f << endl; return 0; }
const_cast常量转换
const_cast用于常量指针和非常量指针间的转换,同样适用于引用
函数和模块接口,由于会暴漏给很多文件或代码使用,难免会遇到需要修改const属性的情况,因为凡事总有特例,不可能一个接口适用于所有情景
即便是在单个文件中,我们也可能希望某个变量在大多时候值不被修改,但是在某个特定地方却又必须修改它的值,这时const_cast就派上用场了
const_cast提供了一个解决特殊需求的捷径,但是不应当滥用,否则const属性就失去意义了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28int *getValue() { return new int(10); } int main() { //const转非const int a = 100; //定义一个指针pa,我们希望通过它来访问a,但是不希望它修改a的值,所以定义为const int * const int *pa = &a; //之后我们遇到一个特殊情况,必须得修改a的值,所以我们临时去除pa的const属性,赋值给pb int *pb = const_cast<int *>(pa); //通过pb修改a的值,完成其特殊使命后,我们应当继续使用pa //注意,这里的a并不是const的,否则我们将无法修改a的数值 //我们只是将pa定义为const,禁止pa修改a的值而已 *pb = 200; pb = nullptr; //测试a的值 cout << a << endl; //非const转const //我们不希望函数的返回值被修改,所以将其转为const的 const int *pe = const_cast<const int *>(getValue()); return 0; }
最后
以上就是清爽大树最近收集整理的关于【C++】【类型转换】C++类型转换的五种方式的全部内容,更多相关【C++】【类型转换】C++类型转换内容请搜索靠谱客的其他文章。
发表评论 取消回复