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

相关文章

PostgreSQL中rank()窗口函数实用指南与示例

《PostgreSQL中rank()窗口函数实用指南与示例》在数据分析和数据库管理中,经常需要对数据进行排名操作,PostgreSQL提供了强大的窗口函数rank(),可以方便地对结果集中的行进行排名... 目录一、rank()函数简介二、基础示例:部门内员工薪资排名示例数据排名查询三、高级应用示例1. 每

全面掌握 SQL 中的 DATEDIFF函数及用法最佳实践

《全面掌握SQL中的DATEDIFF函数及用法最佳实践》本文解析DATEDIFF在不同数据库中的差异,强调其边界计算原理,探讨应用场景及陷阱,推荐根据需求选择TIMESTAMPDIFF或inte... 目录1. 核心概念:DATEDIFF 究竟在计算什么?2. 主流数据库中的 DATEDIFF 实现2.1

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

MySQL 中的 CAST 函数详解及常见用法

《MySQL中的CAST函数详解及常见用法》CAST函数是MySQL中用于数据类型转换的重要函数,它允许你将一个值从一种数据类型转换为另一种数据类型,本文给大家介绍MySQL中的CAST... 目录mysql 中的 CAST 函数详解一、基本语法二、支持的数据类型三、常见用法示例1. 字符串转数字2. 数字

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分