【C++ | 类型转换】转换构造函数、类型转换运算符 详解及例子源码

news2024/12/24 9:42:23

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰:

本文未经允许,不得转发!!!

目录

  • 🎄一、概述
  • 🎄二、转换构造函数(converting constructor)
  • 🎄三、类型转换运算符(conversion operator)
  • 🎄四、总结



在这里插入图片描述

🎄一、概述

C++的内置类型之间会进行隐式的类型:

  • 1、char、short、int、long四个类型混合运算时,较小的(占用字节数小)整数类型会被自动提升为较大的(占用字节数大)整数类型,以确保不会丢失精度;
  • 2、signed类型 和 unsigned类型 混合运算的结果是 unsigned类型;
  • 3、整型(char、short、int、long)和浮点类型(float、double)混合运算时,会自动提升为浮点类型;而且,较短的浮点数类型(如float)会被自动提升为更长的浮点数类型(如double)以进行混合运算,以确保不会丢失精度。

在这里插入图片描述
那么,自定义的类类型是否也可以进行类型转换呢?

C++目标之一就是让自定义类型可以像内置类型一样使用,所以,C++提供了 转换构造函数类型转换运算符 两种成员函数来支持类类型的类型转换。


在这里插入图片描述

🎄二、转换构造函数(converting constructor)

这个小节解决4个问题:
1、为什么需要 转换构造函数
2、什么是 转换构造函数
3、怎样声明、定义 转换构造函数
4、怎样使用 转换构造函数

转换构造函数:属于构造函数的一种,目的是让其他类型的对象可以转换成本类对象。

转换构造函数的几个特点:
1、属于构造函数的一种,没有返回值,函数名和类名一样;
2、只有一个形参,或其他形参都有默认值;
3、形参类型可以是内置类型,也可以是其他类类型;
4、可以使用关键字 explicit 限制隐式转换。

声明、定义转换构造函数
下面以CDate类为例,定义一个将int类型转换成CDate类型的转换构造函数。只接收一个int类型参数:

CDate(int intDate); // 类内声明

// 转换构造函数定义
CDate::CDate(int intDate)
{
	m_year = intDate / 10000;
	m_mon = (intDate / 100) % 100;
	m_day = intDate % 100;
	cout << "Calling Converting Constructor(int)" << ", this=" << this <<endl;
}

转换构造函数的使用
1、转换构造函数也是构造函数,所以可以直接用它创造对象。CDate date(20240627);
2、赋值号=左边为类对象,右边为转换构造函数的形参类型时,会调用转换构造函数。CDate date1 = 20240628;
下面是转换构造函数使用的完整例子:定义了三个转换构造函数,可以将intchar*CDateStr对象转换为CDate对象,其中CDateStr为类类型。

// g++ 20_Trans_Date.cpp
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

class CDateStr
{
public:
	CDateStr(int year, int mon, int day)
	{
		sprintf(str, "%d.%d.%d", year, mon, day);
		cout << "DateStr: " << str << endl;
	}
	const char *GetStr() const
	{
		return str;
	}
private:
	enum {MAX_STR_NUM=64};
	char str[MAX_STR_NUM];
};

class CDate
{
public:
	CDate(int year, int mon, int day);	// 构造函数声明
	CDate(int intDate);					// 转换构造函数声明
	CDate(const char *str);				// 转换构造函数声明
	explicit CDate(const CDateStr &str, int i=0);// 带默认值参数的转换构造函数
	void show()
	{
		cout << "Date: " << m_year << "." << m_mon << "." << m_day << ", this=" << this << endl;
	}
private:
	int m_year;
	int m_mon;
	int m_day;
};

// 构造函数定义
CDate::CDate(int year, int mon, int day)
{
	m_year = year;
	m_mon = mon;
	m_day = day;
	cout << "Calling Constructor" << ", this=" << this <<endl;
}

// 转换构造函数定义
CDate::CDate(int intDate)
{
	m_year = intDate / 10000;
	m_mon = (intDate / 100) % 100;
	m_day = intDate % 100;
	cout << "Calling Converting Constructor(int)" << ", this=" << this <<endl;
}

// 转换构造函数定义
CDate::CDate(const char *str)
{
	if(0 == sscanf(str, "%d.%d.%d", &m_year, &m_mon, &m_day))
	{
		m_year=m_mon=m_day=0;
	}
	cout << "Calling Converting Constructor(char*)" << ", this=" << this <<endl;
}

// 转换构造函数定义
CDate::CDate(const CDateStr &str, int i)
{
	if(0 == sscanf(str.GetStr(), "%d.%d.%d", &m_year, &m_mon, &m_day))
	{
		m_year=m_mon=m_day=0;
	}
	cout << "Calling Converting Constructor(CDateStr)" << ", this=" << this <<endl;
}

