it编程 > 编程语言 > C/C++

C++的类型转换详解

40人参与 2026-09-08 C/C++

一.c语言的类型转换

在 c 语言里,当赋值运算符两边类型不一致、形参和实参类型不匹配、或者函数返回值与接收变量类型不一样时,就会触发类型转换。

c 语言的类型转换分为两种:隐式类型转换与显式类型转换。

来看代码:

#include <stdio.h>
void test ()
{
    int i = 1;
    // 隐式类型转换:int自动转为double
    double d = i;
    printf("%d, %.2f\n" , i, d);
    int* p = &i;
    // 显式强制类型转换,把指针地址转为整型
    //注意:指针转int存在平台风险,64位下建议用uintptr_t
    int address = (int) p;
    printf("%p, %d\n" , p, address);
}
int main(void)
{
    test();
    return 0;
}

c语言强转缺陷:转换的可视性较差,所有转换都写成同一种形式,很难定位出错的类型转换,不利于跟踪错误。

二.为什么c++需要四种类型转换

c 风格的转换格式很简单,但是有不少缺点的:

因此 c++ 提出了自己的类型转化风格,注意因为 c++ 要兼容 c 语言,所以 c++ 中还可以使用 c 语言的转化风格。

三.c++ 强制类型转换

标准 c++ 为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:

1.static_cast

static_cast 适用于非多态类型之间的静态转换。凡是编译器能够自动隐式完成的类型转换,都可以使用 static_cast 显式写出;但它不支持两个毫无关联的类型相互转换

#include <iostream>
using namespace std;
int main()
{
    double d = 12.34;
    // 把double转为int,属于相近类型转换,static_cast合法
    int a = static_cast<int>(d);
    cout << a << endl;
    return 0;
}

double 向 int 转换属于合法的数值类型转换,static_cast 在编译阶段完成转换,直接舍弃小数部分,输出 12。static_cast 不支持无关类型(如指针与 int)的转换。

2.reinterpret_cast

reinterpret_cast 会直接对数据的二进制位重新解读,适合把一种完全不同的类型转换成另一种类型,不做类型安全性检查。

注意:这种转换仅仅改变类型解释方式,不会修改内存里的二进制内容,风险很高。

#include <iostream>
using namespace std;
int main()
{
    double d = 12.34;
    int a = static_cast<int>(d);
    cout << a << endl;
    // static_cast不支持整型向指针转换,编译报错
    //int *p = static_cast<int*>(a);
    //强行把整型数值解释成指针地址
    int *p = reinterpret_cast<int*>(a);
    return 0;
}

整型与指针是无关类型,static_cast 不支持转换。reinterpret_cast 直接将 a 中的数值解读成指针地址,仅改变类型视角,不改动二进制数据。该转换语法可行,但得到的是无效地址,不要对指针解引用,风险较大。

3.const_cast

const_cast 主要用来移除或者增加变量的 const 属性,最常见用法是去掉 const 限定。

注意:它不是真正消除常量本身的只读属性,只是修改指针 / 引用的类型;如果原本是常量,强行修改会出现未定义行为。

#include <iostream>
using namespace std;
void test()
{
    const int a = 2;
    //去掉const属性,用普通指针接收常量的地址
    int* p = const_cast<int*>(&a);
    *p = 3;
    cout << a << endl;
}
int main()
{
    test();
    return 0;
}

普通指针无法接收 const 变量的地址,借助 const_cast 去除指针的 const 限制。但 a 本身是常量,通过指针修改常量属于未定义行为,运行结果不确定。const_cast 仅能增减 const 属性,不支持其他类型转换。

补充实用场景:它更适合本来不是常量,只是被 const 指针接收的情况,这种修改是安全的。如果你想要,我可以写一段安全使用 const_cast 的示例。

4.dynamic_cast

dynamic_cast 用来完成父类指针或引用向子类指针或引用的动态转换。

注意: dynamic_cast 只能用在包含虚函数的父类中。 转换时它会先做运行时检查,如果转换合法就正常转换;转换失败,指针会返回空指针 0。

#include <iostream>
using namespace std;
class a
{
public:
    virtual void f() {}
};
class b : public a
{
};
void fun(a* pa)
{
    b* pb1 = static_cast<b*>(pa);
    b* pb2 = dynamic_cast<b*>(pa);
    cout << "pb1:" << pb1 << endl;
    cout << "pb2:" << pb2 << endl;
}
int main()
{
    a a;
    b b;
    fun(&a);
    fun(&b);
    return 0;
}

  1. a 类中写了虚函数,这是 dynamic_cast 能够正常使用的前提。
  2. 第一次调用 fun (&a),传进去的是父类对象地址。 static_cast 不会在运行时校验对象真实类型,直接强制转为 b 类指针,拿到的指针是无效的; dynamic_cast 运行时检测出原始对象是父类,向下转换行不通,直接返回空指针。
  3. 第二次调用 fun (&b),传入子类对象地址。 两种转换都能成功得到子类指针。
  4. static_cast 只在编译期间做简单检查,向下转型存在安全隐患;dynamic_cast 依靠运行时类型判断保证安全,多用于多态代码。

补充:强制类型转换会跳过常规的类型检查。写代码时,优先想想有没有不用强制转换的方案。实在不得不使用强制转换,尽量缩小它的作用范围,减少 bug 出现的可能性。

四.rtti(了解)

rtti:run-time type identification 的缩写,即运行时类型识别,用来在程序运行阶段判断对象的真实类型。

c++ 通过下面几个方式支持 rtti:

补充:rtti 运行时类型识别

rtti 是 c++ 在程序运行阶段判断对象真实类型的机制,依赖虚函数表记录类型信息。核心工具是 typeid(查询实际类型)和 dynamic_cast(安全向下转型),decltype 则是编译期推导类型,配合模板泛型编程用。‌‌

最佳实践‌:写代码时先想想有没有不用强制转换的方案;实在要用,尽量缩小作用范围。强制转换会跳过常规类型检查,是 bug 的温床,能少用就少用。‌‌

通俗理解就是:typeid 负责 "看是什么类型",dynamic_cast 负责 "能不能安全转",decltype 则偏编译期推导,三者应用场景不太一样。

到此这篇关于c++的类型转换详解的文章就介绍到这了,更多相关c++类型转换内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

C++ 哈希表从原理剖析到模拟实现方法

09-08

C语言中字符函数和字符串函数的使用与实现详解

09-08

C语言的递归与尾递归的实现

09-08

c语言分支与循环语句案例详解

09-08

C语言实现结构体、联合和枚举

09-08

C语言中位运算的实现

09-08

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论