掘根宝典之类的自动类型转换和强制类型转换(转换构造函数,转换函数,关键字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

相关文章

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过