深入理解C++中的类型转换

前言

深入理解C语言中的类型转换一文中对C语言中出现的隐式转换和显示转换进行了总结,在那篇文章中所提到的所有类型转换都适用于C++语言,本文将特别关注C++语言中的类型转换,主要概括出C++不同于C语言的知识点。

隐式转换

C语言中的隐式转换

主要参考前言中提到的那篇文章,在此不再重复叙述。

类类型转换

作为一门面向对象的编程语言,C++在C语言基础上从程序语言层次上支持了类及其一系列相关特性,例如继承、虚函数、多态等。每个类都有构造函数,当构造函数只接受一个参数时,通常将其称为转换构造函数,此外,也可以用类型转换操作符将类类型转换为其他类型。

#include <iostream>
using namespace std;

class SmallInt {
public:
    // 转换构造函数,int转为SmallInt
    SmallInt(int i) : val(i) {}
    // 类型转换操作符,SmallInt转为int
    operator int() const {return val;}

private:
    int val;
};

int main()
{
    // 隐式转换,从int到SmallInt
    SmallInt si = 1;
    // 隐式转换,从SmallInt到int
    int i = si;
    cout << i << endl;
    return 0;
}

派生类到基类的转换

可以讲基类的指针或者引用绑定到派生类的对象上,这是有编译器自动完成的转换,所以称为隐式转换。

class A {

};

class B : public A {

};

int main()
{
    A* a = new B();
    return 0;
}

显示转换

在C++中,对于显示转换不再使用像C语言那样的简单粗暴的转换方式,而是提供了四个cast,分别是static_cast,dynamic_cast,const_cast和reinterpret_cast。

static_cast

static_cast主要解决以下几种情况中编译器无法隐式完成的转换。

  • void* 指针转为其他指针;
  • 对于任意两种内置类型间的转换,编译器本身可以自动完成,但是会发出告警,static_cast会清除这些告警。
  • 对于基类向派生类指针的转换来说,当基类中无virtual函数时,用static_cast是可以的;如果有virtual函数时,可以让编译通过,但是由于static_cast缺少运行时检查,会不安全。
class A {

};

class B : public A {

};

class C {
protected:
    virtual void test () {}
};

class D : public C{
    void test() {}
};

int main()
{
    int i = 1;
    double d = 2.0;
    // 成功
    d += static_cast<int>(i);
    
    // 隐式转换
    void* pv = &i;
    // 成功
    int* pi = static_cast<int*>(pv);

    // 失败
    double* pd = static_cast<double*>(pi);

    const char* file = "abc.txt";
    // 失败
    char* myfile = static_cast<char*>(file);
    
    A* a = new B();
    // 成功
    B* b = static_cast<B*>(a);
    
    C* c = new D();
    // 编译通过,但是运行时不安全
    D* dc = static_cast<D*>(c);
    return 0;
}

dynamic_cast

dynamic_cast用于解决含有多态类型(virtual函数)的基类向派生类的转换。

class A {

};

class B : public A {

};

class C {
protected:
    virtual void test () {}
};

class D : public C{
    void test() {}
};

int main()
{
    int i = 1;
    double d = 2.0;
    // 错误
    d += dynamic_cast<int>(i);
    
    // 隐式转换
    void* pv = &i;
    // 错误
    int* pi = dynamic_cast<int*>(pv);

    // 错误
    double* pd = dynamic_cast<double*>(pi);

    const char* file = "abc.txt";
    // 错误
    char* myfile = dynamic_cast<char*>(file);
    
    A* a = new B();
    // 错误, dynamic_cast的操作数必须包含多态类型
    B* b = dynamic_cast<B*>(a);

    C* c = new D();
    // 正确
    D* dc = dynamic_cast<D*>(c);
    return 0;
}

const_cast

const_cast用来解决const指针向非const类型的转换。

class A {

};

class B : public A {

};

class C {
protected:
    virtual void test () {}
};

class D : public C{
    void test() {}
};

int main()
{
    int i = 1;
    double d = 2.0;
    // 错误
    d += const_cast<int>(i);
    
    // 隐式转换
    void* pv = &i;
    // 错误
    int* pi = const_cast<int*>(pv);

    // 错误
    double* pd = const_cast<double*>(pi);

    const char* file = "abc.txt";
    // 正确
    char* myfile = const_cast<char*>(file);
    
    A* a = new B();
    // 错误
    B* b = const_cast<B*>(a);

    C* c = new D();
    // 错误
    D* dc = const_cast<D*>(c);
    return 0;
}

reinterpret_cast

除了const无法转换外,reinterpret_cast可以用来完成其他任意类型的转换,但是其非常不安全,类似于C语言中的显示转换方式。

class A {

};

class B : public A {

};

class C {
protected:
    virtual void test () {}
};

class D : public C{
    void test() {}
};

int main()
{
    int i = 1;
    double d = 2.0;
    // 正确
    d += reinterpret_cast<int>(i);
    
    // 隐式转换
    void* pv = &i;
    // 正确
    int* pi = reinterpret_cast<int*>(pv);

    // 正确
    double* pd = reinterpret_cast<double*>(pi);

    const char* file = "abc.txt";
    // 错误
    // char* myfile = reinterpret_cast<char*>(file);
    
    A* a = new B();
    // 正确
    B* b = reinterpret_cast<B*>(a);

    C* c = new D();
    // 正确
    D* dc = reinterpret_cast<D*>(c);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值