注意:尽量少使用转型操作,尤其是dynamic_cast,耗时较高,会导致性能的下降,尽量使用其他方法替代。
const_cast
定义:const_cast转换符是用来移除变量的const或volatile限定符
const int constant = 21;
const int* const_p = &constant;
int* modifier = const_cast<int*>(const_p);
*modifier = 7;
//传统方式用指针来实现,因为指针之间在类型转换的时候不会检查
//const int constant = 21;
//const int* const_p = &constant;
//int* modifier = (int*)(const_p);
//但是
cout << "constant: "<< constant <<endl;
cout << "const_p: "<< *const_p <<endl;
cout << "modifier: "<< *modifier <<endl;
//结果为
constant: 21
const_p: 7
modifier: 7
说明C++里是const,就是const,外界千变万变,我就不变。不然真的会乱套了,const也没有存在的意义了。
原因:因为我们将数据类型定义为const,自然就不会去改变他,但是,我们可能调用了一个参数不是const的函数,而我们要传进去的实际参数确实const的,但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。
void Printer (int* val,string seperator = "\n")
{
cout << val<< seperator;
}
int main(void)
{
const int consatant = 20;
//Printer(consatant);//Error: invalid conversion from 'int' to 'int*'
Printer(const_cast<int *>(&consatant));
return 0;
}
另一种情况:
int variable = 21;
const int* const_p = &variable;
int* modifier = const_cast<int*>(const_p);
*modifier = 7;
cout << "variable:" << variable << endl;
我们定义了一个非const的变量,但用带const限定的指针去指向它,在某一处我们突然又想修改了,可是我们手上只有指针,这时候我们可以去const来修改了。
static_cast
相当于传统的C语言里的强制转换
- 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的 - 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum
- 把空指针转换成目标类型的空指针
- 把任何类型的表达式转换成void类型
注意:static_cast不能转换掉表达式的const、volatile、或者__unaligned属性
char a = 'a';
int b = static_cast<char>(a);//正确,将char型数据转换成int型数据
double *c = new double;
void *d = static_cast<void*>(c);//正确,将double指针转换成void指针
int e = 10;
const int f = static_cast<const int>(e);//正确,将int型数据转换成const int型数据
const int g = 20;
int *h = static_cast<int*>(&g);//编译错误,static_cast不能转换掉g的const属性
class Base
{};
class Derived : public Base
{}
Base* pB = new Base();
if(Derived* pD = static_cast<Derived*>(pB))
{}//下行转换是不安全的(坚决抵制这种方法)
Derived* pD = new Derived();
if(Base* pB = static_cast<Base*>(pD))
{}//上行转换是安全的
dynamic_cast
只能用于含有虚函数的类,主要用于执行“安全的向下转型”
转换方式:
- dynamic_cast< type* >(e) type必须是一个类类型且必须是一个有效的指针
- dynamic_cast< type& >(e) type必须是一个类类型且必须是一个左值
- dynamic_cast< type&& >(e) type必须是一个类类型且必须是一个右值
e的类型必须符合以下三个条件中的任何一个:
1、e的类型是目标类型type的公有派生类
2、e的类型是目标type的共有基类
3、e的类型就是目标type的类型。
如果一条dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常(该异常定义在typeinfo标准库头文件中)。e也可以是一个空指针,结果是所需类型的空指针。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换(cross cast)。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。dynamic_cast是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。
dynamic_cast与继承层次的指针
向上转型:永远安全,不必要使用
向下转型:
//一种是基类指针所指对象是派生类类型的,这种转换是安全的;
//另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,返回结果为0;
#include<iostream>
using namespace std;
class Base
{
public:
Base(){};
virtual void Show(){cout<<"This is Base calss";}
};
class Derived:public Base
{
public:
Derived(){};
void Show(){cout<<"This is Derived class";}
};
int main()
{
//这是第一种情况
Base* base = new Derived;
if(Derived *der= dynamic_cast<Derived*>(base))
{
cout<<"第一种情况转换成功"<<endl;
der->Show();
cout<<endl;
}
//这是第二种情况
Base * base1 = new Base;
if(Derived *der1 = dynamic_cast<Derived*>(base1))
{
cout<<"第二种情况转换成功"<<endl;
der1->Show();
}
else
{
cout<<"第二种情况转换失败"<<endl;
}
delete(base);
delete(base1);
return 0;
}
dynamic_cast和引用类型
与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常
向上转型:永远安全,不必要使用
向下转型:
int main()
{
//第一种情况,转换成功
Derived b ;
Base &base1= b;
Derived &der1 = dynamic_cast<Derived&>(base1);
cout<<"第一种情况:";
der1.Show();
cout<<endl;
//第二种情况
Base a ;
Base &base = a ;
cout<<"第二种情况:";
try{
Derived & der = dynamic_cast<Derived&>(base);
}
catch(bad_cast)
{
cout<<"转化失败,抛出bad_cast异常"<<endl;
}
system("pause");
}
reinterpret_cast
用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。
注意:严禁随意使用
获取元素类型
#include<typeinfo>
typeid(ss).name()
//typeof()是gnu++11自己添加的