C++ 的 explicit 关键字
exlicit 的用处
explicit
关键字告诉编译器,拒绝隐式转换。主要修饰以下情况的构造函数:
构造函数只有一个参数
构造函数有多个参数,但是除了第一个参数外都具有默认值
输出:
在 Foo a = 42
这句发生了隐式类型转换,效果就是调用了Foo(int)
并且把 42 作为参数。隐式类型转换有一些便利之处,也会带来一些隐患。( ref《more effective C++》)
如果使用了 explicit
,将会禁止把 42 隐式转换为 class Foo 的实例 a,这句将会在编译时报错。
main.cpp:23:13: error: conversion from ‘int’ to non-scalar type ‘Foo’ requested
(更新)C++11 中 explicit 关键字还能作用于 C++11 的列表初始化语法
此时下面的代码是不允许的:
Note: 似乎不必要限制这种转换, 接受一个 std::initializer_list 作为参数的构造函数也应当省略 explicit, 以便支持拷贝初始化 (例如 MyType m = {1, 2};) (参考Google Style Guide)
More
explicit 可以混用,《C++ F&Q 10.22》有个例子如下, 这里本意是允许 double 隐式转换为 Foo,但是不允许 bool 转换为 Foo。
但是发现可以通过编译,并且打印如下
Foo(double)
这里的 true 先被编译器解释为 (double)true, 即 1.0 ,然后通过 Foo(double) 完成了隐式类型转换。这个与设计的本意不符合,可能会带来困惑或者 bug。
何时使用
expilicit 的使用条件如下:
对于单自变量的构造函数:包括单参数构造函数和除了第一个参数外都有默认值的构造函数适用。
如果不想让它被隐式转换。 根据《More Effective C++》中条款 5:对“类型转换函数保持警觉”,在编程实践中如非必要, 禁止允许隐式类型转换。 因此通常若非设计如此,建议使用 explicit。
以 《More Effective C++》的例子来看,
因此, 如非必要,拒绝隐式类型转换。
参考
http://www.cs.technion.ac.il/users/yechiel/c++-faq/explicit-ctors.html
Scott Meyers,《More Effective C++》
版权声明: 本文为 InfoQ 作者【行者孙】的原创文章。
原文链接:【http://xie.infoq.cn/article/e580ddb6f7e1cbd92eb7358b7】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论