当前位置: 首页 > news >正文

C++基础 类的自动转换和强制类型转换

参考

C++ Primer Plus (第6版)

类自动转换

接受一个参数的构造函数允许使用赋值语法将对象初始化一个值

Classname object = value;
等价于
ClassName object(value);
等价于
ClassName object = ClassName(value);

只有接受一个参数的构造函数才能作为转换构造函数(某类型->类)

#include <iostream>class Test{
private:int m_a;double m_b;
public:Test();Test(double b);         		// 可作为转换构造函数// Test(int a, double b = 0);	// 可作为转换构造函数Test(int a, double b);  		// 不可作为转换构造函数Test(const Test& t);Test& operator=(const Test& t);friend void Display(const Test& t, int n);
};Test::Test(){std::cout << "构造 Test()" << std::endl;m_a = 0; m_b = 0;
}Test::Test(double b){std::cout << "构造 Test(double)" << std::endl;m_a  = 0;m_b = b;
}Test::Test(int a, double b){std::cout << "构造 Test(int, double)" << std::endl;m_a  = a;m_b = b;
}Test::Test(const Test& t){std::cout << "复制构造 Test(const Test&)" << std::endl;m_a = t.m_a;m_b = t.m_b;
}Test& Test::operator=(const Test& t)
{std::cout << "operator=" << std::endl;if(this == &t){return *this;}m_a = t.m_a;m_b = t.m_b;return *this;
}void Display(const Test& t, int n){for(int i = 0; i < n; i ++){std::cout << t.m_a << "," << t.m_b << std::endl;}
}
int main(){Test test(10);        // int 转为 double, 使用Test(double b)std::cout << "---------" << std::endl;test = 12;			  // int 转为 double, 使用Test(double b)std::cout << "---------" << std::endl;Test test1 = 11;      // int 转为 double, 使用Test(double b)Test test2 = test1;Display(422, 2);	  // 遇到int类型, 找不到Test(int a), 寻找其它内置类型(int可以转换)的构造函数, Test(int b) 满足要求return 0;
}

在这里插入图片描述

注意, 当且仅当转换不存在二义性时, 才会进行转换, 如果这个类还定义了构造函数Test(long), 则编译器会报错

explicit 可以关闭隐式转换

explicit Test(double b);    // 不支持隐式转换

类强制转换

自动转换把 某类型 转成 类
强制转换把 类 转成 某类型, 需要用到特殊C++运算符函数, 转换函数
转换函数 是 用户定义的强制类型转换, 可以显示和隐式的调用(类->某类型)

Test t(10.2);
double a = double (t);
double b = (double) t;Test tt(10, 3);
double aa = tt;     // 隐式转换, 编译器会查看是否定义于此匹配的转换函数, 没有则生成错误消息

转换函数

operator typeName(); // typeName 是要被转换的类型

注意:
- 必须是类方法
- 不能指定返回类型
- 不能由参数

#include <iostream>class Test{
private:int m_a;double m_b;
public:Test();Test(double b);         	Test(int a, double b);  	// 转换函数operator int() const; operator double() const;
};Test::Test(){m_a = 0; m_b = 0;
}Test::Test(double b){m_a  = 0;m_b = b;
}Test::Test(int a, double b){m_a  = a;m_b = b;
}Test::operator double() const {return m_a + m_b;
}Test::operator int() const{return int(m_a + m_b+ 0.5);
}int main(){Test test(9, 2.8);double p = test;cout << "转换成double = " << p << std::endl;cout << "转换成int = " << int(test) << std::endl;long g = (double) test;  // 使用double 转换long gg = int(test)      // 使用int 转换
}

在这里插入图片描述
转换函数有时候也不需要隐式转换

int ar[20]
...
Test t(120, 2); // 这个Test只有一个转换函数operator int(), 不然ar[t] 这里转换会有二义性
...
int T = 1;
...
cout << ar[t] << endl;   // 写错的地方

原本是要把T作为数组索引, 不小心写错了, 写成对象t, Test类定义了operator int() , 会把转换成122, 作为数组索引, 然后就导致越界
原则上最好使用显示转换, 避免隐式转换
C++98 explicit不能用于转换函数, C++11消除这个限制

class Test{
...explicit operator int() const;explicit operator double() const;
};

也可以用功能相同的非转换函数替换转换函数, 仅在显示调用

class Test{
...int Test_to_int() const {return int(a + b);}
};

总结

  • 只有一个参数的类构造函数 用于类型于参数相同的值 -> 类类型, 构造函数声明中使用explict可防止隐式转换, 只允许显示转换
  • 转换函数是特殊的类成员运算函数, 可将 类 -> 其它类型, 是类成员, 没有返回值, 没有参数, 名为operator typeName(), C++11可以用explict防止隐式转换, 只允许显示转换

转换函数与友元函数

