数据类型转换操作符:const_cast、static_cast、dynamic_cast以及reinterpret_cast

文章目录

      • 数据类型转换
        • const_cast的用法
          • 使用const_cast需要注意的问题:
        • static_const
        • dynamic_cast
        • reinterpret_cast

数据类型转换

在c++编程中,我们经常需要使用到类型转换,但可能不熟悉c++内置的四种类型转换操作符

它们分别是:const_cast、static_cast、dynamic_cast以及reinterpret_cast,它们的语法形式是统一的,type_cast_operator(expression)

  • const_cast主要用于解除常量或者常指针的const属性

  • static_cast主要用于基本类型之间的转换、基类对象指针和派生类对象指针之间的转换、一般指针类型和void*类型之间的转换

  • dynamic_cast运算符的type必须是一个类类型,其功能在于将一个基类的指针或引用安全的转换为派生类的指针或引用

  • reinterpret_cast是四种操作符中转换能力最强的操作符,它设置可以实现char *和class *的类型转换

const_cast的用法

const_cast是一种C++运算符,作用是去除复合类型中的const或volatile属性

变量本身的const属性是不能去掉的,要想修改常量的值,一般是去除指向该变量的指针(引用)的const属性

具体使用实例如下:

#include 
using namespace std;

void constTest1()
{
    const int a = 5;
    int *p;
    p = const_cast(&a);      //如果写成p = &a;则会发生编译错误
    (*p)++;
    cout << "The a is:" << a << endl;
}

void constTest2()
{
    int i;
    cout << "请输入变量值:" << endl;
    cin >> i;

    const int a = i;
    int &n = const_cast(a);
    n++;

    cout << "The n is:" << n << endl;
}

int main()
{
    constTest1();
    constTest2();
    return 0;
}

程序运行结果如下:

The a is:5
请输入变量值:
8
The n is:9

虽然程序中constTest1函数输出的结果为5,但这并不能表明a的值没有改变,而是编译器将a优化为文字常量5

实际上a的值已经变成了6

在constTest2函数中,由于常变量无法转化为文字常量,所以它显示修改之后的值为6

使用const_cast需要注意的问题:
  1. const_cast的使用语法就是const_cast< type >(),且括号不能省略
  2. 原类型和目标类型必须一致,即不能使用const_cast去转换非char *的数据
  3. 一个变量被定义为const类型之后,那它就永远是常变量,即使通过const_cast也只是对间接引用时的改写限制,并不能改变变量的属性
  4. 使用C语言的强制类型转换也可以使const type &转换为type &,但不推荐这样做
static_const

static_const只能用于良性转换,风险很低;例如:原有的自动类型转换、void*和具体类型指针的转换或者用于类之间的转换

但需要注意的是,用于转换的类之间需要存在继承关系

static_const的具体使用实例如下:

#include 
using namespace std;

class A{
public:
    char c;
    int num;
};

class B : public A{};

class C{};

int main()
{
    A *a = new A;
    char *p = static_cast(a);

    B *b = new B;
    a  = static_cast(b);

    C *c = new C;
    a = static_cast(c);
}

程序运行结果如下:

typeChange.cpp:17:36: error: invalid static_cast from type 'A*' to type 'char*'
     char *p = static_cast(a);
                                    ^
typeChange.cpp:23:26: error: invalid static_cast from type 'A*' to type 'C*'
     c = static_cast(a);
                          ^

以上程序报错原因如下:

  1. 无法将A *类型数据转换为char *,如果确实需要以上操作,建议先将A *转换为void *,之后再将void *转换为char *
  2. 无法将没有继承关系的类的指针或引用与其基类指针或引用进行转换

将程序main函数改为以下内容即可编译通过:

int main()
{
    A *a = new A;
    //char *p = static_cast(a);

    void *ptr = a;
    char *p = static_cast(ptr);

    B *b = new B;
    a  = static_cast(b);

    C *c = new C;
    //a = static_cast(c);
}
dynamic_cast

该操作符借助RTTI(运行时类型识别),通过运行时类型信息程序将够使用基类的指针安全的转化为派生类的指针或引用,因此它比static_cast更加安全

dynamic即支持向上转型,也允许向下转型。向上转型(派生类转换为基类)是无条件的,不需要进行任何检测,因此都能成功;向下转型的前提是安全,因此需要借助RTTI,是不一定能够成功的

dynamic_cast操作耗时较高,会影响程序性能,因此尽量少用

dynamic_cast使用实例:

#include 
using namespace std;

class A{};
class B : public A{};

int main()
{
    A *a = new A();
    B *b = new B();

    a = dynamic_cast(b);
    if(b == NULL)
    {
        cout << "The dynamic_cast fail!!!" << endl;
    }
    else
    {
        cout << "The dynamic_cast success!!!" << endl;
    }
    
}
reinterpret_cast

reinterpret_cast一般是不提倡使用的,除非你确保这种操作是安全的

虽然reinterpret_cast的转换能力很强,但并非是万能的,编译器会设法最低限度的保证安全合理

其不支持的转换类型如下所示:

  1. 由一种类对象转换为另一种类对象
  2. 由基本数据类型转换为类对象
  3. 由类对象转换为基本数据类型

reinterpre_cast的使用实例如下:

#include 
using namespace std;

typedef void (*pfunc)();

void func1()
{
    cout << "This is func1(), return void" << endl;
}

int func2()
{
    cout << "This is func2(), return int" << endl;
}

int main()
{
    pfunc FuncArray[2];

    FuncArray[0] = func1;
    FuncArray[1] = reinterpret_cast(func2);

    (*FuncArray[0])();
    (*FuncArray[1])();
}

程序中typedef void (*pfunc)();语句的目的是定义新的数据类型pfunc,且该类型为函数指针,参数列表为空

typedef 返回值 (新类型)(参数列表)

程序运行结果如下所示:

This is func1(), return void
This is func2(), return int

根据程序运行结果得知,reinterpert_cast可以将函数指针int (* )()转化为void(* )(),其它操作符不能完成此操作

文章来源: 陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008

你可能感兴趣的:(C/C++,c++,const_cast,static_cast,dynamic_cast)