5 dynamic_cast
'dynamic_cast'只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里(注:即隐式转换的相反过程),dynamic_cast会检查操作是否有效。也就是说,它会检查转换是否会返回一个被请求的有效的完整对象。检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL.
代码:
class Base { virtual dummy() {} };
class Derived : public Base {};
Base* b1 = new Derived;
Base* b2 = new Base;
Derived* d1 = dynamic_cast<Derived *>(b1); // succeeds
Derived* d2 = dynamic_cast<Derived *>(b2); // fails: returns 'NULL'
如果一个引用类型执行了类型转换并且这个转换是不可能的,一个bad_cast的异常类型被抛出:
代码:
class Base { virtual dummy() {} };
class Derived : public Base { };
Base* b1 = new Derived;
Base* b2 = new Base;
Derived d1 = dynamic_cast<Derived &*>(b1); // succeeds
Derived d2 = dynamic_cast<Derived &*>(b2); // fails: exception thrown
c++类型转换
最新推荐文章于 2022-12-31 08:35:53 发布
C++有四种强制类型转换符,分别是dynamic_cast,const_cast,static_cast,reinterpret_cast。
其中dynamic_cast与运行时类型转换密切相关,在这里我们先介绍dynamic_cast,其他三种在后面介绍。
1、dynamic_cast运算符
该转换符用于
将一个指向派生类的基类指针或引用转换为派生类的指针或引用。
注意:dynamic_cast转换符只能用于含有虚函数的类,其表达式为
dynamic_cast<类型>(表达式)
其中的类型是指把表达式要转换成的目标类型,比如含有虚函数的基类B和从基类B派生出的派生类D,则:
B *pb;
D *pd, md;
pb = &md;
pd = dynamic_cast<D *>(pb);
最后一条语句
表示把指向派生类D的基类指针pb转换为派生类D的指针,然后将这个指针赋给派生类D的指针pd,有人可能会觉得这样做没有意义,既然指针pd要指向派生类为什么不pd = &md;这样做更直接呢?有些时候我们需要强制转换,比如如果指向派生类的基类指针B想访问派生类D中的除虚函数之外的成员时就需要把该指针转换为指向派生类D的指针,以达到访问派生类D中特有的成员的目的,比如派生类D中含有特有的成员函数g(),这时可以这样来访问该成员dynamic_cast<D *>(pb)->g();因为dynamic_cast转换后的结果是一个指向派生类的指针,所以可以这样访问派生类中特有的成员。
但是该语句不影响原来的指针的类型,即基类指针pb仍然是指向基类B的。
如果单独使用该指针仍然不能访问派生类中特有的成员。一般情况下不推见这样使用dynamic_cast转换符,因为dynamic_cast的转换并不会总是成功的,具体情况在后面介绍。
dynamic_cast的注意事项
dynamic_cast转换符只能用于指针或者引用。dynamic_cast转换符只能用于含有虚函数的类。dynamic_cast转换操作符在执行类型转换时首先将检查能否成功转换,如果能成功转换则转换之,如果转换失败,如果是指针则反回一个0值,如果是转换的是引用,则抛出一个bad_cast异常,所以在使用dynamic_cast转换之间应使用if语句对其转换成功与否进行测试,比如
pd = dynamic_cast(pb); if(pd){…}else{…},或者这样测试
if(dynamic_cast(pb)){…}else{…}。
因此,
dynamic_cast操作符一次执行两个操作。首先验证被请求的转换是否有效,只有转换有效,操作符才实际进行转换。基类的指针可以赋值为指向派生类的对象,同样,基类的引用也可以用派生类对象初始化,因此,dynamic_cast操作符执行的验证必须在运行时进行。
2、const_cast操作符
其表达式为
const_cast<类型>(表达式),
其中类型指要把表达式转换为的目标类型。该操作符用于改变const和volatile,
const_cast最常用的用途就是删除const属性,如果某个变量在大多数时候是常量,而在某个时候又是需要修改的,这时就可以使用const_cast操作符了。
const_cast操作符不能改变类型的其他方面,他只能改变const或volatile,即const_cast不能把int改变为double,但可以把const int改变为int。const_cast只能用于指针或引用。
const_cast的用法举例
比如:
int a=3; const int *b=&a; int* c=const_cast(b); *c=4; cout<<a<<*c;这时输出两个4,如果不使用const_cast转换符则常量指针*c的值是不能改变的,在这里使用const_cast操作符,通过指针b就能改变常量指针和变量a的值。
3、static_cast操作符
该操作符用于非多态类型的转换,任何标准转换都可以使用他
,即static_cast可以把int转换为double,
但不能把两个不相关的类对象进行转换,比如类A不能转换为一个不相关的类B类型。
static_cast本质上是传统c语言强制转换的替代品。
static_cast(静态转换)执行非多态的转换,用于代替C中通常的转换操作。因此,被做为隐式类型转换使用。
显式告诉编译器,不关心转换后精度损失。比如:
int i;
float f = 166.7f;
i = static_cast<int>(f);
此时结果,i的值为166。
4、reinterpret_cast操作符
该操作符用于将一种类型转换为另一种不同的类型,比如可以把一个整型转换为一个指针,或把一个指针转换为一个整型,因此使用该操作符的危险性较高,一般不应使用该操作符。
reinterpret_cast(重述转换)主要是将数据从一种类型的转换为另一种类型。
所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。比如:
int i;
char *p = "This is a example.";
i = reinterpret_cast<int>(p);
此时结果,i与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,并赋给i,
一个明显的现象是在转换前后没有数位损失,即一定不改变元数据。