没有转换函数和构造转换函数的Test类重载加法运算符, 重载同一运算符成员函数和友元函数不能都提供


// 成员函数
Test test::operator+(const Test& s) const {Test t(m_a + m_b + s.m_a + s.m_b);return t;
}// 友元函数
Test operator+(const Test& t1, const Test& t2) const {Test t(t1.m_a + t1.m_b + t2.m_a + t2.m_b);return t;
}

第一种情况: a 和 b 都是类

Test a(9, 12);
Test b(12, 8);
Test t;
t = a + b; 
// Test类用的是 成员函数 的话
// t = a + b     ---转换--->       t = a.operator+(b)
// Test类用的是 友元函数 的话
// t = a + b     ---转换--->       t = operator+(a, b)         

这个 成员函数, 友元函数 都可以实现

现在给Test类提供Test(double)构造转换函数
第二种情况: a是类, b不是类, a在前面

Test a(9, 12);
double b = 13.6;
Test t;
t = a + b;
// Test类用的是 成员函数 的话
// t = a + b     ---转换--->       t = a.operator+(Test(b))
// Test类用的是 友元函数 的话
// t = a + b     ---转换--->       t = operator+(a, Test(b))   

这个 成员函数, 友元函数 都可以实现

第三种情况: a是类, b不是类, b在前面

Test a(9, 12);
double b = 13.6;
Test t;
t = b + a;
// Test类用的是 成员函数 的话  不行, 因为b.operator+()的参数要double类型
// Test类用的是 友元函数 的话
// t = b + a     ---转换--->       t = operator+(Test(b), a))   

这个只有 友元函数 都可以实现
要成员函数也可以实现, 可以再加一个友元函数

Test operator+(double x);   // 成员函数, 满足 Test + double
friend Test operator+(double x, Test& t); // 友元函数, 满足 double + Test

相关文章:

C++基础 类的自动转换和强制类型转换

