隐式类型转换操作符,可能导致错误的函数调用,应该提供显示的函数调用
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<false, std::basic_ostream<char>&>’
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<Array<int>>(b[i]))
- 通过explicit禁止隐式转换,报错信息如下:
- error: no match for ‘operator==’ (operand types are ‘Array<int>’ and ‘int’)
- 通过explicit声明的单参数构造函数,还是可以显式调用成功;
template<typename T>
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<int>& lhs, const Array<int>& 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<int> a(2); a[0] = 1; a[1] = 2;
Array<int> b(2); b[0] = 1; b[1] = 2;
for (int i = 0; i < 2; i++) {
// if (a == b[i]) {
if (a == static_cast<Array<int>>(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<int>类型。
template<typename T>
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;
};