【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<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;
};

相关推荐

  1. 【More Effective C++】5警惕类型转换

    2024-02-12 16:42:01       61 阅读
  2. 显示-》初始化 & 类型转换

    2024-02-12 16:42:01       24 阅读
  3. 【mysql】有关mysql查询类型转换的问题

    2024-02-12 16:42:01       60 阅读
  4. js中如何进行类型转换

    2024-02-12 16:42:01       33 阅读
  5. C#中的类型转换和显类型转换

    2024-02-12 16:42:01       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-12 16:42:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-12 16:42:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-12 16:42:01       82 阅读
  4. Python语言-面向对象

    2024-02-12 16:42:01       91 阅读

热门阅读

  1. js_表格全选反选

    2024-02-12 16:42:01       44 阅读
  2. Leetcode 300 最长递增子序列

    2024-02-12 16:42:01       54 阅读
  3. Leetcode 3036. Number of Subarrays That Match a Pattern II

    2024-02-12 16:42:01       69 阅读
  4. C# Avalonia 折线图

    2024-02-12 16:42:01       58 阅读
  5. 倒计时56天

    2024-02-12 16:42:01       57 阅读
  6. 100条安全原则来制定安全策略

    2024-02-12 16:42:01       51 阅读
  7. Jedis

    Jedis

    2024-02-12 16:42:01      55 阅读
  8. tsgctf-2021-lkgit-无锁竞争-userfaultfd

    2024-02-12 16:42:01       44 阅读