1、static_cast
用法:
static_cast<type_id(类型说明符)> (expression(变量或者表达式))
例如:
double d = 3.14159265;
int a = static_cast<int> (d);
该运算符把 (type_id - 变量或者表达式) 转换为 <expression - 类型说明符>类型,但是没有运行时类型检查来保证转换的安全性,主要有如下几种用法:
- 用于类层次结构中基类(父类)和 派生类 (子类)之间指针或引用的转换。但是需要注意的是:
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的- 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。但是这种安全性需要自己注意。
- 把空指针转换成为目标类型的空指针。
- 把任何类型的表达式转换成为void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性。
类层次中不能将两个没有联系的类进行转换
在编译期间强制转换
示例:
class A
{
};
class B :public A
{
};
void Test2()
{
A* ptra = new A;
B* ptrb;
ptrb = static_cast<B*> (ptra);//进行下行转换 将基类指针转换为派生类指针 不安全
ptra = static_cast<A*> (ptrb);//进行上行转换
}
2、const_cast
用法:
const_cast<type_id> (expression)
主要是用来去掉const属性,当然也可以加上const属性。主要是用前者,后者很少用。
例如:
const_case<int*> (&num)
去掉const属性,因为不能把一个const变量直接赋给一个非const变量,必须要转换。
示例:
void Test3(const char* s)
{
ptr[1] = '2';
cout << s << endl;
}
int main()
{
char str1[] = "hello";
Test3(str1);
return 0;
}
这时肯定会报错:
当我们使用 const_cast 去除其const 属性后
void Test3(const char* s)
{
char* ptr = nullptr;
ptr = const_cast<char*> (s);
ptr[1] = '2';
cout << s << endl;
}
int main()
{
char str1[] = "hello";
Test3(str1);
const char* cptr = "hello";
Test2(cptr);//这样是无法进行去除 const 属性的,因为其本身就是const 属性的
return 0;
}
总结 const_cast 的作用:
1、常量指针 被强转为 非常量指针,且仍然指向原来的对象;
2、常量引用 被强转为 非常量引用,且仍然指向原来的对象;
3、常量对象 被强转为 非常量对象。
示例:1、常量指针 被强转为 非常量指针,且仍然指向原来的对象
class A
{
public:
A()
{
m_iNum = 0;
}
public:
int m_iNum;
};
void foo()
{
//1. 指针指向类
const A *pca1 = new A;
A *pa2 = const_cast<A*>(pca1); //常量对象转换为非常量对象
pa2->m_iNum = 200; //fine
//转换后指针指向原来的对象
cout<< pca1->m_iNum <<pa2->m_iNum<<endl; //200 200
//2. 指针指向基本类型
const int ica = 100;
int * ia = const_cast<int *>(&ica);
*ia = 200;
cout<< *ia <<ica<<endl; //200 100
}
2、常量引用转为非常量引用
class A
{
public:
A()
{
m_iNum = 1;
}
public:
int m_iNum;
};
void foo()
{
A a0;
const A &a1 = a0;
A a2 = const_cast<A&>(a1); //常量引用转为非常量引用
a2.m_iNum = 200; //fine
cout<< a0.m_iNum << a1.m_iNum << a2.m_iNum << endl; //1 1 200
}
注意:
const_cast不是用于去除变量的常量性,而是去除指向常数对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用
const_cast是不能用来执行任何类型的转换的(const_cast只能调节类型限定符,不能更改基础类型)
3、reinterpret_cast
用法:
reinterpret_cast<type_id> (expression)
不相关类型的转换(相当于C语言中的强转)
- 改变指针或引用的类型
- 将指针或引用转换为一个足够长度的整形
- 将整型转换为指针或引用类型。
示例:
#include<iostream>
int main()
{
int a = 10;
int* pa = &a;
long b = reinterpret_cast<long>(pa);//把一个指针转换为一个整数,取出地址值
long* pb = reinterpret_cast<long*>(pa);//将 int * 转换为 long *
return 0;
}
4、dynamic_cast
用法:
dynamic_cast<type_id> (expression) type-id必须是类指针,类引用或者void*
用于将一个父类的指针或引用转化为子类的指针或引用(安全的向下转型)
说明:
- 基类指针所指对象是派生类对象,这种转换是安全的;
- 基类指针所指对象为基类对象,转换失败,返回结果为0。
示例:
class Base
{
public:
Base() {};
virtual void show() { cout << "Base\n"; }
};
class Derive :public Base
{
public:
Derive() {};
virtual void show() { cout << "Derive\n"; }
};
int main()
{
Base* base = new Derive;
if (Derive * ptr1 = dynamic_cast<Derive*>(base))
{
cout << "转换成功" << endl;
ptr1->show();
cout << endl;
}
base = new Base;
if (Derive * ptr2 = dynamic_cast<Derive*>(base))
{
cout << "转换成功" << endl;
ptr2->show();
cout << endl;
}
else
{
cout << "转换失败" << endl;
}
delete(base);
return 0;
}
注意:
1.对于类的dynamic_cast转换,基类中一定要有虚函数,否则编译不通过。
2.对指针进行dynamic_cast,失败返回null,成功返回正常cast后的对象指针。
3.对引用进行dynamic_cast,失败抛出一个异常bad_cast,成功返回正常cast后的对象引用。
4.dynamic_cast在运行期强制转换,运行时进行类型检查,较安全。
5.不能用于内置的基本数据类型的强制转换。