int main()
{
	CDate date(20240627);
	date.show();
	cout << endl;
	
	CDate date1 = 20240628;
	date1.show();
	cout << endl;
	
	date1 = "2024.06.29";
	date1.show();
	cout << endl;
	
	CDateStr dateStr(2024,06,30);
	date1 = (CDate)dateStr;
	date1.show();
	cout << endl;

	return 0;
}

运行结果:
在这里插入图片描述


在这里插入图片描述

🎄三、类型转换运算符(conversion operator)

转换构造函数(converting constructor)可以将其他类型的对象转换为本类类型对象。那么怎样将类对象转换为其他类型对象呢?可以使用类型转换运算符(conversion operator)。

这个小节解决4个问题:
1、为什么需要类型转换运算符
2、什么是类型转换运算符
3、怎样声明、定义类型转换运算符
4、怎样使用类型转换运算符

类型转换运算符:是类的成员函数,目的是将本类对象转换为指定类型对象。

类型转换运算符的特点:
1、函数原型没有返回值、没有参数;
2、函数名为关键字operator 类型,类型为要转换的类型;
3、必须要有return语句,return的类型就是要转换为的类型;
4、必须是本类成员函数。
5、转换为的类型可以是内置类型,也可以是其他类类型;
6、C++11支持使用关键字 explicit 限制隐式转换。

声明、定义类型转换运算符
下面以CDate类为例,定义一个将 CDate类型 转换成 int类型 的转换构造函数。

operator int();		// 类型转换运算符

// 类型转换运算符定义
CDate::operator int()
{
	return (int)(m_year*10000 + m_mon*100 + m_day);
}

类型转换运算符的使用
1、类型转换运算符是成员函数,所以可以直调用它,但一般不这样做。int i = date.operator int();
2、显示地将本类对象转换为其他类型对象,或将本类对象赋值给其他类型对象时,会调用类型转换运算符函数。int i = date;
下面是类型转换运算符使用的完整例子,代码是使用上个小节代码修改的:定义了三个类型转换运算符,可以将CDate对象转换为intchar*CDateStr对象,其中CDateStr为类类型。

// g++ 20_Trans_Date.cpp -std=gnu++11
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

class CDateStr
{
public:
	CDateStr(int year, int mon, int day)
	{
		sprintf(str, "%d.%d.%d", year, mon, day);
		cout << "DateStr: " << str << endl;
	}
	const char *GetStr() const
	{
		return str;
	}
private:
	enum {MAX_STR_NUM=64};
	char str[MAX_STR_NUM];
};

class CDate
{
public:
	CDate(int year, int mon, int day);	// 构造函数声明
	CDate(int intDate);					// 转换构造函数声明
	CDate(const char *str);				// 转换构造函数声明
	explicit CDate(const CDateStr &str, int i=0);// 带默认值参数的转换构造函数
	
	operator int();		// 类型转换运算符
	operator char*();	// 类型转换运算符
	explicit operator CDateStr();// 类型转换运算符, C++11支持explicit禁用隐式转换
	
	void show()
	{
		cout << "Date: " << m_year << "." << m_mon << "." << m_day << ", this=" << this << endl;
	}
private:
	int m_year;
	int m_mon;
	int m_day;
};

// 构造函数定义
CDate::CDate(int year, int mon, int day)
{
	m_year = year;
	m_mon = mon;
	m_day = day;
	cout << "Calling Constructor" << ", this=" << this <<endl;
}

// 转换构造函数定义
CDate::CDate(int intDate)
{
	m_year = intDate / 10000;
	m_mon = (intDate / 100) % 100;
	m_day = intDate % 100;
	cout << "Calling Converting Constructor(int)" << ", this=" << this <<endl;
}

// 转换构造函数定义
CDate::CDate(const char *str)
{
	if(0 == sscanf(str, "%d.%d.%d", &m_year, &m_mon, &m_day))
	{
		m_year=m_mon=m_day=0;
	}
	cout << "Calling Converting Constructor(char*)" << ", this=" << this <<endl;
}

// 转换构造函数定义
CDate::CDate(const CDateStr &str, int i)
{
	if(0 == sscanf(str.GetStr(), "%d.%d.%d", &m_year, &m_mon, &m_day))
	{
		m_year=m_mon=m_day=0;
	}
	cout << "Calling Converting Constructor(CDateStr)" << ", this=" << this <<endl;
}

// 类型转换运算符定义
CDate::operator int()
{
	return (int)(m_year*10000 + m_mon*100 + m_day);
}

// 类型转换运算符定义,用完要是否内存
CDate::operator char*()
{
	char *str = new char[64];
	sprintf(str, "%4d.%02d.%02d", m_year, m_mon, m_day);
	return str;
}

// 类型转换运算符定义
CDate::operator CDateStr()
{
	CDateStr dateStr(m_year, m_mon, m_day);
	return dateStr;
}

int main()
{
	CDate date(20240627);
	date.show();
	cout << endl;
	
	CDate date1 = 20240628;
	date1.show();
	cout << endl;
	
	date1 = "2024.06.29";
	date1.show();
	cout << endl;
	
	CDateStr dateStr(2024,06,30);
	date1 = (CDate)dateStr;
	date1.show();
	cout << endl;
	
	int i = date;
	//int i = date.operator int();
	cout << i << endl;
	cout << endl;
	
	char *str = date;
	cout << str << endl;
	cout << endl;
	delete[] str;
	
	CDateStr datestr = (CDateStr)date;
	cout << datestr.GetStr() << endl;
	cout << endl;

	return 0;
}

运行结果:
在这里插入图片描述


在这里插入图片描述

🎄四、总结

👉本文介绍了自定义类型的类型转换,先是介绍 转换构造函数 将其他类型转换为本类类型,然后介绍 类型转换运算符 将本类类型转换为其他类型。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1876776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

steam社区加载异常、加载失败、无法加载、黑屏的解决方法

随着steam夏季特卖的临近&#xff0c;最近几天开启史低折扣的大作已经越来越少了&#xff0c;不过也并不是没有。最经典的知名大作文明6之前已经打到1折的骨折价了&#xff0c;没想到也能背刺&#xff0c;现在是新史低价0.5折11元&#xff0c;很多玩家入手后纷纷前往社区看新手…

SerDes介绍以及原语使用介绍(4)ISERDESE2原语仿真

文章目录 前言一、iserdese2_module模块二、oserdese2_module模块三、顶层模块四、仿真结果分析 前言 上文详细介绍了ISERDESE2原语的使用&#xff0c;本文根据仿真对ISERDESE2原语的使用进一步加深印象。在仿真时&#xff0c;与OSERDESE进行回环。 一、iserdese2_module模块…

程序员学长 | 快速学会一个算法模型,LSTM

本文来源公众号“程序员学长”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;快速学会一个算法模型&#xff0c;LSTM 今天&#xff0c;给大家分享一个超强的算法模型&#xff0c;LSTM。 LSTM&#xff08;Long Short-Term Memory…

AI绘画 Stable Diffusion【实战进阶】:图片的创成式填充,竖图秒变横屏壁纸!想怎么扩就怎么扩!

大家好&#xff0c;我是向阳。 所谓图片的创成式填充&#xff0c;就是基于原有图片进行扩展或延展&#xff0c;在保证图片合理性的同时实现与原图片的高度契合。是目前图像处理中常见应用之一。之前大部分都是通过PS工具来处理的。今天我们来看看在AI绘画工具 Stable Diffusio…

微信内置H5支付

&#x1f9d1;‍&#x1f4bb; 写在开头 点赞 收藏 学会&#x1f923;&#x1f923;&#x1f923; 场景是用户通过微信扫app内的收款码&#xff0c;跳到一个h5页面。然后完成支付。 代码实现的整体流程&#xff1a; 使用微信扫码&#xff0c;码是app内生成的&#xff0c;码…

Qt WPS(有源码)

项目源码地址&#xff1a;WPS完整源码 一.项目详情 该项目仿照WPS&#xff0c;实现了部分的功能&#xff0c;能够很方便对文本和HTML进行修改&#xff0c;并且有打印功能&#xff0c;可以很方便的生成PDF。 应用界面 项目架构分析 这个项目主要可分为两个部分&#xff0c;一…

等保2.0安全计算环境解读

等保2.0&#xff0c;即网络安全等级保护2.0制度&#xff0c;是中国为了适应信息技术的快速发展和安全威胁的新变化而推出的网络安全保护标准。相较于等保1.0&#xff0c;等保2.0更加强调主动防御、动态防御和全面审计&#xff0c;旨在实现对各类信息系统的全面保护。 安全计算环…

鼠尾草(洋苏草)

鼠尾草&#xff08;Salvia japonica Thunb.&#xff09;&#xff0c;又名洋苏草、普通鼠尾草、庭院鼠尾草&#xff0c;属于唇形科鼠尾草属多年生草本植物。鼠尾草以其独特的蓝紫色花序和长而细密的叶片为特点&#xff0c;常用于花坛、庭院和药用植物栽培。 鼠尾草的名字源自于…

Java访问修饰符的区别

