在C语言中,如果要转换类型转换,使用强制类型转换的方法
(T)expression
但是在C++中提供了类型转换符,分别是static_cast,dynamic_cast,reinterpret_cast,const_cast这四个类型转化符,下面一一举例来看
static_cast
用法:static_cast < type-id > ( exdivssion ) 该运算符把exdivssion转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:①用于类层次结构中基类和子类之间指针或引用的转换。 进行上行转换(把子类的指针或引用转换成基类表示)是安全的; 进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。③把空指针转换成目标类型的空指针。④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉exdivssion的const、volitale、或者__unaligned属性。
#include<iostream> using namespace std; class A { public: A(int i):a(i) {} A() {} int a; }; class B:public A { public: int b; }; void main() { //static_cast A* m=new A(10); B* n=static_cast<B*>(m); //向下转换,基类指针转换为子类指针,这里是不安全的 n->a=100; cout<<m->a<<endl; delete m; n=new B; n->b=100; n->a=100; m=static_cast<A*>(n); //向上转换,子类指针转换为父类指针 m->a=1000; cout<<n->a<<endl; cout<<n->b<<endl; delete n; }
运行结果是
100
1000
100
dynamic_cast
用法:dynamic_cast < type-id > ( exdivssion )该运算符把exdivssion转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
#include<iostream> using namespace std; class A { public: A(int i):a(i) {} A() {} virtual void fun(){} int a; }; class B:public A { public: int b; }; void main() { //dynamic_cast A* m=new A(10); B* n=dynamic_cast<B*>(m); //向下转换,基类指针转换为子类指针 n->a=100; cout<<m->a<<endl; delete m; n=new B; n->b=100; n->a=100; m=dynamic_cast<A*>(n); m->a=1000; cout<<n->a<<endl; cout<<n->b<<endl; delete n; }
注意看A类中增加了一个虚函数,否则会编译出错,说A类中没有虚函数表,但是static_cast却不要,这是他们两个的不同之处,
这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。
另外这个程序运行中出错了,异常退出,这是因为在进行下行转换时候,进行了类型检查,这时候由m指针转为n指针时候,n指针为空,所以在访问class A中的a成员变量时候异常了
另外,dynamic_cast可以进行交叉转换,看下面的例子
#include<iostream> using namespace std; class A { public: A(int i):a(i) {} A() {} virtual void fun(){} int a; }; class B:public A { public: int b; }; class C:public A { public: int b; }; void main() { B *n=new B; C *k; k=dynamic_cast<C*>(n); delete n; }
如果使用static_cast就会编译出错,但是dynamic_cast却可以,结果k指针是空指针
reinterpret
reinterpret_cast (exdivssion)type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
该运算符的用法比较多。
看下面的例子
#include<iostream> using namespace std; void main() { int *b=new int[100]; cout<<b<<endl; char *c=new char[11]; strcpy(c,"EcjtuSeany"); cout<<c<<endl; cout<<reinterpret_cast<int>(c)<<endl; delete b; delete c; }
运行结果如下:
const_cast
用法:const_cast (exdivssion)该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和exdivssion的类型是一样的。常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
Voiatile和const类试。
#include<iostream> using namespace std; class A { public: A(int i):a(i) {} A() {} virtual void fun(){} int a; }; class B:public A { public: int b; }; void main() { const A* m=new A(10); A *n=const_cast<A*>(m); n->a=100; cout<<n->a<<endl; delete m; }
结果是100,m指向的对象已经被修改