C++中的类型转换(Type Cast)
一、背景
1)场景1
C语言由于某个强制类型转换出错了,我们需要查找所有代码中相应的强制类型转换,那么会很难寻找。比如:
double num=6.3131; int solve=(int)num;
原因:想要查找C语言风格的类型转换我们需要查找(这样的括号,但是函数也有啊
解决:C++中设计了4中类型转换,而且给他们每个后面都有单词cast
以后,我们快速定位类型转换,直接用Ctrl+F去寻找cast就好了
2)场景2
原因:由于C++中用基类和子类的指针,实现了多态。有时候,有些不熟悉多态的编码人员,可能会进行强制类型转换,导致项目崩溃。
解决:C++中针对这些,设计了比如dynamic_cast
类型转换
二、类型转换总览
- C++相较C增加的新特性
1)C++中4种类型转换如下
- static_cast(静态类型转换)
- 静态类型转换,编译的时c++编译器会做类型检查,基本类型能转换但是不能转换指针类型
- reinterpreter_cast(重新解释类型转换,interpreter,v.诠释,说明)
- 若不同类型之间,进行强制类型转换,用reinterpret_cast进行重新解释
- dynamic_cast(动态类型转换)
- C++中重要的,安全的基类和子类之间转换,运行时类型检查
- const_cast(常量类型准换)
- 去除变量的只读属性
2)一般结论
- 1.C语言中能隐式类型转换的,在c++中可用static_cast进行类型转换。因C++编译器在编译检查一般都能通过;
- 2.C语言中不能隐式类型转换的,在c++中可以用reinterpret_cast进行强行类型解释。
- 3.总结:static_cast和reinterpret_cast基本上把C语言中的 强制类型转换给覆盖,但是reinterpret_cast很难保证移植性。
三、static_cast
代码展示
double pi = 3.1415926; int num1 = static_cast<int> (pi);//c++的新式的类型转换运算符 int num2 = (int)pi;//“强制”类型转换 int num3 = pi;//c语言/C++的“隐式”类型转换
- 静态的类型转换: 在编译的时进行基本类型的转换 能替代c风格的类型转换,可以进行一部分检查
四、reinterpret_cast
char *p1 = "hello wangbaoming " ; int *p2 = NULL; p2 = (int *)p1; //static_cast对于基本类型可以转换,但是不能转换指针类型! //编译的时候就会报错:[Error] invalid static_cast from type 'char*' to type 'int*' //可以使用 reinterpret_cast 进行重新解释 p2 = reinterpret_cast<int *> (p1);
五、dynamic_cast
#include<bits/stdc++.h> using namespace std; class Animal { public: virtual void voice() = 0; }; class Dog : public Animal { public: virtual void voice() { cout << "汪汪" << endl; } void doSwim() { cout << "狗游泳" << endl; } }; class Cat : public Animal { public: virtual void voice() { cout << "喵喵 " << endl; } void doTree() { cout << "猫爬树" << endl; } }; //另一个类群体 class Book { private: int price; public: void printP() { cout << price << endl; } }; //对象运行 void ObjPlay(Animal *base) { base->voice(); //猫没有转换成功 Dog *pDog = dynamic_cast<Dog *>(base); if (NULL != pDog) { pDog->voice(); pDog->doSwim(); } Cat *pCat = dynamic_cast<Cat *>(base); if (NULL != pCat) { pCat->voice(); pCat->doTree(); } } int main() { //基类指针base Animal *base = NULL; //1)可以把子类指针赋给 父类指针 但是反过来是不可以的 需要 如下转换 //pdog = base; Dog *pDog = static_cast<Dog *> (base); //2)把base转换成其他 非动物相关的 err //比如下面这一行在编译时会出错! //Book *book= static_cast<Book *> (base); //3 reinterpret_cast //可以强制类型转换 Book *book2= reinterpret_cast<Book *> (base); //4 dynamic_cast用法 ObjPlay(new Cat()); system("pause"); return 0; }
运行结果是
喵喵 喵喵 猫爬树
六、const_cast
#include<bits/stdc++.h> using namespace std; //典型用法,把形参的只读属性去掉 void Opbuf(const char *p) { cout << p << endl; //把形参的只读属性去掉 char *p2 = const_cast<char*>(p); p2[0] = 'A'; cout << p << endl; } int main() { const char *p1 = "11111111111"; char *p2 = "333333333"; //下面就是用法,虽然会显示 //[Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings] char *p3 = const_cast<char *>(p1); //下面 "000000000000"会自动拆解,放入buf数组中 char buf[100] = "000000000000"; Opbuf(buf); //要保证指针所执行的内存空间能修改才行 若不能修改 还是会引起程序异常!!! //比如下面,因为下面的 "dddddddddddsssssssssssssss"存在常量区 //注意和 char buf[100] = "000000000000";区别 // Opbuf("dddddddddddsssssssssssssss"); system("pause"); return 0; }
000000000000 A00000000000
七、总结
- 1)编码人员要清楚的知道: 要转的变量,类型转换前是什么类型,类型转换后是什么类型。转换后有什么后果。
- 2)一般情况下,不建议进行类型转换;避免进行类型转换。
- 比如上面的“把形参的只读属性去掉”,我在C语言编程的时候,本来就是怕别人写的模块修改我传入的参数才用的const,但是这种类型转换会破坏我设计的初衷!