关于Explicit还是Implicit一直是编程语言中能让程序员们干起架的争议。那些聪明的老鸟总是觉得Implicit的规则让他们能够一目十行,减少样板代码的羁绊。而很多时候,Implicit的很多规则会让新手或者是合作开发的搭档痛苦不堪。文章的标题也写明了笔者的态度,显式的在代码之中指明自己的意图,会让程序更加明晰。所以也借今天这篇文章,我们来聊聊Explicit关键字。

1.隐式类类型转换

好吧,先看一段代码:

(为了简单起见,我这里就没有重载<<操作符了)

class A {
public:
A(int s) {};
}; void printA(A a) {
cout << "hello" << endl;
} int main() {
printA(10);
}

上面这段代码是可以通过编译运行的,可能有些小伙伴会比较困惑,为虾米这里printA函数明明需要接受的是一个A类型,但是传入的一个int类型仍然能够编译通过。

这就被称之为隐式类类型转换,它存在于自定义的类构造函数中。C++的编译器会对只有一个参数的构造函数也定义了一个隐式转换,将该构造函数对应数据类型的数据转换为该类对象。也就是说,上段代码其实可以翻译成下面的代码:

class A {
public:
A(int s) {};
}; void printA(A a) {
cout << "hello" << endl;
} int main() {
printA(A(10));
}

这里10作为int类型的参数,通过隐式的类类型转换,被默认构造了一个A类型的匿名对象,传入了函数printA,所以代码能够正常的编译运行。显然,这种类型的代码是十分Confused。所以我们来看看这么解决这个问题的。

有一个折衷的解决方案,将代码做下面的修改:

void printA(A &a) {
cout << "hello" << endl;
}

这里通过引用类型就可以避开这个陷阱,因为编译器不会构造这个匿名对象的引用,所以此时的代码是无法通过编译的。

显然,这个方案改变了我们不使用引用类型的初衷,我们看看C++有木有更加优雅的解决方案。

2.Explicit关键字

explicit主要用于"修饰"构造函数,使得它不用于程序中需要通过此构造函数进行"隐式"转换的情况。指定此关键字,需要隐式转换方可进行的程序将不能编译通过。

class A {
public:
explicit A(int s) {};
}; void printA(A a) {
cout << "hello" << endl;
} int main() {
printA(10); //无法通过编译
}

这里我们添加了explicit关键字,阻止了编译器的隐式类类型转换,让代码更加明晰了。当然,我们这里是可以使用static_cast关键字可以显式的类型转换,通过代码的编译。

int main() {
printA(static_cast<A>(32));
}

explicit关键字只对一个参数的构造函数有效,需要多个实参的构造函数不能用于隐式类型转换。

3.讨论一下

  • Scala

    类型系统几乎是Scala之中最复杂的内容,Scala设计的讨巧之处,是通过implicit关键字,显式的指定了隐式类类型转换。虽然隐式类类型转换减少了很多冗余的代码,但是这样的设计会降低代码的可读性。Scala也一直因为可读性被诟病,所以这样的设计,见仁见智。

  • Golang

    如果是接口interface与Python是类似的鸭子类型,不需要什么隐式转换了。

    而如果是struct类的话,那Golang就十分严格的执行强类型的判断。不符合是不行的。

  • Java

    Java一直是拒绝这种Confuse做法的语言,所以通过一大堆繁琐的样板代码规避这样的问题。

“Explicit's better than implicit”。Explicit保证了代码的可读性和维护性。这点对于一个系统的工程性是很有帮助的。Implicit的转换容易带来那种“看上去很美,但是非常容易出错”的 feature 。希望我们能够告别对它的依赖。

