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

news2024/12/23 8:44:09

参考

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

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

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

相关文章

windows下开发ffmpeg(亲测可用)下载FFmpeg的源码、库、链接文件(二)

1,首先安装opencv在clion下的使用 参见我的另外一篇文章Windows上使用CLion配置OpenCV环境,亲测可用的方法 2,亲测可以用,建议使用迅雷下载ffmpeg(全部的包都有) Windows10 下 CLion 配置 FFmpeg 开发环境 3,参考文章,碰到系统提示缺少.dll库,问题解决 参考文章1:…

HCIA-RS实验-STP和RSTP(1)

这篇文章开始前&#xff0c;先简单说下这2个协议&#xff1b; 本文介绍了STP和RSTP的基本原理、优缺点以及应用场景。STP和RSTP都是生成树协议&#xff0c;主要作用于避免网络中的环路&#xff0c;保证数据包能够正常转发。在实际应用中&#xff0c;需要根据实际情况选择合适的…

6.MapReduce(1)

本章节将分为InputFormat,split,OutputFormat三个小章节来介绍框架原理 1.InputFormat 1.1 切片: 将输入数据分成几份,每份交给一个MapTask去处理(getSplit方法) 对于MapRedcue,切片发生在客户端,任务提交的时候 机制:MapTask并行度决定机制 切了多少片,就开启多少个M…

颠覆世界的“数字孪生”到底是什么?这篇文章带你搞懂全部内涵!

在春节很火的电影《流浪地球2》中&#xff0c;已经去世的小女孩图丫丫&#xff0c;被她的父亲重新将其个人的信息模型导入最强大的计算机而“复活”了。屏幕中的丫丫就是一个数字孪生体。我们可以看到她的一颦一笑&#xff0c;听到她跟你的对话&#xff0c;看到她做出反应。这就…

【细读Spring Boot源码】启动步骤

前言 版本&#xff1a;spring-boot-2.7.3 | spring-context-5.3.22 main函数 直接使用静态函数启动 public static void main(String[] args) {SpringApplication.run(SettlleApplication.class, args); }静态帮助程序&#xff0c;可用于使用默认设置从指定源运行SpringAppli…

港联证券|人民币大消息!美科技股涨嗨,微软一夜暴增超万亿!

当地时间26日&#xff0c;美股三大股指收盘涨跌纷歧。到收盘&#xff0c;道指报33301.87点&#xff0c;下跌0.68%&#xff1b;标普500指数报4055.99点&#xff0c;下跌0.38%&#xff1b;纳指报11854.35点&#xff0c;上涨0.47%。 榜首共和银行大跌29.75%&#xff0c;该股昨天大…

SuperMap iClient3D for Cesium 构建隧道

背景 前段时间看到一篇构建隧道的文章&#xff08;https://blog.csdn.net/supermapsupport/article/details/128453116&#xff09;&#xff0c;突然想到一个使用场景&#xff1a;隧道通常是建在山体下面&#xff0c;是否可以通过这种方式构建出一条贯穿山体的隧道&#xff0c…

mysql如何加行锁

一、概述 InnoDB 引擎是支持行级锁的&#xff0c;而 MyISAM 引擎并不支持行级锁&#xff0c;所以后面的内容都是基于 InnoDB 引擎的。当我们使用delete、update进行数据库删除、更新的时候&#xff0c;数据库会自动加上行锁。但是&#xff0c;行锁有时也会失效。 数据库版本&a…

正则表达式 - 边界

目录 一、零宽断言 二、行的开始和结束 1 . ^ 与 $ 2. dotall 模式 三、单词边界和非单词边界 1. 统计某个单词出现的次数 2. 统计单词个数 四、主题词的起始与结束位置 五、使用元字符的字面值 六、在段首加标签 一、零宽断言 断言&#xff08;assertions&#xff0…

颜色选择器vue3-colorpicker

其他选择器&#xff1a;一款支持vue3 的颜色选择器 | ColorPickerV3基于vue3的颜色选择器支持颜色透明度与rgba、hexhttps://colorpickerv3.wcrane.cn/guide/#%E7%89%B9%E7%82%B9 这个选择器也挺好看的&#xff0c; 只是貌似不能外部打开选择器面板 官网&#xff1a;Webpack Ap…

