关闭

C++ 类型转换运算符——const_cast

标签: C++类型转换const-cast
159人阅读 评论(0) 收藏 举报
分类:

今天看《Effective C++》,里面提到了关于类型转换的章节,所以就来对C++的类型转换进行一定的分析和测试吧。
C++提供了四个转换运算符:

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

它们有着相同的结构,看起来有点像是模板方法。
这些方法就是提供给开发者用来进行指针和引用的类型转换的。

用const_cast来去除对象的const限定

对于一个const变量,我们不能修改它的值,这是C++强制规定的,也是这个限定符的直接表现,如果我们想修改怎么办?
以下的代码显然是不行的:

    const int Cint = 5;
    Cint =6;             //error

我们也许可以试着用指针和引用试试?

    const int Cint = 5;
//  Cint =6;             //error
    int *P_Cint = (int *)&Cint;
    *P_Cint = 6;

以上的代码并未真正修改到Cint的值,说明C++const 限定符执行的很完善,完全无机可乘

要不用const_cast试试,毕竟它主要就是负责这个的嘛:

const int Cint = 5;
const int *const PCint = &Cint;
    int * castPCint = const_cast<int*>(PCint);//解除const属性
    *castPCint = 6;
    cout << Cint << endl;// 5
    //可以看到,我们对*castPCint的修改并没有修改到Cint的值,说明C++的const的有效性
    cout << "castPCint Add: " << castPCint << endl;
    cout << "Cint Add: " << &castPCint << endl;
    //castPCint Add: 006FF7A4
    //Cint Add : 006FF78C
    //可以看到,两者的地址不一样了,但是我们的确指向了同一块地址
    //这种赋值行为被称为未定义行为(Undefined Behavior)”。所谓未定义,是说这个语句在标准C++中没有明确的规定,由编译器来决定如何处理。
    //对于未定义行为,我们所能做的所要做的就是避免出现这样的语句。对于const数据我们更要这样保证:绝对不对const数据进行重新赋值。

    //如果我们不想修改const变量的值,那我们又为什么要去const呢?
    //原因是,我们可能调用了一个参数不是const的函数,而我们要传进去的实际参数确实const的,
    //但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。

以上就是const_cast的使用方法,是不是感觉很奇怪,转换之后的const内容还是完全不能进行修改,甚至连类型转换之后的指针指向的位置都被修改了,还有我发现了一个很有意思的事情,以下代码:

    const int Cint = 5;
//  Cint =6;             //error
    int *P_Cint = (int *)&Cint;

    *P_Cint = 7;

    const int *const PCint = &Cint;
    int * castPCint = const_cast<int*>(PCint);//解除const属性
    *castPCint = 6;
    cout << Cint << endl;// 5

    cout << "PC_int Add : " << P_Cint << endl;
    cout << "castPCint Add : " << castPCint << endl;
    cout << "Cint Add : " << &castPCint << endl;
    cout << "castPCint value : " << *castPCint << endl;
    cout << "PC_int value : " << *P_Cint << endl;

输出内容如下:

5  //最原始的const value的值
PC_int Add : 0097FBE8
castPCint Add : 0097FBE8
Cint Add : 0097FBC4
castPCint value : 6
PC_int value : 6

很奇怪,为什么const_cast 和强制类型转换得到的内容地址相同呢,这就涉及到C++的未定义行为了:

所谓未定义,是说这个语句在标准C++中没有明确的规定,由编译器来决定如何处理。

位运算的左移操作也可算一种未定义行为,因为我们不确定是逻辑左移,还是算数左移。

再比如下边的语句:v[i] = i++; 也是一种未定义行为,因为我们不知道是先做自增,还是先用来找数组中的位置。

对于未定义行为,我们所能做的所要做的就是避免出现这样的语句。

对于const数据我们更要这样保证:绝对不对const数据进行重新赋值。

如果我们不想修改const变量的值,那我们又为什么要去const呢?(以下转自其他博客):

原因是,我们可能调用了一个参数不是const的函数,而我们要传进去的实际参数却是const的,但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。

#include <iostream>
using namespace std;

void Printer (int* val,string seperator = "\n")
{
    cout << val<< seperator;
}

int main(void) 
{   
    const int consatant = 20;
    //Printer(consatant);//Error: invalid conversion from 'int' to 'int*'
    Printer(const_cast<int *>(&consatant));

    return 0;
}

出现这种情况的原因,可能是我们所调用的方法是别人写的。还有一种我能想到的原因,是出现在const对象想调用自身的非const方法的时候,因为在类定义中,const也可以作为函数重载的一个标示符。

最后,还是要说一句:

使用const_cast去除const限定的目的绝对不是为了修改它的内容,通过这篇,想告诉大家的就是,尽量不要使用类型转换(如果必定要使用,请使用类型转换符,方便查错)

2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:14309次
    • 积分:630
    • 等级:
    • 排名:千里之外
    • 原创:47篇
    • 转载:2篇
    • 译文:1篇
    • 评论:0条
    文章分类