C++显性契约与隐性规则:类型转换
关于类型转换通常是隐式转换或者强制转换C提供了一些能够显式表示转换的运算符能够更好的规避一些风险和错误1.传统的类型转换在C语言中如果赋值运算符左右两侧类型不同或者形参与实参类型不匹配或者返回值类型与接收返回值类型不一致时就需要发生类型转化代码语言javascriptAI代码解释void Test() { int i 1; // 隐式类型转换 double d i; printf(%d, %.2f\n, i, d); int* p i; // 显示的强制类型转换 int address (int)p; printf(%x, %d\n, p, address); }转换分为显式和隐式隐式类型转化编译器在编译阶段自动进行能转就转不能转就编译失败显式类型转化需要用户自己处理然而这两种转换的前提是逻辑相近基本类型间的转换如int↔double继承层级中的转换如子类→父类、父类→子类用户定义的转换如operator T()或带参数的构造函数代码语言javascriptAI代码解释string s; vectorint (vectorint) s;这种转换就会失败因为逻辑不相近对于强制转换还有一种特殊易错的场景代码语言javascriptAI代码解释int main() { const int n 10; int* p (int*) n; (*p); string s; vectorint (vectorint) s; cout n endl; cout *p endl; return 0; }无论是有点C语言基础的人甚至是学完C的初学者都很容易认为这里的输出结果是n为11*p为11。但是结果并非所愿输出结果n为10*p为11实际上这里涉及到存储规则的问题因为n是const变量那么会被识别为一个常变量可能会是一个经常被使用的值就把n存入寄存器把频繁使用的变量的值暂存到寄存器中这样在后续对该变量的读取操作中就不需要每次都去内存中读取直接从寄存器中获取即可因为寄存器的读写速度比内存快很多通常cout输出的值都是在内存里读取的相比寄存器内存读写速度较慢但内存容量相对寄存器大很多大多的代码都是存在这里的因此这里输出的n是取自内存器*p取自内存代码语言javascriptAI代码解释volatile const int n 10;volatile关键字表示该变量的值可能会在程序未明确指定的情况下被改变编译器不会对其进行优化即不会被存入寄存器这样取到的n就是内存中及时更新的值C风格的转换格式很简单但是有不少缺点的隐式类型转化有些情况下可能会出问题比如数据精度丢失显式类型转换将所有情况混合在一起代码不够清晰因此C提出了自己的类型转化风格注意因为C要兼容C语言所以C中还可以使用C语言的转化风格2.C强制类型转换2.1 static_cast代码语言javascriptAI代码解释int main() { double d 12.34; int a static_castint(d); cout a endl; return 0; }static_cast需要逻辑上的相近性2.2 reinterpret_cast代码语言javascriptAI代码解释int main() { // 这里使用static_cast会报错应该使用reinterpret_cast //int *p static_castint*(a); int* p reinterpret_castint*(a); return 0; }reinterpret_cast几乎无类型限制不要求类型相近可强制转换任意指针或整数类型但极其危险可能导致违反别名规则如通过char*修改int函数指针转换后调用引发崩溃平台依赖如不同架构的指针大小不同2.3 const_cast代码语言javascriptAI代码解释void Test() { volatile const int a 2; int* p const_castint*(a); *p 3; cout a endl; }仅改变类型的const/volatile属性这里用reinterpret_cast也不行的因为const的转换是有风险的2.4 dynamic_cast代码语言javascriptAI代码解释class A { public: virtual void f() {} }; class B : public A {}; void fun(A* pa) { // dynamic_cast会先检查是否能转换成功能成功则转换不能则返回 B* pb1 static_castB*(pa); B* pb2 dynamic_castB*(pa); cout pb1: pb1 endl; cout pb2: pb2 endl; } int main() { A a; B b; fun(a); fun(b); return 0; }dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)向上转型子类对象指针/引用-父类指针/引用(不需要转换赋值兼容规则)向下转型父类对象指针/引用-子类指针/引用(用dynamic_cast转型是安全的)pa是指向子类对象B的转换可以成功正常返回地址pa是指向父类对象A的转换失败返回空指针值得注意的是必须是继承关系中的类基类必须包含虚函数3.RTTIRTTIRun-time Type identification的简称即运行时类型识别C通过以下方式来支持RTTItypeid运算符dynamic_cast运算符decltype
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2429233.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!