目录
1.1基本类型间的转换
1.2指针转换的限制
1.3空指针的转换
1.4弃值表达式
1.5左值转到右值
1.6类层次结构基类和派生类间的指针或引用转换
用法:static_cast<type_name> (expression) 说明:该运算符把expression转换为type_name类型static_cast 在编译时使用类型信息执行转换在转换执行必要的检测诸如指针越界计算,类型检查等);但没有运行时类型检查来保证转换的安全性。
1.1基本类型间的转换
enum WeekType{sum=0,mon=1,tues,wed,thurs,fir,sat};
int main()
{
int a=10;
char ch='a';
double dx=12.23;
a=static_cast<int>(ch);//ok
ch=static_cast<char>(a);//ok
a=static_cast<int>(dx);//ok
dx = static_cast<double>(a);//ok
WeekType x=mon;
a=x;//ok
x=a;//error
x=static_cast<WeekType>(a);//ok
return 0;
}
1.2指针转换的限制
对于不同类型的指针不能相互转换,空指针和类的继承层次中的父子类指针是个特例
int main()
{
int a=10;
double dx=12.23;
int* p=&a;
int* s=static_cast<int*>(&a);//ok
s=static_cast<int*>(&dx);//error
const int* cip=&a;
s=static_cast<int*>(cip);//error
char* cp=static_cast<char*>(p);//error,指针类型不同不能转换。
}
1.3空指针的转换
void*可以转换为其他类型
int main()
{
int a=10;
int* ip=nullptr;
double* dp=nullptr;
void* vp=&a;//ok
vp=&ip;//ok
vp=&vp;//ok
ip=vp;//error
dp=vp;//error
ip=static_cast<int*>(vp);//ok
dp=static_cast<double*>(vp);//ok
}
1.4弃值表达式
int main()
{
int a=10,b=20;
static_cast<void>(a+b);//ok,弃值表达式
int c=static_cast<void>(a+b);//error,将a+b的值转换为void类型
}
1.5左值转到右值
int main()
{
int a=10;
int& x=a;//ok
int&& rx=a;//error,a为左值不能被右值引用引用
int&& rx=static_cast<int&&>(a);//ok
int&& ry=std::move(a);//ok
//但是给变量加上常性就会出现问题
const int b=20;
int&& rx=static_cast<int&&>(a);//error
int&& ry=std::move(a);//error
}
对于强转、静态转换、移动函数间对于左值转换为右值过程中的不同在附加中给出。
1.6类层次结构基类和派生类间的指针或引用转换
进行上行转换(把派生类的指针或引用转换为基类)是安全的;
进行下行转换(把基类指针或引用转换为派生类表示)时,由于没有动态类型检查,所以不安全。
class Object
{
int value;
public:
Object(int x=0):value(x){}
void func(){}
virtual void func()
{
cout<<"Object::func"<<endl;
}
};
class Base:public Object
{
int num;
public:
Base(int x=0):Object(x+10),num(x){}
void show()const{}
virtual void func()
{
cout<<"Base::func"<<endl;
}
};
int main()
{
Object* op=nullptr;
Base* bp=nullptr;
Base base;
Object obj;
op=&obj;
bp=&base;
op=static_cast<Object*>(&base);//ok
//下行转换:基类转换为派生类;(是不安全的,没有动态类型检查
bp=static_cast<Base*>(&obj);//编译通过,但本事存在安全问题。因为bp在解引用时是按照8字节取值,而obj对象占四字节,这样会使得num的值为随机值。
}
下行转换的安全问题还有一个
int main()
{
Object* op=nullptr;
Base* bp=nullptr;
Base base;
Object obj;
op=&obj;
bp=&base;
bp=static_cast<Base*>(&obj);
bp->func();//打印Object::func
}
原因就是在下行转换时没有进行安全检查,调用func时依然查的是obj的虚表。
注意: 隐式执行任何类型转换都可由static_cast显示完成。static_cast不能转换掉expression的const、volatile、或者 unaligned属性。