参考 C Primer Plus (第6版) 类自动转换 接受一个参数的构造函数允许使用赋值语法将对象初始化一个值 Classname object value; 等价于 ClassName object(value); 等价于 ClassName object ClassName(value); 只有接受一个参数的构造函数才能作为转换构造函数(某类型->…...

MySQL索引的底层实现原理

索引的底层实现原理 数据库索引是存储在磁盘上的&#xff0c;当数据量大时&#xff0c;就不能把整个索引全部加载到内存了&#xff0c;只能逐一加载每一个磁盘块&#xff08;对应索引树的节点&#xff09;&#xff0c;索引树越低&#xff0c;越“矮胖”&#xff0c;磁盘IO次数…...

Linux 更新

Linux权限系统 01 只读 1 10 只写 2 100 只执行 4 11 可读写 3 101 可读执行 5 110 可写执行 6 111 可读写执行 7...

华为OD机试 - 端口合并(Python)

题目描述 有M个端口组(1<=M<=10), 每个端口组是长度为N的整数数组(1<=N<=100), 如果端口组间存在2个及以上不同端口相同,则认为这2个端口组互相关联,可以合并。 输入描述 第一行输入端口组个数M,再输入M行,每行逗号分割,代表端口组。 备注:端口组内数字…...

分部积分法习题

前置知识&#xff1a;分部积分法 例题 计算积分 I n ∫ [ ( x a ) 2 b 2 ] − k d x ( n ≥ 1 ) I_n\int [(xa)^2b^2]^{-k}dx \quad(n\geq 1) In​∫[(xa)2b2]−kdx(n≥1) 解&#xff1a; \qquad 用分部积分法&#xff0c;对任何自然数 k ≥ 1 k\geq 1 k≥1&#xff0c;…...

C++—非递归【循环】遍历二叉树(前序,中序,后序)思路讲解+代码实现

非递归遍历二叉树 前序中序后序 接下来我们在研究如何使用循环实现遍历二叉树时&#xff0c;以下面的二叉树为例&#xff1a; 在下文的讲解中&#xff0c;不对如何构建这颗二叉树做讲解&#xff0c;直接给出代码&#xff0c;如果有不懂的地方欢迎私信我。 文章中的完整源代码链…...

前端002_初始化项目

1、命名和启动项目 将目录名 vue-admin-template-master 重命名为 db-manager-system 将 db-manager-system/package.json 中的 name 值改为 db-manager-system {"name": "db-manager-system","version": "1.0.1","descriptio…...

组合设计模式

组合模式 组合模式定义使用场景1、文件系统的目录结构&#xff1a;2、组织架构图&#xff1a;3、菜单和菜单项&#xff1a;4、使用场景总结&#xff1a; 角色定义Component 抽象构件角色:Leaf 叶子构件:Composite 树枝构件: 需求背景代码实现Component&#xff08;抽象构件角色…...

【MySQL】多表查询

上一篇介绍了外键约束,外键约束是用于连接两张数据表的,所以在此基础上就有了多表查询 之前的查询都是单表查询,这里我们会将多个数据表的数据结果返回在一张表上 文章目录 1.多表关系2.多表查询2.1 多表查询分类2.2 内连接2.3 外连接2.4 自连接2.5 联合查询2.6子查询 1.多表关…...

关于在线帮助中心你需要思考以下几个问题

搭建帮助中心是大多数企业都在尝试做的事情&#xff0c;它的重要性对于企业来说不言而喻。现在对于企业来说&#xff0c;搭建帮助中心或许不是什么难事&#xff0c;但是关于帮助中心&#xff0c;有几个问题需要思考清楚&#xff0c;才能让其发挥最大的价值。 一、如何让用户养成…...

基于FPGA+JESD204B 时钟双通道 6.4GSPS 高速数据采集模块设计(一)总体方案

本章将根据高速数据采集指标要求&#xff0c;分析并确定高速数据采集模块的设计方 案&#xff0c;由此分析数据存储需求及存储速度需求给出高速大容量数据存储方案&#xff0c;完成 双通道高速数据采集模块总体设计方案&#xff0c;并综合采集、存储方案及 AXIe 接口需求 …...

二、Spring Cloud Alibaba环境搭建

一、依赖环境 SpringCloud Alibaba 依赖 Java 环境来运行。还需要为此配置 Maven环境&#xff0c;请确保是在以下版本环境中安装使用。 64 bit JDK 1.8;Maven 3.2.x。 spring-cloud-alibaba相关网址&#xff1a; 地址&#xff1a;https://github.com/alibaba/spring-cloud-…...

瑞萨e2studio(24)----电容触摸配置(1)

瑞萨e2studio.24--电容触摸配置1 概述硬件准备新建工程工程模板保存工程路径芯片配置工程模板选择时钟配置添加TOUCH驱动配置CapTouch开启调优界面启动 CapTouch 调优通过电容触摸点亮LED 概述 这篇文档将创建一个使用 e2 studio 集成 QE 的电容式触摸应用示例&#xff0c;通…...

数据开发常见问题

目录 环境变量过多或者参数值过长时&#xff0c;为什么提交作业失败&#xff1f; 为什么Shell作业状态和相关的YARN Application状态不一致&#xff1f; 创建作业和执行计划的区别是什么&#xff1f; 如何查看作业运行记录&#xff1f; 如何在OSS上查看日志&#xff1f; 读…...

Ae:橡皮擦工具

橡皮擦工具 Eraser Tool 快捷键&#xff1a;Ctrl B 橡皮擦工具 Eraser Tool在工作原理上同 Ae 中的其它绘画工具&#xff08;画笔、仿制图章&#xff09;工具基本一致&#xff0c;都是通过绘制路径&#xff0c;然后基于此路径进行描边&#xff08;可统称为“绘画描边”&…...

干货 | 正确引用参考文献的6大技巧

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐&#xff5e; 对于学术研究而言&#xff0c;正确引用参考文献非常重要。参考文献不仅展现了自己的学术水平&#xff0c;同时也给研究定位&#xff0c;突显研究在前人研究基础上作出的贡献。 …...

区块链系统探索之路:基于椭圆曲线的私钥与公钥生成

前两节我们探讨了抽象代数的重要概念&#xff1a;有限域&#xff0c;然后研究了基于椭圆曲线上点的怪异”“操作&#xff0c;两者表面看起来牛马不相及&#xff0c;实际上两者在逻辑上有着紧密的联系&#xff0c;简单来说如果我们在椭圆曲线上取一点G,然后让它跟自己做”“操作…...

Linux命令集(Linux常用命令--echo指令篇)

Linux命令集&#xff08;Linux常用命令--echo指令篇&#xff09; Linux常用命令集&#xff08;echo指令篇&#xff09;2.echo(echo)1. 输出自定义内容2. 禁止输出末尾换行符3. 转义功能4. 与特殊字符配合使用实现其余功能 Linux常用命令集&#xff08;echo指令篇&#xff09; 如…...

【电子学会】2023年03月图形化一级 -- 甲壳虫走迷宫

甲壳虫走迷宫 1. 准备工作 &#xff08;1&#xff09;绘制如图所示迷宫背景图&#xff0c;入口在左下角&#xff0c;出口在右上角&#xff0c;线段的颜色为黑色&#xff1b; &#xff08;2&#xff09;删除默认小猫角色&#xff0c;添加角色&#xff1a;Beetle&#xff1b; …...

老外从神话原型中提取的12个品牌个性

老外从神话原型中提取的12个品牌个性 也是西方视角&#xff0c;需要本土化 参照心理学大师荣格的理论&#xff1a;心理学潜意识派 趣讲大白话&#xff1a;品牌的调调是啥 【趣讲信息科技151期】 **************************** 12种原型又归属于4种人性动机。 1、稳定&#xff0…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...