C++知识篇--强制类型转换

static_cast<new_type>(expression)
dynamic_cast<new_type>(expression)
const_cast<new_type>(expression)
reinterpret_cast<new_type>(expression)

一、static_cast

static_cast相当于传统的C语言里的强制转换,该运算符把expression转换为new_type类型,用来强迫隐式转换,但没有运行时类型检查来保证转换的安全性

它主要有如下几种用法:

  • 用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
    • 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的(派生类必定包含基类的成员和方法);
    • 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
  • 用于基本数据类型之间的转换,如把double转换成int,把int转换成enum。这种转换的安全性也要开发人员来保证。
  • 把任何类型的表达式转换成void类型。

static_cast不能转换掉expression的const、volatile。

如果涉及到类的话,static_cast只能在有相互联系的类型中进行相互转换,不一定包含虚函数。

/* 常规的使用方法 */
float f_pi=3.141592f
int   i_pi=static_cast<int>(f_pi); /// i_pi 的值为 3

/* class 的上下行转换 */
class Base{
    // something
};
class Sub:public Base{
    // something
}

//  上行 Sub -> Base
//编译通过,安全
Sub sub;
Base *base_ptr = static_cast<Base*>(&sub);  

//  下行 Base -> Sub
//编译通过,不安全
Base base;
Sub *sub_ptr = static_cast<Sub*>(&base);    

二、dynamic_cast

主要用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换(只能用于类间转换,支持类间交叉转换,不能操作普通数据。)(转换之后可以调用转换之后对象的函数)

(1)在类的转换时,在类层次间进行上行转换时,dynamic_caststatic_cast的效果是一样的。在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

  • 向上转换,即为子类指针指向父类指针(一般不会出问题);向下转换,即将父类指针转化子类指针。
  • 向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败
  • 在C++中,编译期的类型转换有可能会在运行时出现错误,特别是涉及到类对象的指针或引用操作时,更容易产生错误。Dynamic_cast操作符则可以在运行期对可能产生问题的类型转换进行测试。

(2)发生多态时,允许互相转换。
(3)无继承关系的类之间也可以相互转换,类之间的交叉转换。
(4)如果dynamic_cast语句的转换目标是指针类型并且失败了,则结果为null指针。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常
(5)使用 dynamic_cast 进行转换的,基类中一定要有虚函数,否则编译不通过(类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义)。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表。

class base {
public:
    void print1() { cout << "in class base" << endl; }
};

class derived : public base {
public:
    void print2() { cout << "in class derived" << endl; }
};

int main() {
    derived* p, * q;
    // p = new base; //  Compilr Error: 无法从 "base * " 转换为 "derived * "

    // Compile Error: Cannot cast from 'base*' to 'derived*' via dynamic_cast: expression type is not polymorphic(多态的)
    // p = dynamic_cast<derived *>(new base);

    q = static_cast<derived*>(new base); // ok, but not recommended(推荐)

    q->print1(); // in class base
    q->print2(); // in class derived
    
    return 0;
}

#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
    virtual ~Base() {}  //有虚函数,因此是多态基类
};

class Derived : public Base { };

int main()
{
    Base b;
    Derived d;
    Derived* pd;

    pd = reinterpret_cast <Derived*> (&b);  // 此处pd不会为 NULL。reinterpret_cast不检查安全性,总是进行转换
    if (pd == NULL)
        cout << "unsafe reinterpret_cast" << endl; // 不会执行

    pd = dynamic_cast <Derived*> (&b);  // 结果会是NULL,因为 &b 不指向派生类对象,此转换不安全
    if (pd == NULL)
        cout << "unsafe dynamic_cast1" << endl;  // 会执行

    pd = dynamic_cast <Derived*> (&d);  // 安全的转换,此处 pd 不会为 NULL
    if (pd == NULL)
        cout << "unsafe dynamic_cast2" << endl;  // 不会执行

    return 0;
}

三、const_cast

const_cast ,用于修改类型的constvolatile属性,只能对是 引用 或者 指针 的变量添加或移除const。(除了const volatile修饰之外, type_idexpression的类型是一样的。)

const_cast则正是用于强制去掉这种不能被修改的常数特性,但需要特别注意的是const_cast不是用于去除变量的常量性,而是去除 指向常数对象的指针或引用 的常量性,其去除常量性的对象必须为指针或引用。

  • 常量指针被转化成非常量指针,并且仍然指向原来的对象;
  • 常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
const int g = 20;
int *h = const_cast<int*>(&g);//去掉const常量const属性

const int g = 20;
int &h = const_cast<int &>(g);//去掉const引用const属性

 const char *g = "hello";
char *h = const_cast<char *>(g);//去掉const指针const属性

四、reinterpret_cast

reinterpret_cast是强制类型转换符用来处理无关类型转换的,并且其不可移植。他是用在任意的指针之间的转换,引用之间的转换,指针和足够大的int型之间的转换,整数到指针的转换

五、RTTI(Run-Time Type Identification)

通过运行时类型信息程序能够使用 基类的指针或引用 来检查这些指针或引用所指的对象的实际派生类型。(运行时类型识别)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值