c++隐式类型转换和explicit
什么是隐式转换?
众所周知,C++的基本类型中并非完全的对立,部分数据类型之间是可以进行隐式转换的。
所谓隐式转换,是指不需要用户干预,编译器私下进行的类型转换行为。很多时候用户可能都不知道进行了哪些转换。
为什么要进行隐式转换?
C++面向对象的多态特性,就是通过父类的类型实现对子类的封装。
通过隐式转换,你可以直接将一个子类的对象使用父类的类型进行返回。
在比如,数值和布尔类型的转换,整数和浮点数的转换等。
某些方面来说,隐式转换给C++程序开发者带来了不小的便捷。
C++是一门强类型语言,类型的检查是非常严格的。
如果没有类型的隐式转换,这将给程序开发者带来很多的不便。
当然,凡事都有两面性,在你享受方便快捷的一面时,你不得不面对太过智能以至完全超出了你的控制。
风险就在不知不觉间出现。
C++隐式转换的原则
基本数据类型 基本数据类型的转换以取值范围的作为转换基础(保证精度不丢失)。
隐式转换发生在从小->大的转换中。比如从char转换为int。
从int-》long。
自定义对象 子类对象可以隐式的转换为父类对象。
C++隐式转换发生条件
混合类型的算术运算表达式中。例如:
1
2
3
|
int a = 3; double b = 4.5; a + b; // a将会被自动转换为double类型,转换的结果和b进行加法操作 |
不同类型的赋值操作。例如:
1
2
|
int a = true ; ( bool 类型被转换为 int 类型) int * ptr = null;(null被转换为 int *类型) |
函数参数传值。例如:
1
2
|
void func( double a); func(1); // 1被隐式的转换为double类型1.0 |
函数返回值。例如:
1
2
3
4
|
double add( int a, int b) { return a + b; } //运算的结果会被隐式的转换为double类型返回 |
#参考:http://developer.51cto.com/art/201002/183139.htm
#以上四种情况下的隐式转换,都满足了一个基本原则:低精度 –》 高精度转换。
不满足该原则,隐式转换是不能发生的。
当然这个时候就可以使用与之相对于的显式类型转换(又称强制类型转换),使用方法如下:
double a = 2.0;
int b = (int)a;
使用强制类型转换会导致精度的损失,因此使用时务必确保你已经拥有足够的把握。
隐式转换的风险
隐式转换的风险一般存在于自定义的类构造函数中。
按照默认规定,只有一个参数的构造函数也定义了一个隐式转换,将该构造函数对应数据类型的数据转换为该类对象。
例一
如下面所示:
1
2
3
4
5
6
7
8
|
class String { public : String ( const char * p ); // 用C风格的字符串p作为初始化值 //… } String s1 = “hello”; //OK 隐式转换,等价于String s1 = String(”hello”) |
但是有的时候可能会不需要这种隐式转换,如下:
1
2
3
4
5
6
7
8
|
class String { public : String ( int n ); //本意是预先分配n个字节给字符串 String ( const char * p ); // 用C风格的字符串p作为初始化值 //… } |
下面两种写法比较正常:
String s2 ( 10 ); //OK 分配10个字节的空字符串
String s3 = String ( 10 ); //OK 分配10个字节的空字符串
下面两种写法就比较疑惑了:
String s4 = 10; //编译通过,也是分配10个字节的空字符串
String s5 = ‘a’; //编译通过,分配int(‘a’)个字节的空字符串
s4 和s5 分别把一个int型和char型,隐式转换成了分配若干字节的空字符串,容易令人误解。
#参考:http://blog.csdn.net/smilelance/article/details/1528737
例二
如下例:
1
2
3
4
5
6
7
8
9
10
11
12
|
class Test { public : Test( int a); bool isSame(Test other) { return m_val == other.m_val; } private : int m_val; } |
如下调用:
Test a(10);
If(a.isSame(10)) //该语句将返回true
本来用于两个Test对象的比较,竟然和int类型相等了。
这里就是由于发生了隐式转换,实际比较的是一个临时的Test对象。
这个在程序中是绝对不能允许的。
禁止隐式转换
既然隐式转换存在这么多的风险,那如何能够禁止隐式转换的发生呢。
C++中提供了explicit关键字,在构造函数声明的时候加上explicit关键字,能够禁止隐式转换。使用方法如下:
1
2
3
4
5
6
|
class Test { explicit Test( int a); …… } |
加上该关键字以后,如下的操作是合法的:
1
|
Test(10); |
如下的操作就变成非法的了:
1
|
Test aa = 10; |
这样就可以有效的防止隐式转换的发生,从而能够对程序进行精确控制,达到提高品质的目的。
c++隐式类型转换和explicit的更多相关文章
- 【C++】隐式类型转换和 explicit关键字
来自:黄邦勇帅 1. 当类中带有一个参数的构造函数时,将执形对象的隐式转换,比如有类 A,有一个带有一个参数的构造函数A(int i){}则当出现语句A m=1;就会调用带有一个参数的构造函数来创建对 ...
- 21.C++- "++"操作符重载、隐式转换之explicit关键字、类的类型转换函数
++操作符重载 ++操作符分为前置++和后置++,比如: ++a; a++; ++操作符可以进行全局函数或成员函数重载 重载前置++操作符不需要参数 重载后置++操作符需要一个int类型的占位参数 ...
- 从Qt谈到C++(一):关键字explicit与隐式类型转换
转载:果冻虾仁 提出疑问 当我们新建了一个Qt的widgets应用工程时.会自动生成一个框架,包含了几个文件. 其中有个mainwindow.h的头文件.就是你要操纵的UI主界面了.我们看看其中的一段 ...
- c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast
C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...
- C++的隐式类型转换与转换操作符
C++标准允许隐式类型转换,即对特定的类,在特定条件下,某些参数或变量将隐形转换成类对象(创建临时对象).如果这种转换代价很大(调用类的构造函数),隐式转换将影响性能.隐式转换的发生条件:函数调用中, ...
- 【M21】利用重载技术避免隐式类型转换
1.考虑UPint 的加法+,UPint a, b, result; 为了使result = a+10; result= 10+a; 都能通过编译,操作符重载如下: const UPint opera ...
- operator用法:隐式类型转换
operator它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换). 1.操作符重载C++可以通过operator实现重 ...
- C++ 中operator用法:隐式类型转换
[转]C++ operator两种用法 C++,有时它的确是个耐玩的东东,就比如operator,它有两种用法,一种是operator overloading(操作符重载),一种是operator c ...
- C++进阶--隐式类型转换
//############################################################################ /* 隐式类型转换 * * 类型转换可分为 ...
随机推荐
- [转]Marshaling a SAFEARRAY of Managed Structures by P/Invoke Part 2.
1. Introduction. 1.1 In part 1 of this series of articles, I explained how managed arrays may be tra ...
- 在FooterTemplate内显示DropDownList控件
如果想在Gridview控件FooterTemplate内显示DropDownList控件供用户添加数据时所应用.有两种方法可以实现,一种是在GridView控件的OnRowDataBound事件中写 ...
- 四步走查智能硬件异常Case
此文已由作者于真真授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 相比于软件,智能硬件产品由于涉及硬件和软件两个端的状态,其异常case要更加错综复杂.由于硬件产品的迭代更新 ...
- Microsoft Visio绘图
2000年微软公司收购同名公司后,Visio成为微软公司的产品.Microsoft Visio是Windows 操作系统下运行的流程图软件,它现在是Microsoft Office软件的一个部分.Vi ...
- redis-淘汰策略
将redis用作缓存时,如果内存空间用满,就会自动驱逐老的数据.默认情况下,memcached就是这种方式. LRU是Redis唯一支持的回收算法. maxmemory配置指令 maxmemory用于 ...
- vue坑
项目地址:https://pan.baidu.com/s/1c1Dflp2 使用前提:安装nodejs环境,webpack的配置官网的例子跟着跑一遍,会vue开发 研究webpack+vue研究了一个 ...
- vue.js组件之j间的通讯一 子组件接受父祖件数据
Vue2.0的三种常用传值方式.父传子.子传父.非父子组件传值 在Vue的框架开发的项目过程中,经常会用到组件来管理不同的功能,有一些公共的组件会被提取出来.这时必然会产生一些疑问和需求?比如一个组件 ...
- java 的开发工具IDEA使用 中Debug 调试工具使用
IDEA JetBrains(这个公司的名称翻译过来就是“大脑喷射?”) 公司的宣传语是这么说的:Develop with pleasure!(带着快乐开发!) 话不多说 开始debug 1, ...
- 网站后台登录asp 提示错误号:-2147467259
方法/步骤 1 asp 提示错误号:-2147467259 提示:[] 错误号:-2147467259 错误描述:操作必须使用一个可更新的查询. SQL错误 解决方法 把data文件夹的权限改下 ...
- Long类型比较不能直接用等于
在判断两个Long型数据是否相等的时候遇到了一个问题. 使用“==”的疑问 if (user.getId() == admin.getId()) { return true; } else { ret ...