官方查企业的网站,wordpress置顶文章 调用,辅助教学网站开发技术讨论,南皮县网站建设价格一、C语言中的类型转换
在C语言中#xff0c;如果赋值运算符左右两侧类型不同#xff0c;或者形参与实参类型不匹配#xff0c;或者返回值类型与 接收返回值类型不一致时#xff0c;就需要发生类型转化。
C语言中总共有两种形式的类型转换#xff1a;隐式类型转换和显式…一、C语言中的类型转换
在C语言中如果赋值运算符左右两侧类型不同或者形参与实参类型不匹配或者返回值类型与 接收返回值类型不一致时就需要发生类型转化。
C语言中总共有两种形式的类型转换隐式类型转换和显式类型转换。 1. 隐式类型转化编译器在编译阶段自动进行能转就转不能转就编译失败 2. 显式类型转化需要用户自己处理
class A
{
public://explicit A(int a)A(int a):_a(a){}
private:int _a;
};class B
{
public:B(const A a){}
private://...
};int main()
{int i 1;// 隐式类型转换double d i;printf(%d, %.2f\n, i, d);//单参数的构造函数支持隐式类型转换(加上explicit就不支持了)A aa1 1;B bb1 aa1;//自定义类型转换构造一个临时对象然后进行拷贝构造编译器优化成直接构造int* p i;// 显示的强制类型转换int address (int)p;printf(%p, %d\n, p, address);return 0;
}
缺陷 转换的可视性比较差所有的转换形式都是以一种相同形式书写难以跟踪错误的转换
二、 为什么C需要四种类型转换
C风格的转换格式很简单但是有不少缺点的 1. 隐式类型转化有些情况下可能会出问题比如数据精度丢失 2. 显式类型转换将所有情况混合在一起代码不够清晰
下面来看一下c风格转换失败的例子 1. 不是相近类型的形式不能进行显示转换
void test()
{vectorint v;string s;v (vectorint)s;
}
编译报错 2. 隐式类型转换的坑 while循环中用end和pos作为判断条件然而pos是size_t类型当pos为0时end小于pos后为负数end与pos比较时又会转换为size_t类型进行比较所以end会一直大于pos造成死循环。
3. 对const变量进行转换
int main()
{const int n 10;//n 11;// 转换有安全隐患的int* p (int*)n;(*p);cout n endl;cout *p endl;cout p endl;return 0;
}
运行结果 我们发现p指向的确实是n的地址但是p对n进行修改后打印出来的还是10而p解引用的值是11。
我们再来监视窗口查看 我们发现监视窗口中n的值是11那为什么打印出来的是10呢。
这是因为编译器认为对const变量进行类型转换是有安全隐患的所以编译器将const变量的开始的值存到寄存器中打印的时候直接在寄存器中去取或者直接用类似typedef进行常量替换所以打印出来的是10而监视串口查看的是内存中的值这是确实发生了修改的。
那我们有什么办法将内存中的值打印出来呢
答案是用volatile关键字。
int main()
{// volatile 修饰的变量每次都要去内存取volatile const int n 10;//n 11;// 转换有安全隐患的int* p (int*)n;(*p);cout n endl;cout *p endl;cout p endl;cout p endl;return 0;
}
运行结果 volatile 修饰的变量每次都要去内存取所以我们可以看到这次运行的结果都是11了。
因此C提出了自己的类型转化风格注意因为C要兼容C语言所以C中还可以使用C语言的 转化风格。
三、 C强制类型转换
标准C为了加强类型转换的可视性引入了四种命名的强制类型转换操作符 static_cast、reinterpret_cast、const_cast、dynamic_cast
3.1 static_cast
static_cast用于非多态类型的转换静态转换编译器隐式执行的任何类型转换都可用 static_cast但它不能用于两个不相关的类型进行转换
int main()
{// 相关类型/相近类型double d 12.34;int a static_castint(d);cout a endl;
}
3.2 reinterpret_cast
reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释用于将一种类型转换 为另一种不同的类型
int main()
{double d 12.34;int a static_castint(d);cout a endl;// 这里使用static_cast会报错应该使用reinterpret_cast//int *p static_castint*(a);int* p reinterpret_castint*(a);return 0;
}
3.3 const_cast
const_cast最常用的用途就是删除变量的const属性方便赋值
注意这里要加上volatile 关键字才能输出修改后的数字
int main()
{// 去掉const属性volatile const int n 10;int* p2 const_castint*(n);*p2 3;cout n endl;
}
3.4 dynamic_cast
dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换) 向上转型子类对象指针/引用-父类指针/引用(不需要转换赋值兼容规则) 向下转型父类对象指针/引用-子类指针/引用(用dynamic_cast转型是安全的) 注意
dynamic_cast只能用于父类含有虚函数的类(虚函数的类有虚表可以认为编译器在虚表中做了一个记号通过这个记号判断是父类对象指针/引用是指向父类还是指向子类)dynamic_cast会先检查是否能转换成功能成功则转换不能则返回0
class A
{
public:virtual void f() {}int _x 0;
};class B : public A
{
public:int _y 0;
};void fun(A* pa)
{// pa是指向子类对象B的转换可以成功正常返回地址// pa是指向父类对象A的转换失败返回空指针B* pb dynamic_castB*(pa);if (pb){cout 转换成功 endl;pb-_x;pb-_y;}else{cout 转换失败 endl;}
}int main()
{A aa;fun(aa);B bb;fun(bb);return 0;
}
运行结果 可以看到aa是指向父类对象A的转换失败返回空指针bb是指向子类对象B的转换可以成功正常返回地址。
注意 强制类型转换关闭或挂起了正常的类型检查每次使用强制类型转换前程序员应该仔细考虑是 否还有其他不同的方法达到同一目的如果非强制类型转换不可则应限制强制转换值的作用 域以减少发生错误的机会。强烈建议避免使用强制类型转换
四、RTTI了解
RTTIRun-time Type identification的简称即运行时类型识别。 C通过以下方式来支持RTTI 1. typeid运算符 2. dynamic_cast运算符 3. decltype