5.C++里的4种新型类型转换
2018-06-17 21:13:12来源:未知 阅读 ()
1首先来回顾C的强制转换
大家都知道,在编译C语言中的强制转换时,编译器不会检查转换是否成功,都会编译正确.
比如:
#include "stdio.h" struct Position { int x; int y; }; int main() { int i; struct Position *p; i=0x123456; p=(struct Position *)i; printf("px=%d,py=%d\n",p->x,p->y); }
输出结果如下图所示:
从上图可以看到,只有当运行代码时,才会出现段错误问题.
当C代码上千行时,若出现这种问题,是非常难找的.
2.C++的新型类型转换
所以在C++中,便引入了4种强制类型转换
2.1 static_cast(静态类型转换)
- 用于基本数据类型以及对象之间的转换(char,int,const int等)
- 不能用于基本数据类型指针之间的转换(char *,int *等)
- 用于有继承关系类对象指针之间的转换
- 用于类指针之间的转换
示例-基本数据:
int i = 0x45; char c = 'c'; c = static_cast<char>(i); //char* pc = static_cast<char*>(&i); //此行错误,不能用于基本指针之间转换
示例-基本数据与对象转换:
class Test{ public: explicit Test(int i) //只能显示调用 { cout<<i<<endl; } }; int main() { Test t = static_cast<Test>(3); //等价于 : Test t(3); }
示例-有继承关系的类对象指针转换:
class Parent { public: int mm; Parent(int i) { mm=i; cout<<"Parent:"<<i<<endl; } }; class Child : public Parent { public: int mval; Child(int i):Parent(i) { mval=i; cout<<"Child:"<<i<<endl; } }; int main() { Parent *p =new Parent(3); //会调用父类构造函数 Child *c = static_cast <Child *> (p) ; //并不会调用子类构造函数 c->mval=100; cout<<"mval:"<<c->mval<<endl; }
运行打印:
Parent:3 mval:100
2.2 const_cast(去常类型转换)
- 用于去除变量的只读属性
- 且强制转换的类型必须是指针*或引用&
示例:
const int x =1; //const:定义一个常量x const int& j =2; //const引用:定义一个只读变量j int& p1= const_cast<int&>(x); //强制转换int & int *p2 = const_cast<int*>(&j); //强制转换int* //int p3 = const_cast<int>(j); //此行错误,不能转换普通数据型 p1=3; *p2=4; printf("x=%d, j=%d\n",x,j); printf("p1=%d *p2=%d\n",p1,*p2);
输出结果:
x=1 j=4 p1=3 *p2=4
从输出结果,可以看出修改p1,p2,只有j内容变换了,是因为变量j用const引用定义的,所以是个只读变量.
2.3 dynamic_cast(动态类型转换)
- 用于有继承关系的类指针(引用)间的转换
- 用于有交叉关系的类指针(引用)间的转换
- 具有类型检查的功能,编译时会去检查使用的方法是否正确,转换是否成功只有在程序运行时才能知道
- 类中必须有虚函数的支持
- 不能用于基本数据类型指针之间的转换(char *,int *等)
-当转换为指针时:
- 转换成功 : 得到目标类型的指针
- 转换失败 : 得到一个空指针
-当转换为引用时:
- 转换成功 : 得到目标类型的引用
- 转换失败 : 得到一个异常操作信息
示例-通过子类指针去指向父类:
#include <iostream> using namespace std; class Base { public: Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } }; class Derived : public Base { }; int main() { Base* p = new Base; //初始化父类指针 Derived* pd = dynamic_cast<Derived*>(p); //由于父类指针指向的是父类,没有子类虚函数表,所以转换失败 cout << "pd = " << pd << endl; //转换失败,打印 0
delete p; p = new Derived; pd = dynamic_cast<Derived*>(p); //由于父类指针指向的是子类,所以有子类虚函数表 cout <<"pd = " << pd <<endl; //转换成功,打印地址值 delete p; return 0; }
示例-通过多重继承下的类指针转换:
class BaseA { public: virtual void funcA() { cout<<"BaseA: funcA()"<<endl; } };
class BaseB { public: virtual void funcB() { cout<<"BaseB: funcB()"<<endl; } };
class Derived : public BaseA,public BaseB { };
int main() { Derived d; BaseA *pa=&d; pa->funcA(); //打印 BaseA: funcA() /*通过强制转换执行*/ BaseB *pb=(BaseB *)pa; pb->funcB(); //还是打印 BaseA: funcA(), 因为pb还是指向pa,执行的还是pa的虚函数表 /*通过dynamic_cast执行*/ pb = dynamic_cast<BaseB *>(pa); pb->funcB(); //打印 BaseB: funcB() //编译器会去检测pa所在的地址,发现有多个虚函数表,然后根据 <BaseB *>来修正指针pb return 0; }
2.4 reinterpret_ cast(解读类型转换)
- 用于所有指针的强制转换
(解读是指:对要转换的数据进行重新的解读)
例如:
int i = 0; char j='c'; int *p1=reinterpret_cast<int *>(&i); char *p2=reinterpret_cast<char *>(&j); //int p3=reinterpret_cast<int >i; //此行错误,不能转换普通数据型
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- C++ 实现Golang里的defer 2018-11-20
- 25.C++- 泛型编程之函数模板(详解) 2018-06-27
- 获取json串里的某个属性值 2018-06-27
- 全局变量、局部变量、静态全局变量、静态局部变量在内存里的 2018-06-18
- 链表补充及链表和数组的区别 2018-06-18
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash