C++中不同类型的默认转换详解

作者:码事漫谈日期:2025/11/27

不熟悉默认类型转换,真的很容易写出bug!!!

在C++中,类型转换是一个非常重要的概念。下面详细讲解C++中各种默认类型转换的规则和机制。

1. 算术类型转换

整型提升 (Integral Promotion)

1char c = 'A';
2short s = 100;
3int i = c + s;  // char和short都提升为int
4

算术转换规则

1// 转换优先级:long double > double > float > unsigned long long > long long > 
2// unsigned long > long > unsigned int > int
3
4int i = 10;
5double d = 3.14;
6double result = i + d;  // int转换为double
7
8unsigned int u = 100;
9int j = -50;
10unsigned int result2 = u + j;  // int转换为unsigned int
11

2. 指针类型转换

隐式指针转换

1// 派生类指针到基类指针
2class Base {};
3class Derived : public Base {};
4
5Derived d;
6Base* bp = &d;  // 隐式向上转换
7
8// 数组到指针退化
9int arr[5];
10int* ptr = arr;  // 数组退化为指针
11
12// 0或nullptr到指针
13int* p1 = 0;
14int* p2 = nullptr;
15
16// 任意指针到void*
17int x = 10;
18void* vp = &x;
19

3. 引用类型转换

1class Base {
2public:
3    virtual void show() { cout << "Base" << endl; }
4};
5
6class Derived : public Base {
7public:
8    void show() override { cout << "Derived" << endl; }
9};
10
11Derived d;
12Base& br = d;  // 派生类引用到基类引用
13br.show();     // 输出: Derived (多态)
14

4. 限定符转换 (Qualification Conversions)

const转换

1int x = 10;
2const int* cp = &x;     // 非const到const
3// int* p = cp;         // 错误: 不能去掉const限定
4
5const int y = 20;
6// int* p2 = &y;        // 错误: 不能去掉const限定
7const int* cp2 = &y;    // OK
8

volatile转换

1int normal = 10;
2volatile int vi = 20;
3volatile int* vp = &normal;  // 非volatile到volatile
4// int* p = &vi;            // 错误: 不能去掉volatile限定
5

5. 布尔转换

1// 以下情况会隐式转换为bool
2int* ptr = nullptr;
3if (ptr) {  // 指针到bool: nullptr→false, 其他→true
4    cout << "Pointer is valid" << endl;
5}
6
7int value = 10;
8if (value) {  // 算术类型到bool: 0→false, 非0→true
9    cout << "Value is non-zero" << endl;
10}
11

6. 用户定义类型转换

转换构造函数

1class MyString {
2private:
3    char* str;
4public:
5    // 转换构造函数: const char*  MyString
6    MyString(const char* s) {
7        str = new char[strlen(s) + 1];
8        strcpy(str, s);
9    }
10    
11    ~MyString() { delete[] str; }
12};
13
14MyString s = "Hello";  // 隐式调用转换构造函数
15

类型转换运算符

1class SmartBool {
2private:
3    bool value;
4public:
5    SmartBool(bool b) : value(b) {}
6    
7    // 类型转换运算符: SmartBool  bool
8    operator bool() const {
9        return value;
10    }
11};
12
13SmartBool sb = true;
14if (sb) {  // 隐式调用operator bool()
15    cout << "SmartBool is true" << endl;
16}
17

7. 标准转换序列

C++编译器会尝试以下标准转换序列:

1class A {};
2class B : public A {};
3class C {};
4
5void func(A a) {}
6
7int main() {
8    B b;
9    func(b);  // 标准转换: B  A (派生类到基类)
10    
11    // 可能的转换序列:
12    // 1. 精确匹配
13    // 2. 提升转换
14    // 3. 标准转换
15    // 4. 用户定义转换
16    // 5. 省略号匹配
17}
18

8. 显式控制隐式转换

explicit关键字

1class ExplicitClass {
2public:
3    explicit ExplicitClass(int x) {}  // 禁止隐式转换
4};
5
6void test(ExplicitClass ec) {}
7
8int main() {
9    // ExplicitClass ec = 10;  // 错误: 不能隐式转换
10    ExplicitClass ec(10);      // OK: 直接初始化
11    test(ExplicitClass(10));   // OK: 显式转换
12}
13

删除转换函数

1class NoConvert {
2public:
3    NoConvert(int) {}
4    
5    // 删除不需要的转换
6    NoConvert(double) = delete;
7    operator bool() = delete;
8};
9
10NoConvert nc(10);    // OK
11// NoConvert nc(3.14); // 错误: 使用已删除的函数
12// if (nc) {}         // 错误: 使用已删除的函数
13

9. 转换的优先级和歧义

1class Ambiguous {
2public:
3    Ambiguous(int x) {}
4    Ambiguous(double x) {}
5};
6
7void func(Ambiguous a) {}
8
9int main() {
10    // func(10);     // 歧义: int可以转换为int或double
11    func(Ambiguous(10));  // 必须显式指定
12}
13

10. 最佳实践和注意事项

  1. 避免意外的隐式转换
1// 使用explicit防止意外的构造函数转换  
2// 小心算术类型转换的精度损失  
  1. 注意符号性和大小
1unsigned int u = 10;  
2int i = -5;  
3if (u > i) {  // i转换为unsigned int, 结果可能出乎意料  
4    cout << "Unexpected result!" << endl;  
5}  
  1. 使用static_cast进行显式转换
1double d = 3.14;  
2int i = static_cast<int>(d);  // 明确的意图  

理解C++的类型转换规则对于编写安全、高效的代码至关重要。在可能产生歧义或意外行为的地方,建议使用显式转换来明确意图。


C++中不同类型的默认转换详解》 是转载文章,点击查看原文


相关推荐


一次性讲清楚常见的软件架构图
uzong2025/11/25

本文是根据 ProcessOn 整理汇总而来,ProcessOn 是一个非常不错的画图软件,功能强大,界面优美。 作者:面汤放盐(微信公众号) 时间:2025.11.24 架构图详细分类 架构图作为一种重要的工具,用于可视化展示软件、系统、应用程序等的体系结构及其组成部分之间的关系。 常用的架构图种类有:业务架构图、应用架构图、系统架构图、技术架构图、部署架构图、数据架构图、产品架构图、功能架构图、信息架构图等。 关于架构图所处位置,可见下图所示: 1. 业务架构图 1.1. 什么是业务架构图


Lua 的 getmetatable 函数
IMPYLH2025/11/23

Lua 的 getmetatable 函数 用于获取指定对象的元表(metatable)。元表是Lua中实现面向对象编程和运算符重载的重要机制。以下是关于getmetatable函数的详细说明: 基本语法: metatable = getmetatable(object) 参数说明: object: 可以是任意Lua值(table、userdata、string等)返回值:如果对象有元表则返回元表,否则返回nil 特性细节: 对不同类型的对象处理方式: 普通table:返回


Lua 的 error 函数
IMPYLH2025/11/21

Lua 的 error 函数是一个用于显式抛出错误的内置函数,它会中断当前程序的正常执行流程。该函数有两种调用形式: error(message, level)error(message) 参数说明: message:字符串类型的错误信息,是必选参数level:可选参数,指定错误发生的位置层级,默认为1(表示调用error的位置) 使用示例: 通过 Shift 运行 function divide(a, b) if b == 0 then error("除数不


使用 Docker 部署 RabbitMQ 的详细指南
s***55812025/11/19

使用 Docker 部署 RabbitMQ 的详细指南 在现代应用程序开发中,消息队列系统是不可或缺的一部分。RabbitMQ 是一个流行的开源消息代理软件,它实现了高级消息队列协议(AMQP)。本文将详细介绍如何使用 Docker 部署 RabbitMQ,并提供一些配置和管理的技巧。 1. 前期准备 在开始之前,请确保您的系统上已经安装了 Docker。如果尚未安装,可以参考 Docker 官方文档 或我写的前面一篇文章 CentOS 上安装 Docker 的详细指南 进行安装。 2.


LVS-NAT 模式负载均衡集群部署与配置
ttthe_MOon2025/11/18

LVS(Linux Virtual Server)是基于 Linux 的负载均衡群集技术,NAT 模式通过地址转换实现内外网通信与负载分发,核心是 LVS 服务器充当网关,将外网请求转发至后端 Web 服务器。 一、核心概念 1. LVS 基础 本质:作用在四层的负载均衡器,不提供网页服务,仅通过算法为后端服务器分流减压。 核心价值:解决单台服务器性能瓶颈,实现高可用(HA)和负载均衡(LB)。 集群定义:3 台以上服务器对外表现为一个整体,提供单一访问入口(IP / 域名)。 2. NAT 模


关于No Chatbot的思考
HeteroCat2025/11/17

前言 近期在大模型圈子里,“No Chatbot”这一概念潇潇浮出江面,它意指不再将智能体局限于传统的对话式问答系统,而是发展为具备主动规划、调用工具和协作能力的智能助理。作为一名长期研究提示词工程和智能体应用的创作者,我想结合最近的思考,与大家探讨这一趋势的内涵与意义。 什么是“No Chatbot” “No Chatbot”并不是不要聊天机器人,而是指下一代智能体需要突破单纯聊天交互的框架,具备更强的自主性和执行力。它主要包含以下特征: 任务导向:关注完成复杂任务,而不是只回答问题。系统会


Spring boot启动原理及相关组件
q***38512025/11/16

优质博文:IT-BLOG-CN 一、Spring Boot应用启动 一个Spring Boot应用的启动通常如下: @SpringBootApplication @Slf4j public class ApplicationMain { public static void main(String[] args) { ConfigurableApplicationContext ctx = SpringApplication.run(ApplicationMain.


UDP服务端绑定INADDR_ANY后,客户端该用什么IP访问?
咸鱼_要_翻身2025/11/15

目录 一、问题 二、详细解释 1、INADDR_ANY 到底是什么? 2、客户端可以使用什么IP访问? 三、为什么要传IP? 1、网络层寻址的需要 2、操作系统协议栈的需要 3、服务端主机区分流量的需要 四、总结 一、问题         在UDP协议中,服务端使用INADDR_ANY了,然后客户端可以使用什么IP可以访问服务端?为什么要传IP?这是一个非常经典且重要的问题。我们来分步拆解和解答。 核心答案:当UDP服务端绑定到 INADDR_ANY (其值通常是


【Kubernetes】K8s 集群 Ingress 入口规则
陈陈CHENCHEN2025/11/14

Ingress 是管理从集群外部访问集群内部服务的入口规则(HTTP 和 HTTPS)的 API 对象,核心功能是将外部到达集群的 HTTP/HTTPS 请求,根据主机名(host)和路径(path)转发到不同的后端 Service,一起来看看如何使用吧! 1、概念 1.1、Ingress(资源) 在 K8s 中创建的 YAML 文件,只是一份规则声明,定义 “当访问 a.example.com 时,将流量转发给 service-a” 之类的规则 1.2、Ingress Control


11种方法解决iPhone上共享相册不显示的问题[2025]
Digitally2025/11/12

如果你想查看或下载朋友或家人通过iCloud链接邀请与你共享的照片,你可以利用iPhone上的共享相册功能。然而,有时这个看似无缝的过程会出现问题,让用户不禁想问:“为什么我没有收到共享相册邀请?”或“如何修复共享相册不显示”。好的,本页面致力于揭示背后的原因,并提供有效的解决方法,确保你的共享相册体验保持完美。但在那之前,让我们先简要了解一下“共享相册”。 第一部分:什么是共享相册?如何接受共享相册邀请? 什么是共享相册?“共享相册”是一个在线空间,多人可以在此添加、查看和互动照片和视频。

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读