C++中的类型转换细节

我们在C++常用四种类型转换: static_cast<type>, const_cast<type>reinterpret_cast<type>,以及dynamic_cast<type>。其中static_cast<type>转换如果出错, 则发生在编译时, 其他三种类型转换需要谨慎, 使用了他们代表着程序员事先清楚运行时不会出现错误。

static_cast<type>主要用于下面三种情况:
1. void指针转换为目标指针或者相反
2. 改变通常的标准隐式转换
3. 类层次中转换, 子类转向父类或者相反(这类转换后文还会讨论)
const_cast<type>主要是用来去掉对象底层的const属性,从而适配一些重载函数,比如:

const int i = 0;
const int *cpi = &i;
int *pi = const_cast<int *>(cpi);

但值得注意的是,虽然我们通过指针pi获得了变量i的写权限, 但写操作是未定义的。
reinterpret_cast<type>是最危险的操作, 因为这个转换是可以在毫不相干的类型中间转换但编译器是允许的, 比如

char c = 'a'
char *p = &a;
double *pd = reinterpret_cast<double*>(p);

这其实是一种底层的重新解释。
重点说一下dynamic_cast<type>, 这个转换运算符主要用在具有多态行为的类之间, 关注的是对象的动态类型。注意与static_cast<type>的区别, 举例如下:

class Base {
    virtual void f();
};
class Derived : public Base {
    void f();
    void m();
};
void foo(Base *b) {
    Derived *d1 = static_cast<Derived*>(b);
    Derived *d2 = dynamic_cast<Derived*>(b);
}

在上面的例子中如果我们有以下的调用形式:

Base *p = new Derived();
foo(p);

那么上文中的两种转换是没有区别的, 但是如果我们按照下面的形式调用:

Base *p = new Base();
foo(p);

那么当d1调用基类中没有的方法void m()的时候就会有运行时错误, 但是d2就不会有这样的问题出现, 因为dynamic_cast<type>检测p的运行时类型, 因为与等号左边的类型不符, 所以给d2赋值为nullptr,我们只需要检测d2是不是一个空值,就可以避免运行时错误了。
如果Base又派生了一个新类:

class NewDerived : public Base {}
Base *pb = new NewDerived();
Derived *pd1 = static_cast<Derived *>(pb);
Derived *pd2 = dynamic_cast<Derived *>(pb);

由于多了运行时检查,pd2返回nullptr,而pd1知道运行遇到错误才会发现。
除此之外, 我们还可以在程序中用这种方式转换得到不同的派生类指针, 调用不同的成员函数, 实现手动的多态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值