【More Effective C++】条款5:警惕隐式类型转换

隐式类型转换操作符,可能导致错误的函数调用,应该提供显示的函数调用

class Rational {
public:
    Rational(int numerator = 0, int denominator = 1) : _numerator(numerator), _denominator(denominator) {}
    // 隐式类型转换操作符
    // operator double() const {
    //     return double(_numerator)/_denominator;
    // }
    double asDouble() const {
        return double(_numerator)/_denominator;
    }

private:
    int _numerator;
    int _denominator;
};

int main() {
    Rational r(1, 2);
    std::cout << r << "\n"; // error: no type named ‘type’ in ‘struct std::enable_if&>’
    std::cout << r.asDouble() << "\n";
    // double d = r*0.5;
    // std::cout << d << "\n";
    return 0;
}

但个参数的构造函数也会存在隐式转换,考虑如下场景:

  • if (a == b[i]) 忘记写了a[i],编译器不会报错,是因为发生的隐式转换;

    • 转换成这种形式 if (a == static_cast>(b[i]))

  • 通过explicit禁止隐式转换,报错信息如下:
    •  error: no match for ‘operator==’ (operand types are ‘Array’ and ‘int’)
  • 通过explicit声明的单参数构造函数,还是可以显式调用成功;
template
class Array {
public:
    Array(int lowBound, int highBound) {}
    explicit Array(int size) : _size(size) {
        data = new T(_size);
    }
    T& operator[](int index) const {
        if (index >= _size) std::out_of_range("out_of_range");
        return data[index];
    }
    int size() const { return _size; }
private:
    T* data;
    int _size;
};
bool operator==(const Array& lhs, const Array& rhs) {
    if (lhs.size() != rhs.size()) return false;
    for (int i = 0; i < lhs.size(); i++) {
        if (lhs[i] != rhs[i]) return false;
    }
    return true;
}

int main() {
    Array a(2); a[0] = 1; a[1] = 2;
    Array b(2); b[0] = 1; b[1] = 2;
    for (int i = 0; i < 2; i++) {
        // if (a == b[i]) {
        if (a == static_cast>(b[i]))
            std::cout << "equal\n";
        } else {
            std::cout << "not equal\n";
        }
    }
    return 0;
}

还可以通过proxy class方式来禁止隐式转换:

  • if (a == b[i]),该步骤中隐式转换会经过两次用户定制的转换,该行为是不被允许的
    • b[i]从一个int先会被转换为ArraySize类型,
    • 然后从ArraySize转换为Array类型。
template
class Array {
public:
    class ArraySize {
    public:
        ArraySize(int numElements) : theSize(numElements) {}
        int size() const { return theSize; }
    private:
        int theSize;
    };
    Array(ArraySize size) : _size(size.size()) {
        data = new T(_size);
    }
    T& operator[](int index) const {
        if (index >= _size) std::out_of_range("out_of_range");
        return data[index];
    }
    int size() const { return _size; }
private:
    T* data;
    int _size;
};

你可能感兴趣的:(More,Effective,C++,c++,开发语言)