系统自动进行,不需要程序开发人员介入。
int m = 3 +45.6; //把小数部分截掉,也属于隐式类型转换的一种行为。
doublen = 3 +45.6;
int k = 5 % 3.2; // 语法错
int k = 5 %(int)3.2; // OK,C语言风格的强制类型转换
int k = 5 % int(3.2); // 函数风格的强制类型转换(C语言风格的强制类型转换)
c++强制类型转换分为4中:我们现在写程序应该使用c++风格的强制类型转换。
这4种强制类型转换,分别用于不同的目的,每一个都有一个不同的名字。提供4中类的目的:提供更丰富的含义和功能,更好的类型检查机制,方便代码的熟悉和维护
a)static_cast
b)dynamic_cast
c)const_cast
d)reinterpret_cast
这四个强制类型转换都被称呼为“命名的强制类型转换”
通用形式
强制类型转换名
强制类型转换名是上边a,b,c,d四个名字之一
type:换换的目标类型
express:你要转换的值
static_cast:静态转换,大家就理解成“正常转换”,编译的时候就会进行类型转换的检查
代码中要保证转换的安全性和正确性,static_cast含义跟c语言中的强制类型转换这种差不多
c风格的强制类型转换,以及编译器能够进行的隐式类型转换,都可以用static_cast类显示完成
可用于:
a)相关类型转换,比如整形和实型之间的转换:
double f = 100.34f;
int i = (int)f; // c风格的
int i2 = static(f) // c++风格的类型转换
b)子类转成父类类型(继承关系),也能用这个static_cast转
class A {};
class B : public A {};
B b
A a = static_cast(b); // 把子类转成父类的对象
c)void*与其他类型指针之间的转换,void*:无类型指针:可以指向任意类型指针(万能指针)
int i = 10;
int *p = &i;
void *q = static_cast(p); // int *转成void *,或者 void* q = p;
int *db = static_cast(q); // 需要使用static_cast才可以将void* 转为 int *
不可用于:
a)一般不能用于指针类型之间的转换比如int*转double*,float*转double*等。
d.static_cast总结:
编译器隐式执行的任何类型转换都可以由static_cast完成
当一个较大的算术类型赋值给较小的类型时,可以用static_cast进行强制转换。
可以将void*指针转换为某一类型的指针
可以将基类指针转换为派生类指针
#include
using namespace std;
class Base {
};
class Derived :public Base {
};
int main() {
Base* base = new Derived;
Derived* derive = static_cast(base);
//Derived* derive = dynamic_cast(base); // 错误的,原因:因为Base没有虚函数
}
主要应用运行时类型识别的检查。主要用来父类型和子类型之间转换(父类型指针指向子类型对象,然后用dynamic_cast把父指针类型往子指针类型转)
a)去除指针或者引用的const属性。该转换能够将const性质转换掉。
编译时进行类型检查
const int ai = 90;
int ai2 = const_cast(ai); // ai不是指针也不是引用不能转
const int *pai = &ai;
int *pai2 = const_cast(pai); // 语法正确
*pai2 = 120; // 这种写值行为是属于一种未定义行为。大家不要这么干
cout << ai << endl;
cout << *pai << endl;
// c风格强制类型转换
const int ai = 90;
int *pai = (int*)&ai;
*pai = 120; // 未定义行为
cout << ai << endl;
cout << *pai << endl;
#include
using namespace std;
void func(int& val) {
cout << "func: " << val << endl;
}
//const_cast 用来移除对象的常量性
//const_cast一般用来用于指针或者引用
//const_cast去除常量性,不是为了修改他指定的内容
//const_cast去除常量性,为了函数能接受实参
int main() {
const int val = 100;
//int n = const_cast(val);
//const_cast一般用于指针或者引用
//int* p = &val;
int* p = const_cast(&val);
*p = 200;
cout << val << endl; // val 还是 100, 改变临时对象值
cout << "addr p: " << p << endl;
cout << "addr val: " << &val << endl;
const int val2 = 200;
//int& refval2 = val2;
int& refval2 = const_cast(val2);
refval2 = 300;
cout << "val2: " << val2 << endl; // 改变临时对象值
//func(val2);
func(const_cast(val2));
return 0;
}
b)const_cast总结
用来移除对象的常量性(cast away the constness)
const_cast一般用于指针或者引用
使用const_cast去除const限定的目的不是为了修改它的内容
使用const_cast去除const限定,通常是为了函数能够接受这个实际参数
reinterpret:重新解释。(将操作系统内容解释为另一种不同的类型【能把操作数的类型都转了】)
处理无关类型的转换。也就是两个转换类型之间没有什么关系。就等于可以乱转,自由转。
常用于如下两种转换:
a)将一个整型(地址)转换成指针,一种类型指针转换成另一种类型指针,按照转换后的内容重新解释内存中的内容;
b)也可以从一个指针类型转换成一个整型
int i = 10;
int *pi = &i;
int *p2 = reinterpret_cast(&i);
char *pc = reinterpret_cast(pi); // 任意指针类型之间的转换
int i = 10;
int *pi = &i;
void *pvoid = reinterpret_cast(&i);
int *pi2 = reinterpret_cast(pvoid);
被认为是危险的类型转换,随便转,怎么搞都行,编译器都不报错
int iv1 = 100;
long long lv1 = 8898899400; // 8 字节的 十六进制: 2 126A 6DC8
int*piv1 = (int*)iv1; // c语言风格
int *piv2 = reinterpret_cast(iv1);
piv2 = reinterpret_cast(lv1); // 整型转指针
long long ne = reinterpret_cast(piv2); // 指针转整型
c.reinterpret_cast总结
通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。
三.总结
(1)强制类型转换,不建议使用。强制类型转换能够抑制编译器报错
(2)学习目的:认识这些类型转换符,方便大家阅读别人代码。
(3)资料说:reinterpret_cast危险。使用const_cast意味着设计缺陷。
(4)如果实在需要使用类型转换,不要再使用c语言风格的类型转换了,而用c++风格的类型转换
(5)一般static_cast和reinterpret_cast就能够很好的取代c语言风格的类型转换