const_cast
reinterpret_cast
运行时类型识别(RTTI)
dynamic_cast
哪种情况下dynamic_cast和static_cast使用的情况一样?
什么情况下使用dynamic_cast代替虚函数?
typeid
命名的强制类型转换形式如下:
cast_name(expression);
其中:cast_name指static_cast、dynamic_cast、const_cast、reinterpret_cast中的一种;
type指要转换的目标类型;
expression指要转换的值或表达式。
static_cast:任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast。同时,对于编译器无法自动执行的类型转换也非常有用。static_cast不能转换掉expression的const、volitale、或者__unaligned属性。没有运行时类型检查来保证转换的安全性。
它主要有如下几种用法:
①用于类层次结构中基类和子类之间指针或引用的转换。
进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换。如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
如:
【代码1】
double *d;
void* p = &d; //正确,任何"非常量对象"的地址都能存入void*
double* dp = static_cast(p);//正确,将void*转换为初始指针类型
const_cast:只改变运算对象的底层const性质,不改变表达式(运算对象)的类型。可用于增加/去除运算对象的const属性。同时,只能使用const_cast来进行更改const属性,其他任何形式的命名强制类型转换都会引起编译器错误。如:
【代码2】
const char *pc;
char *p = const_cast(pc);//正确:但通过p写值是未定义的行为
char *q = static_cast(pc);//错误:static_cast不能转换const性质
static_cast(pc);//正确:字符串字面值转换为string类型
const_cast(pc); //错误:const_cast只用来改变常量属性
const_cast常常用于函数重载的上下文中。如:
【代码3】
//比较两个string对象的长度,返回较短的那个引用
const string &shorterString(const string &s1, const string &s2){
return s1.size()<=s2.size() s1 : s2;
}
string & shorterString(string &s1, string &s2){
//调用const版本,先将s1和s2转换为const版本,返回的引用 r 为const版本
auto &r = shorterString(const_cast(s1),
const_cast(s2));
return const_cast
(r); //再次使用const_cast消除掉r的const属性,得到一个普通的引用
}
reinterpret_cast:C++ Primer中解释:通常为运算对象的位模式提供较低层次上的重新解释。不懂~~有如下例子:
【代码4】
int *ip;
char *pc = reinterpret_cast(ip);
在代码4中,必须牢记pc实际上指向的是一个int而不是字符,如果把pc当成普通的字符指针使用就可能在运行时发生错误。如:
1
string str(pc); //错误!
谨记:使用reinterpret_cast是非常危险的!要想安全的使用,必须对涉及的类型和编译器实现转换的过程都非常了解。所以,还是尽量不要使用的好!
同时,所有的强制类型转换,能不使用的情况尽量不要使用,因为其干扰了正常的类型检查。
运行时类型识别(RTTI):(由两个运算符实现)
typeid运算符,用来返回表达式的类型;
dynamic_cast运算符,用于将基类的指针或引用安全的转换成派生类的指针或引用。
这两个运算符特别适用于以下情况:使用‘基类对象’的‘指针或引用’执行某个‘派生类操作’并且’该操作‘不是‘虚函数’。
dynamic_cast运算符的使用形式:
//以下形式中:type必须为一个类类型,且通常该类型应该含有虚函数
dynamic_cast(e); //e必须是一个有效的指针;转换失败时结果为0
dynamic_cast(e); //e必须为左值;转换失败时抛出bad_cast异常
dynamic_cast(e); //e不能为左值;转换失败时抛出bad_cast异常
其中,e的类型必须满足以下三个条件中的任一个:
e的类型是目标type的公有派生类;
e的类型是目标type的公有基类;
e的类型是目标type的类型。
如果不满足上述三个中的任一个条件,则转换失败。同时,当使用dynamic_cast对一个空指针执行转换时,结果是所需类型的空指针。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。如:
【代码5】
class A{
public:
A();
~A();
virtual void fun1();
void fun2();
};
class B:public A{
B();
~B();
virtual void fun3();
void fun4();
};
void f1(const A &a){ //引用类型的dynamic_cast
try{
const B &b = dynamic_cast(a);
//使用a引用的B对象
}catch(std::bad_cast){