与dynamic_cast对应的是static_cast(静态强制)。static_cast关键字一般用来将枚举类型转换成整型,或者短整形转换成长整形,又或者整型转换成浮点型。也可以用来将指向父类的指针转换成指向子类的指针。
数据类型转换系列文章:
static_cast可以用于类层次结构中基类和子类之间指针或引用的转换。static_cast仅仅是依靠类型转换语句中提供的信息(尖括号中的类型)来进行转换。
static_cast使用注意事项:
1)static_cast可以用于基本类型的转换,如short与int、int与float、enum与int之间;
2)static_cast也可以用于类类型的转换,但目标类型必须含有相应的构造函数;
3)static_cast还可以转换对象的指针类型,但它不进行运行时类型检查,所以是不安全的;
4)static_cast甚至可以把任何表达式都转换成void类型;
5)satic_cast不能移除变量的const属性,请参考const_cast操作符;
6)static_cast进行的是简单粗暴的转换(仅仅依靠尖括号中的类型),所以其正确性完全由程序员自己保证。
7)static_cast是在编译时进行的,这与dynamic_cast正好相反。
static_cast的使用形式:
static_cast< T >(exp)
dynamic_cast< T >(exp)
其中,T为目标数据类型,exp为原始数据类型变量或者表达式。
代码举例1: 普通类型使用static_cast转换:
#include <iostream>
//#include <typeinfo>
using namespace std;
void test() {
char ch = 'a';
short sh = 10;
int i1 = static_cast<char>(ch);//成功,将char型数据转换成int型数据
int i2 = static_cast<short>(sh);
cout<<i1<<endl; //97
cout<<i2<<endl; //10
double *d = new double;
void *v = static_cast<void*>(d);//成功,将double指针转换成void指针
cout<<v<<endl; //0x7f7f9ec05960
int i = 20;
const int iConst = static_cast<const int>(i);//成功,将int型数据转换成const int型数据
cout<<iConst<<endl; //20
const int jConst = 30;
//int *p = static_cast<int*>(&jConst);//error: static_cast from 'const int *' to 'int *' is not allowed
}
int main()
{
test();
return 0;
}
/*
编译环境:mac os下用g++编译.
*/
分析:
const int jConst = 30;
//int *p = static_cast<int*>(&jConst);
发生编译错误:error: static_cast from 'const int *' to 'int *' is not allowed。
根据提示也很明显,原因是static_cast不能将“const int *”转换成“int *”,即违反了static_cast使用注意事项的第5条:satic_cast不能移除变量的const属性。
代码举例2: 普通类型使用static_cast转换:
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
int a;
void fun1() {cout<<"Base::fun1"<<endl;}
void fun2() {cout<<"Base::fun2"<<endl;}
};
class Derive : public Base{
public:
int b;
void fun2() {cout<<"Derive::fun2"<<endl;}
void fun4() {cout<<"Derive::fun4"<<endl;}
};
void test() {
Base b;
Derive d;
Base *pB = static_cast<Base*>(&d); //派生类指针->父类指针
Derive *pD = static_cast<Derive*>(&b); //父类指针->派生类指针
pB->fun1(); // 调用父类的fun1
pB->fun2(); // 调用父类的fun2
//pB->fun4(); // 编译错误:error: no member named 'fun4' in 'Base'。 因为fun4是派生类的成员函数,只能通过派生类对象进行访问。
pD->fun1(); //调用父类的fun1
pD->fun2(); //调用派生类类的fun2
pD->fun4(); //调用派生类类的fun4,fun4是派生类的成员函数,而不是父类的成员函数。
}
int main()
{
test();
return 0;
}
/*
编译环境:mac os下用g++编译:
*/
可见,使用static_cast能够进行派生类和父类的相互转换。
再看一个例子:互不相关的类之间使用static_cast进行转换
#include <iostream>
#include <typeinfo>
using namespace std;
class A {
public:
int a;
void fun1() {cout<<"A::fun1"<<endl;}
};
class B{
public:
int b;
B(A& a) {cout<<"B::constructor"<<endl;}
void fun2() {cout<<"B::fun2"<<endl;}
};
void test() {
A a;
B b = static_cast<B>(a); //A->B
//b.fun1(); //编译错误,error: no member named 'fun1' in 'B'; did you mean 'fun2'?。 因为对于b,没有fun1成员函数。
b.fun2(); //B::fun2
}
int main()
{
test();
return 0;
}
/*
编译环境:mac os下用g++编译:
*/
运行结果:
B::constructor
B::fun2
但是,如果在B中,没有定义 B(A& a)的话,就会发生编译错误:
error: no matching conversion for static_cast from 'A' to 'B'
note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument
可见,如果A和B没有继承关系的两个互不相关的类,想要由A转换为B,则在B中必须定义“以A为参数的”构造函数。
在/frameworks/base/core/jni/android_util_Binder.cpp, 部分代码如下:
static void conditionally_log_binder_call(int64_t start_millis,
IBinder* target, jint code) {
int duration_ms = static_cast<int>(uptimeMillis() - start_millis);
......
}
分析:
很明显,这里要实现一个时间差的计算,而且要求返回值是int类型。而uptimeMillis()函数返回类型是int64_t,"uptimeMillis() - start_millis"的结果也是int64_t。
所以,需要将这个计算结果强制转换为int。这就用到了static_cast。