C++强制类型转换

C++提供了四种类型转换方法,分别为

  • static_cast<类型说明符>(表达式)
  • dynamic_cast<类型说明符>(表达式)
  • const_cast<类型说明符>(表达式)
  • reinterpret_cast<类型说明符>(表达式)

按照适用范围从窄到宽的顺序介绍,先从使用频率比较低的reinterpret_cast开始,然后依次是const_cast,dynamic_cast,最后介绍static_cast。

reinterpret_cast

interpret是“解释,诠释”的意思,加上前缀“re”,就是“重新诠释”的意思;
cast在这里可以翻译成“转型”,这样整个词顺下来就是“重新诠释的转型”。

#include 
using namespace std;
int main(int argc, char** argv) {
        int num = 0x00636261;//用16进制表示32位int,0x61是字符'a'的ASCII码
        int * pnum = & num;
        char * pstr = reinterpret_cast(pnum);
        cout<<"pnum指针的值: "<(pstr)<

reinterpret_cast 运算符并不会改变括号中运算对象的值,而是对该对象从位模式上进行重新解释

滥用 reinterpret_cast 操作很容易就会不安全。 除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。

const_cast

用法

const_cast是一种C++运算符,主要是用来去除复合类型中const和volatile属性.

//对于const变量,若想修改其值,下面的方法虽然能够通过编译,但是想修改值明显是做不到的。
const int constant = 10;
int modifier = constant;

//而下面的方法,虽然可以修改值,但是显然编译器是不会通过编译的。
const int constant = 21;
int* modifier = &constant// Error: invalid conversion from 'const int*' to 'int*'

//因此const_cast派上用场了
const int constant = 21;
const int* const_p = &constant;
nt* modifier = const_cast(const_p);
*modifier = 7;

注意点

  • 虽然对modifier进行了重新赋值,但是constant并没有被修改。
  • 对于const数据我们更要这样保证:绝对不对const数据进行重新赋值。

使用场景

  • const对象想调用自身的非const方法的时候,因为在类定义中,const也可以作为函数重载的一个标示符。

dynamic_cast

C++强制类型转换操作符dynamic_cast

dynamic_cast是四个强制类型转换操作符中最特殊的一个,它支持运行时识别指针或引用。
首先,dynamic_cast依赖于RTTI信息(它对编译器有要求,需要编译器启动“运行时类型信息”这一选项),其次,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,这种检查不是语法上的,而是真实情况的检查。

dynamic_cast主要用于“安全地向下转型”

dynamic_cast用于类继承层次间的指针或引用转换。主要还是用于执行“安全的向下转型(safe downcasting)”,
也即是基类对象的指针或引用转换为同一继承层次的其他指针或引用。
至于“先上转型”(即派生类指针或引用类型转换为其基类类型),本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是需要开销的。

dynamic_cast转换指针

对于“向下转型”有两种情况。

  • 一种是基类指针所指对象是派生类类型的,这种转换是安全的;
  • 另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,返回结果为0;
#include 
#include 

class Base {
public:
    virtual void show() {
        std::cout << "here is Base class" << std::endl;
    }
};

class Derive : public Base {
public:
    virtual void show() {
        std::cout << "here is Derived class" << std::endl;
    }
    void show1() {
        std::cout << "unique show1 function" << std::endl;
    }
};

int main(int argc, char ** argv) {
    Base *b1 = new Base();
    Base *b2 = new Derive();
    Derive *d1 = dynamic_cast(b2);     //第一种情况,成功
    Derive *d2 = dynamic_cast(b1);     //第二种情况,失败

    b1->show();
    b2->show();
    d1->show1();
}

dynamic_cast转换引用

  • 与指针一样,引用的向上转换总是安全的。
  • 与指针一样,引用的向下转型也可以分为两种情况,与指针不同的是,并不存在空引用,所以引用的dynamic_cast检测失败时会抛出一个bad_cast异常。

使用dynamic_cast转换的Base类至少带有一个虚函数

虚表是C++多态实现的一个重要手段,也是dynamic_cast操作符转换能够进行的前提条件。当类没有虚函数表的时候(也即一个虚函数都没有定义),不能通过编译。

static_cast

C++强制类型转换操作符 static_cast
static_cast conversion

  • 编译器隐式执行的任何类型转换都可以由static_cast来完成,比如int与float、double与char、enum与int之间的转换等。

当编译器隐式执行类型转换时,大多数的编译器都会给出一个警告。

使用static_cast可以明确告诉编译器,这种损失精度的转换是在知情的情况下进行的,也可以让阅读程序的其他程序员明确你转换的目的而不是由于疏忽。

把精度大的类型转换为精度小的类型,static_cast使用位截断进行处理。

  • 使用static_cast可以找回存放在void* 指针中的值。
    double a = 1.999;
    void * vptr = & a;
    double * dptr = static_cast(vptr);
    cout<<*dptr<
  • static_cast也可以用在于基类与派生类指针或引用类型之间的转换。

然而它不做运行时的检查,不如dynamic_cast安全。static_cast仅仅是依靠类型转换语句中提供的信息来进行转换,而dynamic_cast则会遍历整个类继承体系进行类型检查,因此dynamic_cast在执行效率上比static_cast要差一些。

  • static_cast可以把任何类型的表达式转换成void类型。

  • 另外,与const_cast相比,static_cast不能把换掉变量的const属性,也包括volitale或者__unaligned属性。

  • 一般不能用于指针类型之间的转换比如int * 转double * ,float * 转 double* 等等。

你可能感兴趣的:(c++,c++,开发语言)