以下节选自More Effective C++,觉得是对你的问题的一个很好的说明。建议你看看More Effective C++ Item 5:
C++编译器能够在两种数据类型之间进行隐式转换(implicit conversions),你对这些类型转换是无能为力的,因为它们是语言本身的特性。不过当你增加自己的类型时,你就可以有更多的控制力,因为你能选择是否提供函数让编译器进行隐式类型转换。有两种函数允许编译器进行这些的转换:单参数构造函数(single-argument constructors)和隐式类型转换运算符。 单参数构造函数是指只用一个参数即可以调用的构造函数。该函数可以是只定义了一个参数,也可以是虽定义了多个参数但第一个参数以后的所有参数都有缺省值。以下有两个例子: class Name { // for names of things public: Name(const string& s); // 转换 string 到 // Name ... }; class Rational { // 有理数类 public: Rational(int numerator = 0, // 转换int到 int denominator = 1); // 有理数类 ... }; 通过单参数构造函数进行隐式类型转换更难消除。而且在很多情况下这些函数所导致的问题要甚于隐式类型转换运算符。 举一个例子,一个array类模板,这些数组需要调用者确定边界的上限与下限: template <class T> class Array { public: Array(int lowBound, int highBound); Array(int size); T& operator[](int index); ... }; 第一个构造函数允许调用者确定数组索引的范围,例如从10到20。它是一个两参数构造函数,所以不能做为类型转换函数。第二个构造函数让调用者仅仅定义数组元素的个数(使用方法与内置数组的使用相似),不过不同的是它能做为类型转换函数使用,能导致无穷的痛苦。 例如比较Array <int> 对象,部分代码如下: bool operator==( const Array <int> & lhs, const Array <int> & rhs); Array <int> a(10); Array <int> b(10); ... for (int i = 0; i < 10; ++i) if (a == b[i]) { // 哎呦! "a " 应该是 "a[i] " do something for when a[i] and b[i] are equal; } else { do something for when they 're not; } 我们想用a的每个元素与b的每个元素相比较,但是当录入a时,我们偶然忘记了数组下标。当然我们希望编译器能报出各种各样的警告信息,但是它根本没有。因为它把这个调用看成用Array <int> 参数(对于a)和int(对于b[i])参数调用operator==函数,然而没有operator==函数是这样的参数类型,我们的编译器注意到它能通过调用Array <int> 构造函数能转换int类型到Array <int> 类型,这个构造函数只有一个int类型的参数。然后编译器如此去编译,生成的代码就象这样: for (int i = 0; i < 10; ++i) if (a == static_cast < Array <int> > (b[i])) ... 每一次循环都把a的内容与一个大小为b[i]的临时数组(内容是未定义的)比较。这不仅不可能以正确的方法运行,而且还是效率低下的。因为每一次循环我们都必须建立和释放Array <int> 对象 |
explicit 用法
最新推荐文章于 2024-07-08 21:02:58 发布