C++中的类型转换

C++中的类型转换

隐式转换

在这里插入图片描述

  • 当一个值拷贝给另一个兼容类型的时候,隐式转换会自动进行,有编译器操作。
  • C++面向对象的多态特性,本质就是通过父类指针实现对子类指针的封装,这其中也发生了隐式转换。除此之外,各种数值类型的转换等等,都给开发带来了不小便利。
  • 隐式转换的原则:低精度 -> 高精度,子类 -> 父类
  • 发生的条件:
    • 混合类型的运算中
    • 不同类型的赋值操作
    • 参数传递
    • 返回值传递
  • 隐式转换的风险一般在于自定义的类构造函数中,如果类的构造函数只有一个参数,编译器会默认规定这也是一个隐式的类型转换,可能会把参数类型的数据隐式转换成这个类类型。
class Test{
public:
    Test(int i) : x(i) {}
    int x;
};

int main () {
    Test t(10);
    t = 20;//编译通过,20隐式转换为了Test(20)
}
  • 另外可以用 operator Typename () const {return (Typename) xx}将该类类型隐式转换成Typename类型
  • 在一个参数的构造函数前加上explicit可以禁止隐式转换

显示转换

在这里插入图片描述

  • 类C型的显示转换,即在前面加上(Typename),虽然也能满足需求,但是有风险,因为如果在指针上使用这种强制转换成其他类型的指针,编译器不会报错,但是运行的时候可能会出错。比如有两个指针分别指向A、B两个类,我把B的指针强制转换为A类型并赋给A的指针,如果我们用这个指针调用A的函数,此时编译不会报错,但是运行的时候就会崩溃
static_cast

首先是静态转化,static_cast,也是我们经常使用的类型转化,叫做静态转化的原因是它在编译时检查类型,也就是我们在写代码的时候就已经会检测类型转化是否正确了。

  • 运用场景第一就是各种数值类型的转化,比如float转化成int,或者字符转化成int之类的,类似于C的隐式转化;
  • 第二个就是空指针和实际类型的转化,把void指针转化成实际类型,或者反过来。
  • 第三个使用场景就是类的层次之间的转化,比如子类指针转化成父类指针,或者父类到子类的转化,但是下行转化是不安全的,因为它只会检查这两个类型是不是父子类,而不会检查这个指针指向的对象是不是对的,比如我们把一个指向父类的指针,转化成子类指针,调用子类的函数,编译不会报错,但是它实际并不是子类,调用子类函数在运行时就会报错了。
dynamic_cast
  • 所以也就引入了第二个类型转化,dynamic_cast,动态转化,应用场景也就是把父类指针转化为子类指针。在C++中为了实现动态多态,我们会使用一个父类指针实际指向一个子类对象,但有时候我们需要调用到子类特有的函数或者字段,这是无法通过父类指针做到了,我们就需要用动态转化把父类指针转化成子类指针,并且动态转化会在运行时检查类型,如果实际对象确实是子类,就返回子类指针,否则返回一个空指针。至于如何实现动态检查的,实际上是通过虚函数表来实现的,当父子类中存在虚函数的时候,就会有一个虚函数表,动态转化在运行时通过虚函数指针查找到虚函数表,进而确定实际对象是不是子类,这其实也是虚函数多态的实现方式。
  • dynamic_cast只能用于指向类的指针和引用或者void*,目的是确保类型转换的结果指向目标指针类型的有效完整对象
  • dynamic_cast可以将父类指针转换为子类的指针,如果此时父类指针确实指向的是一个子类对象,则转换成功,否则转换失败,指向null。但是要求父类必须要有虚函数,因为dynamic_cast是使用了RTTI信息在运行时推导父类指针实际的对象
class Test {
public:
    virtual void test (){
        cout << "ss" << endl;
    }
};
class Test2 : public Test{

};

class Test3{
public:
    virtual void test() {
        cout << "ss" << endl;
    }
};

int main() {
    Test* t1 = new Test2; 
    Test* t2 = new Test;
    Test3* t3 = new Test3;

    Test2* tt;
    tt = dynamic_cast<Test2*>(t1);
    cout << tt << endl;
    tt = dynamic_cast<Test2*>(t2);
    cout << tt << endl;
    tt = dynamic_cast<Test2*>(t3);
    cout << tt << endl;
}

//结果为
//00C6F820
//00000000
//00000000
//只有第一个转换成功
const_cast
  • const_cast: 把const属性去掉,即将const转换为非const(也可以反过来),const_cast只能用于指针或引用.
reinterpret_cast
  • 最后一个,也是最少使用的一个转化,reinterpret_cast,直接翻译过来应该是重新解释,或者重译,说明白点其实就是强制转化,把一个类型的对象重新翻译成新类型,跟C的强制转化一样,可以转化任意类型的对象,所以在使用上需要小心。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值