什么是隐式转换?

众所周知,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
inta = true; (bool类型被转换为int类型)
int* ptr = null;(null被转换为int*类型)

函数参数传值。例如:

1
2
voidfunc(doublea);
func(1); // 1被隐式的转换为double类型1.0

函数返回值。例如:

1
2
3
4
doubleadd(inta, intb)
{
    returna + 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
classTest
{
public:
  Test(inta);
  boolisSame(Test other)
  {
    returnm_val == other.m_val;
  }
private
  intm_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的更多相关文章

  1. 【C++】隐式类型转换和 explicit关键字

    来自:黄邦勇帅 1. 当类中带有一个参数的构造函数时,将执形对象的隐式转换,比如有类 A,有一个带有一个参数的构造函数A(int i){}则当出现语句A m=1;就会调用带有一个参数的构造函数来创建对 ...

  2. 21.C++- "++"操作符重载、隐式转换之explicit关键字、类的类型转换函数

    ++操作符重载 ++操作符分为前置++和后置++,比如: ++a;  a++; ++操作符可以进行全局函数或成员函数重载 重载前置++操作符不需要参数 重载后置++操作符需要一个int类型的占位参数 ...

  3. 从Qt谈到C++(一):关键字explicit与隐式类型转换

    转载:果冻虾仁 提出疑问 当我们新建了一个Qt的widgets应用工程时.会自动生成一个框架,包含了几个文件. 其中有个mainwindow.h的头文件.就是你要操纵的UI主界面了.我们看看其中的一段 ...

  4. c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast

    C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...

  5. C++的隐式类型转换与转换操作符

    C++标准允许隐式类型转换,即对特定的类,在特定条件下,某些参数或变量将隐形转换成类对象(创建临时对象).如果这种转换代价很大(调用类的构造函数),隐式转换将影响性能.隐式转换的发生条件:函数调用中, ...

  6. 【M21】利用重载技术避免隐式类型转换

    1.考虑UPint 的加法+,UPint a, b, result; 为了使result = a+10; result= 10+a; 都能通过编译,操作符重载如下: const UPint opera ...

  7. operator用法:隐式类型转换

    operator它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换). 1.操作符重载C++可以通过operator实现重 ...

  8. C++ 中operator用法:隐式类型转换

    [转]C++ operator两种用法 C++,有时它的确是个耐玩的东东,就比如operator,它有两种用法,一种是operator overloading(操作符重载),一种是operator c ...

  9. C++进阶--隐式类型转换

    //############################################################################ /* 隐式类型转换 * * 类型转换可分为 ...

随机推荐

  1. socket网络服务实战

    一.epoll模型的构建 由于网络服务高并发的需求,一般socket网络模型都采用epoll模型,有关epoll模型的原理在相关论坛中有许多讲述,在此不做重复讲解,主要讲一讲epoll模型的封装实现. ...

  2. 阿里开源混沌工程工具 ChaosBlade

    https://github.com/chaosblade-io/chaosblade

  3. 公司内部Wiki及搭建wiki系统-confluence

    Wiki 是一个协同著作平台或称开放编辑系统.我们可以用Wiki来建设帮助系统,知识库系统.国内公共wiki最著名就是百度百科.那公司内部为什么要使用wiki呢? 2.内部wiki的作用 1.鼓励分享 ...

  4. 对MySQL性能影响较大的五类配置参数

    以下主要是对MySQL 性能影响关系紧密的五大配置参数的介绍. 一.      连接 连接通常来自Web 服务器,下面列出了一些与连接有关的参数,以及该如何设置它们. (一).             ...

  5. Vue.js 60分钟快速入门

    原文链接:http://www.cnblogs.com/keepfool/p/5619070.html Vue.js介绍 Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和 ...

  6. phantomjs截图中文网站网页页面乱码,安装字体解决

    用phantomjs去截取中文页面的网站可能会出现乱码的情况,也就是截图中中文的位置全是方框. 解决办法就是安装字体. 在centos中执行:yum install bitmap-fonts bitm ...

  7. SpriteBuilder 不能 Portrait

    最近用最新的SpriteBuilder V1.3.6和Xcode 6.0.1,发现一个bug.就是在使用Xcode6的时候的SpriteBuilder已经在Project settings 里面设置了 ...

  8. 【论文】CornerNet:几点疑问

    1.cornerpooling的设计,个人觉得解释有些牵强. 这里的两个特征图如何解释,corner点为何是横向与纵向响应最强的点.如果仅仅当成一种奇特的池化方式,恰好也有着不错的效果,那倒是可以接受 ...

  9. C#后端调用WebApi地址

    using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using Syst ...

  10. AngularJS页面【uib-dropdown】控件在模态窗口(弹出窗)中无法使用问题

    如果你的下拉框中有属性 dropdown-append-to-body 将它去掉,即可正常使用该插件. <div class="btn-group dropdown" uib ...