第五章:多表查询

一、笛卡尔积的多表查询 1.案例 查询员工名为’Abel’的员工在哪个城市工作? 2.出现笛卡尔积&#xff08;交叉连接&#xff09;的错误 select employee_id, department_name from employees,departments为什么出现2889条记录&#xff1f; Employees 107 Departments 27 …

Python 一元线性回归模型预测实验完整版

一元线性回归预测模型 实验目的 通过一元线性回归预测模型&#xff0c;掌握预测模型的建立和应用方法&#xff0c;了解线性回归模型的基本原理 实验内容 一元线性回归预测模型 实验步骤和过程 (1)第一步&#xff1a;学习一元线性回归预测模型相关知识。 线性回归模型属于…

如何高质量的提问题让chatgpt更明白我们的意图

如何更好地向 ChatGPT 提问 ChatGPT是一款基于深度学习的人工智能语言模型&#xff0c;用户可以通过文本输入向其提问并获得自然语言回答。以下是如何更好地向ChatGPT提问的几个建议&#xff1a; 确定问题类型。ChatGPT的训练数据源广泛&#xff0c;支持各种类型的问题&#x…

[INFOCOM 2019] NeuralWalk:使用神经网络的在线社交网络中的信任评估

NeuralWalk: Trust Assessment in Online Social Networks with Neural Networks | IEEE Conference Publication | IEEE Xplore 摘要&#xff1a; 评估信任社交网络&#xff08;TSN&#xff09;中用户之间的信任是许多应用中的关键问题&#xff0c;例如电影推荐&#xff0c;…

buuctf5

目录 [极客大挑战 2019]BabySQL [极客大挑战 2019]PHP 神秘龙卷风 假如给我三天光明 后门查杀 webshell后门 [极客大挑战 2019]BabySQL 1. 发现存在sql注入 2.使用bp用fuzz字典爆破一下哪些词被过滤了&#xff0c;发现or&#xff0c;select等都被过滤了 尝试双写注入 3.…

Vue.js 框架能力的官方认证

这两天Vue官方推出了Vue.js 认证计划。 即框架能力官方认证&#xff0c;即 Vue.js 框架能力证书。该认证由 Vue School 与 Vue.js 团队合作提供支持。官网&#xff1a;Vue.js - Official Certification Program 官方介绍此次的试题集和代码挑战由 Vue.js 核心团队审核&#xff…

docker 安装 datax和datax-web 之 datax-web登录时提示账号或密码错误

docker 安装docker 安装 datax和datax-web 安装教程地址&#xff1a; https://www.cnblogs.com/leihongnu/p/16612273.html 根据该博客的教程安装成功后&#xff0c;登录页面能打开&#xff0c;但是所提供的账户密码一直报错&#xff0c;这个就需要根据日志一步步去寻找原因了…

《编程思维与实践》1037.一元多项式乘法

《编程思维与实践》1037.一元多项式乘法 题目 思路 比较容易想到将步骤分为三步: 1.读取多项式每项的系数(coefficient)和对应的指数(dim); 2.进行多项式乘法; 3.输出进行多项式乘法后的非零项系数. 其中多项式乘法可以通过循环来处理,输出可以用if来判断系数是否为0,需要考虑…

多重共线性问题如何解决?

​ 一、多重共线性说明 多重共线性一般是指&#xff1a;如果有两个或者多个自变量高度相关&#xff08;相关系数大于0.8&#xff09;&#xff0c;难以区分一个自变量对因变量的影响和作用&#xff0c;将自变量相关性产生的后果定义为多重共线性&#xff0c;一般提出多重共线性…

Pytorch 安装

Pytorch PyTorch介绍 特点&#xff1a; 1.简单易用、分布式训练、服务器部署方便、移动端部署方便&#xff1b; 2.PyTorch 是基于以下两个目的而打造的python科学计算框架&#xff1a; 无缝替换NumPy&#xff0c;并且通过利用GPU的算力来实现神经网络的加速。 3.通过自动…