C++强制类型转换

本文详细介绍了C++中的四种强制类型转换:static_cast、reinterpret_cast、const_cast和dynamic_cast。static_cast主要用于低风险的转换,如基本类型间的转换;reinterpret_cast处理不同类型指针和引用的转换,以及指针与整型间的转换,但存在风险;const_cast用于移除const属性;dynamic_cast专用于多态基类到派生类的转换并检查安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


以下内容参考北京大学郭炜老师mooc《程序设计与算法(三)C++面向对象程序设计》
有一个问题就是,明明可以用以下的方式来进行强制类型转换,为什么还要用C++提供的四种类型转换呢?

	float a = 1.0;
	int b = (int)a;

那是因为原来的类型转换不能区分转换风险的高低, 比如指针转换就用interpret_castdynamic_cast。这样可以对转换的形式和风险程度分级,这样可以很容易地在程序中搜寻我们在程序中哪里进行了某一类的转换

static_cast

static_cast用来进行比较”自然“和低风险的转换,比如整形和实数型、字符型之间的互相转换。什么叫低风险的转换呢?我们要知道,类型转换是有风险的,比如把浮点数转换为整型数,就有丢失精度的风险;如果把一个基类的指针强制转换成派生类的指针,然后使用这个派生类的指针,实际上指向的是一个基类的对象,如果把它当派生类的指针来用的话,可能调用的就是基类的成员函数,这个时候就会出错
static_cast不能用来在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,也不能用于不同类型的引用之间的转换。

#include <iostream>
using namespace std;

class A
{
public:
    operator int() { return 1; } //类型强制转换运算符重载,这是不写返回值类型的,重载是什么类型,返回值就是什么类型。
    operator char*() { return "who r u"; }
};

int main()
{
    A a;
    int n;
    char *p = "I am zzy";
    n = static_cast<int>(3.14);
    cout << n << endl;
    n = static_cast<int>(a);//调用a.operator int, n的值变为1
    cout << n << endl;
    p = static_cast<char *>(a); //调用a.operator char*, p的值变为"who r u"
    cout << p << endl;
    n = static_cast<int>(p);//编译错误,static_cast不能将指针转换成整型
    p = static_cast<int>(n);//编译错误,static_cast不能将整型转换成指针
    return 0;
}

reinterpret_cast

reinterpret_cast用来进行不同类型指针之间的转换,不同类型的引用之间的转换、以及指针和能容纳得下指针的整数类型之间的转换(比如指针是4个字节,那么只能转换成int及以上的,因为int也是四个字节)。转换的时候,执行的是逐个比特拷贝的操作。

#include <iostream>
using namespace std;

class A
{
public:
    int i;
    int j;
    A(int n) : i(n), j(n){};
};

int main()
{
    A a(100);
    int &r = reinterpret_cast<int &>(a);//强行让r引用a
    r = 200;//通过引用将a.i变成了200
    cout << a.i << "," << a.j << endl;
    int n = 300;
    A *pa = reinterpret_cast<A *>(&n);//强行让A类的指针pa指向n
    pa->i = 400;//n变成400
    pa->j = 500;//词条语句不安全,很可能导致程序崩溃
    cout << n << endl;
    long long la = 0x12345678abcdLL;
    pa = reinterpret_cast<A *>(la);//la太长,只取低32位拷贝给pa
    unsigned int u = reinterpret_cast<unsigned int>(pa);//pa逐个拷贝给u
    cout << hex << u << endl;//输出5678abcd
}

上面这个例子,让r强行引用了a,然后将r赋值为200,就会在r这引用的4个字节里面写入200,而A在内存中占8个字节,前4个是i,后4个是j,而r引用的就是前4个字节也就是i的内存。
而后面让A类的指针pa指向了整型变量n,因为n占4个字节,所以pa->i刚好指向n的内存空间,而pa->j指向n之后的4个字节,就不知道是什么地方了,可能是其他变量的内存空间,甚至可能是根本不允许写的地方,所以可能导致程序崩溃。
在这里插入图片描述

const_cast

用来进行去除const属性的转换。将const引用转换成同类型的非const引用,将const指针转换乘同类型的非const指针。

	const string s = "zzy";
	string &p = const_cast<string&>(s);
	string *ps = const_cast<string*>(&s);//&s的类型是const string*

dynamic_cast

我们经常会做从基类指针到派生类指针的转换,基类指针到派生类指针是需要强制转换的,这个转换的安全性就取决于基类指针是不是确实指向一个派生类的对象。
总而言之,基类指针到派生类指针的强制转换,只有在基类指针指向派生类的对象时才是安全的
dynamic_cast专门用于将多态基类的指针或引用,强制转换成派生类的指针或引用,而且能够检查转换的安全性。对于不安全的指针转换,转换结果将返回NULL指针。
dynamic_cast不能用于将非多态基类的指针或引用,强制转换成派生类的指针或引用。

#include <iostream>
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);//不论安全与否,该转换都能进行
    if(pd==NULL)//pd不为NULL,因为reinterpret_cast不检查安全性,总是进行转换
        cout << "unsafe reinterpret_cast" << endl;
    pd = dynamic_cast<Derived *>(&b);
    if(pd==NULL)//pd为NULL,因为&b不是只想派生类对象,此转换不安全
        cout << "unsafe dynamic_cast" << endl;
    Base *pb = &d;
    pd = dynamic_cast<Derived *>(pb);//安全的转换
    if(pd==NULL)//不为NULL
        cout << "unsafe dynamic_cast2" << endl;
    system("pause");
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值