C++雾中风景5:Explicit's better than implicit.聊聊Explicit.的更多相关文章

  1. 【转】C#中的implicit 和 explicit

    The implicit and explicit keywords in C# are used when declaring conversion operators. Let's say tha ...

  2. jpa CriteriaQueryNo explicit selection and an implicit one could not be determined

    java.lang.IllegalArgumentException: Error occurred validating the Criteria ... Caused by: java.lang. ...

  3. Implicit and Explicit Multithreading MULTITHREADING AND CHIP MULTIPROCESSORS

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION The concept of thread ...

  4. implicit和explicit的基本使用

    class MyAge { public int Age { get; set; } public static implicit operator MyAge(int age) { return n ...

  5. C# 自己定义 implicit和explicit转换

    explicit 和 implicit 属于转换运算符,如用这两者能够让我们自己定义的类型支持相互交换explicti 表示显式转换.如从 A -> B 必须进行强制类型转换(B = (B)A) ...

  6. C#之自己定义的implicit和explicit转换

    在类型转换时常会遇到隐式转换和显式转换.那我们自己定义的类型要怎样去定义隐式转换和显式转换?我们来看一段代码 public class Rational { private Int32 _inner_ ...

  7. implicit和 explicit关键字

    implicit 关键字用于声明隐式的用户定义类型转换运算符. 如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换. class Digit { publi ...

  8. 显示(explicit )与隐式(implicit)转换操作符

    class Program { static void Main(string[] args) { /* * 不管是显示还是隐式转换,一种类型都只能出现一次 */ Console.WriteLine( ...

  9. 操作符(运算符)重载 或者叫 二元运算符 operator + 与 转换式操作符 implicit operator explicit operator

    static void Main(string[] args) { rational r1 = new rational(5); rational r2 = new rational(51); rat ...

随机推荐

  1. JAVA编程之——反射Reflect

    说到反射,首先要说一下Java中的类和对象. 在Java中万事万物皆对象(有两个 例外,一个是普通数据类型,另一个是静态的东西,静态的东西不是对象的,是属于类的). 在Java中,类也是对象,类是ja ...

  2. Android笔记之开机自启

    有时候需要应用具有开机自启的能力,或者更常见的场景是开机时悄悄在后台启动一个Service. 关键点: 1. Android系统在开机的时候会发送一条广播消息,只需要接收这条广播消息即可,不过需要注意 ...

  3. Python练习-Property的用法

    # 编辑者:闫龙 #要求一:自定义用户信息数据结构,写入文件,然后读出内容,利用eval重新获取数据结构 with open('user.db','w') as write_file:#创建并以写入的 ...

  4. Shell基础-通配符

    * - 通配符,代表任意字符 ? - 通配符,代表一个字符 # - 注释 | - 分隔两个管线命令的界定 ; - 连续性命令的界定 ~ - 用户的根目录 $ - 变量前需要加的变量值 ! - 逻辑运算 ...

  5. Linux操作系统介绍

    1Linux操作系统介绍 1.1linux系统的应用 服务器系统:Web应用服务器.数据库服务器.接口服务器.DNS.FTP等等: 嵌入式系统:路由器.防火墙.手机.PDA.IP 分享器.交换器.家电 ...

  6. vuejs心法和技法

    原文地址:http://www.cnblogs.com/kidsitcn/p/5409994.html 所有的vuejs组件都是被扩展的vue实例: var MyComponent = Vue.ext ...

  7. 2016.6.26——Maximum Depth of Binary Tree

    Maximum Depth of Binary Tree 本题收获 1.树时使用递归 2.注意边界条件时输出的值,仔细阅读题意,若是面试时,问清边界条件. 题目: Given a binary tre ...

  8. linux shell语言编程规范安全篇之通用原则【转】

    shell语言编程规范安全篇是针对bash语言编程中的数据校验.加密与解密.脚本执行.目录&文件操作等方面,描述可能导致安全漏洞或风险的常见编码错误.该规范基于业界最佳实践,并总结了公司内部的 ...

  9. java浅复制与深使用接口实现

    1.浅复制与深复制概念⑴浅复制(浅克隆)被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复 ...

  10. 【自用】bat ftp下载前一天备份

    @echo off rem 指定FTP用户名 set ftpUser=app rem 指定FTP密码 set ftpPass=app rem 指定FTP服务器地址 set ftpIP=192.168. ...