C++ 强制类型转换(const_cast/reinterpret_cast)使用详解

本文详细介绍了C++中const_cast和reinterpret_cast的使用方法。const_cast用于移除变量的const属性,但不安全,可能会导致未定义行为。reinterpret_cast则非常灵活,用于类型重新解释,但要求转换前后类型内存大小一致。同时,文章还简述了static_cast和dynamic_cast的作用。

一、const_cast用法

const_cast < new-type > ( expression );

用于转换指针或引用,可以去掉类型的const属性。

在c++参考文档网站上(const_cast conversion - cppreference.com)有这么一个例子:

#include <iostream>

struct type
{
    int i;
    type(): i(3) {}

    void f(int v) const
    {
        // this->i = v; //直接赋值,会编译报错;因为const成员函数,意味着该函数内不能改变当前类成员的值
        const_cast<type*>(this)->i = v; // 只要type对象不是 const 就可以对类成员进行改值了
    }
};

int main()
{
    int i = 3;                 // i is not declared const
    const int& rci = i;
    const_cast<int&>(rci) = 4; // OK: modifies i
    std::cout << "i = " << i << '\n';

    type t;//如果声明为const type t, 那么下一个语句t.f(4),就是一个未定义的行为,所以不要加const了
    t.f(4);
    std::cout << "type::i = " << t.i << '\n';

    const int j = 3;
    [[maybe_unused]]/*抑制针对未使用实体的警告。*/
    int* pj = const_cast<int*>(&j);通过强制转换,将const常量的地址赋值给普通指针
    // *pj = 4;      //通过普通指针修改const常量的值,这是未定义的行为,不要这么写;结果后面例子1会进一步演示这个现象

    [[maybe_unused]]
    void (type::* pmf)(int) const = &type::f; // pointer to member function
    // const_cast<void(type::*)(int)>(pmf);   // 编译错误:const_cast 对函数指针不生效
}

--------------------------------------------------------------------
输出:
i = 4
type::i = 4

例1:

#include <iostream>
using namespace std;

int main(){
    const int a = 10;
    cout << a << endl;
    int *p = const_cast<int*>(&a);
    *p = 1;
    cout << *p << endl;
    cout << a << endl;
    return 0;
}

------------------------
输出:
10
1
10

但是当你调试这段程序的时候,你会发现a是改变了的,而且不同的编译器可能有不同的表现,所以说这样用是未定义的行为。

备注: 函数后加const的意义:

   类的成员函数中,常常有一些成员函数不改变类的数据成员,这些函数是"只读"函数,而有一些函数要修改类数据成员的值。把不改变数据成员的函数后面都加上const关键字进行标识,可提高程序的可读性。定义成const的成员函数,内部编码修改数据成员的值,编译器会报错。
 

二、reinterpret_cast

作用:重新解释类型,既不检查指向的内容,也不检查指针类型本身;但要求转换前后的类型所占用内存大小一致,否则引发编译时错误。由于太过于灵活,所以要慎用。

#include <cstdint>
#include <cassert>
#include <iostream>

int f() { return 42; }

int main()
{
    int i = 7;

    // 指向整数并返回的指针
    std::uintptr_t v1 = reinterpret_cast<std::uintptr_t>(&i);
    std::cout << "The value of &i is " << std::showbase << std::hex << v1 << '\n';
    int *p1 = reinterpret_cast<int *>(v1);
    assert(p1 == &i);
    char* p2 = reinterpret_cast<char*>(&i);

    std::cout << (p2[0] == '\x7' ? "This system is little-endian\n"
                                 : "This system is big-endian\n");

    // 指向另一个函数并返回的指针
    void(*fp1)() = reinterpret_cast<void(*)()>(f);
    //经过强制转换,然后调用
    int(*fp2)() = reinterpret_cast<int(*)()>(fp1);
    std::cout << std::dec << "通过fp2 调用函数 " << fp2() << '\n';
}

三、static_cast

        用于基本类型转换,有继承关系类对象和类指针之间的转换,由程序员来确保转换是安全的,它不会产生动态转换的类型安全检查的开销。

#include "iostream"

using namespace std;
int main(){
    int vlu1 = 666;
    cout << vlu1 << endl;
    double vlu2 = static_cast<double >(vlu1);
    cout << vlu2 << endl;
    double vlu3 = 66.6;
    cout << vlu3 << endl;
    int vlu4 = static_cast<int>(vlu3);
    cout << vlu4 << endl;//丢失精度

}

四、dynamic_cast

        只能用于含有虚函数的类,必须用在多态体系中,用于类层次间的向上和向下转化;向下转化(父类转成子类)时,如果是非法的对于指针返回NULL。

#include "iostream"

using namespace std;

class Base{
public:
    Base():_i(0){;};
    ~Base(){;};
    virtual void T(){cout << "TTTT:" << _i <<endl;}

private:
    int _i;

};

class Derived: public Base{
public:
    Derived():_j(1){;};
    ~Derived(){;};
    virtual void T(){cout << "Derived:" << _j << endl;};
private:
    int _j;
};

int main(){
    Base cb;
    Derived cd;
    Base *pcb;
    Derived* pcd;

    //子类转父类
    pcb = static_cast<Base*>(&cd);
    if(pcb == nullptr){
        cout << "danger action 1" << endl;
    }
    pcb = dynamic_cast<Base*>(&cd);
    if(pcb == nullptr){
        cout << "danger action 2" << endl;
    }

    //父类转子类
    pcd = static_cast<Derived*>(&cb);
    if(pcd == nullptr){
        cout << "danger action 3" << endl;
    }
    pcd = dynamic_cast<Derived*>(&cb);
    if(pcd == nullptr){
        cout << "danger action 4" << endl;
    }
}

输出:
danger action 4

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值