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

相关文章

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

微信公众号脚本-获取热搜自动新建草稿并发布文章

《微信公众号脚本-获取热搜自动新建草稿并发布文章》本来想写一个自动化发布微信公众号的小绿书的脚本,但是微信公众号官网没有小绿书的接口,那就写一个获取热搜微信普通文章的脚本吧,:本文主要介绍微信公众... 目录介绍思路前期准备环境要求获取接口token获取热搜获取热搜数据下载热搜图片给图片加上标题文字上传图片

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

idea中创建新类时自动添加注释的实现

《idea中创建新类时自动添加注释的实现》在每次使用idea创建一个新类时,过了一段时间发现看不懂这个类是用来干嘛的,为了解决这个问题,我们可以设置在创建一个新类时自动添加注释,帮助我们理解这个类的用... 目录前言:详细操作:步骤一:点击上方的 文件(File),点击&nbmyHIgsp;设置(Setti

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark