掘根宝典之类的自动类型转换和强制类型转换(转换构造函数,转换函数,关键字explicit)

本文主要是介绍掘根宝典之类的自动类型转换和强制类型转换(转换构造函数,转换函数,关键字explicit),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C++如何处理内置类型转换

我们先来复习一下C++是如何处理内置类型转换的。将一个标准类型变量的值赋给另一种标准类型的变量时,如果这两种类型兼容,则C++自动将这个值转换为接受变量的类型。比如像下面这样

long a=8;
double b=9;
int c=9.0;

这是因为在C++看来,各种数值类型都表示相同的东西——一个数字,同时C++包含用于进行转换的内置规则。

不过C++不自动转换不兼容的类型

int* a=10;//这是不行的

这个时候我们就要用到强制类型转换了。

int*a=(int*)10;

类的自动转换和强制类型转换

我们可以将类定义成与基本类型或另一个类相关,使得从一种类型转换为另一种类型是有意义的

自动转换(转换构造函数)

1.在C++中,接受一个参数的构造函数为将该类型与参数相同的值转换为类提供了蓝图。

下面看个例子

#include<iostream>
using namespace std;
class AA
{
private:int a;
public:AA(int a_){a = a_;}~AA(){}
};
int main()
{AA a = 3;//将int类型转换为AA类
}

程序将使用构造函数AA(int a_)创建一个临时的AA对象,并将3作为初始化值。随后采用逐成员赋值方式将该临时对象的内容复制到a,这个过程叫隐式转换,因为它是自动进行的,因此不需要显式类型转换。

注意:只有只接受一个参数的构造函数才能作为转换函数

2.有多个参数的构造函数不能用来转换类型,下面看个例子

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:AA(int a,int b){a_ = a;b_ = b;}~AA(){}
};
int main()
{AA a = 3;//这是不行的
}

上面这是不行的

但是如果给第二个参数提供默认值,它便可以用于int

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:AA(int a,int b=5){a_ = a;b_ = b;}~AA(){}
};
int main()
{AA a = 3;//这是可以的
}

3.C++允许使用构造函数来转换其他数值类型

也就是说,C++将允许下面这种情况的发生

#include<iostream>
using namespace std;
class AA
{
private:int a;
public:AA(int a_){a = a_;}~AA(){}
};
int main()
{AA a = 3.0//将浮点型先转换为int类型,再转换为AA类
}

但是当且仅当不存在二义性时,才会进行这种二步转换

像下面这种情况编译器将禁止这种转换

using namespace std;
class AA
{
private:int a;
public:AA(int a_)//第一个构造函数{a = a_;}AA(char a_)//第二个构造函数{a = a_;}~AA() {}
};
int main()
{AA a = 3.0;//存在二义性,编译器将禁止这种情况的发生
}

编译器不知道把3.0转化为int类型还是char类型,这会导致出现错误

关键字explicit

将构造函数用于自动类型转换函数似乎是一项不错的特性。

但是,当程序员有了更丰富的C++经验时,将发现这种自动特性并非总是合乎需要的,因为这会导致意外的类型转换。因此C++新增了关键字explicit用于关闭这种自动转换特性

也就是说,我们可以这样声明构造函数

explicit AA(int a_);

看看例子

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:explicit AA(int a, int b=5){a_ = a;b_ = b;}~AA() {}
};
int main()
{AA a = 3;//这是不行的AA b=(AA)5;//这是可以的AA c=(AA)5.0;//这是可以的
}

使用explicit将关闭这种自动特性,但是只允许强制类型转换

转换函数

在上面都是别的类型转换为类类型,那我们可以做相反的转换吗?也就是说我们可以将AA类转换为int等类型吗?

当然可以

构造函数只用于从某种类型到类类型的转换。要进行相反的转换,必须使用特殊的C++运算符函数——转换函数。

创建转换函数

要转换为typename类型,就要使用下面这种形式的转换函数

operator typename();

比如说要转换为int类型,我们就要用

operator int();

注意点:

1.转换函数必须是类方法

2.转换函数不能指定返回类型

3.转换函数不能有参数

例子(1)

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:explicit AA(int a, int b = 5){a_ = a;b_ = b;}operator int() const{return a_;}~AA() {}
};
int main()
{AA b = (AA)5;int c = b;//这是可以的cout << c << endl;
}

打印出了5

例子(2)

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:AA(int a, int b ){a_ = a;b_ = b;}operator int(){return a_;}operator double(){return b_;}~AA() {}
};
int main()
{AA b = { 2,3 };int c = b;//未发生二义性cout << c << endl;long d = b;//发生了二义性
}

我们发现b不知道使用哪个转换函数,存在二义性

不过只定义一个转换函数就不会有这种情况发生

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:AA(int a, int b ){a_ = a;b_ = b;}operator int(){return a_;}~AA() {}
};
int main()
{AA b = { 2,3 };int c = b;cout << c << endl;long d = b;//未发生二义性cout<<d<<endl;
}

 由于类里只定义了一个转换函数,所以只能调用那个int的

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:AA(int a, int b){a_ = a;b_ = b;}operator double(){return b_;}~AA() {}
};
int main()
{AA b = { 2,3 };int c = b;//未发生二义性cout << c << endl;long d = b;//未发生了二义性cout<<d<<endl;
}

 由于类里只定义了一个转换函数,所以只能调用那个double的

有人想说我就想定义两个转换函数呢?那我们怎么转换呢?

答案是使用强制类型转换

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:AA(int a, int b){a_ = a;b_ = b;}operator int(){return a_;}operator double(){return b_;}~AA() {}
};
int main()
{AA b = { 2,3 };long d =(int) b;//未发生二义性long e = (double)b;//未发生二义性
}

关键字explicit

我们可以用explicit关键字关闭这种自动转换类型

#include<iostream>
using namespace std;
class AA
{
private:int a_;int b_;
public:explicit AA(int a, int b = 5){a_ = a;b_ = b;}explicit operator int() const{return a_;}~AA() {}
};
int main()
{AA b = (AA)5;int c = b;//这是不行的,这时必须使用显式类型转换cout << c << endl;
}

我们就必须使用强制类型转换来实现类型转换

这篇关于掘根宝典之类的自动类型转换和强制类型转换(转换构造函数,转换函数,关键字explicit)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/705543

相关文章

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

python实现svg图片转换为png和gif

《python实现svg图片转换为png和gif》这篇文章主要为大家详细介绍了python如何实现将svg图片格式转换为png和gif,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录python实现svg图片转换为png和gifpython实现图片格式之间的相互转换延展:基于Py

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注