# 显式转换操作符
C++98标准提供隐式和显式两种构造函数,也就是说,声明为显式形式的构造函数所定义的转换只能用于显式转换,而其他形式的构造函数则用于隐式转换。例如:
```
struct S { S(int); }; // “普通构造函数”默认是隐式转换
S s1(1); // ok, 直接构造
S s2 = 1; // ok, 隐式拷贝构造
void f(S);
// 能通过编译(但是经常会产生意外结果——如果S是vector类型会怎么样呢?)
// 译注:详见下一用例的解释
f(1);
struct E { explicit E(int); }; // 显式构造函数
E e1(1); // ok
E e2 = 1; // 错误(但是常常会让人感到意外——这怎么会错呢?)
void f(E);
// 该处会产生编译错误(而非编译通过),以避免因隐式类型转换而得到莫名其妙的结果。
// 例如std::vector::vector(int size), 该构造函数在标准库中定义为显式类型转换,
// (译注:以避免程序员为了初始化一个只含有一个元素10的数组而写出如下代码:
// vector<int> vec = 10;
// 而实际上该代码的含义却是定义一个初始包含10个元素的数组)
f(1);
```
然而,禁止从构造函数作隐式转换(以避免问题),并没有堵住全部漏洞。如果某个类本身禁止改动,那么可以从另一个不同的类中定义一个转换操作符。例如:
```
struct S { S(int) { } /* … */ };
struct SS {>
int m;
SS(int x) :m(x) { }
// 在struct S无须定义S(SS)——所谓的“非侵入”式做法
operator S() { return S(m); }
};
SS ss(1); // ok; 默认构造函数
S s1 = ss; // ok; 隐式转换为S后调用拷贝构造函数
S s2(ss); // ok; 隐式转换为S后调用直接构造函数
void f(S);
f(ss); // ok; 隐式转换为S后传参
```
(译注:这段代码的意义,实际是通过SS作为中间桥梁,将int转换为S。)
遗憾的是,C++98中无法定义”显式转换操作符”来完全禁止某个类相关的隐式转换(因为除此之外鲜有用武之地)。C++11则高瞻远瞩,添加了这个特性。例如:
```
struct S { S(int) { } };
struct SS {
int m;
SS(int x) :m(x) { }
// 因为结构体S中没有定义构造函数S(SS)
// 无法将SS转换为S,所以只好在SS中定义一个返回S的转换操作符,
// 将自己转换为S。
// 转换动作,可以由目标类型S提供,也可以由源类型SS提供。)
explicit operator S() { return S(m); }
};
SS ss(1); // ok; 默认构造函数
S s1 = ss; // 错误; 拷贝构造函数不能使用显式转换
S s2(ss); // ok; 直接构造函数可以使用显式转换
void f(S);
f(ss); // 错误; 从SS向S的转换必须是显式的.
// 译注: 强制类型转换也可使用显式转换,例如
// S s3 = static_cast<S>(ss);
```
参考:
* Standard: 12.3 Conversions
* [N2333=07-0193] Lois Goldthwaite, Michael Wong, and Jens Maurer:
[Explicit Conversion Operator (Revision 1)](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2333.html).
- C++11 FAQ中文版 - C++11 FAQ
- Stroustrup先生关于中文版的授权许可邮件
- Stroustrup先生关于C++11 FAQ的一些说明
- 关于C++11的一般性的问题
- 您是如何看待C++11的?
- 什么时候C++0x会成为一部正式的标准呢?
- 编译器何时将会实现C++11标准呢?
- 我们何时可以用到新的标准库文件?
- C++0x将提供何种新的语言特性呢?
- C++11会提供哪些新的标准库文件呢?
- C++0x努力要达到的目标有哪些?
- 指导标准委员会的具体设计目标是什么?
- 在哪里可以找到标准委员会的报告?
- 从哪里可以获得有关C++11的学术性和技术性的参考资料?
- 还有哪些地方我可以读到关于 C++0x的资料?
- 有关于C++11的视频吗?
- C++0x难学吗?
- 标准委员会是如何运行的?
- 谁在标准委员会里?
- 实现者应以什么顺序提供C++11特性?
- 将会是C++1x吗?
- 标准中的"concepts"怎么了?
- 有你不喜欢的C++特性吗?
- 关于独立的语言特性的问题
- __cplusplus宏
- alignment(对齐方式)
- 属性(Attributes)
- atomic_operations
- auto – 从初始化中推断数据类型
- C99功能特性
- 枚举类——具有类域和强类型的枚举
- carries_dependency
- 复制和重新抛出异常
- 常量表达式(constexpr)
- decltype – 推断表达式的数据类型
- 控制默认函数——默认或者禁用
- 控制默认函数——移动(move)或者复制(copy)
- 委托构造函数(Delegating constructors)
- 并发性动态初始化和析构
- noexcept – 阻止异常的传播与扩散
- 显式转换操作符
- 扩展整型
- 外部模板声明
- 序列for循环语句
- 返回值类型后置语法
- 类成员的内部初始化
- 继承的构造函数
- 初始化列表
- 内联命名空间
- Lambda表达式
- 用作模板参数的局部类型
- long long(长长整数类型)
- 内存模型
- 预防窄转换
- nullptr——空指针标识
- 对重载(override)的控制: override
- 对重载(override)的控制:final
- POD
- 原生字符串标识
- 右角括号
- 右值引用
- Simple SFINAE rule
- 静态(编译期)断言 — static_assert
- 模板别名(正式的名称为"template typedef")
- 线程本地化存储 (thread_local)
- unicode字符
- 统一初始化的语法和语义
- (广义的)联合体
- 用户定义数据标识(User-defined literals)
- 可变参数模板(Variadic Templates)
- 关于标准库的问题
- abandoning_a_process
- 算法方面的改进
- array
- async()
- atomic_operations
- 条件变量(Condition variables)
- 标准库中容器方面的改进
- std::function 和 std::bind
- std::forward_list
- std::future和std::promise
- 垃圾回收(应用程序二进制接口)
- 无序容器(unordered containers)
- 锁(locks)
- metaprogramming(元编程)and type traits
- 互斥
- 随机数的产生
- 正则表达式(regular expressions)
- 具有作用域的内存分配器
- 共享资源的智能指针——shared_ptr
- smart pointers
- 线程(thread)
- 时间工具程序
- 标准库中的元组(std::tuple)
- unique_ptr
- weak_ptr
- system error