public&#xff1a;公开的&#xff0c;任何地方都可以访问。 protected&#xff1a;受保护的&#xff0c;同一个包中的类和所有子类(可跨包)可以访问。 private&#xff1a;私有的&#xff0c;只有在同一个类中可以访问。 默认&#xff08;无修饰符&#xff09;&#xff1a;包级…

[Go 微服务] go-micro + consul 的使用

文章目录 1.go-micro 介绍2.go-micro 的主要功能3.go-micro 安装4.go-micro 的使用4.1 创建服务端4.2 配置服务端 consul4.3 生成客户端 5.goodsinfo 服务5.1 服务端开发5.2 客户端开发 1.go-micro 介绍 Go Micro是一个简化分布式开发 的微服务生态系统&#xff0c;该系统为开…

stm32学习笔记---ADC模数转换器(理论部分)

目录 ADC简介 什么叫逐次逼近型&#xff1f; STM32 ADC框图 模数转换器外围线路 ADC基本结构图 输入通道 规则组的四种转换模式 第一种&#xff1a;单次转换非扫描模式 第二种&#xff1a;连续转换&#xff0c;非扫描模式 第三种&#xff1a;单次转换&#xff0c;扫描…

数据结构03 链表的基本操作【C++数组模拟实现】

前言&#xff1a;本节内容主要了解链表的基本概念及特点&#xff0c;以及能够通过数组模拟学会链表的几种基本操作&#xff0c;下一节我们将通过STL模板完成链表操作&#xff0c;可以通过专栏进入查看下一节哦~ 目录 单链表及其特点 完整链表构成 完整链表简述 创建单链表 …

MySQL自增主键踩坑记录

对于MySQL的自增主键&#xff0c;本文记录、整理下在工作中实际遇到的问题。 下面示例均基于MySQL 8.0 修改列的类型后&#xff0c;自增属性消失 CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL );上面的…

计算机监控软件有哪些?10款常年霸榜的计算机监控软件

计算机监控软件是企业管理和保护信息安全的重要工具&#xff0c;它们帮助企业管理者监督员工的计算机使用行为&#xff0c;确保工作效率、数据安全以及合规性。在众多监控软件中&#xff0c;有些产品因其卓越的功能、易用性、安全性以及持续获得的良好市场反馈而常年占据行业领…

什么是指令微调(LLM)

经过大规模数据预训练后的语言模型已经具备较强的模型能力&#xff0c;能够编码丰富的世界知识&#xff0c;但是由于预训练任务形式所限&#xff0c;这些模型更擅长于文本补全&#xff0c;并不适合直接解决具体的任务。 指令微调是相对“预训练”来讲的&#xff0c;预训练的时…

spring mvc实现一个自定义Formatter请求参数格式化

使用场景 在Spring Boot应用中&#xff0c;Formatter接口用于自定义数据的格式化&#xff0c;比如将日期对象格式化为字符串&#xff0c;或者将字符串解析回日期对象。这在处理HTTP请求和响应时特别有用&#xff0c;尤其是在展示给用户或从用户接收特定格式的数据时。下面通过…

集合,Collection接口

可动态保存任意多个对象&#xff0c;使用比较方便 提供了一系列方便操作对象的方法&#xff1a;add&#xff0c;remove&#xff0c;set&#xff0c;get等 使用集合添加删除新元素&#xff0c;代码简洁明了 单列集合 多列集合 Collection接口 常用方法 List list new Arra…

【原创图解 算法leetcode 146】实现一个LRU缓存淘汰策略策略的数据结构

1 概念 LRU是Least Recently Used的缩写&#xff0c;即最近最少使用&#xff0c;是一种常见的缓存淘汰算法。 其核心思想为&#xff1a;当内存达到上限时&#xff0c;淘汰最久未被访问的缓存。 2 LeetCode LeetCode: 146. LRU缓存 3 实现 通过上面LRU的淘汰策略可知&#…

北京市大兴区餐饮行业协会成立暨职业技能竞赛总结大会成功举办

2024年6月27日下午&#xff0c;北京市大兴区营商服务中心B1层报告厅迎来了北京市大兴区餐饮行业协会成立仪式暨2024年北京市大兴区餐饮行业职工职业技能竞赛总结大会。此次活动不仅标志着大兴区餐饮行业协会的正式成立&#xff0c;也对在2024年大兴区餐饮行业职工职业技能竞赛中…

Python自动化测试:web自动化测试——selenium API、unittest框架的使用

web自动化测试2 1. 设计用例的方法——selenium API1.1 基本元素定位1&#xff09;定位单个唯一元素2&#xff09;定位一组元素3&#xff09;定位多窗口/多框架4&#xff09;定位连续层级5&#xff09;定位下拉框6&#xff09;定位div框 1.2 基本操作1.3 等待1.4 浏览器操作1.5…