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

😁博客主页😁:🚀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;
}

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


在这里插入图片描述

🎄四、总结

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

认识100种电路之稳压电路

在电子电路中&#xff0c;稳压电路扮演着至关重要的角色。那么&#xff0c;为什么电路需要稳压&#xff1f;稳压的原理又是什么&#xff1f;以及稳压需要用到哪些元器件&#xff0c;数量又有多少呢&#xff1f;今天&#xff0c;就让我们一同揭开稳压电路的神秘面纱。 【电路为什…

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

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

Zookeeper节点ACL权限设置—digest模式

ACL全称为Access Control List&#xff08;访问控制列表&#xff09;&#xff0c;用于控制资源的访问权限。ZooKeeper使用ACL来控制对其znode&#xff08;ZooKeeper数据树的数据节点&#xff09;的访问。 zk利用ACL策略控制节点的访问权限: CREATE c 可以创建子节点 DELETE …

Java中System的用法

System指的是当前进程运行的操作系统&#xff0c;属于java.lang包下面的类 常见的用法有以下几种&#xff1a; 第一种简单,我们直接上第二种方法吧 currentTimeMills()用法 // 演示currentTimeMillis方法public static void main(String[] args) {// 获取当前时间所对应的毫秒…

《红黑树大能量——set,map封装模拟》

前言 书接上篇博客《手撕红黑树》&#xff0c;我们学习到了红黑树是如何通过其内部方式来管理数据的&#xff0c;本篇文章将基于上篇文章继续探讨红黑树的更多应用。set&#xff0c;map是STL库中很重要的容器&#xff0c;他们就是利用红黑树作为底层来实现的&#xff0c;今天让…

入门Java爬虫:认识其基本概念和应用方法

Java爬虫初探&#xff1a;了解它的基本概念与用途&#xff0c;需要具体代码示例 随着互联网的快速发展&#xff0c;获取并处理大量的数据成为企业和个人不可或缺的一项任务。而爬虫&#xff08;Web Scraping&#xff09;作为一种自动化的数据获取方法&#xff0c;不仅能够快速…

数据结构--堆(图文)

在开始学习堆之前&#xff0c;我们要先简单了解二叉树 二叉树 一棵二叉树是结点的一个有限集合&#xff0c;该集合: 为空由一个根结点加上两棵子树&#xff08;左子树和右子树&#xff09; 特殊的二叉树&#xff1a; 满二叉树&#xff1a;一个二叉树&#xff0c;如果每一…

【高考】人生规划指南

作为一个正处在这个选择的十字路口的高考考生&#xff0c;我认为在选择专业和学校时&#xff0c;要根据自己的具体情况和个人目标来权衡。首先&#xff0c;我认为专业是首要考虑因素。因为专业是直接决定未来职业发展方向的&#xff0c;如果不喜欢或者不适合的专业选择&#xf…

1976 ssm 营地管理系统开发mysql数据库web结构java编程计算机网页源码Myeclipse项目

一、源码特点 ssm 营地管理系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开…

C++【引用】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

2024年Stable Diffusion应用入门,AI绘画超详细兼职攻略,从零开始!

. AI绘画&#xff1a; 利用AI工具在AI绘画上的应用非常广泛&#xff0c;涵盖了从艺术创作到工业设计等多个领域。 目前市面上有许多AI绘画软件和工具&#xff0c;适合不同需求的用户。 例如&#xff0c;Midjourney、DALL-E 2、Stable Diffusion、DreamStudio等都是较为知名的…

docker配置容器——环境变量

很多时候&#xff0c;我们需要为运行在容器中的应用程序提供一些配置。配置通常用于允许同一个容器在完全不同的环境中运行&#xff0c;例如开发、测试或生产环境。在 Linux 中&#xff0c;配置值通常通过环境变量提供。我们已经了解到&#xff0c;在容器内运行的应用程序与其主…

快手正式推出Vision Pro版本,引领虚拟现实社交新潮流

6月28日&#xff0c;快手正式推出其专为Apple Vision Pro打造的版本——快手vp版app&#xff0c;成为国内首批登陆Apple Vision Pro的短视频平台。 借助先进的虚拟现实技术&#xff0c;用户可以在快手上体验更真实生动的视频内容&#xff0c;无论是观看趣味短视频内容&#xf…

Ubuntu20.04安装Prometheus监控系统

环境准备&#xff1a; 服务器名称内网IP公网IPPrometheus服务器192.168.0.23047.119.21.167Grafana服务器192.168.0.23147.119.22.8被监控服务器192.168.0.23247.119.22.82 更改主机名方便辨认 hostnamectl set-hostname prometheus hostnamectl set-hostname grafana hostn…

电脑文件夹里的表格删除了怎样恢复?别急,可这样做

在日常工作中&#xff0c;我们经常会使用到各种电子表格来记录、整理和分析数据。然而&#xff0c;有时由于操作失误或其他原因&#xff0c;我们可能会不小心将电脑文件夹中的重要表格删除。面对这种情况&#xff0c;许多人可能会感到惊慌失措&#xff0c;担心数据丢失会给工作…

【wsl2】WIN11借助wsl2挂载ext4磁盘

我有一块ext4文件系统的硬盘&#xff0c;想要在win11上访问&#xff0c;我们可以通过wsl2进行挂载 wsl2的安装就跳过了&#xff0c;可以自行搜索安装。 安装完成后 >>> GET-CimInstance -query "SELECT * from Win32_DiskDrive"通过这个命令&#xff0c;可…

2024下半年必追国漫片单,谁将问鼎巅峰?

随着2024年上半年的落幕&#xff0c;国漫市场再度迎来了百花齐放的盛况。从经典续作到全新IP&#xff0c;从玄幻到科幻&#xff0c;每一部作品都以其独特的魅力吸引着观众的目光。本期为大家盘点下半年值得一看的国漫佳作&#xff0c;大胆预测&#xff0c;谁将成为这场神仙打架…

STM32开发方式的演变与未来展望

一、STM32开发方式的演变 自2007年STM32微控制器首次亮相以来&#xff0c;其开发方式经历了从寄存器到标准库&#xff0c;再到HAL&#xff08;硬件抽象层&#xff09;的演变。 1.寄存器开发&#xff08;2007年-2010年代初&#xff09; 最初&#xff0c;由于初期缺乏足够的软…

基于NURBS曲线的数据拟合算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1NURBS曲线基础 4.2 数据拟合原理 5.完整程序 1.程序功能描述 基于NURBS曲线的数据拟合算法,非均匀有理B样条&#xff08;Non-Uniform Rational B-Splines&#xff0c;简称NURBS&#xf…

探究电子电路中的电压与电平转换

1. 引言 昨天跟好朋友讨论一个项目的时候,我朋友就给我画了一个简化版的电路图&#xff0c;如下图所示&#xff1a; 总觉得这个电路怪怪的&#xff0c;clk信号怎么直接接稳压电路呢。就产生了一个疑问&#xff0c;电平转换和电压转换的区别是啥&#xff1f;稳压电路还有升降压…