什么是隐式转换?

众所周知,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. unity编辑器拓展

    [ExecutelnEditMode]     在EditMode下也可以执行脚本,Unity默认情况下,脚本只有运行时被执行,加上此属性后,不运行程序也能执行.与PlayMode不同的是函数不会不停 ...

  2. 【bzoj3122】: [Sdoi2013]随机数生成器 数论-BSGS

    [bzoj3122]: [Sdoi2013]随机数生成器 当a>=2 化简得 然后 BSGS 求解 其他的特判 : 当 x=t  n=1 当 a=1  当 a=0 判断b==t /* http: ...

  3. java.text.ParseException: Failed to parse date ["未知']

    先把"未知"替换为"" 直接new 出来的Gson 对象是无法解析为""的Date属性的,需要通过GsonBuilder来进行创建 Gson ...

  4. 牛客nowcoder NOIP普及组第三场

    qtmd AK了 直接题解吧 题目链接 A-十七边形 牛牛想在一个半径为r的圆中,找到一个内接的十七边形,使他的面积最大.输入半径r,输出最大的面积. 1 <= r <= 10000 在1 ...

  5. C++并发低级接口:std::thread和std::promise

    std::thread和std::promise 相比std::async,std::thread就原始多了.thread一定会创建新线程(而不是像async那样创建的时候可能不会,后面才创建新线程( ...

  6. kuangbin专题十六 KMP&&扩展KMP HDU3746 Cyclic Nacklace

    CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, ...

  7. pytorch搭建网络,保存参数,恢复参数

    这是看过莫凡python的学习笔记. 搭建网络,两种方式 (1)建立Sequential对象 import torch net = torch.nn.Sequential( torch.nn.Line ...

  8. gradle 使用本地maven 仓库 和 提交代码到maven

    /* * This build file was generated by the Gradle 'init' task. * * This generated file contains a sam ...

  9. django 自带的验证功能

    django.contrib.auth提供了很多验证方法 authenticate(): 提供了用户认证,在自带的数据库表中验证用户名和密码,需要username和password两个关键字参数 如果 ...

  10. Java实现范围内随机数

    JDK1.7及以上 int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1); // 包含max,所以要加1 JDK1.7以前 ...