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++进阶--隐式类型转换
//############################################################################ /* 隐式类型转换 * * 类型转换可分为 ...
随机推荐
- socket网络服务实战
一.epoll模型的构建 由于网络服务高并发的需求,一般socket网络模型都采用epoll模型,有关epoll模型的原理在相关论坛中有许多讲述,在此不做重复讲解,主要讲一讲epoll模型的封装实现. ...
- 阿里开源混沌工程工具 ChaosBlade
https://github.com/chaosblade-io/chaosblade
- 公司内部Wiki及搭建wiki系统-confluence
Wiki 是一个协同著作平台或称开放编辑系统.我们可以用Wiki来建设帮助系统,知识库系统.国内公共wiki最著名就是百度百科.那公司内部为什么要使用wiki呢? 2.内部wiki的作用 1.鼓励分享 ...
- 对MySQL性能影响较大的五类配置参数
以下主要是对MySQL 性能影响关系紧密的五大配置参数的介绍. 一. 连接 连接通常来自Web 服务器,下面列出了一些与连接有关的参数,以及该如何设置它们. (一). ...
- Vue.js 60分钟快速入门
原文链接:http://www.cnblogs.com/keepfool/p/5619070.html Vue.js介绍 Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和 ...
- phantomjs截图中文网站网页页面乱码,安装字体解决
用phantomjs去截取中文页面的网站可能会出现乱码的情况,也就是截图中中文的位置全是方框. 解决办法就是安装字体. 在centos中执行:yum install bitmap-fonts bitm ...
- SpriteBuilder 不能 Portrait
最近用最新的SpriteBuilder V1.3.6和Xcode 6.0.1,发现一个bug.就是在使用Xcode6的时候的SpriteBuilder已经在Project settings 里面设置了 ...
- 【论文】CornerNet:几点疑问
1.cornerpooling的设计,个人觉得解释有些牵强. 这里的两个特征图如何解释,corner点为何是横向与纵向响应最强的点.如果仅仅当成一种奇特的池化方式,恰好也有着不错的效果,那倒是可以接受 ...
- C#后端调用WebApi地址
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using Syst ...
- AngularJS页面【uib-dropdown】控件在模态窗口(弹出窗)中无法使用问题
如果你的下拉框中有属性 dropdown-append-to-body 将它去掉,即可正常使用该插件. <div class="btn-group dropdown" uib ...