当前位置: 首页 > 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
http://www.lryc.cn/news/64895.html

相关文章:

  • MySQL索引的底层实现原理
  • Linux 更新
  • 华为OD机试 - 端口合并(Python)
  • 分部积分法习题
  • C++—非递归【循环】遍历二叉树(前序,中序,后序)思路讲解+代码实现
  • 前端002_初始化项目
  • 组合设计模式
  • 【MySQL】多表查询
  • 关于在线帮助中心你需要思考以下几个问题
  • 基于FPGA+JESD204B 时钟双通道 6.4GSPS 高速数据采集模块设计(一)总体方案
  • 二、Spring Cloud Alibaba环境搭建
  • 瑞萨e2studio(24)----电容触摸配置(1)
  • 数据开发常见问题
  • Ae:橡皮擦工具
  • 干货 | 正确引用参考文献的6大技巧
  • 区块链系统探索之路:基于椭圆曲线的私钥与公钥生成
  • Linux命令集(Linux常用命令--echo指令篇)
  • 【电子学会】2023年03月图形化一级 -- 甲壳虫走迷宫
  • 老外从神话原型中提取的12个品牌个性
  • unity中的Quaternion.AngleAxis
  • 如何设置渗透测试实验室
  • Java时间类(八)-- Instant (时间戳类)(常用于Date与LocalDateTime的相互转化)
  • C++模板
  • 【JavaEE】HTML基础知识
  • mysql与redis区别
  • Hive本地开发/学习环境配置
  • 《基于EPNCC的脉搏信号特征识别与分类研究》阅读笔记
  • Linux下解压和压缩命令大全(详解+案例)
  • Linux的常用指令
  • 第 5 章 HBase 优化