C++基础#22:C++中的静态强制static_cast

简介:

与dynamic_cast对应的是static_cast(静态强制)。static_cast关键字一般用来将枚举类型转换成整型,或者短整形转换成长整形,又或者整型转换成浮点型。也可以用来将指向父类的指针转换成指向子类的指针。

 数据类型转换系列文章:

C++中的动态强制dynamic_cast

C++中的RTTI机制之typeid

C++中的静态强制static_cast

C++中的reinterpret_cast数据类型转换

C++中的const_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为参数的”构造函数。

static_cast在Android系统中的运用:

 在/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。


  • 12
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值